diff --git a/NEWS b/NEWS index 47a88f0d3d..5a2286c2ca 100644 --- a/NEWS +++ b/NEWS @@ -1,254 +1,278 @@ digiKam 6.0.0 - Release date: 2018-xx-xx ***************************************************************************************************** NEW FEATURES: ImageEditor : New clone tool to replace old CImg in-painting tool. ImageEditor : Add Web services Import and Export tools. Showfoto : Add Web services Import and Export tools. LightTable : Add Web services Import and Export tools. Database : Similarity database has been moved to a dedicated file to not bloat core database with computed finger-prints. This will speed-up query in core database in case of Similarity feature is used. Database : New video metadata parser based on ffmpeg to populate database. Search : Add video support to find files based on properties registered on database. General : Add QWebEngine support. -General : Update internal Libraw to last 0.18.13. General : Fix all Krazy static analyzer reports. +General : Update internal Libraw to last 0.19.0. + New camera supported: + * Apple: Phone 8, iPhone 8 plus, iPhone X + * BlackMagic: URSA Mini 4k, URSA Mini 4.6k, URSA Mini Pro 4.6k + * Canon: PowerShot A410, A540, D10, ELPH 130 IS, ELPH 160 IS, SD750, SX100 IS,SX130 IS, SX160 IS, SX510 HS, SX10 IS, IXUS 900Ti + PowerShot G1 X Mark III, G9 X Mark II, EOS 6D Mark II, EOS 77D, EOS 200D, EOS 800D, EOS M6, EOS M100 + * Casio: EX-ZR4100/5100 + * DJI: Phantom4 Pro/Pro+, Zenmuse X5, Zenmuse X5R + * FujiFilm: S6500fd, GFX 50S, X100f, X-A3, X-A5, X-A10, X-A20, X-E3, X-H1, X-T20 + * Hasselblad: H6D-100c, A6D-100c + * Huawei: P9 (EVA-L09/AL00), Honor6a, Honor9, Mate10 (BLA-L29) + * Leica: CL, M10, TL2 + * LG: V20 (F800K), VS995 + * Nikon: D850, D5600, D7500, Coolpix B700 + * Olympus: E-PL9, E-M10 Mark III, TG-5 + * OnePlus: A3303, A5000 + * Panasonic: DMC-FZ45, DMC-FZ72, DC-FZ80/82, DC-G9 (std. res mode only), DC-GF10/GF90, DC-GH5, DC-GX9, DC-GX800/850/GF9, DMC-LX1, DC-ZS70 (DC-TZ90/91/92, DC-T93), DC-TZ100/101/ZS100, DC-TZ200/ZS200 + * PARROT: Bebop 2, Bebop Drone + * Pentax: KP + * PhaseOne: IQ3 100MP Trichromatic + * Samsung: Galaxy Nexus, Galaxy S3, S6 (SM-G920F), S7, S7 Edge, S8 (SM-G950U) + * Sony: A7R III, A9, DSC-RX0, DSC-RX10IV + * Yi: M1 + * YUNEEC: CGO3, CGO3P + * Xiaoyi: YIAC3 (YI 4k) Tags : Add possibility to merge tags by drag & drop. HTML Gallery : New Vanilla theme to emulate export to HTML from Adobe LightRoom. HTML Gallery : New Blue Frame theme. HTML Gallery : New Kiosk-Mode theme. ***************************************************************************************************** BUGFIXES: 001 ==> 172650 - No export tools available. 002 ==> 149591 - The export menu is blank. 003 ==> 300424 - Export tools not detected. 004 ==> 327743 - MediaWiki export not displayed. 005 ==> 348146 - Export tools configuration module. 006 ==> 243275 - Crashing when calling configuration. 007 ==> 257134 - Crashes when entering its settings. 008 ==> 230666 - Crash during start. 009 ==> 306698 - Crashes after update to KDE. 010 ==> 207640 - Crashes immediately at startup, sometimes at closing. 011 ==> 245628 - Crash when enabling/disabling Facebook import/export. 012 ==> 097317 - sigsegv [New Thread 1100241184 (LWP 5665)]. 013 ==> 245776 - Crashes when selecting Settings. 014 ==> 245775 - Crashes even without export tools installed. 015 ==> 254283 - Crash as soon as i click settings. 016 ==> 255733 - crash when reopening configuration dialog. 017 ==> 262050 - Crash after new install and scan to mysql database. 018 ==> 263871 - Crashed after searching for duplicates. 019 ==> 268242 - Crashes after I clicked on 'Settings'. 020 ==> 276882 - Add export tool buttons to toolbar. 021 ==> 284801 - Export to picasaweb crashes. 022 ==> 277669 - Crash after files moved. 023 ==> 281250 - Crash after disabling Export tools. 024 ==> 202637 - Crash trying to start export tool. 025 ==> 306693 - after update to KDE host application crashes on startup. 026 ==> 282781 - Crashes when reopening configuration dialog after disabling export tools. 027 ==> 285499 - Crash when settings window opened. 028 ==> 297629 - Crashed when importing from Nikon P7000. 029 ==> 303338 - Crashes when clicking "send to" button. 030 ==> 307619 - Refuses to load Export tools. 031 ==> 311812 - Export tools not loading, SO version not defined. 032 ==> 313186 - Crashes on attempt to use the "Send to" menu. 033 ==> 313356 - Crashed when clicking the "send to" button. 034 ==> 313577 - Crashes when pressing the "send to" button. 035 ==> 313890 - Crash when clicking "Send to...". 036 ==> 315033 - Crashes on pressing Send To... button. 037 ==> 315914 - The facebook tool crashes everytime on initialization. 038 ==> 326556 - Export tools are not loaded when starting host application for second time. 039 ==> 095175 - crash on loading, signal 11 SIGSEGV. 040 ==> 175844 - Crashes at startup loading Export tools. 041 ==> 306511 - Crash during start. 042 ==> 234021 - Crash on loading. 043 ==> 219772 - Opening the application causes crash. 044 ==> 294173 - Crash after Image resize start. 045 ==> 306881 - Crashed when attempting to open Export tools. 046 ==> 306495 - Crash changing settings linux ubuntu lucid. 047 ==> 306497 - Crash after changing settings segmentation fault possible 2nd report? 048 ==> 185470 - "Import from facebook" is listed twice in import menu. 049 ==> 334045 - MediaWiki option not available in Export menu when plugin activated. 050 ==> 142112 - Can't save on my webspace with ShowFoto. 051 ==> 167417 - Showfoto cannot save files of CIFS mount. 052 ==> 125164 - Flickr export tool should respect host application selection. 053 ==> 238927 - Host application quits when uploading to Flickr. 054 ==> 326740 - Selection of tools is set to default after each update. 055 ==> 233063 - Add progress indicator when moving or copy files [patch]. 056 ==> 361829 - Rotated MP4 video with "Orientation" flag are not played back in the correct rotation angle. 057 ==> 329854 - digiKam doesn't rotate video thumbnail. 058 ==> 376661 - When importing ~200,000 video files Digikam crashes in about 2-5 seconds of starting. 059 ==> 377072 - Cannot read video metadata. 060 ==> 374453 - Extract right video date from MP4 files metadata. 061 ==> 377177 - Geolocation / GPS information doesn't appear in video metadata. 062 ==> 383588 - Imported video files have time shifted exactly 2 hours later. 063 ==> 380847 - MP4 video not importing with correct date. 064 ==> 373682 - geolocalisation filter does not take care of the videos geolocalisation tags. 065 ==> 340925 - digiKam crash when start it. 066 ==> 331506 - digiKam crashes on startup. 067 ==> 335816 - Crash when trying to add a big collection. 068 ==> 353295 - digiKam repeatedly crashes while importing pictures. 069 ==> 341433 - Crash when opening digiKam application. 070 ==> 375562 - digiKam crashes while scanning images into sqlite database. 071 ==> 334782 - Crash while doing nothing. 072 ==> 362672 - Crash on start of digiKam. 073 ==> 341023 - Crash after startup during check for updated images. 074 ==> 386891 - Crashed while adding pictures. 075 ==> 342666 - digiKam crashes during find new items. 076 ==> 341274 - digiKam crash on startup. 077 ==> 343708 - Crash when scanning album. 078 ==> 332721 - Crash when reading a certain MP4 video file. 079 ==> 343736 - Crashes when rebuilding thumbnails from database. 080 ==> 346356 - digiKam crashes when adding 90.000 pictures to library. 081 ==> 343714 - digiKam crash when scanning for new items. 082 ==> 341091 - digiKam crashes when updating the MySQL database of a a hudge photo collection. 083 ==> 340879 - digiKam crashes after getting unexpected but reasonable output from libexiv2. 084 ==> 342712 - Crash on collection scanning. 085 ==> 356704 - digiKam still crashes while scanning a new photo directory and subdirs. 086 ==> 339269 - Segfault when opening a folder that contains unknown file types (mov, avi, xcf). 087 ==> 364635 - digiKam crashes on startup. 088 ==> 357356 - digiKam crash on startup while scanning photos. 089 ==> 341554 - digiKam crashed by Data-Import from NFS. 090 ==> 345457 - digiKam crashes at "loading tools". 091 ==> 349635 - Crash of digiKam - moving album. 092 ==> 342604 - digiKam crash. 093 ==> 331450 - Signal 8 on album opening. 094 ==> 342030 - digiKam crashes when checking an AVI video file using exiv2. 095 ==> 352777 - Crash during scan. 096 ==> 352944 - digiKam crashes on start. 097 ==> 343643 - digiKam crashes while perform initial scanning of custom photo folder. 098 ==> 342000 - digiKam crash when opening folder with Videos (Album or SD Card import). 099 ==> 353447 - digiKam crashes when scanning files. 100 ==> 346807 - Crashes on startup. 101 ==> 364639 - digiKam crashed while opening database. 102 ==> 341504 - Crash while using application. 103 ==> 367691 - Searching for pictures crashes at 30% every time. 104 ==> 334604 - Crash after changing disk partions. 105 ==> 351689 - Crash on opening digiKam. 106 ==> 149267 - digiKam crashes after finding avi and so on. 107 ==> 170387 - Add movies management. 108 ==> 369629 - digiKam does not use GPS data from video files. 109 ==> 367880 - Nexus 5X videos show up upside-down in digiKam. 110 ==> 330116 - digiKam does not take care about GPS info stored in MP4 video files. 111 ==> 339150 - digikam crashes when trying to display video file. 112 ==> 344406 - Crash at start. 113 ==> 339909 - digiKam Segmentation Fault on open. 114 ==> 343231 - Crash at scanning for new fotos. 115 ==> 340373 - Crash on scanning video directory. 116 ==> 134679 - Video and audio files are not imported. 117 ==> 375357 - No video preview. 118 ==> 261773 - Batch renaming does not complete when MP4 video file is processed. 119 ==> 185915 - Album View: "Created" time of video set to "00:00". 120 ==> 303218 - digiKam import crashes when you select video files. 121 ==> 374241 - Bad video date rename. 122 ==> 375646 - Be able to scan only photo, not video and audio. 123 ==> 262499 - Cannot rename .AVI files. 124 ==> 199261 - Import avi movies from sdcard wrong date and no thumbnail. 125 ==> 181521 - NEF's in descending order, AVI in ascending order in import from SD-card. 126 ==> 392019 - Two persons can point to the same face tag in pictures. 127 ==> 392013 - Metadata explorer does not show XMP face rectangles. 128 ==> 389508 - Dates Side Menu Is Not Updated Automatically After Exif Date Change [patch]. 129 ==> 331864 - Merge Tags with same name when moving to same hierarchy level. 130 ==> 347302 - Reassign name to face. 131 ==> 391747 - BQM Tool "Remove Metadata" doesn't remove all metadata from image. 132 ==> 285683 - Already imported pictures not recognized after daylight savings time. 133 ==> 392309 - Icons are pixelated when my display scale factor is 1.2 134 ==> 392405 - Function 'getImageIdsFromArea' argument order different. 135 ==> 386224 - Metadata is not updated when moving tags. 136 ==> 370245 - Be able to rename tags which have been setted in pictures. 137 ==> 374470 - Deleted tags are not removed from file metadata. 138 ==> 374516 - Persons metadata are not updated after a tag removed. 139 ==> 392436 - Count Files in directory. 140 ==> 363859 - digiKam core port from QWebKit to QWebEngine [patch]. 141 ==> 392427 - Cannot add collection on network drive. 142 ==> 392022 - Position of a face tag appears on top of bottom of the list, instead of being sorted alphabetically. 143 ==> 372763 - Rename does not give options on Conflict. 144 ==> 391533 - Feature request: add "NOT" tag matching condition in "Filters" panel. 145 ==> 381222 - digiKam crash on fuzzy search. 146 ==> 386275 - Crash caused by QtAV. 147 ==> 372342 - Face tag area is very short [patch]. 148 ==> 391348 - People Side Menu Shows Only Faces Not People Tagged Images. 149 ==> 385630 - Views Requiring Maps Takes ~30s to Launch. 150 ==> 192908 - Allow to split icon-view in order to show multiple albums at the same time. 151 ==> 339088 - GIT master: crash when clicking through images in preview, with face recognition running in background. 152 ==> 341605 - Crash if I attempt to use left-sidebar tags tab. 153 ==> 227266 - Handle Video Date from metadata. 154 ==> 227259 - Needs to Edit Video Date. 155 ==> 373284 - digiKam crashed with SIGSEGV in QSortFilterProxyModel::parent(). 156 ==> 384807 - digikam 5.7.0 AppImage bundle : provide a more recent ffmpeg version for video support. 157 ==> 391835 - Deleted pictures still appear in group. 158 ==> 387483 - Elegant theme: Selected frame colors swapped [patch]. 159 ==> 375424 - Thumbnails are not being removed from AlbumsView after moving the images to Trash. 160 ==> 368796 - Problem with Exif-tags: ImageDescription and UserComment. 161 ==> 392417 - AppImage (5.9.0-01-x86-64) does not support "--install" cli parameter. 162 ==> 392922 - digikam-6.0.0 fail to start. 163 ==> 391399 - Not possible to add location bookmarks in Digikam >5.6.0. 164 ==> 380876 - Tags in Digikam DB maintained after being removed from file and file re-scanned. 165 ==> 392017 - Merging, renaming and removing face tags. 166 ==> 352711 - Externally removed tags are not removed from digiKam. 167 ==> 393108 - Tags not always visible when selecting multiple pictures in a group. 168 ==> 392656 - Selecting a root album for face scan doesn't include subfolders, but rather scans an unexpected album set. 169 ==> 329438 - Rename function with Date & Time does not work with NTFS. 170 ==> 376473 - Can"t set empty IPTC country code when using metadata templates. 171 ==> 380289 - Cannot write to Albums residing on NFS. 172 ==> 384465 - With Compact Flash Card Created date in thumbnails is wrong. 173 ==> 381958 - Cannot add additional collection. 174 ==> 383747 - "Rotate only by setting a flag" Changes Image Instead. 175 ==> 387977 - No icon only view of "Extras sidebar": sidebar taking up a lot of space. 176 ==> 277502 - All versions of version set always displayed in Album view [patch]. 177 ==> 393283 - Caption not updating Exif.Image.ImageDescription field. 178 ==> 391060 - Crashes on undo of very large tif. 179 ==> 366305 - Add a message at startup about the lack of temporary space to perform Undo operations. 180 ==> 366391 - Rotating an image seems to forget to reset the orientation flag. 181 ==> 393654 - Not able to select gpx file. 182 ==> 367596 - Sub-folder count images but don't show them (unsupported JPEG file?). 183 ==> 379922 - Digikam won't remove tags set by Windows Explorer. 184 ==> 379081 - GPS data are in file but geolocation indicator is not shown and map view empty. 185 ==> 354819 - Specific pictures not showing up in digikam. 186 ==> 393855 - MySQL/MariaDB upgrade fails. 187 ==> 384603 - Camera Creation Date not set from EXIF data. 188 ==> 386959 - Properties view: wrong creation date [patch]. 189 ==> 393970 - No mts video thumbnails. 190 ==> 393728 - Reread metadata from Video uses sidecar only. 191 ==> 393925 - UpdateSchemaFromV7ToV9 fails due to duplicate key in album_2. 192 ==> 393773 - showfoto crashes when geotagging. 193 ==> 388199 - No context menu to copy coordinates from map. 194 ==> 393399 - Windows defender freaks out in windows 10 and Edge. 195 ==> 392134 - SIGSEGV While Scanning Faces [patch]. 196 ==> 394168 - OSM Search Yields No Results. 197 ==> 377719 - Cannot rename file with overwrite [patch]. 198 ==> 388002 - remove kio related legacy [patch] 199 ==> 394242 - Import settings unneccesarily asks to overwrite image database, and crashes when I decline. 200 ==> 394278 - A slideshow theme for kiosk mode. 201 ==> 340389 - digiKam crashes while editing pictures for color balancing on OSX [patch]. 202 ==> 394413 - Unify group handling [patch]. 203 ==> 394573 - Revers geodata from open street map does not work. 204 ==> 394590 - Feature request: being able to filter on all metadatas fields. 205 ==> 394671 - Distortion on Panasonic DMC-LX15. 206 ==> 393205 - Advanced rename very slow. 207 ==> 382474 - Thumbnail regeneration. 208 ==> 394865 - digikam suspicious crash on exit. 209 ==> 390541 - Tooltip background cannot be changed. 210 ==> 391521 - "Tool-tip" box difficult to read due to default color scheme. 211 ==> 377849 - Albums disappear when the network is interrupted. 212 ==> 394988 - PgDown and PgUp hardcoded in preview mode. 213 ==> 366312 - Efficient photo tagging workflow got lost in transition from 4.x to 5. 214 ==> 395093 - Being able to export a list of paths from a selection of thumbnails. 215 ==> 395144 - When zooming in preview, face tags show on wrong places. 216 ==> 275671 - Scan single image for faces. 217 ==> 395199 - Uploading large video files to flickr fails. 218 ==> 348274 - "Change Account" immediately opens web page in browser, before I click Continue 219 ==> 263347 - Print wizard ignores selected paper size, reverts to A4. 220 ==> 395579 - Only one tag being exported to flickr. 221 ==> 395790 - Rename with nested tags breaks due to | bar character. 222 ==> 395875 - ImageEditor window is blank when opened a second time. 223 ==> 385822 - [Suggested feature] Re-use thumbnails from the database for the items in Trash. 224 ==> diff --git a/core/libs/dimg/drawdecoding.cpp b/core/libs/dimg/drawdecoding.cpp index 8327882bc6..dc373968ec 100644 --- a/core/libs/dimg/drawdecoding.cpp +++ b/core/libs/dimg/drawdecoding.cpp @@ -1,731 +1,671 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2008-08-06 * Description : Raw decoding settings for digiKam: * standard RawEngine parameters plus * few customized for post processing. * * Copyright (C) 2008-2018 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "drawdecoding.h" // Qt includes #include // Local includes #include "drawdecoder.h" #include "filteraction.h" #include "digikam_version.h" namespace Digikam { class DRawDecoderSettingsWriter { public: DRawDecoderSettingsWriter(const DRawDecoderSettings& settings, FilterAction& action, const QString& prefix = QString()) : settings(settings), action(action), prefix(prefix) { timeOptimizedSettings.optimizeTimeLoading(); } inline QString combinedKey(const QString& key) { return prefix + key; } template void addParameterIfNotDefault(const QString& key, const T& value, const T& defaultValue) { if (value != defaultValue) { action.addParameter(key, value); } } #define AddParameterIfNotDefault(name) AddParameterIfNotDefaultWithValue(name, name) #define AddParameterIfNotDefaultWithValue(name, value) \ addParameterIfNotDefault(prefix + QLatin1String(#name), settings.value, defaultSettings.value) #define AddParameterIfNotDefaultEnum(name) AddParameterIfNotDefaultEnumWithValue(name, name) #define AddParameterIfNotDefaultEnumWithValue(name, value) \ addParameterIfNotDefault(prefix + QLatin1String(#name), settings.value, defaultSettings.value) #define AddParameter(name) action.addParameter(prefix + QLatin1String(#name), settings.name) #define AddParameterEnum(name) action.addParameter(prefix + QLatin1String(#name), static_cast(settings.name)) void write(); public: const DRawDecoderSettings& settings; FilterAction& action; QString prefix; DRawDecoderSettings defaultSettings; DRawDecoderSettings timeOptimizedSettings; }; void DRawDecoderSettingsWriter::write() { action.addParameter(QLatin1String("RawDecoder"), QLatin1String(digikam_version_short)); if (settings == defaultSettings) { action.addParameter(QLatin1String("RawDefaultSettings"), true); return; } if (settings == timeOptimizedSettings) { action.addParameter(QLatin1String("RawTimeOptimizedSettings"), true); return; } AddParameter(sixteenBitsImage); AddParameter(fixColorsHighlights); AddParameter(autoBrightness); AddParameterEnum(whiteBalance); if (settings.whiteBalance == DRawDecoderSettings::CUSTOM) { AddParameter(customWhiteBalance); AddParameter(customWhiteBalanceGreen); } AddParameterIfNotDefault(RGBInterpolate4Colors); AddParameterIfNotDefault(DontStretchPixels); AddParameterIfNotDefault(unclipColors); AddParameterEnum(RAWQuality); AddParameterIfNotDefault(medianFilterPasses); AddParameterIfNotDefaultEnumWithValue(noiseReductionType, NRType); AddParameterIfNotDefaultWithValue(noiseReductionThreshold, NRThreshold); - AddParameterIfNotDefaultWithValue(enableChromaticAberrationCorrection, enableCACorrection); - AddParameterIfNotDefaultWithValue(redChromaticAberrationMultiplier, caMultiplier[0]); - AddParameterIfNotDefaultWithValue(blueChromaticAberrationMultiplier, caMultiplier[1]); AddParameterIfNotDefault(brightness); AddParameter(enableBlackPoint); if (settings.enableBlackPoint) { AddParameter(blackPoint); } AddParameter(enableWhitePoint); if (settings.enableWhitePoint) { AddParameter(whitePoint); } AddParameterEnum(inputColorSpace); if (settings.inputColorSpace == DRawDecoderSettings::CUSTOMINPUTCS) { AddParameter(inputProfile); } AddParameterEnum(outputColorSpace); if (settings.outputColorSpace == DRawDecoderSettings::CUSTOMOUTPUTCS) { AddParameter(outputProfile); } AddParameterIfNotDefault(deadPixelMap); if (settings.whiteBalance == DRawDecoderSettings::AERA /*sic*/) { if (!settings.whiteBalanceArea.isNull()) { action.addParameter(prefix + QLatin1String("whiteBalanceAreaX"), settings.whiteBalanceArea.x()); action.addParameter(prefix + QLatin1String("whiteBalanceAreaY"), settings.whiteBalanceArea.y()); action.addParameter(prefix + QLatin1String("whiteBalanceAreaWidth"), settings.whiteBalanceArea.width()); action.addParameter(prefix + QLatin1String("whiteBalanceAreaHeight"), settings.whiteBalanceArea.height()); } } AddParameterIfNotDefault(dcbIterations); AddParameterIfNotDefault(dcbEnhanceFl); - AddParameterIfNotDefault(eeciRefine); - AddParameterIfNotDefault(esMedPasses); - AddParameterIfNotDefaultWithValue(noiseReductionChrominanceThreshold, NRChroThreshold); AddParameterIfNotDefault(expoCorrection); AddParameterIfNotDefaultWithValue(exposureCorrectionShift, expoCorrectionShift); AddParameterIfNotDefaultWithValue(exposureCorrectionHighlight, expoCorrectionHighlight); } // -------------------------------------------------------------------------------------------- class DRawDecoderSettingsReader { public: DRawDecoderSettingsReader(const FilterAction& action, const QString& prefix = QString()) : action(action), prefix(prefix) { } template void readParameter(const QString& key, enumType& setting, const variantType& defaultValue) { setting = static_cast(action.parameter(key, defaultValue)); } #define ReadParameter(name) ReadParameterWithValue(name, name) #define ReadParameterWithValue(name, value) \ settings.value = action.parameter(prefix + QLatin1String(#name), settings.value) #define ReadParameterEnum(name) ReadParameterEnumWithValue(name, name) #define ReadParameterEnumWithValue(name, value) \ readParameter(prefix + QLatin1String(#name), settings.value, static_cast(settings.value)) void read(); public: const FilterAction& action; QString prefix; DRawDecoderSettings settings; }; void DRawDecoderSettingsReader::read() { if (action.parameter(QLatin1String("RawDefaultSettings")).toBool()) { return; } if (action.parameter(QLatin1String("RawTimeOptimizedSettings")).toBool()) { settings.optimizeTimeLoading(); return; } ReadParameter(sixteenBitsImage); ReadParameter(fixColorsHighlights); ReadParameter(autoBrightness); ReadParameterEnum(whiteBalance); if (settings.whiteBalance == DRawDecoderSettings::CUSTOM) { ReadParameter(customWhiteBalance); ReadParameter(customWhiteBalanceGreen); } ReadParameter(RGBInterpolate4Colors); ReadParameter(DontStretchPixels); ReadParameter(unclipColors); ReadParameterEnum(RAWQuality); ReadParameter(medianFilterPasses); ReadParameterEnumWithValue(noiseReductionType, NRType); ReadParameterWithValue(noiseReductionThreshold, NRThreshold); - ReadParameterWithValue(enableChromaticAberrationCorrection, enableCACorrection); - ReadParameterWithValue(redChromaticAberrationMultiplier, caMultiplier[0]); - ReadParameterWithValue(blueChromaticAberrationMultiplier, caMultiplier[1]); ReadParameter(brightness); ReadParameter(enableBlackPoint); if (settings.enableBlackPoint) { ReadParameter(blackPoint); } ReadParameter(enableWhitePoint); if (settings.enableWhitePoint) { ReadParameter(whitePoint); } ReadParameterEnum(inputColorSpace); if (settings.inputColorSpace == DRawDecoderSettings::CUSTOMINPUTCS) { ReadParameter(inputProfile); } ReadParameterEnum(outputColorSpace); if (settings.outputColorSpace == DRawDecoderSettings::CUSTOMOUTPUTCS) { ReadParameter(outputProfile); } ReadParameter(deadPixelMap); if (!action.hasParameter(QLatin1String("whiteBalanceAreaX"))) { int x = action.parameter(prefix + QLatin1String("whiteBalanceAreaX"), 0); int y = action.parameter(prefix + QLatin1String("whiteBalanceAreaY"), 0); int width = action.parameter(prefix + QLatin1String("whiteBalanceAreaWidth"), 0); int height = action.parameter(prefix + QLatin1String("whiteBalanceAreaHeight"), 0); QRect rect(x, y, width, height); if (rect.isValid()) { settings.whiteBalanceArea = rect; } } ReadParameter(dcbIterations); ReadParameter(dcbEnhanceFl); - ReadParameter(eeciRefine); - ReadParameter(esMedPasses); - ReadParameterWithValue(noiseReductionChrominanceThreshold, NRChroThreshold); ReadParameter(expoCorrection); ReadParameterWithValue(exposureCorrectionShift, expoCorrectionShift); ReadParameterWithValue(exposureCorrectionHighlight, expoCorrectionHighlight); } // -------------------------------------------------------------------------------------------- DRawDecoding::DRawDecoding() { resetPostProcessingSettings(); } DRawDecoding::DRawDecoding(const DRawDecoderSettings& prm) { rawPrm = prm; resetPostProcessingSettings(); } DRawDecoding::~DRawDecoding() { } void DRawDecoding::optimizeTimeLoading() { rawPrm.optimizeTimeLoading(); resetPostProcessingSettings(); } void DRawDecoding::resetPostProcessingSettings() { bcg = BCGContainer(); wb = WBContainer(); curvesAdjust = CurvesContainer(); } bool DRawDecoding::postProcessingSettingsIsDirty() const { return !(bcg == BCGContainer() && wb == WBContainer() && curvesAdjust.isEmpty()); } bool DRawDecoding::operator==(const DRawDecoding& other) const { return (rawPrm == other.rawPrm && bcg == other.bcg && wb == other.wb && curvesAdjust == other.curvesAdjust); } DRawDecoding DRawDecoding::fromFilterAction(const FilterAction& action, const QString& prefix) { DRawDecoding settings; DRawDecoderSettingsReader reader(action, prefix); reader.read(); settings.rawPrm = reader.settings; settings.bcg = BCGContainer::fromFilterAction(action); settings.wb = WBContainer::fromFilterAction(action); settings.curvesAdjust = CurvesContainer::fromFilterAction(action); return settings; } void DRawDecoding::writeToFilterAction(FilterAction& action, const QString& prefix) const { DRawDecoderSettingsWriter writer(rawPrm, action, prefix); writer.write(); if (!bcg.isDefault()) { bcg.writeToFilterAction(action, prefix); } if (!wb.isDefault()) { wb.writeToFilterAction(action, prefix); } if (!curvesAdjust.isEmpty()) { curvesAdjust.writeToFilterAction(action, prefix); } } void DRawDecoding::decodingSettingsToXml(const DRawDecoderSettings& prm, QDomElement& elm) { QDomDocument doc = elm.ownerDocument(); QDomElement data; data = doc.createElement(QString::fromLatin1("autobrightness")); data.setAttribute(QString::fromLatin1("value"), prm.autoBrightness); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("fixcolorshighlights")); data.setAttribute(QString::fromLatin1("value"), prm.fixColorsHighlights); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("sixteenbitsimage")); data.setAttribute(QString::fromLatin1("value"), prm.sixteenBitsImage); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("brightness")); data.setAttribute(QString::fromLatin1("value"), prm.brightness); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("rawquality")); data.setAttribute(QString::fromLatin1("value"), prm.RAWQuality); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("inputcolorspace")); data.setAttribute(QString::fromLatin1("value"), prm.inputColorSpace); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("outputcolorspace")); data.setAttribute(QString::fromLatin1("value"), prm.outputColorSpace); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("rgbinterpolate4colors")); data.setAttribute(QString::fromLatin1("value"), prm.RGBInterpolate4Colors); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("dontstretchpixels")); data.setAttribute(QString::fromLatin1("value"), prm.DontStretchPixels); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("unclipcolors")); data.setAttribute(QString::fromLatin1("value"), prm.unclipColors); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("whitebalance")); data.setAttribute(QString::fromLatin1("value"), prm.whiteBalance); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("customwhitebalance")); data.setAttribute(QString::fromLatin1("value"), prm.customWhiteBalance); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("customwhitebalancegreen")); data.setAttribute(QString::fromLatin1("value"), prm.customWhiteBalanceGreen); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("halfsizecolorimage")); data.setAttribute(QString::fromLatin1("value"), prm.halfSizeColorImage); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("enableblackpoint")); data.setAttribute(QString::fromLatin1("value"), prm.enableBlackPoint); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("blackpoint")); data.setAttribute(QString::fromLatin1("value"), prm.blackPoint); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("enablewhitepoint")); data.setAttribute(QString::fromLatin1("value"), prm.enableWhitePoint); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("whitepoint")); data.setAttribute(QString::fromLatin1("value"), prm.whitePoint); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("noisereductiontype")); data.setAttribute(QString::fromLatin1("value"), prm.NRType); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("noisereductionthreshold")); data.setAttribute(QString::fromLatin1("value"), prm.NRThreshold); elm.appendChild(data); - data = doc.createElement(QString::fromLatin1("enablecacorrection")); - data.setAttribute(QString::fromLatin1("value"), prm.enableCACorrection); - elm.appendChild(data); - - data = doc.createElement(QString::fromLatin1("redchromaticaberrationmultiplier")); - data.setAttribute(QString::fromLatin1("value"), prm.caMultiplier[0]); - elm.appendChild(data); - - data = doc.createElement(QString::fromLatin1("bluechromaticaberrationmultiplier")); - data.setAttribute(QString::fromLatin1("value"), prm.caMultiplier[1]); - elm.appendChild(data); - data = doc.createElement(QString::fromLatin1("medianfilterpasses")); data.setAttribute(QString::fromLatin1("value"), prm.medianFilterPasses); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("inputprofile")); data.setAttribute(QString::fromLatin1("value"), prm.inputProfile); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("outputprofile")); data.setAttribute(QString::fromLatin1("value"), prm.outputProfile); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("deadpixelmap")); data.setAttribute(QString::fromLatin1("value"), prm.deadPixelMap); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("whitebalanceareax")); data.setAttribute(QString::fromLatin1("value"), prm.whiteBalanceArea.x()); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("whitebalanceareay")); data.setAttribute(QString::fromLatin1("value"), prm.whiteBalanceArea.y()); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("whitebalanceareawidth")); data.setAttribute(QString::fromLatin1("value"), prm.whiteBalanceArea.width()); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("whitebalanceareaheight")); data.setAttribute(QString::fromLatin1("value"), prm.whiteBalanceArea.height()); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("dcbiterations")); data.setAttribute(QString::fromLatin1("value"), prm.dcbIterations); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("dcbenhancefl")); data.setAttribute(QString::fromLatin1("value"), prm.dcbEnhanceFl); elm.appendChild(data); - data = doc.createElement(QString::fromLatin1("eecirefine")); - data.setAttribute(QString::fromLatin1("value"), prm.eeciRefine); - elm.appendChild(data); - - data = doc.createElement(QString::fromLatin1("esmedpasses")); - data.setAttribute(QString::fromLatin1("value"), prm.esMedPasses); - elm.appendChild(data); - - data = doc.createElement(QString::fromLatin1("nrchrominancethreshold")); - data.setAttribute(QString::fromLatin1("value"), prm.NRChroThreshold); - elm.appendChild(data); - data = doc.createElement(QString::fromLatin1("expocorrection")); data.setAttribute(QString::fromLatin1("value"), prm.expoCorrection); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("expocorrectionshift")); data.setAttribute(QString::fromLatin1("value"), prm.expoCorrectionShift); elm.appendChild(data); data = doc.createElement(QString::fromLatin1("expocorrectionhighlight")); data.setAttribute(QString::fromLatin1("value"), prm.expoCorrectionHighlight); elm.appendChild(data); } void DRawDecoding::decodingSettingsFromXml(const QDomElement& elm, DRawDecoderSettings& prm) { bool ok = false; for (QDomNode node = elm.firstChild(); !node.isNull(); node = node.nextSibling()) { QDomElement echild = node.toElement(); if (echild.isNull()) { continue; } QString key = echild.tagName(); QString val = echild.attribute(QString::fromLatin1("value")); if (key == QLatin1String("autobrightness")) { prm.autoBrightness = (bool)val.toInt(&ok); } else if (key == QLatin1String("fixcolorshighlights")) { prm.fixColorsHighlights = (bool)val.toInt(&ok); } else if (key == QLatin1String("sixteenbitsimage")) { prm.sixteenBitsImage = (bool)val.toInt(&ok); } else if (key == QLatin1String("brightness")) { prm.brightness = val.toDouble(&ok); } else if (key == QLatin1String("rawquality")) { prm.RAWQuality = (DRawDecoderSettings::DecodingQuality)val.toInt(&ok); } else if (key == QLatin1String("inputcolorspace")) { prm.inputColorSpace = (DRawDecoderSettings::InputColorSpace)val.toInt(&ok); } else if (key == QLatin1String("outputcolorspace")) { prm.outputColorSpace = (DRawDecoderSettings::OutputColorSpace)val.toInt(&ok); } else if (key == QLatin1String("rgbinterpolate4colors")) { prm.RGBInterpolate4Colors = (bool)val.toInt(&ok); } else if (key == QLatin1String("dontstretchpixels")) { prm.DontStretchPixels = (bool)val.toInt(&ok); } else if (key == QLatin1String("unclipcolors")) { prm.unclipColors = (int)val.toInt(&ok); } else if (key == QLatin1String("whitebalance")) { prm.whiteBalance = (DRawDecoderSettings::WhiteBalance)val.toInt(&ok); } else if (key == QLatin1String("customwhitebalance")) { prm.customWhiteBalance = val.toInt(&ok); } else if (key == QLatin1String("customwhitebalancegreen")) { prm.customWhiteBalanceGreen = val.toDouble(&ok); } else if (key == QLatin1String("halfsizecolorimage")) { prm.halfSizeColorImage = (bool)val.toInt(&ok); } else if (key == QLatin1String("enableblackpoint")) { prm.enableBlackPoint = (bool)val.toInt(&ok); } else if (key == QLatin1String("blackpoint")) { prm.blackPoint = val.toInt(&ok); } else if (key == QLatin1String("enablewhitepoint")) { prm.enableWhitePoint = (bool)val.toInt(&ok); } else if (key == QLatin1String("whitepoint")) { prm.whitePoint = val.toInt(&ok); } else if (key == QLatin1String("noisereductiontype")) { prm.NRType = (DRawDecoderSettings::NoiseReduction)val.toInt(&ok); } else if (key == QLatin1String("noisereductionthreshold")) { prm.NRThreshold = val.toInt(&ok); } - else if (key == QLatin1String("enablecacorrection")) - { - prm.enableCACorrection = (bool)val.toInt(&ok); - } - else if (key == QLatin1String("redchromaticaberrationmultiplier")) - { - prm.caMultiplier[0] = val.toDouble(&ok); - } - else if (key == QLatin1String("bluechromaticaberrationmultiplier")) - { - prm.caMultiplier[1] = val.toDouble(&ok); - } else if (key == QLatin1String("medianfilterpasses")) { prm.medianFilterPasses = val.toInt(&ok); } else if (key == QLatin1String("inputprofile")) { prm.inputProfile = val; } else if (key == QLatin1String("outputprofile")) { prm.outputProfile = val; } else if (key == QLatin1String("deadpixelmap")) { prm.deadPixelMap = val; } else if (key == QLatin1String("whitebalanceareax")) { prm.whiteBalanceArea.setX(val.toInt(&ok)); } else if (key == QLatin1String("whitebalanceareay")) { prm.whiteBalanceArea.setY(val.toInt(&ok)); } else if (key == QLatin1String("whitebalanceareawidth")) { prm.whiteBalanceArea.setWidth(val.toInt(&ok)); } else if (key == QLatin1String("whitebalanceareaheight")) { prm.whiteBalanceArea.setHeight(val.toInt(&ok)); } else if (key == QLatin1String("dcbiterations")) { prm.dcbIterations = val.toInt(&ok); } else if (key == QLatin1String("dcbenhancefl")) { prm.dcbEnhanceFl = (bool)val.toInt(&ok); } - else if (key == QLatin1String("eecirefine")) - { - prm.eeciRefine = (bool)val.toInt(&ok); - } - else if (key == QLatin1String("esmedpasses")) - { - prm.esMedPasses = val.toInt(&ok); - } - else if (key == QLatin1String("nrchrominancethreshold")) - { - prm.NRChroThreshold = val.toInt(&ok); - } else if (key == QLatin1String("expocorrection")) { prm.expoCorrection = (bool)val.toInt(&ok); } else if (key == QLatin1String("expocorrectionshift")) { prm.expoCorrectionShift = val.toDouble(&ok); } else if (key == QLatin1String("expocorrectionhighlight")) { prm.expoCorrectionHighlight = val.toDouble(&ok); } } } } // namespace Digikam diff --git a/core/libs/rawengine/CMakeLists.txt b/core/libs/rawengine/CMakeLists.txt index 1d5bebe371..393b631d27 100644 --- a/core/libs/rawengine/CMakeLists.txt +++ b/core/libs/rawengine/CMakeLists.txt @@ -1,29 +1,34 @@ # # Copyright (c) 2010-2017, Gilles Caulier, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. if (POLICY CMP0063) cmake_policy(SET CMP0063 NEW) endif (POLICY CMP0063) # LibRaw use C++ exceptions kde_enable_exceptions() add_subdirectory(libraw) set(librawengine_SRCS drawdecoder.cpp drawdecoder_p.cpp drawdecodersettings.cpp + drawdecoderwidget.cpp rawinfo.cpp ) include_directories( ${CMAKE_CURRENT_BINARY_DIR}/libraw/libraw $ $ + $ + + $ + $ ) add_library(rawengine_srcs OBJECT ${librawengine_SRCS}) diff --git a/core/libs/rawengine/drawdecoder_p.cpp b/core/libs/rawengine/drawdecoder_p.cpp index 8cbf56070b..912f38f145 100644 --- a/core/libs/rawengine/drawdecoder_p.cpp +++ b/core/libs/rawengine/drawdecoder_p.cpp @@ -1,687 +1,659 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2008-10-09 * Description : internal private container for DRawDecoder * * Copyright (C) 2008-2018 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "drawdecoder_p.h" // Qt includes #include #include // Local includes #include "digikam_debug.h" namespace Digikam { int callbackForLibRaw(void* data, enum LibRaw_progress p, int iteration, int expected) { if (data) { DRawDecoder::Private* const d = static_cast(data); if (d) { return d->progressCallback(p, iteration, expected); } } return 0; } // -------------------------------------------------------------------------------------------------- DRawDecoder::Private::Private(DRawDecoder* const p) { m_progress = 0.0; m_parent = p; } DRawDecoder::Private::~Private() { } void DRawDecoder::Private::createPPMHeader(QByteArray& imgData, libraw_processed_image_t* const img) { QString header = QString::fromUtf8("P%1\n%2 %3\n%4\n").arg(img->colors == 3 ? QLatin1String("6") : QLatin1String("5")) .arg(img->width) .arg(img->height) .arg((1 << img->bits)-1); imgData.append(header.toLatin1()); imgData.append(QByteArray((const char*)img->data, (int)img->data_size)); } int DRawDecoder::Private::progressCallback(enum LibRaw_progress p, int iteration, int expected) { qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw progress: " << libraw_strprogress(p) << " pass " << iteration << " of " << expected; // post a little change in progress indicator to show raw processor activity. setProgress(progressValue()+0.01); // Clean processing termination by user... if (m_parent->checkToCancelWaitingData()) { qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw process terminaison invoked..."; m_parent->m_cancel = true; m_progress = 0.0; return 1; } // Return 0 to continue processing... return 0; } void DRawDecoder::Private::setProgress(double value) { m_progress = value; m_parent->setWaitingDataProgress(m_progress); } double DRawDecoder::Private::progressValue() const { return m_progress; } void DRawDecoder::Private::fillIndentifyInfo(LibRaw* const raw, RawInfo& identify) { identify.dateTime.setTime_t(raw->imgdata.other.timestamp); identify.make = QString::fromUtf8(raw->imgdata.idata.make); identify.model = QString::fromUtf8(raw->imgdata.idata.model); identify.owner = QString::fromUtf8(raw->imgdata.other.artist); identify.DNGVersion = QString::number(raw->imgdata.idata.dng_version); identify.sensitivity = raw->imgdata.other.iso_speed; identify.exposureTime = raw->imgdata.other.shutter; identify.aperture = raw->imgdata.other.aperture; identify.focalLength = raw->imgdata.other.focal_len; identify.imageSize = QSize(raw->imgdata.sizes.width, raw->imgdata.sizes.height); identify.fullSize = QSize(raw->imgdata.sizes.raw_width, raw->imgdata.sizes.raw_height); identify.outputSize = QSize(raw->imgdata.sizes.iwidth, raw->imgdata.sizes.iheight); identify.thumbSize = QSize(raw->imgdata.thumbnail.twidth, raw->imgdata.thumbnail.theight); identify.topMargin = raw->imgdata.sizes.top_margin; identify.leftMargin = raw->imgdata.sizes.left_margin; identify.hasIccProfile = raw->imgdata.color.profile ? true : false; identify.isDecodable = true; identify.pixelAspectRatio = raw->imgdata.sizes.pixel_aspect; identify.rawColors = raw->imgdata.idata.colors; identify.rawImages = raw->imgdata.idata.raw_count; identify.blackPoint = raw->imgdata.color.black; for (int ch = 0; ch < 4; ch++) { identify.blackPointCh[ch] = raw->imgdata.color.cblack[ch]; } identify.whitePoint = raw->imgdata.color.maximum; identify.orientation = (RawInfo::ImageOrientation)raw->imgdata.sizes.flip; memcpy(&identify.cameraColorMatrix1, &raw->imgdata.color.cmatrix, sizeof(raw->imgdata.color.cmatrix)); memcpy(&identify.cameraColorMatrix2, &raw->imgdata.color.rgb_cam, sizeof(raw->imgdata.color.rgb_cam)); memcpy(&identify.cameraXYZMatrix, &raw->imgdata.color.cam_xyz, sizeof(raw->imgdata.color.cam_xyz)); if (raw->imgdata.idata.filters) { if (!raw->imgdata.idata.cdesc[3]) { raw->imgdata.idata.cdesc[3] = 'G'; } for (int i=0; i < 16; i++) { identify.filterPattern.append(QChar::fromLatin1(raw->imgdata.idata.cdesc[raw->COLOR(i >> 1, i & 1)])); } identify.colorKeys = QString::fromLatin1(raw->imgdata.idata.cdesc); } for(int c = 0 ; c < raw->imgdata.idata.colors ; c++) { identify.daylightMult[c] = raw->imgdata.color.pre_mul[c]; } if (raw->imgdata.color.cam_mul[0] > 0) { for(int c = 0 ; c < 4 ; c++) { identify.cameraMult[c] = raw->imgdata.color.cam_mul[c]; } } } bool DRawDecoder::Private::loadFromLibraw(const QString& filePath, QByteArray& imageData, int& width, int& height, int& rgbmax) { m_parent->m_cancel = false; LibRaw raw; // Set progress call back function. raw.set_progress_handler(callbackForLibRaw, this); QByteArray deadpixelPath = QFile::encodeName(m_parent->m_decoderSettings.deadPixelMap); QByteArray cameraProfile = QFile::encodeName(m_parent->m_decoderSettings.inputProfile); QByteArray outputProfile = QFile::encodeName(m_parent->m_decoderSettings.outputProfile); if (!m_parent->m_decoderSettings.autoBrightness) { // Use a fixed white level, ignoring the image histogram. raw.imgdata.params.no_auto_bright = 1; } if (m_parent->m_decoderSettings.sixteenBitsImage) { // (-4) 16bit ppm output raw.imgdata.params.output_bps = 16; } if (m_parent->m_decoderSettings.halfSizeColorImage) { // (-h) Half-size color image (3x faster than -q). raw.imgdata.params.half_size = 1; } if (m_parent->m_decoderSettings.RGBInterpolate4Colors) { // (-f) Interpolate RGB as four colors. raw.imgdata.params.four_color_rgb = 1; } if (m_parent->m_decoderSettings.DontStretchPixels) { // (-j) Do not stretch the image to its correct aspect ratio. raw.imgdata.params.use_fuji_rotate = 1; } // (-H) Unclip highlight color. raw.imgdata.params.highlight = m_parent->m_decoderSettings.unclipColors; if (m_parent->m_decoderSettings.brightness != 1.0) { // (-b) Set Brightness value. raw.imgdata.params.bright = m_parent->m_decoderSettings.brightness; } if (m_parent->m_decoderSettings.enableBlackPoint) { // (-k) Set Black Point value. raw.imgdata.params.user_black = m_parent->m_decoderSettings.blackPoint; } if (m_parent->m_decoderSettings.enableWhitePoint) { // (-S) Set White Point value (saturation). raw.imgdata.params.user_sat = m_parent->m_decoderSettings.whitePoint; } if (m_parent->m_decoderSettings.medianFilterPasses > 0) { // (-m) After interpolation, clean up color artifacts by repeatedly applying a 3x3 median filter to the R-G and B-G channels. raw.imgdata.params.med_passes = m_parent->m_decoderSettings.medianFilterPasses; } if (!m_parent->m_decoderSettings.deadPixelMap.isEmpty()) { // (-P) Read the dead pixel list from this file. raw.imgdata.params.bad_pixels = deadpixelPath.data(); } switch (m_parent->m_decoderSettings.whiteBalance) { case DRawDecoderSettings::NONE: { break; } case DRawDecoderSettings::CAMERA: { // (-w) Use camera white balance, if possible. raw.imgdata.params.use_camera_wb = 1; break; } case DRawDecoderSettings::AUTO: { // (-a) Use automatic white balance. raw.imgdata.params.use_auto_wb = 1; break; } case DRawDecoderSettings::CUSTOM: { /* Convert between Temperature and RGB. */ double T; double RGB[3]; double xD, yD, X, Y, Z; RawInfo identify; T = m_parent->m_decoderSettings.customWhiteBalance; /* Here starts the code picked and adapted from ufraw (0.12.1) to convert Temperature + green multiplier to RGB multipliers */ /* Convert between Temperature and RGB. * Base on information from http://www.brucelindbloom.com/ * The fit for D-illuminant between 4000K and 12000K are from CIE * The generalization to 2000K < T < 4000K and the blackbody fits * are my own and should be taken with a grain of salt. */ const double XYZ_to_RGB[3][3] = { { 3.24071, -0.969258, 0.0556352 }, {-1.53726, 1.87599, -0.203996 }, {-0.498571, 0.0415557, 1.05707 } }; // Fit for CIE Daylight illuminant if (T <= 4000) { xD = 0.27475e9/(T*T*T) - 0.98598e6/(T*T) + 1.17444e3/T + 0.145986; } else if (T <= 7000) { xD = -4.6070e9/(T*T*T) + 2.9678e6/(T*T) + 0.09911e3/T + 0.244063; } else { xD = -2.0064e9/(T*T*T) + 1.9018e6/(T*T) + 0.24748e3/T + 0.237040; } yD = -3*xD*xD + 2.87*xD - 0.275; X = xD/yD; Y = 1; Z = (1-xD-yD)/yD; RGB[0] = X*XYZ_to_RGB[0][0] + Y*XYZ_to_RGB[1][0] + Z*XYZ_to_RGB[2][0]; RGB[1] = X*XYZ_to_RGB[0][1] + Y*XYZ_to_RGB[1][1] + Z*XYZ_to_RGB[2][1]; RGB[2] = X*XYZ_to_RGB[0][2] + Y*XYZ_to_RGB[1][2] + Z*XYZ_to_RGB[2][2]; /* End of the code picked to ufraw */ RGB[1] = RGB[1] / m_parent->m_decoderSettings.customWhiteBalanceGreen; /* By default, decraw override his default D65 WB We need to keep it as a basis : if not, colors with some DSLR will have a high dominant of color that will lead to a completely wrong WB */ if (rawFileIdentify(identify, filePath)) { RGB[0] = identify.daylightMult[0] / RGB[0]; RGB[1] = identify.daylightMult[1] / RGB[1]; RGB[2] = identify.daylightMult[2] / RGB[2]; } else { RGB[0] = 1.0 / RGB[0]; RGB[1] = 1.0 / RGB[1]; RGB[2] = 1.0 / RGB[2]; qCDebug(DIGIKAM_RAWENGINE_LOG) << "Warning: cannot get daylight multipliers"; } // (-r) set Raw Color Balance Multipliers. raw.imgdata.params.user_mul[0] = RGB[0]; raw.imgdata.params.user_mul[1] = RGB[1]; raw.imgdata.params.user_mul[2] = RGB[2]; raw.imgdata.params.user_mul[3] = RGB[1]; break; } case DRawDecoderSettings::AERA: { // (-A) Calculate the white balance by averaging a rectangular area from image. raw.imgdata.params.greybox[0] = m_parent->m_decoderSettings.whiteBalanceArea.left(); raw.imgdata.params.greybox[1] = m_parent->m_decoderSettings.whiteBalanceArea.top(); raw.imgdata.params.greybox[2] = m_parent->m_decoderSettings.whiteBalanceArea.width(); raw.imgdata.params.greybox[3] = m_parent->m_decoderSettings.whiteBalanceArea.height(); break; } } // (-q) Use an interpolation method. raw.imgdata.params.user_qual = m_parent->m_decoderSettings.RAWQuality; switch (m_parent->m_decoderSettings.NRType) { case DRawDecoderSettings::WAVELETSNR: { // (-n) Use wavelets to erase noise while preserving real detail. raw.imgdata.params.threshold = m_parent->m_decoderSettings.NRThreshold; break; } case DRawDecoderSettings::FBDDNR: { // (100 - 1000) => (1 - 10) conversion raw.imgdata.params.fbdd_noiserd = lround(m_parent->m_decoderSettings.NRThreshold / 100.0); break; } - case DRawDecoderSettings::LINENR: - { - // (100 - 1000) => (0.001 - 0.02) conversion. - raw.imgdata.params.linenoise = m_parent->m_decoderSettings.NRThreshold * 2.11E-5 + 0.00111111; - raw.imgdata.params.cfaline = true; - break; - } - - case DRawDecoderSettings::IMPULSENR: - { - // (100 - 1000) => (0.005 - 0.05) conversion. - raw.imgdata.params.lclean = m_parent->m_decoderSettings.NRThreshold * 5E-5; - raw.imgdata.params.cclean = m_parent->m_decoderSettings.NRChroThreshold * 5E-5; - raw.imgdata.params.cfa_clean = true; - break; - } default: // No Noise Reduction { raw.imgdata.params.threshold = 0; raw.imgdata.params.fbdd_noiserd = 0; - raw.imgdata.params.linenoise = 0; - raw.imgdata.params.cfaline = false; - raw.imgdata.params.lclean = 0; - raw.imgdata.params.cclean = 0; - raw.imgdata.params.cfa_clean = false; break; } } - // Chromatic aberration correction. - raw.imgdata.params.ca_correc = m_parent->m_decoderSettings.enableCACorrection; - raw.imgdata.params.cared = m_parent->m_decoderSettings.caMultiplier[0]; - raw.imgdata.params.cablue = m_parent->m_decoderSettings.caMultiplier[1]; - // Exposure Correction before interpolation. raw.imgdata.params.exp_correc = m_parent->m_decoderSettings.expoCorrection; raw.imgdata.params.exp_shift = m_parent->m_decoderSettings.expoCorrectionShift; raw.imgdata.params.exp_preser = m_parent->m_decoderSettings.expoCorrectionHighlight; switch (m_parent->m_decoderSettings.inputColorSpace) { case DRawDecoderSettings::EMBEDDED: { // (-p embed) Use input profile from RAW file to define the camera's raw colorspace. raw.imgdata.params.camera_profile = (char*)"embed"; break; } case DRawDecoderSettings::CUSTOMINPUTCS: { if (!m_parent->m_decoderSettings.inputProfile.isEmpty()) { // (-p) Use input profile file to define the camera's raw colorspace. raw.imgdata.params.camera_profile = cameraProfile.data(); } break; } default: { // No input profile break; } } switch (m_parent->m_decoderSettings.outputColorSpace) { case DRawDecoderSettings::CUSTOMOUTPUTCS: { if (!m_parent->m_decoderSettings.outputProfile.isEmpty()) { // (-o) Use ICC profile file to define the output colorspace. raw.imgdata.params.output_profile = outputProfile.data(); } break; } default: { // (-o) Define the output colorspace. raw.imgdata.params.output_color = m_parent->m_decoderSettings.outputColorSpace; break; } } //-- Extended demosaicing settings ---------------------------------------------------------- raw.imgdata.params.dcb_iterations = m_parent->m_decoderSettings.dcbIterations; raw.imgdata.params.dcb_enhance_fl = m_parent->m_decoderSettings.dcbEnhanceFl; - raw.imgdata.params.eeci_refine = m_parent->m_decoderSettings.eeciRefine; - raw.imgdata.params.es_med_passes = m_parent->m_decoderSettings.esMedPasses; //------------------------------------------------------------------------------------------- setProgress(0.1); qCDebug(DIGIKAM_RAWENGINE_LOG) << filePath; qCDebug(DIGIKAM_RAWENGINE_LOG) << m_parent->m_decoderSettings; int ret = raw.open_file((const char*)(QFile::encodeName(filePath)).constData()); if (ret != LIBRAW_SUCCESS) { qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run open_file: " << libraw_strerror(ret); raw.recycle(); return false; } if (m_parent->m_cancel) { raw.recycle(); return false; } setProgress(0.2); ret = raw.unpack(); if (ret != LIBRAW_SUCCESS) { qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run unpack: " << libraw_strerror(ret); raw.recycle(); return false; } if (m_parent->m_cancel) { raw.recycle(); return false; } setProgress(0.25); if (m_parent->m_decoderSettings.fixColorsHighlights) { qCDebug(DIGIKAM_RAWENGINE_LOG) << "Applying LibRaw highlights adjustments"; // 1.0 is fallback to default value raw.imgdata.params.adjust_maximum_thr = 1.0; } else { qCDebug(DIGIKAM_RAWENGINE_LOG) << "Disabling LibRaw highlights adjustments"; // 0.0 disables this feature raw.imgdata.params.adjust_maximum_thr = 0.0; } ret = raw.dcraw_process(); if (ret != LIBRAW_SUCCESS) { qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run dcraw_process: " << libraw_strerror(ret); raw.recycle(); return false; } if (m_parent->m_cancel) { raw.recycle(); return false; } setProgress(0.3); libraw_processed_image_t* img = raw.dcraw_make_mem_image(&ret); if(!img) { qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run dcraw_make_mem_image: " << libraw_strerror(ret); raw.recycle(); return false; } if (m_parent->m_cancel) { // Clear memory allocation. Introduced with LibRaw 0.11.0 raw.dcraw_clear_mem(img); raw.recycle(); return false; } setProgress(0.35); width = img->width; height = img->height; rgbmax = (1 << img->bits)-1; if (img->colors == 3) { imageData = QByteArray((const char*)img->data, (int)img->data_size); } else { // img->colors == 1 (Grayscale) : convert to RGB imageData = QByteArray(); for (int i = 0 ; i < (int)img->data_size ; ++i) { for (int j = 0 ; j < 3 ; ++j) { imageData.append(img->data[i]); } } } // Clear memory allocation. Introduced with LibRaw 0.11.0 raw.dcraw_clear_mem(img); raw.recycle(); if (m_parent->m_cancel) { return false; } setProgress(0.4); qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: data info: width=" << width << " height=" << height << " rgbmax=" << rgbmax; return true; } bool DRawDecoder::Private::loadEmbeddedPreview(QByteArray& imgData, LibRaw& raw) { int ret = raw.unpack_thumb(); if (ret != LIBRAW_SUCCESS) { raw.recycle(); qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run unpack_thumb: " << libraw_strerror(ret); raw.recycle(); return false; } libraw_processed_image_t* const thumb = raw.dcraw_make_mem_thumb(&ret); if(!thumb) { qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run dcraw_make_mem_thumb: " << libraw_strerror(ret); raw.recycle(); return false; } if(thumb->type == LIBRAW_IMAGE_BITMAP) { createPPMHeader(imgData, thumb); } else { imgData = QByteArray((const char*)thumb->data, (int)thumb->data_size); } // Clear memory allocation. Introduced with LibRaw 0.11.0 raw.dcraw_clear_mem(thumb); raw.recycle(); if ( imgData.isEmpty() ) { qCDebug(DIGIKAM_RAWENGINE_LOG) << "Failed to load JPEG thumb from LibRaw!"; return false; } return true; } bool DRawDecoder::Private::loadHalfPreview(QImage& image, LibRaw& raw) { raw.imgdata.params.use_auto_wb = 1; // Use automatic white balance. raw.imgdata.params.use_camera_wb = 1; // Use camera white balance, if possible. raw.imgdata.params.half_size = 1; // Half-size color image (3x faster than -q). QByteArray imgData; int ret = raw.unpack(); if (ret != LIBRAW_SUCCESS) { qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run unpack: " << libraw_strerror(ret); raw.recycle(); return false; } ret = raw.dcraw_process(); if (ret != LIBRAW_SUCCESS) { qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run dcraw_process: " << libraw_strerror(ret); raw.recycle(); return false; } libraw_processed_image_t* halfImg = raw.dcraw_make_mem_image(&ret); if(!halfImg) { qCDebug(DIGIKAM_RAWENGINE_LOG) << "LibRaw: failed to run dcraw_make_mem_image: " << libraw_strerror(ret); raw.recycle(); return false; } Private::createPPMHeader(imgData, halfImg); // Clear memory allocation. Introduced with LibRaw 0.11.0 raw.dcraw_clear_mem(halfImg); raw.recycle(); if ( imgData.isEmpty() ) { qCDebug(DIGIKAM_RAWENGINE_LOG) << "Failed to load half preview from LibRaw!"; return false; } if (!image.loadFromData(imgData)) { qCDebug(DIGIKAM_RAWENGINE_LOG) << "Failed to load PPM data from LibRaw!"; return false; } return true; } } // namespace Digikam diff --git a/core/libs/rawengine/drawdecodersettings.cpp b/core/libs/rawengine/drawdecodersettings.cpp index bc678b344b..6c29b79a02 100644 --- a/core/libs/rawengine/drawdecodersettings.cpp +++ b/core/libs/rawengine/drawdecodersettings.cpp @@ -1,272 +1,240 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2006-12-09 * Description : Raw decoding settings * * Copyright (C) 2006-2018 by Gilles Caulier * Copyright (C) 2006-2013 by Marcel Wiesweg * Copyright (C) 2007-2008 by Guillaume Castagnino * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "drawdecodersettings.h" namespace Digikam { DRawDecoderSettings::DRawDecoderSettings() { fixColorsHighlights = false; autoBrightness = true; sixteenBitsImage = false; brightness = 1.0; RAWQuality = BILINEAR; inputColorSpace = NOINPUTCS; outputColorSpace = SRGB; RGBInterpolate4Colors = false; DontStretchPixels = false; unclipColors = 0; whiteBalance = CAMERA; customWhiteBalance = 6500; customWhiteBalanceGreen = 1.0; medianFilterPasses = 0; halfSizeColorImage = false; enableBlackPoint = false; blackPoint = 0; enableWhitePoint = false; whitePoint = 0; NRType = NONR; NRThreshold = 0; - enableCACorrection = false; - caMultiplier[0] = 0.0; - caMultiplier[1] = 0.0; - inputProfile = QString(); outputProfile = QString(); deadPixelMap = QString(); whiteBalanceArea = QRect(); //-- Extended demosaicing settings ---------------------------------------------------------- dcbIterations = -1; dcbEnhanceFl = false; - eeciRefine = false; - esMedPasses = 0; - NRChroThreshold = 0; expoCorrection = false; expoCorrectionShift = 1.0; expoCorrectionHighlight = 0.0; } DRawDecoderSettings::~DRawDecoderSettings() { } DRawDecoderSettings& DRawDecoderSettings::operator=(const DRawDecoderSettings& o) { fixColorsHighlights = o.fixColorsHighlights; autoBrightness = o.autoBrightness; sixteenBitsImage = o.sixteenBitsImage; brightness = o.brightness; RAWQuality = o.RAWQuality; inputColorSpace = o.inputColorSpace; outputColorSpace = o.outputColorSpace; RGBInterpolate4Colors = o.RGBInterpolate4Colors; DontStretchPixels = o.DontStretchPixels; unclipColors = o.unclipColors; whiteBalance = o.whiteBalance; customWhiteBalance = o.customWhiteBalance; customWhiteBalanceGreen = o.customWhiteBalanceGreen; halfSizeColorImage = o.halfSizeColorImage; enableBlackPoint = o.enableBlackPoint; blackPoint = o.blackPoint; enableWhitePoint = o.enableWhitePoint; whitePoint = o.whitePoint; NRType = o.NRType; NRThreshold = o.NRThreshold; - enableCACorrection = o.enableCACorrection; - caMultiplier[0] = o.caMultiplier[0]; - caMultiplier[1] = o.caMultiplier[1]; medianFilterPasses = o.medianFilterPasses; inputProfile = o.inputProfile; outputProfile = o.outputProfile; deadPixelMap = o.deadPixelMap; whiteBalanceArea = o.whiteBalanceArea; //-- Extended demosaicing settings ---------------------------------------------------------- dcbIterations = o.dcbIterations; dcbEnhanceFl = o.dcbEnhanceFl; - eeciRefine = o.eeciRefine; - esMedPasses = o.esMedPasses; - NRChroThreshold = o.NRChroThreshold; expoCorrection = o.expoCorrection; expoCorrectionShift = o.expoCorrectionShift; expoCorrectionHighlight = o.expoCorrectionHighlight; return *this; } bool DRawDecoderSettings::operator==(const DRawDecoderSettings& o) const { return fixColorsHighlights == o.fixColorsHighlights && autoBrightness == o.autoBrightness && sixteenBitsImage == o.sixteenBitsImage && brightness == o.brightness && RAWQuality == o.RAWQuality && inputColorSpace == o.inputColorSpace && outputColorSpace == o.outputColorSpace && RGBInterpolate4Colors == o.RGBInterpolate4Colors && DontStretchPixels == o.DontStretchPixels && unclipColors == o.unclipColors && whiteBalance == o.whiteBalance && customWhiteBalance == o.customWhiteBalance && customWhiteBalanceGreen == o.customWhiteBalanceGreen && halfSizeColorImage == o.halfSizeColorImage && enableBlackPoint == o.enableBlackPoint && blackPoint == o.blackPoint && enableWhitePoint == o.enableWhitePoint && whitePoint == o.whitePoint && NRType == o.NRType && NRThreshold == o.NRThreshold - && enableCACorrection == o.enableCACorrection - && caMultiplier[0] == o.caMultiplier[0] - && caMultiplier[1] == o.caMultiplier[1] && medianFilterPasses == o.medianFilterPasses && inputProfile == o.inputProfile && outputProfile == o.outputProfile && deadPixelMap == o.deadPixelMap && whiteBalanceArea == o.whiteBalanceArea //-- Extended demosaicing settings ---------------------------------------------------------- && dcbIterations == o.dcbIterations && dcbEnhanceFl == o.dcbEnhanceFl - && eeciRefine == o.eeciRefine - && esMedPasses == o.esMedPasses - && NRChroThreshold == o.NRChroThreshold && expoCorrection == o.expoCorrection && expoCorrectionShift == o.expoCorrectionShift && expoCorrectionHighlight == o.expoCorrectionHighlight ; } void DRawDecoderSettings::optimizeTimeLoading() { fixColorsHighlights = false; autoBrightness = true; sixteenBitsImage = true; brightness = 1.0; RAWQuality = BILINEAR; inputColorSpace = NOINPUTCS; outputColorSpace = SRGB; RGBInterpolate4Colors = false; DontStretchPixels = false; unclipColors = 0; whiteBalance = CAMERA; customWhiteBalance = 6500; customWhiteBalanceGreen = 1.0; halfSizeColorImage = true; medianFilterPasses = 0; enableBlackPoint = false; blackPoint = 0; enableWhitePoint = false; whitePoint = 0; NRType = NONR; NRThreshold = 0; - enableCACorrection = false; - caMultiplier[0] = 0.0; - caMultiplier[1] = 0.0; - inputProfile = QString(); outputProfile = QString(); deadPixelMap = QString(); whiteBalanceArea = QRect(); //-- Extended demosaicing settings ---------------------------------------------------------- dcbIterations = -1; dcbEnhanceFl = false; - eeciRefine = false; - esMedPasses = 0; - NRChroThreshold = 0; expoCorrection = false; expoCorrectionShift = 1.0; expoCorrectionHighlight = 0.0; } QDebug operator<<(QDebug dbg, const DRawDecoderSettings& s) { dbg.nospace() << endl; dbg.nospace() << "-- RAW DECODING SETTINGS --------------------------------" << endl; dbg.nospace() << "-- autoBrightness: " << s.autoBrightness << endl; dbg.nospace() << "-- sixteenBitsImage: " << s.sixteenBitsImage << endl; dbg.nospace() << "-- brightness: " << s.brightness << endl; dbg.nospace() << "-- RAWQuality: " << s.RAWQuality << endl; dbg.nospace() << "-- inputColorSpace: " << s.inputColorSpace << endl; dbg.nospace() << "-- outputColorSpace: " << s.outputColorSpace << endl; dbg.nospace() << "-- RGBInterpolate4Colors: " << s.RGBInterpolate4Colors << endl; dbg.nospace() << "-- DontStretchPixels: " << s.DontStretchPixels << endl; dbg.nospace() << "-- unclipColors: " << s.unclipColors << endl; dbg.nospace() << "-- whiteBalance: " << s.whiteBalance << endl; dbg.nospace() << "-- customWhiteBalance: " << s.customWhiteBalance << endl; dbg.nospace() << "-- customWhiteBalanceGreen: " << s.customWhiteBalanceGreen << endl; dbg.nospace() << "-- halfSizeColorImage: " << s.halfSizeColorImage << endl; dbg.nospace() << "-- enableBlackPoint: " << s.enableBlackPoint << endl; dbg.nospace() << "-- blackPoint: " << s.blackPoint << endl; dbg.nospace() << "-- enableWhitePoint: " << s.enableWhitePoint << endl; dbg.nospace() << "-- whitePoint: " << s.whitePoint << endl; dbg.nospace() << "-- NoiseReductionType: " << s.NRType << endl; dbg.nospace() << "-- NoiseReductionThreshold: " << s.NRThreshold << endl; - dbg.nospace() << "-- enableCACorrection: " << s.enableCACorrection << endl; - dbg.nospace() << "-- caMultiplier: " << s.caMultiplier[0] - << ", " << s.caMultiplier[1] << endl; dbg.nospace() << "-- medianFilterPasses: " << s.medianFilterPasses << endl; dbg.nospace() << "-- inputProfile: " << s.inputProfile << endl; dbg.nospace() << "-- outputProfile: " << s.outputProfile << endl; dbg.nospace() << "-- deadPixelMap: " << s.deadPixelMap << endl; dbg.nospace() << "-- whiteBalanceArea: " << s.whiteBalanceArea << endl; //-- Extended demosaicing settings ---------------------------------------------------------- dbg.nospace() << "-- dcbIterations: " << s.dcbIterations << endl; dbg.nospace() << "-- dcbEnhanceFl: " << s.dcbEnhanceFl << endl; - dbg.nospace() << "-- eeciRefine: " << s.eeciRefine << endl; - dbg.nospace() << "-- esMedPasses: " << s.esMedPasses << endl; - dbg.nospace() << "-- NRChrominanceThreshold: " << s.NRChroThreshold << endl; dbg.nospace() << "-- expoCorrection: " << s.expoCorrection << endl; dbg.nospace() << "-- expoCorrectionShift: " << s.expoCorrectionShift << endl; dbg.nospace() << "-- expoCorrectionHighlight: " << s.expoCorrectionHighlight << endl; dbg.nospace() << "---------------------------------------------------------" << endl; return dbg.space(); } } // namespace Digikam diff --git a/core/libs/rawengine/drawdecodersettings.h b/core/libs/rawengine/drawdecodersettings.h index dd3ba43c51..9469f3fe9b 100644 --- a/core/libs/rawengine/drawdecodersettings.h +++ b/core/libs/rawengine/drawdecodersettings.h @@ -1,359 +1,309 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2006-12-09 * Description : Raw decoding settings * * Copyright (C) 2006-2018 by Gilles Caulier * Copyright (C) 2006-2013 by Marcel Wiesweg * Copyright (C) 2007-2008 by Guillaume Castagnino * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_DRAW_DECODER_SETTINGS_H #define DIGIKAM_DRAW_DECODER_SETTINGS_H // Qt includes #include #include #include // Local includes #include "digikam_export.h" namespace Digikam { class DIGIKAM_EXPORT DRawDecoderSettings { public: /** RAW decoding Interpolation methods * * NOTE: from original dcraw demosaic * * Bilinear: use high-speed but low-quality bilinear * interpolation (default - for slow computer). In this method, * the red value of a non-red pixel is computed as the average of * the adjacent red pixels, and similar for blue and green. * VNG: use Variable Number of Gradients interpolation. * This method computes gradients near the pixel of interest and uses * the lower gradients (representing smoother and more similar parts * of the image) to make an estimate. * PPG: use Patterned Pixel Grouping interpolation. * Pixel Grouping uses assumptions about natural scenery in making estimates. * It has fewer color artifacts on natural images than the Variable Number of * Gradients method. * AHD: use Adaptive Homogeneity-Directed interpolation. * This method selects the direction of interpolation so as to * maximize a homogeneity metric, thus typically minimizing color artifacts. - * - * NOTE: from GPL2 demosaic pack. - * * DCB: DCB interpolation (see http://www.linuxphoto.org/html/dcb.html for details) - * PL_AHD: modified AHD interpolation (see http://sites.google.com/site/demosaicalgorithms/modified-dcraw - * for details). - * AFD: demosaicing through 5 pass median filter from PerfectRaw project. - * VCD: VCD interpolation. - * VCD_AHD: mixed demosaicing between VCD and AHD. - * LMMSE: LMMSE interpolation from PerfectRaw. - * - * NOTE: from GPL3 demosaic pack. - * - * AMAZE: AMaZE interpolation and color aberration removal from RawTherapee project. + * DHT: DHT interpolation. + * AAHD: Enhanced Adaptative AHD interpolation. */ enum DecodingQuality { - // from original dcraw demosaic BILINEAR = 0, VNG = 1, PPG = 2, AHD = 3, - // Extended demosaicing method from GPL2 demosaic pack DCB = 4, - PL_AHD = 5, - AFD = 6, - VCD = 7, - VCD_AHD = 8, - LMMSE = 9, - // Extended demosaicing methods from GPL3 demosaic pack - AMAZE = 10 + DHT = 11, + AAHD = 12 }; /** White balances alternatives * NONE: no white balance used : reverts to standard daylight D65 WB. * CAMERA: Use the camera embedded WB if available. Reverts to NONE if not. * AUTO: Averages an auto WB on the entire image. * CUSTOM: Let use set it's own temperature and green factor (later converted to RGBG factors). * AERA: Let use an aera from image to average white balance (see whiteBalanceArea for details). */ enum WhiteBalance { NONE = 0, CAMERA = 1, AUTO = 2, CUSTOM = 3, AERA = 4 }; /** Noise Reduction method to apply before demosaicing * NONR: No noise reduction. * WAVELETSNR: wavelets correction to erase noise while preserving real detail. It's applied after interpolation. * FBDDNR: Fake Before Demosaicing Denoising noise reduction. It's applied before interpolation. - * LINENR: CFA Line Denoise. It's applied after interpolation. - * IMPULSENR: Impulse Denoise. It's applied after interpolation. */ enum NoiseReduction { NONR = 0, WAVELETSNR, - FBDDNR, - LINENR, - IMPULSENR + FBDDNR }; /** Input color profile used to decoded image * NOINPUTCS: No input color profile. * EMBEDDED: Use the camera profile embedded in RAW file if exist. * CUSTOMINPUTCS: Use a custom input color space profile. */ enum InputColorSpace { NOINPUTCS = 0, EMBEDDED, CUSTOMINPUTCS }; /** Output RGB color space used to decoded image * RAWCOLOR: No output color profile (Linear RAW). * SRGB: Use standard sRGB color space. * ADOBERGB: Use standard Adobe RGB color space. * WIDEGAMMUT: Use standard RGB Wide Gamut color space. * PROPHOTO: Use standard RGB Pro Photo color space. * CUSTOMOUTPUTCS: Use a custom workspace color profile. */ enum OutputColorSpace { RAWCOLOR = 0, SRGB, ADOBERGB, WIDEGAMMUT, PROPHOTO, CUSTOMOUTPUTCS }; /** Standard constructor with default settings */ DRawDecoderSettings(); /** Equivalent to the copy constructor */ DRawDecoderSettings& operator=(const DRawDecoderSettings& prm); /** Compare for equality */ bool operator==(const DRawDecoderSettings& o) const; /** Standard destructor */ virtual ~DRawDecoderSettings(); /** Method to use a settings to optimize time loading, for exemple to compute image histogram */ void optimizeTimeLoading(); public: /** If true, images with overblown channels are processed much more accurate, * without 'pink clouds' (and blue highlights under tungsteen lamps). */ bool fixColorsHighlights; /** If false, use a fixed white level, ignoring the image histogram. */ bool autoBrightness; /** Turn on RAW file decoding in 16 bits per color per pixel instead 8 bits. */ bool sixteenBitsImage; /** Half-size color image decoding (twice as fast as "enableRAWQuality"). * Turn on this option to reduce time loading to render histogram for example, * no to render an image to screen. */ bool halfSizeColorImage; /** White balance type to use. See WhiteBalance values for detail */ WhiteBalance whiteBalance; /** The temperature and the green multiplier of the custom white balance */ int customWhiteBalance; double customWhiteBalanceGreen; /** Turn on RAW file decoding using RGB interpolation as four colors. */ bool RGBInterpolate4Colors; /** For cameras with non-square pixels, do not stretch the image to its * correct aspect ratio. In any case, this option guarantees that each * output pixel corresponds to one RAW pixel. */ bool DontStretchPixels; /** Unclip Highlight color level: * 0 = Clip all highlights to solid white. * 1 = Leave highlights unclipped in various shades of pink. * 2 = Blend clipped and unclipped values together for a gradual * fade to white. * 3-9 = Reconstruct highlights. Low numbers favor whites; high numbers * favor colors. */ int unclipColors; /** RAW quality decoding factor value. See DecodingQuality values * for details. */ DecodingQuality RAWQuality; /** After interpolation, clean up color artifacts by repeatedly applying * a 3x3 median filter to the R-G and B-G channels. */ int medianFilterPasses; /** Noise reduction method to apply before demosaicing. */ NoiseReduction NRType; /** Noise reduction threshold value. Null value disable NR. Range is between 100 and 1000. * For IMPULSENR : set the amount of Luminance impulse denoise. */ int NRThreshold; - /** Turn on chromatic aberrations correction - */ - bool enableCACorrection; - - /** Magnification factor for Red and Blue layers - * - caMultiplier[0] = amount of correction on red-green axis. - * - caMultiplier[1] = amount of correction on blue-yellow axis. - * - Both values set to 0.0 = automatic CA correction. - */ - double caMultiplier[2]; - /** Brightness of output image. */ double brightness; /** Turn on the black point setting to decode RAW image. */ bool enableBlackPoint; /** Black Point value of output image. */ int blackPoint; /** Turn on the white point setting to decode RAW image. */ bool enableWhitePoint; /** White Point value of output image. */ int whitePoint; /** The input color profile used to decoded RAW data. See OutputColorProfile * values for details. */ InputColorSpace inputColorSpace; /** Path to custom input ICC profile to define the camera's raw colorspace. */ QString inputProfile; /** The output color profile used to decoded RAW data. See OutputColorProfile * values for details. */ OutputColorSpace outputColorSpace; /** Path to custom output ICC profile to define the color workspace. */ QString outputProfile; /** Path to text file including dead pixel list. */ QString deadPixelMap; /** Rectangle used to calculate the white balance by averaging the region of image. */ QRect whiteBalanceArea; //-- Extended demosaicing settings ---------------------------------------------------------- /// For DCB interpolation. /** Number of DCB median filtering correction passes. * -1 : disable (default) * 1-10 : DCB correction passes */ int dcbIterations; /** Turn on the DCB interpolation with enhance interpolated colors. */ bool dcbEnhanceFl; - /// For VCD_AHD interpolation. - - /** Turn on the EECI refine for VCD Demosaicing. - */ - bool eeciRefine; - - /** Use edge-sensitive median filtering for artifact supression after VCD demosaicing. - * 0 : disable (default) - * 1-10 : median filter passes. - */ - int esMedPasses; - - /** For IMPULSENR Noise reduction. Set the amount of Chrominance impulse denoise. - Null value disable NR. Range is between 100 and 1000. - */ - int NRChroThreshold; - /** Turn on the Exposure Correction before interpolation. */ bool expoCorrection; /** Shift of Exposure Correction before interpolation in linear scale. * Usable range is from 0.25 (darken image 1 stop : -2EV) to 8.0 (lighten ~1.5 photographic stops : +3EV). */ double expoCorrectionShift; /** Amount of highlight preservation for exposure correction before interpolation in E.V. * Usable range is from 0.0 (linear exposure shift, highlights may blow) to 1.0 (maximum highlights preservation) * This settings can only take effect if expoCorrectionShift > 1.0. */ double expoCorrectionHighlight; }; //! qDebug() stream operator. Writes settings @a s to the debug output in a nicely formatted way. QDebug operator<<(QDebug dbg, const DRawDecoderSettings& s); } // namespace Digikam #endif // DIGIKAM_DRAW_DECODER_SETTINGS_H diff --git a/core/libs/widgets/files/drawdecoderwidget.cpp b/core/libs/rawengine/drawdecoderwidget.cpp similarity index 81% rename from core/libs/widgets/files/drawdecoderwidget.cpp rename to core/libs/rawengine/drawdecoderwidget.cpp index b89fc5e64f..74d62ea92e 100644 --- a/core/libs/widgets/files/drawdecoderwidget.cpp +++ b/core/libs/rawengine/drawdecoderwidget.cpp @@ -1,1402 +1,1197 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * date : 2006-09-13 * Description : Raw Decoder settings widgets * * Copyright (C) 2006-2018 by Gilles Caulier * Copyright (C) 2006-2011 by Marcel Wiesweg * Copyright (C) 2007-2008 by Guillaume Castagnino * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #define OPTIONFIXCOLORSHIGHLIGHTSENTRY "FixColorsHighlights" #define OPTIONDECODESIXTEENBITENTRY "SixteenBitsImage" #define OPTIONWHITEBALANCEENTRY "White Balance" #define OPTIONCUSTOMWHITEBALANCEENTRY "Custom White Balance" #define OPTIONCUSTOMWBGREENENTRY "Custom White Balance Green" #define OPTIONFOURCOLORRGBENTRY "Four Color RGB" #define OPTIONUNCLIPCOLORSENTRY "Unclip Color" #define OPTIONDONTSTRETCHPIXELSSENTRY "Dont Stretch Pixels" // krazy:exclude=spelling #define OPTIONMEDIANFILTERPASSESENTRY "Median Filter Passes" // krazy:exclude=spelling #define OPTIONNOISEREDUCTIONTYPEENTRY "Noise Reduction Type" #define OPTIONNOISEREDUCTIONTHRESHOLDENTRY "Noise Reduction Threshold" -#define OPTIONUSECACORRECTIONENTRY "EnableCACorrection" -#define OPTIONCAREDMULTIPLIERENTRY "caRedMultiplier" -#define OPTIONCABLUEMULTIPLIERENTRY "caBlueMultiplier" #define OPTIONAUTOBRIGHTNESSENTRY "AutoBrightness" #define OPTIONDECODINGQUALITYENTRY "Decoding Quality" #define OPTIONINPUTCOLORSPACEENTRY "Input Color Space" #define OPTIONOUTPUTCOLORSPACEENTRY "Output Color Space" #define OPTIONINPUTCOLORPROFILEENTRY "Input Color Profile" #define OPTIONOUTPUTCOLORPROFILEENTRY "Output Color Profile" #define OPTIONBRIGHTNESSMULTIPLIERENTRY "Brightness Multiplier" #define OPTIONUSEBLACKPOINTENTRY "Use Black Point" #define OPTIONBLACKPOINTENTRY "Black Point" #define OPTIONUSEWHITEPOINTENTRY "Use White Point" #define OPTIONWHITEPOINTENTRY "White Point" //-- Extended demosaicing settings ---------------------------------------------------------- #define OPTIONDCBITERATIONSENTRY "Dcb Iterations" #define OPTIONDCBENHANCEFLENTRY "Dcb Enhance Filter" -#define OPTIONEECIREFINEENTRY "Eeci Refine" -#define OPTIONESMEDPASSESENTRY "Es Median Filter Passes" -#define OPTIONNRCHROMINANCETHRESHOLDENTRY "Noise Reduction Chrominance Threshold" #define OPTIONEXPOCORRECTIONENTRY "Expo Correction" #define OPTIONEXPOCORRECTIONSHIFTENTRY "Expo Correction Shift" #define OPTIONEXPOCORRECTIONHIGHLIGHTENTRY "Expo Correction Highlight" #include "drawdecoderwidget.h" // C++ includes #include // Qt includes #include #include #include #include #include #include #include // KDE includes #include // Local includes #include "drawdecoder.h" #include "dnuminput.h" #include "dcombobox.h" #include "digikam_debug.h" namespace Digikam { class Q_DECL_HIDDEN DRawDecoderWidget::Private { public: explicit Private() { autoBrightnessBox = 0; sixteenBitsImage = 0; fourColorCheckBox = 0; brightnessLabel = 0; brightnessSpinBox = 0; blackPointCheckBox = 0; blackPointSpinBox = 0; whitePointCheckBox = 0; whitePointSpinBox = 0; whiteBalanceComboBox = 0; whiteBalanceLabel = 0; customWhiteBalanceSpinBox = 0; customWhiteBalanceLabel = 0; customWhiteBalanceGreenSpinBox = 0; customWhiteBalanceGreenLabel = 0; unclipColorLabel = 0; dontStretchPixelsCheckBox = 0; RAWQualityComboBox = 0; RAWQualityLabel = 0; noiseReductionComboBox = 0; NRSpinBox1 = 0; - NRSpinBox2 = 0; NRLabel1 = 0; - NRLabel2 = 0; - enableCACorrectionBox = 0; - autoCACorrectionBox = 0; - caRedMultSpinBox = 0; - caBlueMultSpinBox = 0; - caRedMultLabel = 0; - caBlueMultLabel = 0; unclipColorComboBox = 0; reconstructLabel = 0; reconstructSpinBox = 0; outputColorSpaceLabel = 0; outputColorSpaceComboBox = 0; demosaicingSettings = 0; whiteBalanceSettings = 0; correctionsSettings = 0; colormanSettings = 0; medianFilterPassesSpinBox = 0; medianFilterPassesLabel = 0; inIccUrlEdit = 0; outIccUrlEdit = 0; inputColorSpaceLabel = 0; inputColorSpaceComboBox = 0; fixColorsHighlightsBox = 0; refineInterpolationBox = 0; noiseReductionLabel = 0; expoCorrectionBox = 0; expoCorrectionShiftSpinBox = 0; expoCorrectionHighlightSpinBox = 0; expoCorrectionShiftLabel = 0; expoCorrectionHighlightLabel = 0; } /** Convert Exposure correction shift E.V value from GUI to Linear value needs by libraw decoder. */ double shiftExpoFromEvToLinear(double ev) const { // From GUI : -2.0EV => 0.25 // +3.0EV => 8.00 return (1.55*ev + 3.35); } /** Convert Exposure correction shift Linear value from liraw decoder to E.V value needs by GUI. */ double shiftExpoFromLinearToEv(double lin) const { // From GUI : 0.25 => -2.0EV // 8.00 => +3.0EV return ((lin-3.35) / 1.55); } public: QWidget* demosaicingSettings; QWidget* whiteBalanceSettings; QWidget* correctionsSettings; QWidget* colormanSettings; QLabel* whiteBalanceLabel; QLabel* customWhiteBalanceLabel; QLabel* customWhiteBalanceGreenLabel; QLabel* brightnessLabel; QLabel* RAWQualityLabel; QLabel* NRLabel1; - QLabel* NRLabel2; - QLabel* caRedMultLabel; - QLabel* caBlueMultLabel; QLabel* unclipColorLabel; QLabel* reconstructLabel; QLabel* inputColorSpaceLabel; QLabel* outputColorSpaceLabel; QLabel* medianFilterPassesLabel; QLabel* noiseReductionLabel; QLabel* expoCorrectionShiftLabel; QLabel* expoCorrectionHighlightLabel; QCheckBox* blackPointCheckBox; QCheckBox* whitePointCheckBox; QCheckBox* sixteenBitsImage; QCheckBox* autoBrightnessBox; QCheckBox* fourColorCheckBox; QCheckBox* dontStretchPixelsCheckBox; - QCheckBox* enableCACorrectionBox; - QCheckBox* autoCACorrectionBox; QCheckBox* fixColorsHighlightsBox; QCheckBox* refineInterpolationBox; QCheckBox* expoCorrectionBox; DFileSelector* inIccUrlEdit; DFileSelector* outIccUrlEdit; DComboBox* noiseReductionComboBox; DComboBox* whiteBalanceComboBox; DComboBox* RAWQualityComboBox; DComboBox* unclipColorComboBox; DComboBox* inputColorSpaceComboBox; DComboBox* outputColorSpaceComboBox; DIntNumInput* customWhiteBalanceSpinBox; DIntNumInput* reconstructSpinBox; DIntNumInput* blackPointSpinBox; DIntNumInput* whitePointSpinBox; DIntNumInput* NRSpinBox1; - DIntNumInput* NRSpinBox2; DIntNumInput* medianFilterPassesSpinBox; DDoubleNumInput* customWhiteBalanceGreenSpinBox; - DDoubleNumInput* caRedMultSpinBox; - DDoubleNumInput* caBlueMultSpinBox; DDoubleNumInput* brightnessSpinBox; DDoubleNumInput* expoCorrectionShiftSpinBox; DDoubleNumInput* expoCorrectionHighlightSpinBox; }; DRawDecoderWidget::DRawDecoderWidget(QWidget* const parent, int advSettings) : DExpanderBox(parent), d(new Private) { setup(advSettings); } void DRawDecoderWidget::setup(int advSettings) { setObjectName( QLatin1String("DCRawSettings Expander" )); // --------------------------------------------------------------- // DEMOSAICING Settings panel d->demosaicingSettings = new QWidget(this); QGridLayout* const demosaicingLayout = new QGridLayout(d->demosaicingSettings); int line = 0; d->sixteenBitsImage = new QCheckBox(i18nc("@option:check", "16 bits color depth"), d->demosaicingSettings); d->sixteenBitsImage->setWhatsThis(xi18nc("@info:whatsthis", "If enabled, all RAW files will " "be decoded in 16-bit color depth using a linear gamma curve. To " "prevent dark picture rendering in the editor, it is recommended to " "use Color Management in this mode." "If disabled, all RAW files will be decoded in 8-bit color " "depth with a BT.709 gamma curve and a 99th-percentile white point. " "This mode is faster than 16-bit decoding.")); demosaicingLayout->addWidget(d->sixteenBitsImage, 0, 0, 1, 2); if (advSettings & SIXTEENBITS) { d->sixteenBitsImage->show(); line = 1; } else { d->sixteenBitsImage->hide(); } d->fourColorCheckBox = new QCheckBox(i18nc("@option:check", "Interpolate RGB as four colors"), d->demosaicingSettings); d->fourColorCheckBox->setWhatsThis(xi18nc("@info:whatsthis", "Interpolate RGB as four " "colors" "The default is to assume that all green pixels are the same. " "If even-row green pixels are more sensitive to ultraviolet light " "than odd-row this difference causes a mesh pattern in the output; " "using this option solves this problem with minimal loss of detail." "To resume, this option blurs the image a little, but it " "eliminates false 2x2 mesh patterns with VNG quality method or " "mazes with AHD quality method.")); demosaicingLayout->addWidget(d->fourColorCheckBox, line, 0, 1, line == 0 ? 2 : 3); line++; QLabel* const dcrawVersion = new QLabel(d->demosaicingSettings); dcrawVersion->setAlignment(Qt::AlignRight); dcrawVersion->setToolTip(i18nc("@info:tooltip", "Visit LibRaw project website")); dcrawVersion->setOpenExternalLinks(true); dcrawVersion->setTextFormat(Qt::RichText); dcrawVersion->setTextInteractionFlags(Qt::LinksAccessibleByMouse); dcrawVersion->setText(QString::fromLatin1("%2") .arg(QLatin1String("http://www.libraw.org")) .arg(QString::fromLatin1("libraw %1").arg(DRawDecoder::librawVersion()))); demosaicingLayout->addWidget(dcrawVersion, 0, 2, 1, 1); d->dontStretchPixelsCheckBox = new QCheckBox(i18nc("@option:check", "Do not stretch or rotate pixels"), d->demosaicingSettings); d->dontStretchPixelsCheckBox->setWhatsThis(xi18nc("@info:whatsthis", "Do not stretch or rotate pixels" "For Fuji Super CCD cameras, show the image tilted 45 degrees. " "For cameras with non-square pixels, do not stretch the image to " "its correct aspect ratio. In any case, this option guarantees that " "each output pixel corresponds to one RAW pixel.")); demosaicingLayout->addWidget(d->dontStretchPixelsCheckBox, line, 0, 1, 3); line++; d->RAWQualityLabel = new QLabel(i18nc("@label:listbox", "Quality:"), d->demosaicingSettings); d->RAWQualityComboBox = new DComboBox(d->demosaicingSettings); // Original Raw engine demosaicing methods - d->RAWQualityComboBox->insertItem(DRawDecoderSettings::BILINEAR, i18nc("@item:inlistbox Quality", "Bilinear")); - d->RAWQualityComboBox->insertItem(DRawDecoderSettings::VNG, i18nc("@item:inlistbox Quality", "VNG")); - d->RAWQualityComboBox->insertItem(DRawDecoderSettings::PPG, i18nc("@item:inlistbox Quality", "PPG")); - d->RAWQualityComboBox->insertItem(DRawDecoderSettings::AHD, i18nc("@item:inlistbox Quality", "AHD")); - - // Extended demosaicing method from GPL2 pack - d->RAWQualityComboBox->insertItem(DRawDecoderSettings::DCB, i18nc("@item:inlistbox Quality", "DCB")); - d->RAWQualityComboBox->insertItem(DRawDecoderSettings::PL_AHD, i18nc("@item:inlistbox Quality", "AHD v2")); - d->RAWQualityComboBox->insertItem(DRawDecoderSettings::AFD, i18nc("@item:inlistbox Quality", "AFD")); - d->RAWQualityComboBox->insertItem(DRawDecoderSettings::VCD, i18nc("@item:inlistbox Quality", "VCD")); - d->RAWQualityComboBox->insertItem(DRawDecoderSettings::VCD_AHD, i18nc("@item:inlistbox Quality", "VCD & AHD")); - d->RAWQualityComboBox->insertItem(DRawDecoderSettings::LMMSE, i18nc("@item:inlistbox Quality", "LMMSE")); - // Extended demosaicing method from GPL3 pack - d->RAWQualityComboBox->insertItem(DRawDecoderSettings::AMAZE, i18nc("@item:inlistbox Quality", "AMaZE")); - - d->RAWQualityComboBox->setDefaultIndex(DRawDecoderSettings::BILINEAR); - d->RAWQualityComboBox->setCurrentIndex(DRawDecoderSettings::BILINEAR); + d->RAWQualityComboBox->insertItem(0, i18nc("@item:inlistbox Quality", "Bilinear"), QVariant(DRawDecoderSettings::BILINEAR)); + d->RAWQualityComboBox->insertItem(1, i18nc("@item:inlistbox Quality", "VNG"), QVariant(DRawDecoderSettings::VNG)); + d->RAWQualityComboBox->insertItem(2, i18nc("@item:inlistbox Quality", "PPG"), QVariant(DRawDecoderSettings::PPG)); + d->RAWQualityComboBox->insertItem(3, i18nc("@item:inlistbox Quality", "AHD"), QVariant(DRawDecoderSettings::AHD)); + d->RAWQualityComboBox->insertItem(4, i18nc("@item:inlistbox Quality", "DCB"), QVariant(DRawDecoderSettings::DCB)); + d->RAWQualityComboBox->insertItem(5, i18nc("@item:inlistbox Quality", "DHT"), QVariant(DRawDecoderSettings::DHT)); + d->RAWQualityComboBox->insertItem(6, i18nc("@item:inlistbox Quality", "AAHD"), QVariant(DRawDecoderSettings::AAHD)); + + d->RAWQualityComboBox->setDefaultIndex(0); + d->RAWQualityComboBox->setCurrentIndex(0); d->RAWQualityComboBox->setWhatsThis(xi18nc("@info:whatsthis", "Quality (interpolation)" "Select here the demosaicing method to use when decoding RAW " "images. A demosaicing algorithm is a digital image process used to " "interpolate a complete image from the partial raw data received " "from the color-filtered image sensor, internal to many digital " "cameras, in form of a matrix of colored pixels. Also known as CFA " "interpolation or color reconstruction, another common spelling is " "demosaicing. The following methods are available for demosaicing " "RAW images:" - // Original Raw engine demosaicing methods - "Bilinear: use " "high-speed but low-quality bilinear interpolation (default - for " "slow computers). In this method, the red value of a non-red pixel " "is computed as the average of the adjacent red pixels, and similarly " "for blue and green." "VNG: use Variable Number " "of Gradients interpolation. This method computes gradients near " "the pixel of interest and uses the lower gradients (representing " "smoother and more similar parts of the image) to make an estimate." "PPG: use Patterned-Pixel-" "Grouping interpolation. Pixel Grouping uses assumptions about " "natural scenery in making estimates. It has fewer color artifacts " "on natural images than the Variable Number of Gradients method." "AHD: use Adaptive " "Homogeneity-Directed interpolation. This method selects the " "direction of interpolation so as to maximize a homogeneity metric, " "thus typically minimizing color artifacts." - // Extended demosaicing method - "DCB: DCB interpolation from " "linuxphoto.org project." - "AHD v2: modified AHD " - "interpolation using Variance of Color Differences method." - - "AFD: Adaptive Filtered " - "Demosaicing interpolation through 5 pass median filter from PerfectRaw " - "project." - - "VCD: Variance of Color " - "Differences interpolation." - - "VCD & AHD: Mixed demosaicing " - "between VCD and AHD." - - "LMMSE: color demosaicing via " - "directional linear minimum mean-square error estimation interpolation " - "from PerfectRaw." + "DHT: DHT interpolation." + "See https://www.libraw.org/node/2306 for details." - "AMaZE: Aliasing Minimization " - "interpolation and Zipper Elimination to apply color aberration removal " - "from RawTherapee project." - - "Note: some methods can be unavailable if RAW decoder have been built " - "without extension packs.")); + "AAHD: modified AHD " + "interpolation." + "")); demosaicingLayout->addWidget(d->RAWQualityLabel, line, 0, 1, 1); demosaicingLayout->addWidget(d->RAWQualityComboBox, line, 1, 1, 2); line++; d->medianFilterPassesSpinBox = new DIntNumInput(d->demosaicingSettings); d->medianFilterPassesSpinBox->setRange(0, 10, 1); d->medianFilterPassesSpinBox->setDefaultValue(0); d->medianFilterPassesLabel = new QLabel(i18nc("@label:slider", "Pass:"), d->whiteBalanceSettings); d->medianFilterPassesSpinBox->setWhatsThis(xi18nc("@info:whatsthis", "Pass" "Set here the passes used by the median filter applied after " "interpolation to Red-Green and Blue-Green channels." "This setting is only available for specific Quality options: " "Bilinear, " "VNG, PPG, " "AHD, " "DCB, and VCD & AHD.")); demosaicingLayout->addWidget(d->medianFilterPassesLabel, line, 0, 1, 1); demosaicingLayout->addWidget(d->medianFilterPassesSpinBox, line, 1, 1, 2); line++; d->refineInterpolationBox = new QCheckBox(i18nc("@option:check", "Refine interpolation"), d->demosaicingSettings); d->refineInterpolationBox->setWhatsThis(xi18nc("@info:whatsthis", "Refine interpolation" "This setting is available only for few Quality options:" "DCB: turn on " "the enhance interpolated colors filter." "VCD & AHD: turn on the " "enhanced effective color interpolation (EECI) refine to improve " "sharpness.")); demosaicingLayout->addWidget(d->refineInterpolationBox, line, 0, 1, 2); d->medianFilterPassesLabel->setEnabled(false); d->medianFilterPassesSpinBox->setEnabled(false); d->refineInterpolationBox->setEnabled(false); addItem(d->demosaicingSettings, QIcon::fromTheme(QLatin1String("image-x-adobe-dng")).pixmap(16, 16), i18nc("@label", "Demosaicing"), QLatin1String("demosaicing"), true); // --------------------------------------------------------------- // WHITE BALANCE Settings Panel d->whiteBalanceSettings = new QWidget(this); QGridLayout* const whiteBalanceLayout = new QGridLayout(d->whiteBalanceSettings); d->whiteBalanceLabel = new QLabel(i18nc("@label:listbox", "Method:"), d->whiteBalanceSettings); d->whiteBalanceComboBox = new DComboBox(d->whiteBalanceSettings); d->whiteBalanceComboBox->insertItem(DRawDecoderSettings::NONE, i18nc("@item:inlistbox", "Default D65")); d->whiteBalanceComboBox->insertItem(DRawDecoderSettings::CAMERA, i18nc("@item:inlistbox", "Camera")); d->whiteBalanceComboBox->insertItem(DRawDecoderSettings::AUTO, i18nc("@item:inlistbox set while balance automatically", "Automatic")); d->whiteBalanceComboBox->insertItem(DRawDecoderSettings::CUSTOM, i18nc("@item:inlistbox set white balance manually", "Manual")); d->whiteBalanceComboBox->setDefaultIndex(DRawDecoderSettings::CAMERA); d->whiteBalanceComboBox->setWhatsThis(xi18nc("@info:whatsthis", "White Balance" "Configure the raw white balance:" "Default D65: " "Use a standard daylight D65 white balance." "Camera: Use the white " "balance specified by the camera. If not available, reverts to " "default neutral white balance." "Automatic: Calculates an " "automatic white balance averaging the entire image." "Manual: Set a custom " "temperature and green level values.")); d->customWhiteBalanceSpinBox = new DIntNumInput(d->whiteBalanceSettings); d->customWhiteBalanceSpinBox->setRange(2000, 12000, 10); d->customWhiteBalanceSpinBox->setDefaultValue(6500); d->customWhiteBalanceLabel = new QLabel(i18nc("@label:slider", "T(K):"), d->whiteBalanceSettings); d->customWhiteBalanceSpinBox->setWhatsThis(xi18nc("@info:whatsthis", "Temperature" "Set here the color temperature in Kelvin.")); d->customWhiteBalanceGreenSpinBox = new DDoubleNumInput(d->whiteBalanceSettings); d->customWhiteBalanceGreenSpinBox->setDecimals(2); d->customWhiteBalanceGreenSpinBox->setRange(0.2, 2.5, 0.01); d->customWhiteBalanceGreenSpinBox->setDefaultValue(1.0); d->customWhiteBalanceGreenLabel = new QLabel(i18nc("@label:slider Green component", "Green:"), d->whiteBalanceSettings); d->customWhiteBalanceGreenSpinBox->setWhatsThis(xi18nc("@info:whatsthis", "Set here the " "green component to set magenta color cast removal level.")); d->unclipColorLabel = new QLabel(i18nc("@label:listbox", "Highlights:"), d->whiteBalanceSettings); d->unclipColorComboBox = new DComboBox(d->whiteBalanceSettings); d->unclipColorComboBox->insertItem(0, i18nc("@item:inlistbox", "Solid white")); d->unclipColorComboBox->insertItem(1, i18nc("@item:inlistbox", "Unclip")); d->unclipColorComboBox->insertItem(2, i18nc("@item:inlistbox", "Blend")); d->unclipColorComboBox->insertItem(3, i18nc("@item:inlistbox", "Rebuild")); d->unclipColorComboBox->setDefaultIndex(0); d->unclipColorComboBox->setWhatsThis(xi18nc("@info:whatsthis", "Highlights" "Select here the highlight clipping method:" "Solid white: " "clip all highlights to solid white" "Unclip: leave highlights " "unclipped in various shades of pink" "Blend:Blend clipped and " "unclipped values together for a gradual fade to white" "Rebuild: reconstruct " "highlights using a level value")); d->reconstructLabel = new QLabel(i18nc("@label:slider Highlight reconstruct level", "Level:"), d->whiteBalanceSettings); d->reconstructSpinBox = new DIntNumInput(d->whiteBalanceSettings); d->reconstructSpinBox->setRange(0, 6, 1); d->reconstructSpinBox->setDefaultValue(0); d->reconstructSpinBox->setWhatsThis(xi18nc("@info:whatsthis", "Level" "Specify the reconstruct highlight level. Low values favor " "whites and high values favor colors.")); d->expoCorrectionBox = new QCheckBox(i18nc("@option:check", "Exposure Correction (E.V)"), d->whiteBalanceSettings); d->expoCorrectionBox->setWhatsThis(xi18nc("@info:whatsthis", "Turn on the exposure " "correction before interpolation.")); d->expoCorrectionShiftLabel = new QLabel(i18nc("@label:slider", "Linear Shift:"), d->whiteBalanceSettings); d->expoCorrectionShiftSpinBox = new DDoubleNumInput(d->whiteBalanceSettings); d->expoCorrectionShiftSpinBox->setDecimals(2); d->expoCorrectionShiftSpinBox->setRange(-2.0, 3.0, 0.01); d->expoCorrectionShiftSpinBox->setDefaultValue(0.0); d->expoCorrectionShiftSpinBox->setWhatsThis(xi18nc("@info:whatsthis", "Shift" "Linear Shift of exposure correction before interpolation in E.V")); d->expoCorrectionHighlightLabel = new QLabel(i18nc("@label:slider", "Highlight:"), d->whiteBalanceSettings); d->expoCorrectionHighlightSpinBox = new DDoubleNumInput(d->whiteBalanceSettings); d->expoCorrectionHighlightSpinBox->setDecimals(2); d->expoCorrectionHighlightSpinBox->setRange(0.0, 1.0, 0.01); d->expoCorrectionHighlightSpinBox->setDefaultValue(0.0); d->expoCorrectionHighlightSpinBox->setWhatsThis(xi18nc("@info:whatsthis", "Highlight" "Amount of highlight preservation for exposure correction " "before interpolation in E.V. Only take effect if Shift Correction is > 1.0 E.V")); d->fixColorsHighlightsBox = new QCheckBox(i18nc("@option:check", "Correct false colors in highlights"), d->whiteBalanceSettings); d->fixColorsHighlightsBox->setWhatsThis(xi18nc("@info:whatsthis", "If enabled, images with " "overblown channels are processed much more accurately, without " "'pink clouds' (and blue highlights under tungsten lamps).")); d->autoBrightnessBox = new QCheckBox(i18nc("@option:check", "Auto Brightness"), d->whiteBalanceSettings); d->autoBrightnessBox->setWhatsThis(xi18nc("@info:whatsthis", "If disable, use a fixed white level " "and ignore the image histogram to adjust brightness.")); d->brightnessLabel = new QLabel(i18nc("@label:slider", "Brightness:"), d->whiteBalanceSettings); d->brightnessSpinBox = new DDoubleNumInput(d->whiteBalanceSettings); d->brightnessSpinBox->setDecimals(2); d->brightnessSpinBox->setRange(0.0, 10.0, 0.01); d->brightnessSpinBox->setDefaultValue(1.0); d->brightnessSpinBox->setWhatsThis(xi18nc("@info:whatsthis", "Brightness" "Specify the brightness level of output image. The default " "value is 1.0 (works in 8-bit mode only).")); if (! (advSettings & POSTPROCESSING)) { d->brightnessLabel->hide(); d->brightnessSpinBox->hide(); } d->blackPointCheckBox = new QCheckBox(i18nc("@option:check Black point", "Black:"), d->whiteBalanceSettings); d->blackPointCheckBox->setWhatsThis(xi18nc("@info:whatsthis", "Black point" "Use a specific black point value to decode RAW pictures. If " "you set this option to off, the Black Point value will be " "automatically computed.")); d->blackPointSpinBox = new DIntNumInput(d->whiteBalanceSettings); d->blackPointSpinBox->setRange(0, 1000, 1); d->blackPointSpinBox->setDefaultValue(0); d->blackPointSpinBox->setWhatsThis(xi18nc("@info:whatsthis", "Black point value" "Specify specific black point value of the output image.")); d->whitePointCheckBox = new QCheckBox(i18nc("@option:check White point", "White:"), d->whiteBalanceSettings); d->whitePointCheckBox->setWhatsThis(xi18nc("@info:whatsthis", "White point" "Use a specific white point value to decode RAW pictures. If " "you set this option to off, the White Point value will be " "automatically computed.")); d->whitePointSpinBox = new DIntNumInput(d->whiteBalanceSettings); d->whitePointSpinBox->setRange(0, 20000, 1); d->whitePointSpinBox->setDefaultValue(0); d->whitePointSpinBox->setWhatsThis(xi18nc("@info:whatsthis", "White point value" "Specify specific white point value of the output image.")); if (! (advSettings & BLACKWHITEPOINTS)) { d->blackPointCheckBox->hide(); d->blackPointSpinBox->hide(); d->whitePointCheckBox->hide(); d->whitePointSpinBox->hide(); } const int spacing = QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing); whiteBalanceLayout->addWidget(d->whiteBalanceLabel, 0, 0, 1, 1); whiteBalanceLayout->addWidget(d->whiteBalanceComboBox, 0, 1, 1, 2); whiteBalanceLayout->addWidget(d->customWhiteBalanceLabel, 1, 0, 1, 1); whiteBalanceLayout->addWidget(d->customWhiteBalanceSpinBox, 1, 1, 1, 2); whiteBalanceLayout->addWidget(d->customWhiteBalanceGreenLabel, 2, 0, 1, 1); whiteBalanceLayout->addWidget(d->customWhiteBalanceGreenSpinBox, 2, 1, 1, 2); whiteBalanceLayout->addWidget(d->unclipColorLabel, 3, 0, 1, 1); whiteBalanceLayout->addWidget(d->unclipColorComboBox, 3, 1, 1, 2); whiteBalanceLayout->addWidget(d->reconstructLabel, 4, 0, 1, 1); whiteBalanceLayout->addWidget(d->reconstructSpinBox, 4, 1, 1, 2); whiteBalanceLayout->addWidget(d->expoCorrectionBox, 5, 0, 1, 2); whiteBalanceLayout->addWidget(d->expoCorrectionShiftLabel, 6, 0, 1, 1); whiteBalanceLayout->addWidget(d->expoCorrectionShiftSpinBox, 6, 1, 1, 2); whiteBalanceLayout->addWidget(d->expoCorrectionHighlightLabel, 7, 0, 1, 1); whiteBalanceLayout->addWidget(d->expoCorrectionHighlightSpinBox, 7, 1, 1, 2); whiteBalanceLayout->addWidget(d->fixColorsHighlightsBox, 8, 0, 1, 3); whiteBalanceLayout->addWidget(d->autoBrightnessBox, 9, 0, 1, 3); whiteBalanceLayout->addWidget(d->brightnessLabel, 10, 0, 1, 1); whiteBalanceLayout->addWidget(d->brightnessSpinBox, 10, 1, 1, 2); whiteBalanceLayout->addWidget(d->blackPointCheckBox, 11, 0, 1, 1); whiteBalanceLayout->addWidget(d->blackPointSpinBox, 11, 1, 1, 2); whiteBalanceLayout->addWidget(d->whitePointCheckBox, 12, 0, 1, 1); whiteBalanceLayout->addWidget(d->whitePointSpinBox, 12, 1, 1, 2); whiteBalanceLayout->setContentsMargins(spacing, spacing, spacing, spacing); whiteBalanceLayout->setSpacing(spacing); addItem(d->whiteBalanceSettings, QIcon::fromTheme(QLatin1String("bordertool")).pixmap(16, 16), i18nc("@label", "White Balance"), QLatin1String("whitebalance"), true); // --------------------------------------------------------------- // CORRECTIONS Settings panel d->correctionsSettings = new QWidget(this); QGridLayout* const correctionsLayout = new QGridLayout(d->correctionsSettings); d->noiseReductionLabel = new QLabel(i18nc("@label:listbox", "Noise reduction:"), d->correctionsSettings); d->noiseReductionComboBox = new DComboBox(d->colormanSettings); d->noiseReductionComboBox->insertItem(DRawDecoderSettings::NONR, i18nc("@item:inlistbox Noise Reduction", "None")); d->noiseReductionComboBox->insertItem(DRawDecoderSettings::WAVELETSNR, i18nc("@item:inlistbox Noise Reduction", "Wavelets")); d->noiseReductionComboBox->insertItem(DRawDecoderSettings::FBDDNR, i18nc("@item:inlistbox Noise Reduction", "FBDD")); - d->noiseReductionComboBox->insertItem(DRawDecoderSettings::LINENR, i18nc("@item:inlistbox Noise Reduction", "CFA Line Denoise")); - d->noiseReductionComboBox->insertItem(DRawDecoderSettings::IMPULSENR, i18nc("@item:inlistbox Noise Reduction", "Impulse Denoise")); d->noiseReductionComboBox->setDefaultIndex(DRawDecoderSettings::NONR); d->noiseReductionComboBox->setWhatsThis(xi18nc("@info:whatsthis", "Noise Reduction" "Select here the noise reduction method to apply during RAW " "decoding." "None: no " "noise reduction." "Wavelets: wavelets " "correction to erase noise while preserving real detail. It is " "applied after interpolation." "FBDD: Fake Before " "Demosaicing Denoising noise reduction. It is applied before " - "interpolation." - "CFA Line Denoise: Banding " - "noise suppression. It is applied after interpolation." - "Impulse Denoise: Impulse " - "noise suppression. It is applied after interpolation.")); + "interpolation.")); d->NRSpinBox1 = new DIntNumInput(d->correctionsSettings); d->NRSpinBox1->setRange(100, 1000, 1); d->NRSpinBox1->setDefaultValue(100); d->NRLabel1 = new QLabel(d->correctionsSettings); - d->NRSpinBox2 = new DIntNumInput(d->correctionsSettings); - d->NRSpinBox2->setRange(100, 1000, 1); - d->NRSpinBox2->setDefaultValue(100); - d->NRLabel2 = new QLabel(d->correctionsSettings); - - d->enableCACorrectionBox = new QCheckBox(i18nc("@option:check", "Enable Chromatic Aberration correction"), d->correctionsSettings); - d->enableCACorrectionBox->setWhatsThis(xi18nc("@info:whatsthis", "Enable Chromatic " - "Aberration correction" - "Enlarge the raw red-green and blue-yellow axis by the given " - "factors (automatic by default).")); - - d->autoCACorrectionBox = new QCheckBox(i18nc("@option:check", "Automatic color axis adjustments"), d->correctionsSettings); - d->autoCACorrectionBox->setWhatsThis(xi18nc("@info:whatsthis", "Automatic Chromatic " - "Aberration correction" - "If this option is turned on, it will try to shift image " - "channels slightly and evaluate Chromatic Aberration change. Note " - "that if you shot blue-red pattern, the method may fail. In this " - "case, disable this option and tune manually color factors.")); - - d->caRedMultLabel = new QLabel(i18nc("@label:slider", "Red-Green:"), d->correctionsSettings); - d->caRedMultSpinBox = new DDoubleNumInput(d->correctionsSettings); - d->caRedMultSpinBox->setDecimals(1); - d->caRedMultSpinBox->setRange(-4.0, 4.0, 0.1); - d->caRedMultSpinBox->setDefaultValue(0.0); - d->caRedMultSpinBox->setWhatsThis(xi18nc("@info:whatsthis", "Red-Green multiplier" - "Set here the amount of correction on red-green axis")); - - d->caBlueMultLabel = new QLabel(i18nc("@label:slider", "Blue-Yellow:"), d->correctionsSettings); - d->caBlueMultSpinBox = new DDoubleNumInput(d->correctionsSettings); - d->caBlueMultSpinBox->setDecimals(1); - d->caBlueMultSpinBox->setRange(-4.0, 4.0, 0.1); - d->caBlueMultSpinBox->setDefaultValue(0.0); - d->caBlueMultSpinBox->setWhatsThis(xi18nc("@info:whatsthis", "Blue-Yellow multiplier" - "Set here the amount of correction on blue-yellow axis")); - correctionsLayout->addWidget(d->noiseReductionLabel, 0, 0, 1, 1); correctionsLayout->addWidget(d->noiseReductionComboBox, 0, 1, 1, 2); correctionsLayout->addWidget(d->NRLabel1, 1, 0, 1, 1); correctionsLayout->addWidget(d->NRSpinBox1, 1, 1, 1, 2); - correctionsLayout->addWidget(d->NRLabel2, 2, 0, 1, 1); - correctionsLayout->addWidget(d->NRSpinBox2, 2, 1, 1, 2); - correctionsLayout->addWidget(d->enableCACorrectionBox, 3, 0, 1, 3); - correctionsLayout->addWidget(d->autoCACorrectionBox, 4, 0, 1, 3); - correctionsLayout->addWidget(d->caRedMultLabel, 5, 0, 1, 1); - correctionsLayout->addWidget(d->caRedMultSpinBox, 5, 1, 1, 2); - correctionsLayout->addWidget(d->caBlueMultLabel, 6, 0, 1, 1); - correctionsLayout->addWidget(d->caBlueMultSpinBox, 6, 1, 1, 2); - correctionsLayout->setRowStretch(7, 10); + correctionsLayout->setRowStretch(2, 10); correctionsLayout->setContentsMargins(spacing, spacing, spacing, spacing); correctionsLayout->setSpacing(spacing); addItem(d->correctionsSettings, QIcon::fromTheme(QLatin1String("document-edit")).pixmap(16, 16), i18nc("@label", "Corrections"), QLatin1String("corrections"), false); // --------------------------------------------------------------- // COLOR MANAGEMENT Settings panel d->colormanSettings = new QWidget(this); QGridLayout* const colormanLayout = new QGridLayout(d->colormanSettings); d->inputColorSpaceLabel = new QLabel(i18nc("@label:listbox", "Camera Profile:"), d->colormanSettings); d->inputColorSpaceComboBox = new DComboBox(d->colormanSettings); d->inputColorSpaceComboBox->insertItem(DRawDecoderSettings::NOINPUTCS, i18nc("@item:inlistbox Camera Profile", "None")); d->inputColorSpaceComboBox->insertItem(DRawDecoderSettings::EMBEDDED, i18nc("@item:inlistbox Camera Profile", "Embedded")); d->inputColorSpaceComboBox->insertItem(DRawDecoderSettings::CUSTOMINPUTCS, i18nc("@item:inlistbox Camera Profile", "Custom")); d->inputColorSpaceComboBox->setDefaultIndex(DRawDecoderSettings::NOINPUTCS); d->inputColorSpaceComboBox->setWhatsThis(xi18nc("@info:whatsthis", "Camera Profile" "Select here the input color space used to decode RAW data." "None: no " "input color profile is used during RAW decoding." "Embedded: use embedded " "color profile from RAW file, if it exists." "Custom: use a custom " "input color space profile.")); d->inIccUrlEdit = new DFileSelector(d->colormanSettings); d->inIccUrlEdit->setFileDlgMode(QFileDialog::ExistingFile); d->inIccUrlEdit->setFileDlgFilter(i18n("ICC Files (*.icc *.icm)")); d->outputColorSpaceLabel = new QLabel(i18nc("@label:listbox", "Workspace:"), d->colormanSettings); d->outputColorSpaceComboBox = new DComboBox( d->colormanSettings ); d->outputColorSpaceComboBox->insertItem(DRawDecoderSettings::RAWCOLOR, i18nc("@item:inlistbox Workspace", "Raw (no profile)")); d->outputColorSpaceComboBox->insertItem(DRawDecoderSettings::SRGB, i18nc("@item:inlistbox Workspace", "sRGB")); d->outputColorSpaceComboBox->insertItem(DRawDecoderSettings::ADOBERGB, i18nc("@item:inlistbox Workspace", "Adobe RGB")); d->outputColorSpaceComboBox->insertItem(DRawDecoderSettings::WIDEGAMMUT, i18nc("@item:inlistbox Workspace", "Wide Gamut")); d->outputColorSpaceComboBox->insertItem(DRawDecoderSettings::PROPHOTO, i18nc("@item:inlistbox Workspace", "Pro-Photo")); d->outputColorSpaceComboBox->insertItem(DRawDecoderSettings::CUSTOMOUTPUTCS, i18nc("@item:inlistbox Workspace", "Custom")); d->outputColorSpaceComboBox->setDefaultIndex(DRawDecoderSettings::SRGB); d->outputColorSpaceComboBox->setWhatsThis(xi18nc("@info:whatsthis", "Workspace" "Select here the output color space used to decode RAW data." "Raw (linear): " "in this mode, no output color space is used during RAW decoding." "sRGB: this is an RGB " "color space, created cooperatively by Hewlett-Packard and " "Microsoft. It is the best choice for images destined for the Web " "and portrait photography." "Adobe RGB: this color " "space is an extended RGB color space, developed by Adobe. It is " "used for photography applications such as advertising and fine " "art." "Wide Gamut: this color " "space is an expanded version of the Adobe RGB color space." "Pro-Photo: this color " "space is an RGB color space, developed by Kodak, that offers an " "especially large gamut designed for use with photographic outputs " "in mind." "Custom: use a custom " "output color space profile.")); d->outIccUrlEdit = new DFileSelector(d->colormanSettings); d->outIccUrlEdit->setFileDlgMode(QFileDialog::ExistingFile); d->outIccUrlEdit->setFileDlgFilter(i18n("ICC Files (*.icc *.icm)")); colormanLayout->addWidget(d->inputColorSpaceLabel, 0, 0, 1, 1); colormanLayout->addWidget(d->inputColorSpaceComboBox, 0, 1, 1, 2); colormanLayout->addWidget(d->inIccUrlEdit, 1, 0, 1, 3); colormanLayout->addWidget(d->outputColorSpaceLabel, 2, 0, 1, 1); colormanLayout->addWidget(d->outputColorSpaceComboBox, 2, 1, 1, 2); colormanLayout->addWidget(d->outIccUrlEdit, 3, 0, 1, 3); colormanLayout->setRowStretch(4, 10); colormanLayout->setContentsMargins(spacing, spacing, spacing, spacing); colormanLayout->setSpacing(spacing); addItem(d->colormanSettings, QIcon::fromTheme(QLatin1String("preferences-desktop-display-color")).pixmap(16, 16), i18nc("@label", "Color Management"), QLatin1String("colormanagement"), false); if (! (advSettings & COLORSPACE)) { removeItem(COLORMANAGEMENT); } addStretch(); // --------------------------------------------------------------- connect(d->unclipColorComboBox, static_cast(&DComboBox::activated), this, &DRawDecoderWidget::slotUnclipColorActivated); connect(d->whiteBalanceComboBox, static_cast(&DComboBox::activated), this, &DRawDecoderWidget::slotWhiteBalanceToggled); connect(d->noiseReductionComboBox, static_cast(&DComboBox::activated), this, &DRawDecoderWidget::slotNoiseReductionChanged); - connect(d->enableCACorrectionBox, &QCheckBox::toggled, - this, &DRawDecoderWidget::slotCACorrectionToggled); - - connect(d->autoCACorrectionBox, &QCheckBox::toggled, - this, &DRawDecoderWidget::slotAutoCAToggled); - connect(d->blackPointCheckBox, SIGNAL(toggled(bool)), d->blackPointSpinBox, SLOT(setEnabled(bool))); connect(d->whitePointCheckBox, SIGNAL(toggled(bool)), d->whitePointSpinBox, SLOT(setEnabled(bool))); connect(d->sixteenBitsImage, &QCheckBox::toggled, this, &DRawDecoderWidget::slotsixteenBitsImageToggled); connect(d->inputColorSpaceComboBox, static_cast(&DComboBox::activated), this, &DRawDecoderWidget::slotInputColorSpaceChanged); connect(d->outputColorSpaceComboBox, static_cast(&DComboBox::activated), this, &DRawDecoderWidget::slotOutputColorSpaceChanged); connect(d->expoCorrectionBox, &QCheckBox::toggled, this, &DRawDecoderWidget::slotExposureCorrectionToggled); connect(d->expoCorrectionShiftSpinBox, &DDoubleNumInput::valueChanged, this, &DRawDecoderWidget::slotExpoCorrectionShiftChanged); // Wrapper to emit signal when something is changed in settings. connect(d->inIccUrlEdit->lineEdit(), &QLineEdit::textChanged, this, &DRawDecoderWidget::signalSettingsChanged); connect(d->outIccUrlEdit->lineEdit(), &QLineEdit::textChanged, this, &DRawDecoderWidget::signalSettingsChanged); connect(d->whiteBalanceComboBox, static_cast(&DComboBox::activated), this, &DRawDecoderWidget::signalSettingsChanged); connect(d->RAWQualityComboBox, static_cast(&DComboBox::activated), this, &DRawDecoderWidget::slotRAWQualityChanged); connect(d->unclipColorComboBox, static_cast(&DComboBox::activated), this, &DRawDecoderWidget::signalSettingsChanged); connect(d->inputColorSpaceComboBox, static_cast(&DComboBox::activated), this, &DRawDecoderWidget::signalSettingsChanged); connect(d->outputColorSpaceComboBox, static_cast(&DComboBox::activated), this, &DRawDecoderWidget::signalSettingsChanged); connect(d->blackPointCheckBox, &QCheckBox::toggled, this, &DRawDecoderWidget::signalSettingsChanged); connect(d->whitePointCheckBox, &QCheckBox::toggled, this, &DRawDecoderWidget::signalSettingsChanged); connect(d->sixteenBitsImage, &QCheckBox::toggled, this, &DRawDecoderWidget::signalSettingsChanged); connect(d->fixColorsHighlightsBox, &QCheckBox::toggled, this, &DRawDecoderWidget::signalSettingsChanged); connect(d->autoBrightnessBox, &QCheckBox::toggled, this, &DRawDecoderWidget::signalSettingsChanged); connect(d->fourColorCheckBox, &QCheckBox::toggled, this, &DRawDecoderWidget::signalSettingsChanged); connect(d->dontStretchPixelsCheckBox, &QCheckBox::toggled, this, &DRawDecoderWidget::signalSettingsChanged); connect(d->refineInterpolationBox, &QCheckBox::toggled, this, &DRawDecoderWidget::signalSettingsChanged); connect(d->customWhiteBalanceSpinBox, &DIntNumInput::valueChanged, this, &DRawDecoderWidget::signalSettingsChanged); connect(d->reconstructSpinBox, &DIntNumInput::valueChanged, this, &DRawDecoderWidget::signalSettingsChanged); connect(d->blackPointSpinBox, &DIntNumInput::valueChanged, this, &DRawDecoderWidget::signalSettingsChanged); connect(d->whitePointSpinBox, &DIntNumInput::valueChanged, this, &DRawDecoderWidget::signalSettingsChanged); connect(d->NRSpinBox1, &DIntNumInput::valueChanged, this, &DRawDecoderWidget::signalSettingsChanged); - connect(d->NRSpinBox2, &DIntNumInput::valueChanged, - this, &DRawDecoderWidget::signalSettingsChanged); - connect(d->medianFilterPassesSpinBox, &DIntNumInput::valueChanged, this, &DRawDecoderWidget::signalSettingsChanged); connect(d->customWhiteBalanceGreenSpinBox, &DDoubleNumInput::valueChanged, this, &DRawDecoderWidget::signalSettingsChanged); - connect(d->caRedMultSpinBox, &DDoubleNumInput::valueChanged, - this, &DRawDecoderWidget::signalSettingsChanged); - - connect(d->caBlueMultSpinBox, &DDoubleNumInput::valueChanged, - this, &DRawDecoderWidget::signalSettingsChanged); - connect(d->brightnessSpinBox, &DDoubleNumInput::valueChanged, this, &DRawDecoderWidget::signalSettingsChanged); connect(d->expoCorrectionHighlightSpinBox, &DDoubleNumInput::valueChanged, this, &DRawDecoderWidget::signalSettingsChanged); } DRawDecoderWidget::~DRawDecoderWidget() { delete d; } void DRawDecoderWidget::updateMinimumWidth() { int width = 0; for (int i = 0; i < count(); i++) { if (widget(i)->width() > width) { width = widget(i)->width(); } } setMinimumWidth(width); } DFileSelector* DRawDecoderWidget::inputProfileUrlEdit() const { return d->inIccUrlEdit; } DFileSelector* DRawDecoderWidget::outputProfileUrlEdit() const { return d->outIccUrlEdit; } void DRawDecoderWidget::resetToDefault() { setSettings(DRawDecoderSettings()); } void DRawDecoderWidget::slotsixteenBitsImageToggled(bool b) { setEnabledBrightnessSettings(!b); emit signalSixteenBitsImageToggled(d->sixteenBitsImage->isChecked()); } void DRawDecoderWidget::slotWhiteBalanceToggled(int v) { if (v == 3) { d->customWhiteBalanceSpinBox->setEnabled(true); d->customWhiteBalanceGreenSpinBox->setEnabled(true); d->customWhiteBalanceLabel->setEnabled(true); d->customWhiteBalanceGreenLabel->setEnabled(true); } else { d->customWhiteBalanceSpinBox->setEnabled(false); d->customWhiteBalanceGreenSpinBox->setEnabled(false); d->customWhiteBalanceLabel->setEnabled(false); d->customWhiteBalanceGreenLabel->setEnabled(false); } } void DRawDecoderWidget::slotUnclipColorActivated(int v) { if (v == 3) // Reconstruct Highlight method { d->reconstructLabel->setEnabled(true); d->reconstructSpinBox->setEnabled(true); } else { d->reconstructLabel->setEnabled(false); d->reconstructSpinBox->setEnabled(false); } } void DRawDecoderWidget::slotNoiseReductionChanged(int item) { d->NRSpinBox1->setEnabled(true); d->NRLabel1->setEnabled(true); - d->NRSpinBox2->setEnabled(true); - d->NRLabel2->setEnabled(true); d->NRLabel1->setText(i18nc("@label", "Threshold:")); d->NRSpinBox1->setWhatsThis(xi18nc("@info:whatsthis", "Threshold" "Set here the noise reduction threshold value to use.")); switch(item) { case DRawDecoderSettings::WAVELETSNR: case DRawDecoderSettings::FBDDNR: - case DRawDecoderSettings::LINENR: - d->NRSpinBox2->setVisible(false); - d->NRLabel2->setVisible(false); - break; - - case DRawDecoderSettings::IMPULSENR: - d->NRLabel1->setText(i18nc("@label", "Luminance:")); - d->NRSpinBox1->setWhatsThis(xi18nc("@info:whatsthis", "Luminance" - "Amount of Luminance impulse noise reduction.")); - d->NRLabel2->setText(i18nc("@label", "Chrominance:")); - d->NRSpinBox2->setWhatsThis(xi18nc("@info:whatsthis", "Chrominance" - "Amount of Chrominance impulse noise reduction.")); - d->NRSpinBox2->setVisible(true); - d->NRLabel2->setVisible(true); + // NOTE : no ops break; default: d->NRSpinBox1->setEnabled(false); d->NRLabel1->setEnabled(false); - d->NRSpinBox2->setEnabled(false); - d->NRLabel2->setEnabled(false); - d->NRSpinBox2->setVisible(false); - d->NRLabel2->setVisible(false); break; } emit signalSettingsChanged(); } -void DRawDecoderWidget::slotCACorrectionToggled(bool b) -{ - d->autoCACorrectionBox->setEnabled(b); - slotAutoCAToggled(d->autoCACorrectionBox->isChecked()); -} - -void DRawDecoderWidget::slotAutoCAToggled(bool b) -{ - if (b) - { - d->caRedMultSpinBox->setValue(0.0); - d->caBlueMultSpinBox->setValue(0.0); - } - - bool mult = (!b) && (d->autoCACorrectionBox->isEnabled()); - d->caRedMultSpinBox->setEnabled(mult); - d->caBlueMultSpinBox->setEnabled(mult); - d->caRedMultLabel->setEnabled(mult); - d->caBlueMultLabel->setEnabled(mult); - emit signalSettingsChanged(); -} - void DRawDecoderWidget::slotExposureCorrectionToggled(bool b) { d->expoCorrectionShiftLabel->setEnabled(b); d->expoCorrectionShiftSpinBox->setEnabled(b); d->expoCorrectionHighlightLabel->setEnabled(b); d->expoCorrectionHighlightSpinBox->setEnabled(b); slotExpoCorrectionShiftChanged(d->expoCorrectionShiftSpinBox->value()); } void DRawDecoderWidget::slotExpoCorrectionShiftChanged(double ev) { // Only enable Highligh exposure correction if Shift correction is >= 1.0, else this settings do not take effect. bool b = (ev >= 1.0); d->expoCorrectionHighlightLabel->setEnabled(b); d->expoCorrectionHighlightSpinBox->setEnabled(b); emit signalSettingsChanged(); } void DRawDecoderWidget::slotInputColorSpaceChanged(int item) { d->inIccUrlEdit->setEnabled(item == DRawDecoderSettings::CUSTOMINPUTCS); } void DRawDecoderWidget::slotOutputColorSpaceChanged(int item) { d->outIccUrlEdit->setEnabled(item == DRawDecoderSettings::CUSTOMOUTPUTCS); } void DRawDecoderWidget::slotRAWQualityChanged(int quality) { switch (quality) { case DRawDecoderSettings::DCB: - case DRawDecoderSettings::VCD_AHD: - // These options can be only avaialble if Libraw use GPL2 pack. d->medianFilterPassesLabel->setEnabled(true); d->medianFilterPassesSpinBox->setEnabled(true); d->refineInterpolationBox->setEnabled(true); break; - case DRawDecoderSettings::PL_AHD: - case DRawDecoderSettings::AFD: - case DRawDecoderSettings::VCD: - case DRawDecoderSettings::LMMSE: - case DRawDecoderSettings::AMAZE: - d->medianFilterPassesLabel->setEnabled(false); - d->medianFilterPassesSpinBox->setEnabled(false); - d->refineInterpolationBox->setEnabled(false); - break; - default: // BILINEAR, VNG, PPG, AHD d->medianFilterPassesLabel->setEnabled(true); d->medianFilterPassesSpinBox->setEnabled(true); d->refineInterpolationBox->setEnabled(false); break; } emit signalSettingsChanged(); } void DRawDecoderWidget::setEnabledBrightnessSettings(bool b) { d->brightnessLabel->setEnabled(b); d->brightnessSpinBox->setEnabled(b); } bool DRawDecoderWidget::brightnessSettingsIsEnabled() const { return d->brightnessSpinBox->isEnabled(); } void DRawDecoderWidget::setSettings(const DRawDecoderSettings& settings) { d->sixteenBitsImage->setChecked(settings.sixteenBitsImage); switch(settings.whiteBalance) { case DRawDecoderSettings::CAMERA: d->whiteBalanceComboBox->setCurrentIndex(1); break; case DRawDecoderSettings::AUTO: d->whiteBalanceComboBox->setCurrentIndex(2); break; case DRawDecoderSettings::CUSTOM: d->whiteBalanceComboBox->setCurrentIndex(3); break; default: d->whiteBalanceComboBox->setCurrentIndex(0); break; } slotWhiteBalanceToggled(d->whiteBalanceComboBox->currentIndex()); d->customWhiteBalanceSpinBox->setValue(settings.customWhiteBalance); d->customWhiteBalanceGreenSpinBox->setValue(settings.customWhiteBalanceGreen); d->fourColorCheckBox->setChecked(settings.RGBInterpolate4Colors); d->autoBrightnessBox->setChecked(settings.autoBrightness); d->fixColorsHighlightsBox->setChecked(settings.fixColorsHighlights); switch(settings.unclipColors) { case 0: d->unclipColorComboBox->setCurrentIndex(0); break; case 1: d->unclipColorComboBox->setCurrentIndex(1); break; case 2: d->unclipColorComboBox->setCurrentIndex(2); break; default: // Reconstruct Highlight method d->unclipColorComboBox->setCurrentIndex(3); d->reconstructSpinBox->setValue(settings.unclipColors-3); break; } slotUnclipColorActivated(d->unclipColorComboBox->currentIndex()); d->dontStretchPixelsCheckBox->setChecked(settings.DontStretchPixels); d->brightnessSpinBox->setValue(settings.brightness); d->blackPointCheckBox->setChecked(settings.enableBlackPoint); d->blackPointSpinBox->setEnabled(settings.enableBlackPoint); d->blackPointSpinBox->setValue(settings.blackPoint); d->whitePointCheckBox->setChecked(settings.enableWhitePoint); d->whitePointSpinBox->setEnabled(settings.enableWhitePoint); d->whitePointSpinBox->setValue(settings.whitePoint); - int q = settings.RAWQuality; + int q = d->RAWQualityComboBox->combo()->findData(settings.RAWQuality); + + if (q == -1) + q = 0; // Fail back to bilinear d->RAWQualityComboBox->setCurrentIndex(q); - switch(q) + switch (q) { case DRawDecoderSettings::DCB: d->medianFilterPassesSpinBox->setValue(settings.dcbIterations); d->refineInterpolationBox->setChecked(settings.dcbEnhanceFl); break; - case DRawDecoderSettings::VCD_AHD: - d->medianFilterPassesSpinBox->setValue(settings.eeciRefine); - d->refineInterpolationBox->setChecked(settings.eeciRefine); - break; default: d->medianFilterPassesSpinBox->setValue(settings.medianFilterPasses); d->refineInterpolationBox->setChecked(false); // option not used. break; } slotRAWQualityChanged(q); d->inputColorSpaceComboBox->setCurrentIndex((int)settings.inputColorSpace); slotInputColorSpaceChanged((int)settings.inputColorSpace); d->outputColorSpaceComboBox->setCurrentIndex((int)settings.outputColorSpace); slotOutputColorSpaceChanged((int)settings.outputColorSpace); d->noiseReductionComboBox->setCurrentIndex(settings.NRType); slotNoiseReductionChanged(settings.NRType); d->NRSpinBox1->setValue(settings.NRThreshold); - d->NRSpinBox2->setValue(settings.NRChroThreshold); - - d->enableCACorrectionBox->setChecked(settings.enableCACorrection); - d->caRedMultSpinBox->setValue(settings.caMultiplier[0]); - d->caBlueMultSpinBox->setValue(settings.caMultiplier[1]); - d->autoCACorrectionBox->setChecked((settings.caMultiplier[0] == 0.0) && (settings.caMultiplier[1] == 0.0)); - slotCACorrectionToggled(settings.enableCACorrection); d->expoCorrectionBox->setChecked(settings.expoCorrection); slotExposureCorrectionToggled(settings.expoCorrection); d->expoCorrectionShiftSpinBox->setValue(d->shiftExpoFromLinearToEv(settings.expoCorrectionShift)); d->expoCorrectionHighlightSpinBox->setValue(settings.expoCorrectionHighlight); d->inIccUrlEdit->setFileDlgPath(settings.inputProfile); d->outIccUrlEdit->setFileDlgPath(settings.outputProfile); } DRawDecoderSettings DRawDecoderWidget::settings() const { DRawDecoderSettings prm; prm.sixteenBitsImage = d->sixteenBitsImage->isChecked(); switch(d->whiteBalanceComboBox->currentIndex()) { case 1: prm.whiteBalance = DRawDecoderSettings::CAMERA; break; case 2: prm.whiteBalance = DRawDecoderSettings::AUTO; break; case 3: prm.whiteBalance = DRawDecoderSettings::CUSTOM; break; default: prm.whiteBalance = DRawDecoderSettings::NONE; break; } prm.customWhiteBalance = d->customWhiteBalanceSpinBox->value(); prm.customWhiteBalanceGreen = d->customWhiteBalanceGreenSpinBox->value(); prm.RGBInterpolate4Colors = d->fourColorCheckBox->isChecked(); prm.autoBrightness = d->autoBrightnessBox->isChecked(); prm.fixColorsHighlights = d->fixColorsHighlightsBox->isChecked(); switch(d->unclipColorComboBox->currentIndex()) { case 0: prm.unclipColors = 0; break; case 1: prm.unclipColors = 1; break; case 2: prm.unclipColors = 2; break; default: // Reconstruct Highlight method prm.unclipColors = d->reconstructSpinBox->value()+3; break; } prm.DontStretchPixels = d->dontStretchPixelsCheckBox->isChecked(); prm.brightness = d->brightnessSpinBox->value(); prm.enableBlackPoint = d->blackPointCheckBox->isChecked(); prm.blackPoint = d->blackPointSpinBox->value(); prm.enableWhitePoint = d->whitePointCheckBox->isChecked(); prm.whitePoint = d->whitePointSpinBox->value(); - prm.RAWQuality = (DRawDecoderSettings::DecodingQuality)d->RAWQualityComboBox->currentIndex(); + prm.RAWQuality = (DRawDecoderSettings::DecodingQuality)d->RAWQualityComboBox->combo()->currentData().toInt(); switch(prm.RAWQuality) { case DRawDecoderSettings::DCB: prm.dcbIterations = d->medianFilterPassesSpinBox->value(); prm.dcbEnhanceFl = d->refineInterpolationBox->isChecked(); break; - case DRawDecoderSettings::VCD_AHD: - prm.esMedPasses = d->medianFilterPassesSpinBox->value(); - prm.eeciRefine = d->refineInterpolationBox->isChecked(); - break; default: prm.medianFilterPasses = d->medianFilterPassesSpinBox->value(); break; } prm.NRType = (DRawDecoderSettings::NoiseReduction)d->noiseReductionComboBox->currentIndex(); switch (prm.NRType) { case DRawDecoderSettings::NONR: { prm.NRThreshold = 0; - prm.NRChroThreshold = 0; break; } - case DRawDecoderSettings::WAVELETSNR: - case DRawDecoderSettings::FBDDNR: - case DRawDecoderSettings::LINENR: + default: // WAVELETSNR and FBDDNR { prm.NRThreshold = d->NRSpinBox1->value(); - prm.NRChroThreshold = 0; - break; - } - default: // IMPULSENR - { - prm.NRThreshold = d->NRSpinBox1->value(); - prm.NRChroThreshold = d->NRSpinBox2->value(); break; } } - prm.enableCACorrection = d->enableCACorrectionBox->isChecked(); - prm.caMultiplier[0] = d->caRedMultSpinBox->value(); - prm.caMultiplier[1] = d->caBlueMultSpinBox->value(); - prm.expoCorrection = d->expoCorrectionBox->isChecked(); prm.expoCorrectionShift = d->shiftExpoFromEvToLinear(d->expoCorrectionShiftSpinBox->value()); prm.expoCorrectionHighlight = d->expoCorrectionHighlightSpinBox->value(); prm.inputColorSpace = (DRawDecoderSettings::InputColorSpace)(d->inputColorSpaceComboBox->currentIndex()); prm.outputColorSpace = (DRawDecoderSettings::OutputColorSpace)(d->outputColorSpaceComboBox->currentIndex()); prm.inputProfile = d->inIccUrlEdit->fileDlgPath(); prm.outputProfile = d->outIccUrlEdit->fileDlgPath(); return prm; } void DRawDecoderWidget::readSettings(KConfigGroup& group) { DRawDecoderSettings prm; readSettings(prm, group); setSettings(prm); DExpanderBox::readSettings(group); } void DRawDecoderWidget::writeSettings(KConfigGroup& group) { DRawDecoderSettings prm = settings(); writeSettings(prm, group); DExpanderBox::writeSettings(group); } void DRawDecoderWidget::readSettings(DRawDecoderSettings& prm, KConfigGroup& group) { DRawDecoderSettings defaultPrm; prm.fixColorsHighlights = group.readEntry(OPTIONFIXCOLORSHIGHLIGHTSENTRY, defaultPrm.fixColorsHighlights); prm.sixteenBitsImage = group.readEntry(OPTIONDECODESIXTEENBITENTRY, defaultPrm.sixteenBitsImage); prm.whiteBalance = (DRawDecoderSettings::WhiteBalance)group.readEntry(OPTIONWHITEBALANCEENTRY, (int)defaultPrm.whiteBalance); prm.customWhiteBalance = group.readEntry(OPTIONCUSTOMWHITEBALANCEENTRY, defaultPrm.customWhiteBalance); prm.customWhiteBalanceGreen = group.readEntry(OPTIONCUSTOMWBGREENENTRY, defaultPrm.customWhiteBalanceGreen); prm.RGBInterpolate4Colors = group.readEntry(OPTIONFOURCOLORRGBENTRY, defaultPrm.RGBInterpolate4Colors); prm.unclipColors = group.readEntry(OPTIONUNCLIPCOLORSENTRY, defaultPrm.unclipColors); prm.DontStretchPixels = group.readEntry(OPTIONDONTSTRETCHPIXELSSENTRY, defaultPrm.DontStretchPixels); prm.NRType = (DRawDecoderSettings::NoiseReduction)group.readEntry(OPTIONNOISEREDUCTIONTYPEENTRY, (int)defaultPrm.NRType); prm.brightness = group.readEntry(OPTIONBRIGHTNESSMULTIPLIERENTRY, defaultPrm.brightness); prm.enableBlackPoint = group.readEntry(OPTIONUSEBLACKPOINTENTRY, defaultPrm.enableBlackPoint); prm.blackPoint = group.readEntry(OPTIONBLACKPOINTENTRY, defaultPrm.blackPoint); prm.enableWhitePoint = group.readEntry(OPTIONUSEWHITEPOINTENTRY, defaultPrm.enableWhitePoint); prm.whitePoint = group.readEntry(OPTIONWHITEPOINTENTRY, defaultPrm.whitePoint); prm.medianFilterPasses = group.readEntry(OPTIONMEDIANFILTERPASSESENTRY, defaultPrm.medianFilterPasses); prm.NRThreshold = group.readEntry(OPTIONNOISEREDUCTIONTHRESHOLDENTRY, defaultPrm.NRThreshold); - prm.enableCACorrection = group.readEntry(OPTIONUSECACORRECTIONENTRY, defaultPrm.enableCACorrection); - prm.caMultiplier[0] = group.readEntry(OPTIONCAREDMULTIPLIERENTRY, defaultPrm.caMultiplier[0]); - prm.caMultiplier[1] = group.readEntry(OPTIONCABLUEMULTIPLIERENTRY, defaultPrm.caMultiplier[1]); prm.RAWQuality = (DRawDecoderSettings::DecodingQuality)group.readEntry(OPTIONDECODINGQUALITYENTRY, (int)defaultPrm.RAWQuality); prm.outputColorSpace = (DRawDecoderSettings::OutputColorSpace)group.readEntry(OPTIONOUTPUTCOLORSPACEENTRY, (int)defaultPrm.outputColorSpace); prm.autoBrightness = group.readEntry(OPTIONAUTOBRIGHTNESSENTRY, defaultPrm.autoBrightness); //-- Extended demosaicing settings ---------------------------------------------------------- prm.dcbIterations = group.readEntry(OPTIONDCBITERATIONSENTRY, defaultPrm.dcbIterations); prm.dcbEnhanceFl = group.readEntry(OPTIONDCBENHANCEFLENTRY, defaultPrm.dcbEnhanceFl); - prm.eeciRefine = group.readEntry(OPTIONEECIREFINEENTRY, defaultPrm.eeciRefine); - prm.esMedPasses = group.readEntry(OPTIONESMEDPASSESENTRY, defaultPrm.esMedPasses); - prm.NRChroThreshold = group.readEntry(OPTIONNRCHROMINANCETHRESHOLDENTRY, defaultPrm.NRChroThreshold); prm.expoCorrection = group.readEntry(OPTIONEXPOCORRECTIONENTRY, defaultPrm.expoCorrection); prm.expoCorrectionShift = group.readEntry(OPTIONEXPOCORRECTIONSHIFTENTRY, defaultPrm.expoCorrectionShift); prm.expoCorrectionHighlight = group.readEntry(OPTIONEXPOCORRECTIONHIGHLIGHTENTRY, defaultPrm.expoCorrectionHighlight); } void DRawDecoderWidget::writeSettings(const DRawDecoderSettings& prm, KConfigGroup& group) { group.writeEntry(OPTIONFIXCOLORSHIGHLIGHTSENTRY, prm.fixColorsHighlights); group.writeEntry(OPTIONDECODESIXTEENBITENTRY, prm.sixteenBitsImage); group.writeEntry(OPTIONWHITEBALANCEENTRY, (int)prm.whiteBalance); group.writeEntry(OPTIONCUSTOMWHITEBALANCEENTRY, prm.customWhiteBalance); group.writeEntry(OPTIONCUSTOMWBGREENENTRY, prm.customWhiteBalanceGreen); group.writeEntry(OPTIONFOURCOLORRGBENTRY, prm.RGBInterpolate4Colors); group.writeEntry(OPTIONUNCLIPCOLORSENTRY, prm.unclipColors); group.writeEntry(OPTIONDONTSTRETCHPIXELSSENTRY, prm.DontStretchPixels); group.writeEntry(OPTIONNOISEREDUCTIONTYPEENTRY, (int)prm.NRType); group.writeEntry(OPTIONBRIGHTNESSMULTIPLIERENTRY, prm.brightness); group.writeEntry(OPTIONUSEBLACKPOINTENTRY, prm.enableBlackPoint); group.writeEntry(OPTIONBLACKPOINTENTRY, prm.blackPoint); group.writeEntry(OPTIONUSEWHITEPOINTENTRY, prm.enableWhitePoint); group.writeEntry(OPTIONWHITEPOINTENTRY, prm.whitePoint); group.writeEntry(OPTIONMEDIANFILTERPASSESENTRY, prm.medianFilterPasses); group.writeEntry(OPTIONNOISEREDUCTIONTHRESHOLDENTRY, prm.NRThreshold); - group.writeEntry(OPTIONUSECACORRECTIONENTRY, prm.enableCACorrection); - group.writeEntry(OPTIONCAREDMULTIPLIERENTRY, prm.caMultiplier[0]); - group.writeEntry(OPTIONCABLUEMULTIPLIERENTRY, prm.caMultiplier[1]); group.writeEntry(OPTIONDECODINGQUALITYENTRY, (int)prm.RAWQuality); group.writeEntry(OPTIONOUTPUTCOLORSPACEENTRY, (int)prm.outputColorSpace); group.writeEntry(OPTIONAUTOBRIGHTNESSENTRY, prm.autoBrightness); //-- Extended demosaicing settings ---------------------------------------------------------- group.writeEntry(OPTIONDCBITERATIONSENTRY, prm.dcbIterations); group.writeEntry(OPTIONDCBENHANCEFLENTRY, prm.dcbEnhanceFl); - group.writeEntry(OPTIONEECIREFINEENTRY, prm.eeciRefine); - group.writeEntry(OPTIONESMEDPASSESENTRY, prm.esMedPasses); - group.writeEntry(OPTIONNRCHROMINANCETHRESHOLDENTRY, prm.NRChroThreshold); group.writeEntry(OPTIONEXPOCORRECTIONENTRY, prm.expoCorrection); group.writeEntry(OPTIONEXPOCORRECTIONSHIFTENTRY, prm.expoCorrectionShift); group.writeEntry(OPTIONEXPOCORRECTIONHIGHLIGHTENTRY, prm.expoCorrectionHighlight); } } // NameSpace Digikam diff --git a/core/libs/widgets/files/drawdecoderwidget.h b/core/libs/rawengine/drawdecoderwidget.h similarity index 97% rename from core/libs/widgets/files/drawdecoderwidget.h rename to core/libs/rawengine/drawdecoderwidget.h index 1a60a23ddd..cc8ab973fe 100644 --- a/core/libs/widgets/files/drawdecoderwidget.h +++ b/core/libs/rawengine/drawdecoderwidget.h @@ -1,126 +1,124 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * date : 2006-09-13 * Description : Raw Decoder settings widgets * * Copyright (C) 2006-2018 by Gilles Caulier * Copyright (C) 2006-2011 by Marcel Wiesweg * Copyright (C) 2007-2008 by Guillaume Castagnino * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_DRAW_DECODER_WIDGET_H #define DIGIKAM_DRAW_DECODER_WIDGET_H // Qt includes #include // KDE includes #include // Local includes #include "drawdecodersettings.h" #include "dlayoutbox.h" #include "dexpanderbox.h" #include "dfileselector.h" #include "digikam_export.h" namespace Digikam { class DIGIKAM_EXPORT DRawDecoderWidget : public DExpanderBox { Q_OBJECT public: enum AdvancedSettingsOptions { SIXTEENBITS = 0x00000001, COLORSPACE = 0x00000002, POSTPROCESSING = 0x00000004, BLACKWHITEPOINTS = 0x00000008 }; enum SettingsTabs { DEMOSAICING = 0, WHITEBALANCE, CORRECTIONS, COLORMANAGEMENT }; public: /** * @param advSettings the default value is COLORSPACE */ explicit DRawDecoderWidget(QWidget* const parent, int advSettings = COLORSPACE); virtual ~DRawDecoderWidget(); DFileSelector* inputProfileUrlEdit() const; DFileSelector* outputProfileUrlEdit() const; void setup(int advSettings); void setEnabledBrightnessSettings(bool b); bool brightnessSettingsIsEnabled() const; void updateMinimumWidth(); void resetToDefault(); void setSettings(const DRawDecoderSettings& settings); DRawDecoderSettings settings() const; void readSettings(KConfigGroup& group); void writeSettings(KConfigGroup& group); static void readSettings(DRawDecoderSettings& setting, KConfigGroup& group); static void writeSettings(const DRawDecoderSettings& setting, KConfigGroup& group); Q_SIGNALS: void signalSixteenBitsImageToggled(bool); void signalSettingsChanged(); private Q_SLOTS: void slotWhiteBalanceToggled(int); void slotsixteenBitsImageToggled(bool); void slotUnclipColorActivated(int); void slotNoiseReductionChanged(int); - void slotCACorrectionToggled(bool); void slotExposureCorrectionToggled(bool); - void slotAutoCAToggled(bool); void slotInputColorSpaceChanged(int); void slotOutputColorSpaceChanged(int); void slotRAWQualityChanged(int); void slotExpoCorrectionShiftChanged(double); private: class Private; Private* const d; }; } // NameSpace Digikam #endif // DIGIKAM_DRAW_DECODER_WIDGET_H diff --git a/core/libs/rawengine/libraw/COPYRIGHT b/core/libs/rawengine/libraw/COPYRIGHT index b2fd61f068..17f0d6a842 100644 --- a/core/libs/rawengine/libraw/COPYRIGHT +++ b/core/libs/rawengine/libraw/COPYRIGHT @@ -1,26 +1,26 @@ ** LibRaw: Raw images processing library ** -Copyright (C) 2008-2017 LibRaw LLC (http://www.libraw.org, info@libraw.org) +Copyright (C) 2008-2018 LibRaw LLC (http://www.libraw.org, info@libraw.org) LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). LibRaw uses code from dcraw.c -- Dave Coffin's raw photo decoder, -dcraw.c is copyright 1997-2012 by Dave Coffin, dcoffin a cybercom o net. +dcraw.c is copyright 1997-2016 by Dave Coffin, dcoffin a cybercom o net. LibRaw uses DCB demosaic and FBDD denoise licensed under BSD-like 3-clause license DCB and FBDD are Copyright (C) 2010, Jacek Gozdz (cuniek@kft.umcs.lublin.pl) LibRaw uses X3F library to unpack Foveon Files, licensed BSD-style license Copyright (c) 2010, Roland Karlsson (roland@proxel.se) All rights reserved. LibRaw uses pieces of code from Adobe DNG SDK 1.4, Copyright (c) 2005 Adobe Systems Incorporated licensed under MIT license diff --git a/core/libs/rawengine/libraw/Changelog.txt b/core/libs/rawengine/libraw/Changelog.txt index b6377721a9..396aa580c8 100644 --- a/core/libs/rawengine/libraw/Changelog.txt +++ b/core/libs/rawengine/libraw/Changelog.txt @@ -1,1822 +1,1948 @@ 2018-06-28 Alex Tutubalin * changed wrong fix for Canon D30 white balance * fixed possible stack overrun while reading zero-sized strings * fixed possible integer overflow - * LibRaw 0.18.13 + * LibRaw 0.19.0-Release -2018-05-11 Alex Tutubalin +2018-06-11 Alex Tutubalin + * Sony uncompressed/untiled DNGs: do not set bits-per-sample to 14 bit + * Do not change tiff_bps for DNG files + * Another possible stack overflow in kodak radc reader * Secunia Advisory SA83507, credits Kasper Leigh Haabb, - Secunia Research at Flexera + Secunia Research at Flexera" - parse_qt: possible integer overflow - reject broken/crafted NOKIARAW files - - Backported 0.19-patch to recover read position if TIFF/EXIF tag is too long - * LibRaw 0.18.12 + * LibRaw 0.19-Beta6 2018-05-10 Alex Tutubalin - * Secunia Advisory SA83050: possible infinite loop in parse_minolta() - * Fixed stack overrun in kodak_radc_load_raw - * restored static for utf2char() lost in previous bugfix - * Fixed possible div by zero in EOS D30 WB data parse - * packed_load_raw(): EOF check on each row + * Put rogue printf's behind #ifdef DCRAW_VERBOSE * Exceptions was not caught in x3f_new_from_file resulting in x3f handle leak - * LibRaw 0.18.11 + * packed_load_raw(): EOF check on each row + * define LIBRAW_USE_CALLOC_INSTEAD_OF_MALLOC to use ::calloc instead of + ::malloc in LibRaw_mem_mgr malloc calls; + Note: realloc is not changed, so only partial fix + * Fixed possible div by zero in EOS D30 WB data parse + * U-suffix for filter-var manipulation consts + * restored static specifier for utf2char() lost in previous bugfix + * Fixed stack overrun in kodak_radc_load_raw + * Secunia Advisory SA83050: possible infinite loop in parse_minolta() + * LibRaw 0.19-Beta5 2018-05-03 Alex Tutubalin * CVE-2018-10529 fixed: out of bounds read in X3F parser * CVE-2018-10528 fixed: possible stack overrun in X3F parser - * LibRaw 0.18.10 + * LibRaw 0.19-Beta4 -2018-04-24 Alex Tutubalin -Secunia #81800: -Credit: Laurent Delosieres, Secunia Research at Flexera - * samsung_load_raw: possible buffer overrun - * rollei_load_raw: possible buffer overrun - * nikon_coolscan_load_raw: possible buffer overrun, possible NULL pointer - * find_green: possible stack overrun - * parse_exif: possible stack overrun - * LibRaw 0.18.9 - -2018-02-23 Alex Tutubalin +2018-04-24 Alex Tutubalin + * LibRaw 0.19-Beta3 + * fixed lot of bugs reported by ImageMagic/oss-fuzz + * fixed several bugs reported by Secunia team (adv 81800, + Credit: Laurent Delosieres, Secunia Research at Flexera) + +2018-03-22 Alex Tutubalin + * LibRaw 0.19-Beta2 + * Better handling of broken JPEG thumbnails + * Panasonic GH5S/G9-hires decoder, thanks to Alexey Danilchenko + Note: ABI has changed due to this patch, so shlib version increased + * Fujifilm X-A5/A20 metadata parsing fix + * New error code LIBRAW_TOO_BIG: image data size excess LIBRAW_MAX_ALLOC_MB + * winsock2 included before windows.h to make MinGW happy + +2018-02-23 Alex Tutubalin + + * LibRaw 0.19-Beta1 + + * 84 cameras added compared to 0.18 (1014 total): + Apple + iPhone 8(*), iPhone 8 plus, iPhone X + BlackMagic + URSA Mini 4k, URSA Mini 4.6k, URSA Mini Pro 4.6k + Canon CHDK hack + PowerShot A410, A540, D10, ELPH 130 IS, ELPH 160 IS, SD750, + SX100 IS,SX130 IS, SX160 IS, SX510 HS, SX10 IS, IXUS 900Ti + Canon + PowerShot G1 X Mark III, G9 X Mark II, EOS 6D Mark II, EOS 77D, + EOS 200D, EOS 800D, EOS M6, EOS M100 + Casio EX-ZR4100/5100 + DJI + Phantom4 Pro/Pro+, Zenmuse X5, Zenmuse X5R + FujiFilm + S6500fd, GFX 50S, X100f, X-A3, X-A5, X-A10, X-A20, X-E3, X-H1, X-T20 + GITUP GIT2P + Hasselblad + H6D-100c, A6D-100c + Huawei + P9 (EVA-L09/AL00), Honor6a, Honor9, Mate10 (BLA-L29) + Leica + CL, M10, TL2 + LG + V20 (F800K), VS995, + Nikon + D850, D5600, D7500, Coolpix B700 + Olympus + E-PL9, E-M10 Mark III, TG-5 + OnePlus + One, A3303, A5000 + Panasonic + DMC-FZ45, DMC-FZ72, DC-FZ80/82, DC-G9 (std. res mode only), DC-GF10/GF90, + DC-GH5, DC-GX9, DC-GX800/850/GF9, DMC-LX1, DC-ZS70 (DC-TZ90/91/92, DC-T93), + DC-TZ100/101/ZS100, DC-TZ200/ZS200 + PARROT + Bebop 2, Bebop Drone + Pentax KP + PhaseOne IQ3 100MP Trichromatic + Samsung + Galaxy Nexus, Galaxy S3, S6 (SM-G920F), S7, S7 Edge, S8 (SM-G950U), + Sony + A7R III, A9, DSC-RX0, DSC-RX10IV + Yi M1 + YUNEEC + CGO3, CGO3P + Xiaoyi YIAC3 (YI 4k) + + Note(*): for mobile phones with DNG format recording, only really tested cameras + are added to supported camera list. Really LibRaw should support any correct DNG. + + * No more built-in support for LibRaw demosaic packs (GPL2/GPL3). + We're unable to support this (very old code), so we'll be happy to transfer this + code to some maintainer who wish to work with it. + + In LibRaw 0.19 we provide extension API: user-settable callbacks to be called in + code points where demosaic pack code was called. + + - int callbacks.pre_identify_cb(void *) => to be called in LibRaw::open_datastream + before call to (standard) identify() function. If this call returns 1, this means + that RAW file is identified and all metadata fields are set, so no need to run + standard identify code. + - void callbacks.post_identify_cb(void*) => called just after identify(), but before + any cleanup code; + - dcraw_process() callbacks are called before dcraw_process phases (name speaks for itself): + pre_subtractblack_cb, pre_scalecolors_cb, pre_preinterpolate_cb, pre_interpolate_cb, + interpolate_bayer_cb, interpolate_xtrans_cb, post_interpolate_cb, pre_converttorgb_cb, + post_converttorgb_cb + + All these new callbacks are called with (this) as the only arg. + To continue LibRaw-demosaic-pack-GPLx support one need to subclass LibRaw, set needed + callbacks in (e.g.) constructor code, than these callbacks to be called + + * Better DNG parser: + - support for DefaultCrop Origin/Size tags (add LIBRAW_PROCESSING_USE_DNG_DEFAULT_CROP to raw_processing_options to enable) + - better parsing for nested DNG tags (use tag from RAW IFD, fallback to IFD0 if no tag in current IFD) + - DNG PreviewColorspace extracted into dng_levels.preview_colorspace + + * Metadata extraction: + - Better extraction of camera measured balance (LIBRAW_WBI_Auto and WBI_Measured), + this not the same as 'as shot' if some preset/manual tune is used. + - Extraction of camera custom balances (LIBRAW_WBI_CustomN) + - Nikon data compression tag extracted into makernotes.nikon.NEFCompression + - Hasselblad BaseISO and Gain extracted into makernotes.hasselblad + - Canon multishot params extracted into makernotes.canon.multishot + - lot of other vendor-specific makernotes data (see data structures definitions for details). + + * New LibRaw::open_bayer call allows to pass sensor dump w/o metadata directly to LibRaw: + virtual int open_bayer(unsigned char *data, unsigned datalen, + ushort _raw_width, ushort _raw_height, ushort _left_margin, ushort _top_margin, + ushort _right_margin, ushort _bottom_margin, + unsigned char procflags, unsigned char bayer_pattern, unsigned unused_bits, unsigned otherflags, + unsigned black_level); + Parameters: + data, datalen - buffer passed + width/height/margins - speaks for itself + procflags: + for 10-bit format: + 1: "4 pixels in 5 bytes" packing is used + 0: "6 pixels in 8 bytes" packing is used + for 16-bit format: + 1: Big-endian data + bayer_pattern: one of LIBRAW_OPENBAYER_RGGB,LIBRAW_OPENBAYER_BGGR, + LIBRAW_OPENBAYER_GRBG,LIBRAW_OPENBAYER_GBRG + unused_bits: count of upper zero bits + otherflags: + Bit 1 - filter (average neighbors) for pixels with values of zero + Bits 2-4 - the orientation of the image (0=do not rotate, 3=180, 5=90CCW, 6=90CW) + black_level: file black level (it also may be specified via imgdata.params) + + see samples/openbayer_sample.cpp for usage sample (note, this sample is 'sample only', suited for + Kodak KAI-0340 sensor, you'll need change open_bayer() params for your data). + + * Color data added/updated/fixed for many cameras + + * Correct data maximum for Fuji X-* cameras + + * Thumbnail processing: + - JPEG thumbnails: if compiled with libjpeg, color count is extracted into imgdata.thumbnail.tcolors + - PPM (bitmap) thumbnails: color count is set according to thumbnail IFD tag + - PPM16 thumbnails: if LIBRAW_PROCESSING_USE_PPM16_THUMBS set in raw_processing_options, than thumbnail will be extracted + as is, not converted to 8 bit. thumbnail.tformat is set to LIBRAW_THUMBNAIL_BITMAP16 in this case. + Untested, because it is hard to find RAWs with 16-bit bitmaps. + +== Compatibility fixes + + * struct tiff_tag renamed to libraw_tiff_tag + * pow64f renamed to libraw_pow64f + +== Bugs fixed: + + * COLOR(r,c) works correctly on X-Trans files + +== Security fixes: Secunia #81000: Credit: Laurent Delosieres, Secunia Research at Flexera * leaf_hdr_load_raw: check for image pointer for demosaiced raw * NOKIARAW parser: check image dimensions readed from file * quicktake_100_load_raw: check width/height limits - * LibRaw 0.18.8 -2018-01-29 Alex Tutubalin - * Checks for width+left_margin/height+top_margin not larger than 64k - * LIBRAW_MAX_ALLOC_MB define limits maximum image/raw_image allocation - (default is 2048 so 2Gb per array) - * LibRaw::read_shorts item count is now unsigned - -2018-01-19 Alex Tutubalin -Secunia #79000: +Secunia #79000: Credit: Laurent Delosieres, Secunia Research at Flexera * All legacy (RGB raw) image loaders checks for imgdata.image is not NULL * kodak_radc_load_raw: check image size before processing * legacy memory allocator: allocate max(widh,raw_width)*max(height,raw_height) - * LibRaw 0.18.7 - -2017-12-06 Alex Tutubalin Secunia #76000: * Fixed fuji_width handling if file is neither fuji nor DNG * Fixed xtrans interpolate for broken xtrans pattern * Fixed panasonic decoder * LibRaw 0.18.6 -2017-09-22 Alex Tutubalin - * Fixed possible out of bound access in Kodak 6500 loader - * LibRaw 0.18.5 - -2017-09-12 Alex Tutubalin +Other fixes: + * Checks for width+left_margin/height+top_margin not larger than 64k + * LIBRAW_MAX_ALLOC_MB define limits maximum image/raw_image allocation + (default is 2048 so 2Gb per array) + * LibRaw::read_shorts item count is now unsigned + * Fixed possible out of bound access in Kodak 65000 loader * CVE-2017-14348: Fix for possible heap overrun in Canon makernotes parser Credit: Henri Salo from Nixu Corporation - * LibRaw 0.18.4 - -2017-09-09 Alex Tutubalin * Fix for CVE-2017-13735 * CVE-2017-14265: Additional check for X-Trans CFA pattern data - * LibRaw 0.18.3 - -2017-03-08 Alex Tutubalin * Fixed several errors (Secunia advisory SA75000) * ACES colorspace output option included in dcraw_emu help page * Avoided possible 32-bit overflows in Sony metadata parser - * Phase One flat field code called even for half-s - * LibRaw 0.18.2 - -2017-02-12 Alex Tutubalin - * Camera Support: Sigma Quatto H - * Fixed bug in FujiExpoMidPointShift parser - * Fixed wrong black level in Sony A350 - * Added standard integer types for VisualStudio 2008 and earlier - * LibRaw 0.18.1 - + * Phase One flat field code called even for half-size + + 2016-12-27 Alex Tutubalin * Licensing changes: - there is no 'LibRaw Software License 27032010' licensing anymore (and all signed agreements have expired) - LibRaw is now dual-licensed: LGPL 2.1 or CDDL 1.0 * Camera support (+87): Apple: iPad Pro, iPhone SE, iPhone 6s, iPhone 6 plus, iPhone 7, iPhone 7 plus BlackMagic Micro Cinema Camera, URSA, URSA Mini Canon PowerShot G5 X, PowerShot G7 X Mark II, PowerShot G9 X, IXUS 160 (CHDK hack), EOS 5D Mark IV, EOS 80D, EOS 1300D, EOS M10, EOS M5, EOS-1D X Mark II Casio EX-ZR4000/5000 DXO One, FujiFilm X-Pro2, X70, X-E2S, X-T2 Gione E7 GITUP GIT2 Google Pixel,Pixel XL Hasselblad X1D, True Zoom HTC MyTouch 4G, One (A9), One (M9), 10 Huawei P9 Leica M (Typ 262), M-D (Typ 262), S (Typ 007), SL (Typ 601), X-U (Typ 113), TL LG G3, G4 Meizy MX4 Nikon D5, D500, D3400 Olympus E-PL8, E-M10 Mark II, Pen F, SH-3, E-M1-II Panasonic DMC-G8/80/81/85, DMC-GX80/85, DMC-TZ80/81/85/ZS60, DMC-TZ100/101/ZS100,DMC-LX9/10/15, FZ2000/FZ2500 Pentax K-1, K-3 II, K-70 PhaseOne IQ3 100MP RaspberryPi Camera, Camera V2 Ricoh GR II Samsung Galaxy S7, S7 Edge Sigma sd Quattro Sony A7S II, ILCA-68 (A68),ILCE-6300,DSC-RX1R II,DSC-RX10III, DSC-RX100V,ILCA-99M2 (A99-II), a6500 IMX214, IMX219, IMX230, IMX298-mipi 16mp, IMX219-mipi 8mp, Xperia L PtGrey GRAS-50S5C YUNEEC CGO4 Xiaomi MI3, RedMi Note3 Pro * Floating point DNG support: - new data fields: imgdata.rawdata.float_image - bayer float data imgdata.rawdata.float3_image - 3-component float data imgdata.rawdata.float4_image - 4-component float data imgdata.color.fmaximum - float data maximum (calculated from real data, rounded to 1.0 if below 1.0) - new raw processing flag LIBRAW_PROCESSING_CONVERTFLOAT_TO_INT - converts float data to 16-bit integer immediately after decoding with default parameters - new API Calls: int LibRaw::is_floating_point() returns non-zero if RAW file contains floating point data int LibRaw::have_fpdata() returns non-zero if rawdata.float*_image is not null (so FP data has been unpacked but not converted to integrer, see below). LibRaw::convertFloatToInt(float dmin=4096.f, float dmax=32767.f, float dtarget = 16383.f) converts float/float3/float4_image to raw_image/color3/color4_image with or without scaling: - if both real data maximum and metadata maximum are within the range ( >= dmin && <=dmax), float data is just converted to integer - if data is out of the range given above, values are scaled so real data maximum becomes dtarget - if data was rescaled (normalized), scale multiplier is stored in imgdata.color.fnorm * LibRaw can be built with Adobe DNG SDK support to decode exotic DNG formats (e.g. 8 bit). See README.DNGSDK.txt for details * New API calls unsigned LibRaw::capabilities and C-API libraw_capabilities() allows developers to determine LibRaw compile flags at runtime. Returns ORed bit fields: LIBRAW_CAPS_RAWSPEED - LibRaw was compiled with RawSpeed Support LIBRAW_CAPS_DNGSDK - LibRaw was compiled with Adobe DNG SDK LIBRAW_CAPS_DEMOSAICSGPL2, LIBRAW_CAPS_DEMOSAICSGPL3 - LibRaw was compiled with demosaic packs (GPL2/GPL3) * More metadata parsed: - White balance coefficients stored in the raw file are extracted into: int imgdata.color.WBCoeffs[256][4] - array indexed by EXIF lightsource type for example, WBCoeffs[21][..] contains coefficients for D65 lightsource float imgdata.color.WBCT_Coeffs[64][5] contains white balance data specified for given color temperature: WBCT_Coeffs[i][0] contains temperature value, and [1]..[4] are WB coefficients. - DNG analog balance, per-channel black/white level, and forward matrix - vendor specific metadata stored in vendor-specific data structures * new C-API calls: void libraw_set_user_mul(libraw_data_t *lr,int index, float val); void libraw_set_ca_correction(libraw_data_t *lr,int ca_correc, float ca_red, float ca_blue); void libraw_set_cfalinenoise(libraw_data_t *lr,int cfaline, float linenoise); void libraw_set_wf_debanding(libraw_data_t *lr, int wf_debanding, float wfd0, float wfd1, float wfd2, float wfd3); void libraw_set_interpolation_passes(libraw_data_t *lr,int passes); * Existing API changes: imgdata.params fields (all very specific purpose): sony_arw2_options, sraw_ycc, and params.x3f_flags replaced with single bit-field raw_processing_options See LIBRAW_PROCESSING_* bits in documentation. * zlib library is optional Use -DUSE_ZLIB to compile with zlib (to provide deflate DNG support) * libjpeg version: jpeg_mem_src() is mandatory, so use libjpeg-turbo or libjpeg 8+ * Fixes in vng_intepolate to make modern compilers happy * Fixed bug in Sony SR2 files black level * DNG files with BlackLevel both in vendor makernotes and BlackLevel: BlackLevel tag always takes precedence * strlen replaced with strnlen in most cases, added local version of strnlen * ChannelBlackLevel added to canon makernotes * unpack_thumb() data size/offset check against file size 2015-08-15 Alex Tutubalin * LibRaw 0.17 * Fixed dcraw.c ljpeg_start possibly buffer overrun * fixed several bugs detected by using American Fuzzy Lop * C-API extension to support 3DLut Creator * More metadata parsing/extraction: - XMP packet extracted (if exists) - DNG Color information parsed - GPS data (partially) parsed - EXIF/Makernotes parsed for used optics (for both RAW files and DNG converted by Adobe convertor). * Exif/Makernotes parser callback (called for each processed tag) * Sony ARW2.3 decoder: - params.sony_arw2_hack removed, decoded data are always in 0...17k range (note the difference with dcraw!) - Additional processing options for Sony lossy compression techincal analysis. * Dcraw 9.26 imported (but some changes not approved because Libraw do it better) with some exceptions: - no Pentax K3-II frame selection code - no built-in JPEG decompressor * Many improvements in data decoding/processing: - Correct decoding of black level values from metadata for many formats, LibRaw do not rely on hardcoded black levels. * 224 camera models added to supported camera list. Some of them are new (released since LibRaw 0.16 come out), some was supported before, but missed from the list. Added cameras are: Alcatel 5035D BlackMagic Pocket Cinema Camera, Production Camera 4k Canon PowerShot A550, A3300 IS, G1 X Mark II, G7 X, SD950, SX60 HS, EOS 7D Mark II, EOS 20Da, EOS 60Da, EOS 1200D, EOS-1D C, 5DS, 5DS R, 750D, 760D, M2, M3, G3 X Casio EX-FC300S, EX-FC400S, EX-Z1080, EX-ZR700, EX-ZR710, EX-ZR750, EX-ZR800, EX-ZR850, EX-ZR1000, EX-ZR1100, ZR1200, ZR1300, EX-ZR1500, EX-100, EX-10 Digital Bolex D16,D16M DJI 4384x3288, Epson R-D1s, R-D1x FujiFilm E505,S1,S205EXR,HS10,HS11,HS22EXR,HS33EXR,HS35EXR,F505EXR,F605EXR,F775EXR,F900EXR,X100T,X30,X-T1,X-T1 Graphite Silver, XQ2, X-A2, X-T10 Hasselblad H5D-60, H5D-50,H5D-50c,H5D-40,H4D-60,H4D-50,H4D-40,H4D-31,H3DII-22,H3DII-31,H3DII-39,H3DII-50,H3D-22,H3D-31,H3D-39,H2D-22,H2D-39,CF-22,CF-31,CF-39,Stellar II,HV HTC UltraPixel Imacon Ixpress 96, 96C, 384, 384C (single shot only),132C, 528C (single shot only) ISG 2020x1520 Ikonoskop A-Cam dII Panchromatic, A-Cam dII Kinefinity KineMINI, KineRAW Mini, KineRAW S35 Kodak DCS460D, S-1 Leaf Credo 50 Lenovo a820 Leica Digital-Modul-R, D-Lux (Typ 109), M (Typ 240), Monochrom (Typ 240), M-E, M-P, R8, S, T (Typ 701), X (Typ 113), X2, X-E (Typ 102), V-Lux (Typ 114), Monochrom (Typ 246), Q Matrix 4608x3288 Nikon D4s, D600, D610, D750, D800, D800E, D810, D3300, D5500, Df, 1 J4, 1 S2, 1 V3, Coolpix P340, Coolscan NEF, D7200, 1 J5,D810A Nokia 1200x1600 Olympus E-450, E-600, E-PL6, E-PL7, E-M1, E-M10, E-M5 Mark II, SP565UZ, STYLUS1s, SH-2, TG-4, AIR-A01 Panasonic DMC-CM1, DMC-FZ7, DMC-FZ70, DMC-FZ1000, DMC-GF7, DMC-GH4, AG-GH4, DMC-GM1s, DMC-GM5, DMC-LX100, DMC-TZ60/61/SZ40, DMC-TZ70, FZ300/330, GX8 Pentax GR, K110D, K-01, K-S1, Q, QS-1, 645Z, K-S2, K3 II PhaseOne IQ250, IQ260, IQ260 Achromatic, IQ280, Achromatic+, P 20+, P 21, P 25+, P 30+, P 40+ Ricoh GXR MOUNT A12, GXR MOUNT A16 24-85mm F3.5-5.5, GXR, S10 24-72mm F2.5-4.4 VC, GXR, GR A12 50mm F2.5 MACRO, GXR, GR LENS A12 28mm F2.5, GXR, GXR P10 Samsung GX-1L, NX1, NX5, NX1000, NX1100, NX30, NX300, NX300M, NX3000, NX mini, Galaxy S3, Galaxy Nexus, NX500 Sigma dp1 Quattro, dp2 Quattro, dp3 Quattro, dp0 Quattro Sinar eMotion 22, eMotion 54, eSpirit 65, eMotion 75, eVolution 75, Sinarback 54 Sony A7 II, A7S, ILCA-77M2 (A77-II), ILCE-3000, ILCE-5000, ILCE-5100, ILCE-6000, ILCE-QX1, DSC-RX100III, DSLR-A560, NEX-VG20, NEX-VG30, NEX-VG900, IMX135-mipi 13mp, IMX135-QCOM, IMX072-mipi, RX100-IV, A7R-II, RX10-II * Fujifilm F700/S20Pro second frame support 2014-02-01 Alex Tutubalin * Updated Oly E-M10 & Panasonic TZ60/61 color data * Updated foveon SD9-14 white level * Support for 1x1 BlackLevelRepeatDim 2014-01-31 Alex Tutubalin * imported dcraw 1.461: fixed error in BlackLevelDim handling * Accurate work with pattern black-level (cblack[6+]) * Support for Olympus E-M10 and Fujifilm X-T1 * Adjusted possbile maximum value for Sigma SD9 small raws 2014-01-27 Alex Tutubalin * dcraw 1.460: Nikon D3300, Panasonic DMC-TZ61, Sony ILCE-5000 2014-01-25 Alex Tutubalin * PhaseOne IQ250 support (both compressed and uncompressed) 2014-01-21 Alex Tutubalin * imgdata.params.sony_arw2_hack removed. It always on for ARW2-files. * New imgdata.params.sony_arw2_options processing flags Values: LIBRAW_SONYARW2_NONE - normal processing LIBRAW_SONYARW2_BASEONLY - BASE pixels outputeed, delta pixels set to 0 LIBRAW_SONYARW2_DELTAONLY - Delta pixels written to raw data, base pixels zeroed LIBRAW_SONYARW2_DELTAZEROBASE - Only deltas written without base offset 2014-01-20 Alex Tutubalin * Imported dcraw 9.20: - Support for DNG BlackLevelRepeatDim tags - imgdata.color.cblack[] holds variable BlackLevel for DNG files (up to ~4k values) - imgdata.params.use_camera_matrix is now ON by default. Set it to 3 if you want to force use of DNG embedded matrix. - Tone curve for Canon RMF format supported - Color data for Canon C500 * Additional camera support: Alcatel 5035D DJI 4384x3288 Fujifilm F900EXR Kodak 12MP Matrix 4608x3288 Nokia 1200x1600 Olympus E-PL6 Panasonic DMC-FZ7 2014-01-17 Alex Tutubalin * Camera support: Added: Fujifilm XE2, XQ1 Color data updated: Nikon D4 1 AW1/J3, Fuji X-M2 Fixes: Nikon D610 visible image area, Canon A3300 bayer pattern * RawSpeed support: enabled processing for cameras, unknown to RawSpeed * Fixed error in LibRaw::unpack_thumb() * little improve performance in my_strcasestr * Fix compiler errors for VS2012/OpenMP * Fixed typo which prevents to use Demosaic Pack GPL2 * LibRaw 0.16.0-Release 2013-11-15 Alex Tutubalin * New cameras supported Leica C, X VARIO Nikon D5300, D610, Df, 1 AW1 Nokia Lumia 1020, 1520 Olympus STYLUS1 Pentax K-3 Sony RX10, A3000 (ILCE-3000), * Color data updated: Canon S120 Nikon P7800, 1 J3 Olympus E-M1 * Corrected image visible area sizes Canon G16 Sigma pre-Merrill cameras: small and medium-sized RAWs * Better EXIF parsing: - ISO values for new Nikon cameras (D4, D800) - black level extraction for Nikon D5300 - correct Olympus color data conversion * Better Visual Studio compatibility (esp. old versions) * Cmake build: added ws2_32 library for MinGW builds * LibRaw 0.16.0-Beta1 2013-10-22 Alex Tutubalin * Support for new cameras: Sony A7, A7R Panasonic GM1 * Sony RX1R and RX100M2 color data updated. * Sony cameras model name is set by SonyModelID EXIF tag * Sony ARW2: black level and color matrix extracted from EXIF data * Samsung: black level and color matrix extracted from EXIF; Camera multipliers are now extracted correctly even if black is not 0 * Better source compatibility with Mac OS X compilation * Better source compatibility with Win32 compilation * DNG without Compression tag assumed uncompressed * Better X3F-tools based Foveon support: - new Foveon metadata parser based on X3F-tools. So, if LibRaw compiled without demosaic-pack-GPL2, then no dcraw Foveon code used. - Support for Medium resolution RAWs from DPx Merrill and SD1 cameras. RAW data extracted as is (4800x1600 pixels), aspect ratio is set to 0.5, so these RAWs are processed to full-size 4800x3200 RGB. - Support for Foveon thumbnail extraction. Only JPEG and bitmap thumbnails extracted, but 'foveon' (RAW) thumbnails are really not used in production cameras. - New imgdata.params.force_foveon_x3f flag Forces use of x3f-tools based code for Foveon processing if LibRaw compiled with demosaic-pack-GPL2 (and does nothing if LibRaw compiled without this pack). New flag -disadcf added to dcraw_emu sample to use this flag. - LibRaw do not calls exit() on broken Foveon files. * API/ABI changed, so all code using LibRaw should be recompiled. * LibRaw 0.16.0-Alpha3 2013-10-16 Alex Tutubalin * Support for new cameras: Canon S120 (preliminary color data), G16 Fujifilm X-A1 (preliminary color data) Hasselblad Lunar, Stellar Nikon P7800 (preliminary color data) Pentax K50, K500, Q7 Samsung Galaxy NX (EK-GN120) Sony NEX-5T * Updated color data for: Samsung NX300 Sony RX1R Sigma SD1, SD1 Merrill, DPxx (only if non-GPL2 foveon decoder used) * Image dimensions table for Foveon cameras (only if non-GPL2 foveon decoder used) * Fixed memory leak in x3f-tools code (new Foveon decoder) * Fixed DHT-demosaic incompatibility with MS VisualStudio in OpenMP directives * Additional image size checks. * LibRaw 0.16-Alpha2 2013-09-22 Alex Tutubalin * Support for new cameras: Baumer TXG14 Blackmagic Cinema Canon EOS 70D, C500 Fujifilm X-M1 Nikon D5200 Olympus E-P5,E-M1 OmniVision OV5647 (Raspberry Pi) Panasonic LF1, GX7, GF6 Richon GR Samsung NX300, NX1100, NX2000 Sony RX100II, RX1R, NEX-3N * Support for Foveon sensor based on X3F code by Roland Karlsson BSD-like license, so included in main LibRaw code. No 'foveon intepolation', so no way to get good colors from old Sigma cameras (SD9, SD14, Polaroid x530). For modern Foveon cameras one may try to create ICC profile (not supplied). TODO: thumbnail extraction, fast cancelation Old foveon_*_load_raw (from dcraw) code is used if compiled with LIBRAW_DEMOSAIC_PACK_GPL2 * API Changes: + New parameters in imgdata.params: - imgdata.params.no_interpolation - disables interpolation step in LibRaw::dcraw_process() call. - imgdata.params.no_auto_scale - disables call to scale_colors() in LibRaw::dcraw_process() call. - imgdata.params.sraw_ycc - disables Canon sRAW YCbCr to RGB conversion in LibRaw::unpack() call (use for RAW analyzers + New Fuji X-Trans handling: - imgdata.iparams.filters value is now 9 for Fuji X-Trans (instead of 2) - imgdata.iparams.xtrans[6][6] matrix contains row/col to color mapping for Fuji X-Trans sensor. + LibRaw::setCancelFlag() - use for fast decoder termination + LibRaw_abstract_datastream::make_byte_buffer() call is not needed more. + New demosaic code: DHT Demosaic by Anton Petrusevich Set params.user_qual=11 to use. + New demosaic code: Modified AHD Demosaic by Anton Petrusevich Set params.user_qual=12 to use. + New C-API call libraw_COLOR(libraw_data_t *t, int row,int col) (so LibRaw::COLOR(row,col) exposed to C-API users) * Removed faster lossless jpeg decoder ported from RawSpeed library some years ago. Build LibRaw with RawSpeed to get fast decoding. * Fixed decoding error for some Canon sRAW files. * Disabled RawSpeed's bad pixel processing if RawSpeed used. * EOS M and EOS 70D added to unique Canon ID table * Canon EOS model name normalized by unique ID table * Backported 0.15.4 input data checks * Support for CMake builds * Updated RawSpeed supported camera list * Internals changed, so all code using LibRaw should be recompiled. * LibRaw 0.16.0-Alpha1 2013-05-23 Alex Tutubalin LibRaw 0.15-Release New camera/format support: * Adobe DNG: fast Load DNG (LightRoom 4.x), support for lossy-compressed DNG (LR 4.x, requires libjpeg 6+) * Canon: G1 X, SX220 HS, EOS 5D Mark III, EOS 650D, EOS 1D-X, 100D (Rebel SL1), 700D (Rebel T5i), 6D, EOS M, G15, S110, SX50 * Casio: EX-ZR100,EX-Z8 * Fujifilm: X-S1, HS30EXR, X1-Pro,X-E1, X20, X100S, SL1000, HS50EXR, F800EXR, XF1 * Leica: D-LUX6 and V-LUX4 * Nikon: D4, D3200, D800, D800E, 1 J2, 1 V2, D600, 1 J3, 1 S1, Coolpix A, Coolpix P330, Coolpix P7700, D7100 * Olympus: E-M5, XZ-2, XZ-10, E-PL5, E-PM2 * Panasonic: G5, G6, DMC-GF5, FZ200, GH3, LX7 * Pentax: MX-1, K-5 II, K-5 IIs, K-30, Q10 * Samsung: EX2F, NX20, NX210, support for the new firmware for NX100 * Sigma: SD15, SD1, SD1 Merill, DP1, DP1S, DP1X, DP2, DP2S, DP2X (only with Demosaic-pack-GPL2) * Sony: SLT-A58, RX-1, SLT-A99, NEX-5R, NEX-6, NEX-F3, SLT-A37, SLT-A57 * Multishot files: Imacon Ixpress 39Mpix API changes: 1. dcraw_process() can now be called several times with different parameters without re-opening and unpacking the file for second and consecutive calls to dcraw_process 2. deleted (nobody uses those) - LibRaw::dcraw_document_mode_processing (and respective C-API) - imgdata.color.color_flags data field 3. LibRaw::unpack() now decodes data into different buffers, the buffer depends on the raw data type - imgdata.rawdata.raw_image - 1 color component per pixel, for b/w and Bayer type sensors - imgdata.rawdata.color3_image - 3 color components per pixel, sRAW/mRAW files, RawSpeed decoding - imgdata.rawdata.color4_image - 4 components per pixel, the 4th component can be void 4. Support for compiling with RawSpeed library, http://rawstudio.org/blog/?p=800 details are in README.RawSpeed 5. Suppression of banding 6. New API calls - recycle_datastream(), - open_file(wchar_t*) (Win32) 2012-04-05 Alex Tutubalin * Casio EX-Z500 support * (possible) I/O exceptions on file open catched in open_datastream * Fixed possible read-after-buffer in Sony ARW2 decoder * Fixed mingw32 errors when compiling LibRaw_windows_datastream * Makefile.msvc: support of OpenMP and LCMS (uncomment to use) * Fixed decoding of some Leaf Aptus II files * LibRaw 0.14.6-Release 2011-12-24 Alex Tutubalin * Fixed bug (uninitialized variable) in SMAL format decoding. * Imported new dcraw 9.12 (1.446): support for Leica V-LUX 3, updated color data for Canon S100, Fujifilm X10, Nikon 1 J1/V1, Panasonic GX1, Samsung NX200, Sony NEX-7 * LibRaw 0.14.5-Release 2011-12-12 Alex Tutubalin * Fixes to Panasonic/Leica file parser to prevent crash on broken jpegs. * Fixes to include order in src/libraw_datastream.cpp to better compile with KDEWIN * Floating-point DNGs are rejected on early processing stage. * Support for new cameras: Canon S100, Fuji X10, Panasonic GX1, Samsung NX200, Sony NEX-7. * LibRaw 0.14.4-Release 2011-10-26 Alex Tutubalin * Bug fixes in black level subtraction code for PhaseOne files * New API call LibRaw::get_internal_data_pointer() for developers who need access to libraw_internal_data fields (i.e. Fuji SuperCCD layout). * doc/API-overview fixes to reflect 0.14 changes * LibRaw 0.14.3-Release 2011-10-19 Alex Tutubalin * Fixed bug in Canon 1D and 1Ds files decoding. * New decoder information bit DECODER_HASRAWCURVE * LibRaw 0.14.2-Release 2011-10-11 Alex Tutubalin * Imported dcraw 9.11/1.445: + Support for new cameras added: Fujifilm F600EXR, Nikon P7100, Olympus E-PL3 and E-PM1, Panasonic DMC-FZ150, Sony NEX-5N, A65 and A77. + Changed color data for: Olympus E-P3, Panasonic G3 and GF3, PhaseOne H25, P40 and P65, Sony NEX-C3, NEX-5, NEX-3, A35 and A55. + Support for dark frame extraction on Sony cameras. * DCB demosaicing: reserving 6 pixels instead of 3 to suppress colored image frame. * LibRaw 0.14.1-Release 2011-09-21 Alex Tutubalin * Cosmetic changes to make Visual C++/OpenMP more happy * Fix megapixel calculation for postprocessing_benchmark in half mode * Shlib version number increment * LibRaw 0.14.0-Release 2011-09-04 Alex Tutubalin * Fixed bug with Kodak thumbnail extraction * raw2image_ex() always return value * LibRaw 0.14.0-Beta2 2011-09-02 Alex Tutubalin * Cosmetic changes to LibRaw_file_datastream interface * OpenMP speedup of postprocessing steps (up to 50% for half mode and 4-core machine) * LibRaw 0.14.0-Beta1 2011-08-20 Alex Tutubalin * Patch to dcraw_emu for SunStudio compiler compatibility * Fixed crash in unprocessed_raw sample due to uninitialized timestamp variable. * Fixed crash in raw decoding if raw_width/raw_height is less than resulting image width/height. * imgdata.sizes.flip is set from user_flip only on postprocessing and/or adjust_sizes_info_only() * Fixed buffer overrun for some LJPEG-compressed files * Most of LibRaw_datastream function bodies are moved to separate source file * LibRaw_windows_datastream is merged to main sourcetree * LibRaw 0.14.0-Alpha5 2011-08-11 Alex Tutubalin * Imported dcraw 9.10 (1.444), support for new cameras added: ARRIRAW format, Canon SX30 IS, Leica D-LUX 5 and V-LUX2, Olympus E-P3, Panasonic G3 and GF3, Sony NEX-C3 and SLT-A35 * Support for RedOne digital movie cameras (R3D format). To enable this support you should: + install libjasper JPEG2000 support library + compile LibRaw with -DUSE_JASPER compiler switch (./configure will do it for you) + If you use own LibRaw_datastream implementation, you should implement make_jas_stream() call for your datastream. See bottom of src/libraw_cxx.cpp for implementations in datafile and mem-buffer LibRaw streams. * Bugfix: green matching is turned off if output image is shrinked due to wavelet filtering or aberration correction. * fixed open_file()/adjust_sizes_info_only() code path * Removed imgdata.sizes.bottom_margin and right_margin data fields use imgdata.sizes.raw_width - width - left_margin to get right one, the same with bottom_margin. * minor ./configure cleanup * Qmake files and Visual Studio Project files are updated. * New version check macros: For use at runtime checks: LIBRAW_RUNTIME_CHECK_VERSION_EXACT() - checks that runtime major/minor version numbers are same with compile-time values. LIBRAW_RUNTIME_CHECK_VERSION_NOTLESS() - checks that runtime version is not less that compile-time one. For use at compile-time in preprocessor directives: LIBRAW_COMPILE_CHECK_VERSION_EXACT(major,minor) - Compile-time check that LibRaw version is exact major.minor. LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(major,minor) - Compile-time check that version is not less than major.minor. * all client code should be recompiled due to internals change. * LibRaw 0.14.0-Alpha4 2011-07-19 Alex Tutubalin * New sample samples/postprocessing_benchmark.cpp This sample measures postprocessing speed. All demosaic methods, averaged white balance, median filtering, wavelet filtration, highlight recovery, and cropping are supported. * Removed LibRaw::rotate_fuji_raw() call and corresponding C-API call. * The LibRaw::adjust_sizes_info_only() call may be called repeated and mixed with dcraw_process() call. * Postprocessing speedup and optimization, especially if cropping set. * Cropping works for FujiCCD raws. For the technical reasons, the position of top-left corner of crop area will be rounded to the nearest multiple of 4 (the corner is shifted top-left). * LibRaw 0.14.0-Alpha3 2011-07-15 Alex Tutubalin * imported cropping code from 0.13 branch 2011-07-12 Alex Tutubalin * samples/multirender_test - check for different clip settings 2011-07-11 Alex Tutubalin * New call LibRaw::free_image(), deallocates imgdata.image buffer. Use this call if current postprocessing results are not needed, but it is to early to call recycle() because dcraw_process() may be called later. * New C-API calls libraw_raw2image() - C API for LibRaw::raw2image() libraw_free_image() - C API for LibRaw::free_image() libraw_get_decoder_info() - C API for LibRaw::get_decoder_info() * Bugfix: change of params.user_flip aftee open()/unpack() calls should work. * LibRaw 0.14.0-Alpha2 2011-07-10 Alex Tutubalin * Multiple rendering (LibRaw::dcraw_process() calls) allowed without re-opening RAW file thrfough the sequence of open()/unpack() calls. You should be able to change any processing parameters (except shot_select parameter) between dcraw_process() calls. + New sample in samples/multirender_test.cpp: renders data 4 times: in half and full modes with different white balance settings. + Unprocessed RAW data is stored in separate data buffer: (2 bytes per pixel for all Bayer-pattern images, 8 bytes per pixel for Foveon, sRAW, and other full-color raw formats), so now LibRaw uses 25% more memory for full processing of most common Bayer images; while for just unpack memory is reduced 4 times. + New call LibRaw::raw2image() fills imgdata.image array with fresh copy of data. There is no need to call raw2image() separately if you use dcraw_process() or dcraw_document_mode_processing() calls. + New call LibRaw::get_decoder_info() to determine raw data storage layout. See samples/unprocessed_raw.cpp for an example of how to use it. If your code uses usual open()/unpack()/dcraw_process() call sequence, then NOTHING CHANGED: your program should produce same results. For interactive programs you may skip open()/unpack() calls after adjusting processing parameters, so user should see image refreshed much faster. If your code uses raw data (open+unpack calls), you need to call LibRaw::raw2image(), and imgdata.image will contain same bitmap as in LibRaw 0.13.x If you code uses access to masked borders data, you need to rewrite it. See samples/unprocessed_raw.cpp as a sample. Unfortunately, documentation is untouched yet. This problem will be fixed in next Alpha release. Other changes: * No separate imgdata.masked_pixels buffers, Bayer raw formats are read to buffer with borders. So, no ugly add_masked_border_to_bitmap() call. * No filtering_mode parameter. Raw tone curve is applied at unpack() stage; zero pixels removed on postprocesing stage. * unprocessed_raw and 4colors samples are adjusted to use new RAW data storage layout. * all client code should be recompiled due to internals change. * LibRaw 0.14.0-Alpha1 2011-07-03 Alex Tutubalin * Cosmetic cleanup in Libraw_memmgr code * Permit OpenMP support on MS VS2008 * More general mem_image interface: + New call get_mem_image_format returns bitmap size and bit depth + New call copy_mem_image can copy bitmap into buffer with different color order (RGB/BGR) and line stride + dcraw_make_mem_image() uses calls mentioned above + see documentation for info on these function parameters. * libraw/librawwindows.h implements LibRaw_datastream class based on Windows memory mapped files.Win32/64-only Thanks to Linc Brookes. * Fixed parallel make errors in configure/Makefile.am * LibRaw 0.13.6-Release 2011-05-18 Alex Tutubalin * Imported new dcraw 9.08/1.443: + New color data for Canon 600D and 1100D, Fuji S200EXR + New camera supported: Fuji HS20EXR and F550EXR, Kodak Z990, Nikon D5100, Olympus E-PL1s and XZ-1, Samsung NX11, Sony A230 and 290. * LibRaw 0.13.5-Release 2011-04-02 Alex Tutubalin * Imported new dcraw 9.07/1.442: + Support for Canon 600D and 1100D, Hasselblad H4D-60, Olympus E-PL2 * Color data for Leaf Aptus II and Canon Powershot S2 IS * LibRaw 0.13.4-Release 2011-03-30 Alex Tutubalin * Preliminary support for Leaf Aptus II cameras (no color data yet): Leaf Aptus II 6,7,8,10 and 12 are tested, Aptus II 5 should work. * Preliminary support for Fujifilm X100 camera (again, no color data). * Fixed possible after the end of buffer read when working with in-memory data. * Fixed possible loss of JPEG stream sync marks in LJPEG decoder (this bug was found only for Leaf Aptus II RAWs). * LibRaw 0.13.3-Release 2011-03-08 Alex Tutubalin * Fixed broken camera white balance reading for some Sony cameras * LibRaw 0.13.2-Release 2011-02-25 Alex Tutubalin * Sony A390 support (colordata from A380) * Leica D-LUX 4: fixed typo in camera name in colordata 2011-02-15 Alex Tutubalin * New -mem option for dcraw_emu: I/O via allocated buffer * Removed debug printf from LibRaw_memory_buffer code * Preliminary shared library support 2011-02-12 Alex Tutubalin * Added qmake .pro and Visual Studio 2008 sln/vcproj project files 2011-02-07 Alex Tutubalin * dcraw_emu documentation updated * ./configure stuff changed for correct linking on some systems * FBDD denoising is disabled for full-color images and 4-color bayer data (including forced 4-color via four_color_rgb option) * LibRaw 0.13.1-Release 2011-02-05 Alex Tutubalin * ./configure fixes for PACKAGE_REQUIRES * Makefile.msvc: correct compiler flags for demosaic packs * dcraw.c 9.06/1.440 imported: + New camera support: Canon S95, Casio EX-Z1080, Panasonic GF2 and GH2, Samsung NX100, Sony A-580 + New color data for: Canon G12, Nikon D3100, D7000 and P7000, Olympus E-5, Pentax K-r and K-5, Samsung NX10 and WB2000 * green_matching() code is disabled for half-size processing * LibRaw 0.13.0-Release 2011-01-15 Alex Tutubalin * Fallback to old huffman decoder for Sony files with unspecified data length (Sony A100) * Fixed incomplete data fields reset in LibRaw::recycle() * LibRaw 0.13.0-Beta3 2011-01-13 Alex Tutubalin * Better parsing of unknown command-line params in dcraw_emu sample * Brigtness table in ahd_demosaic is calculated in reversed order to prevent possible (very unlikely) multithreaded app problem. * New exposure correction code based on linear-cubic root combination. New working correction range is from 0.25 (-2 stops) to 8 (+3 stops) * LibRaw 0.13.0-Beta2 2011-01-10 Alex Tutubalin * Fixed file extension in half_mt.c sample 2011-01-10 Alex Tutubalin * Three patches provided by Jacques Desmis: - Exposure correction before demosaic (demosaic pack GPL3) - OpenMP speed-up in median filters (demosaic pack GPL2) - OpenMP speed-up in green equilibration (demosaic pack GPL3) * Merged 0.12.2-0.12.3 changes: - Patches for ./configure system for better LCMS2 support - Patches for ./configure system - math.h included before any other includes to make KDE compile with Visual C++ happy - Fuji FinePix S5500 size adjusted to ignore (rare?) garbage at top of frame. * all client code should be recompiled due to internals change. * LibRaw 0.13.0-Beta1 2010-12-22 Alex Tutubalin * Zero copy huffman buffer for LibRaw_buffer_datastream * Fixed memory leak in compressed NEFs handling * LibRaw 0.13.0-Alpha2 2010-12-20 Alex Tutubalin * Demosaic-pack-GPL3 changes: + New noise reduction methods before demosaic - Banding suppression - High-frequency noise suppression - Green channel equalization + New chromatic abberration correction. All three methods are written by Emil Martinec for Raw Therapee. Adapted to LibRaw by Jacques Desmis * Merged Foveon code fix from LibRaw 0.12.1 * LJPEG decompressor speed-up (about 1.5 times for Canon cameras and slightly less for others). Some ideas are from RawSpeed library. * all client code should be recompiled due to internals change. * LibRaw 0.13.0-Alpha1 2010-12-12 Alex Tutubalin * Thread-safe and demosaic packs support for MinGW build * Demosaic packs support for MS VC build * LibRaw 0.12.0-Release 2010-12-09 Alex Tutubalin * Fixed bug in add_masked_borders_to_bitmap() call for cameras with odd pixels border. * New command line options for unprocessed_raw sample: -B - subtract black level, -M - add masked pixels to bitmap. * Foveon-sensor cameras added to supported camera list if compiled with demosaic pack GPL2 * LibRaw 0.12.0-Beta4 2010-12-05 Alex Tutubalin * Demosaic packs support in Makefile.dist * Foveon support in LibRaw demosaic pack GPL2 * all client code should be recompiled due to internals change. * LibRaw 0.12.0-Beta3 2010-11-27 Alex Tutubalin * Fixed allocation bug in lmmse_interpolation (demosaic-pack-GPL2) * In LMMSE and AMaZE interpolators allocation changed to calloc to make valgrind happy with uninitialized values * Changes in distribution-making scripts * LibRaw 0.12.0-Beta2 2010-11-21 Alex Tutubalin * Fixes to green_matching code by Sergey Pavlov 2010-11-20 Alex Tutubalin * Update for new demosaic-pack-GPL3 * LibRaw 0.12.0-Beta1 2010-11-19 Alex Tutubalin * Demosaic pack(s) supported via ./configure 2010-11-17 Alex Tutubalin * LCMS2 support * afd_interpolate(2,1) instead of (5,0) * dcraw_emu sample command line keys added and reordered to reflect changes in LibRaw 0.12. * Nikon P7000: color matrix data and black level patch for ISO >=400 Thanks to Gunnar Thorburn * Support for several industrial cameras based on Sony ICX 625/655 sensor: JAI BB500CL/GE, SVS625CL, ptGrey GRAS-50S5C Thanks to kaare 2010-11-15 Alex Tutubalin * Several demosaic algorithms, found in other open-source RAW processing packages are implemented in LibRaw. 1) DCB demosaic and FBDD denoise by Jacek Gozdz are included in main LibRaw source. 2) GPL2 demosaic pack with these demosaic methods: * AFD and LMMSE implementations from PerfectRaw by Manuel Llorens * VCD, Modified AHD, post-demosaic refinemend and median filters by Paul Lee 3) GPL3 demosaic pack with AMaZe interpolation by Emil Martinec See more details in README.demosaic-packs * Current implementation of dcraw_emu sample allows only selection of demosaic method (via -q) options. All other parameters change will be implemented later. * LibRaw 0.12-alpha1 2010-11-11 Alex Tutubalin * Imported 0.11(2) version changes: + Fixed dcraw_emu command line processing code + OpenMP is completely disabled on MacOS X if compiled with -pthread due to well-known MacOS problem. + dcraw 9.05 (1.439) imported, many new cameras supported: Canon: G12, SX120, 60D, Hasselblad H4D, Nokia X2, Olympus E-5, Nikon: D3100, D7000, P7000, Panasonic: FZ40, FZ100, LX5, Pentax: K-r, K-5, 645D, Samsung GX20, WB2000 * LibRaw 0.12-alpha0 2010-11-08 Alex Tutubalin * Fixes for Sun Studio compiler compatibility * Fixes for Visual Studio 2010 compatibility * All russian-language files are converted to UTF-8 * LibRaw 0.11.0-Release 2010-10-18 Alex Tutubalin * Disabled OpenMP for wavelet_denoise under Mac OS X * More Visual C++ 2003 warnings cleaned in libraw/*h files * LibRaw 0.11-Beta7 2010-10-16 Alex Tutubalin * internal/dcraw_fileio.c can be compiled with -DDCRAW_VERBOSE again * fixed comment style in libraw_datastream.h * LibRaw 0.11-Beta6 2010-10-15 Alex Tutubalin * New changes to I/O layer. Three LibRaw_*datastream clasees are exists: + LibRaw_buffer_datastream - buffer reaging + LibRaw_file_datastream - file reading using iostreams (large files are no supported on some systems) + LibRaw_bigfile_datastream - FILE*-based file I/O * file/bigfile_datastream is selected automatically by LibRaw::open_file based on input file size. By default, files larger than 250Mb are opened using bigfile interface, you may change this behaviour by using second optional parameter of open_file() * There is no way to use default parameter values in C API, so new call libraw_open_file_ex added with two parameters (file name and minimal file size for bigfile_datastream use). * all client code should be recompiled due to internals change. * All LibRaw_abstract_datastream functions are virtual again. You may (again) use your own I/O layer. * new -d key for dcraw_emu sample: print timings of processing stages * simple_dcraw sample simplified: no mmap code * LibRaw 0.11-Beta5 2010-10-08 Alex Tutubalin * Fixed bug in exception handling in OpenMP sections in AHD interpolation code. * LibRaw_datastreams are now C++ iostreams based instead of old plain FILE* calls. LibRaw::open_file() in multithreaded programs are WAY faster on many OSes (Linux, Windows, MacOSX) because of no extra locks. * all client code should be recompiled due to internals change. * LibRaw 0.11-Beta4 2010-10-01 Alex Tutubalin * Fixed bug in LibRaw::dcraw_process() code: for half_size processing, params.four_color_rgb was set to 1 internally and not returned back after postprocessing. * Several Visual Studio 2003 compatibility fixes * AHD interpolation refactored. Now it is about 10% faster than dcraw in single-process mode and up to 1.5 times faster on 4-core and OpenMP (total execution time counted, not AHD itself) Thanks to Adam Hooper * AHD interpolation refactored. Now it is about 10% faster than dcraw in single-process mode and up to 1.5 times faster on 4-core and OpenMP (total execution time counted, not AHD itself) Thanks to Adam Hooper * LibRaw 0.11-Beta3 2010-09-07 Alex Tutubalin * Phase One files: LibRaw::unpack() sets colordata.black to approximately correct value. * Fixed minor error in setting colordata.maximum value for Phase One files. * LibRaw::subtract_black() sets colordata.black and colordata.cblack[] to zero to preserve data integrity. * LibRaw 0.11-Beta2 2010-09-04 Alex Tutubalin * It is now possible to crop output image on postprocessing stage (dcraw_process). Coordinates and size of the output box are set via imgdata.params.cropbox[4] parameter. Look into LibRaw documentation for more details. + New fatal error code LIBRAW_BAD_CROP + New dcraw_emu sample command line switch: -B x y w h (sets cropbox) Thanks to Patrick and Jan. * Processing pipeline has changed: the black level is subtracted from data on postprocessing stage either automatically (on dcraw_process() stage) or by special LibRaw API call: + New API calls: LibRaw::subtract_black() (C++ API) and libraw_subtract_black (C API). If you use dcraw_process() or dcraw_document_mode_processing() calls YOU DON'T NEED to call subtract_black() directly. + The raw preprocessing mode LIBRAW_FILTERING_NOBLACKS is deprecated and removed from LibRaw. * New ./configure script. Use ./configure -h for usage details. Thanks to Siddhesh Poyarekar * New API cals static LibRaw::dcraw_clear_mem() (C++ API) and libraw_dcraw_clear_mem(..) (C API). This calls are used to free memory, allocated by dcraw_make_mem_image() and dcraw_make_mem_thumb() instead of free() call. In some cases LibRaw and calling process have different memory managers, so free() of make_mem_image() data results to program crash (especially in Win32/VisualStudio enviroment). * LibRaw::free() is now private instead of public (again). * Minor changes and bugfixes: + Memory allocation exceptions (std::bad_alloc) are caught, so LibRaw API calls will return reasonable error codes instead of C++ exception (possibly unhandled). This problem is very unlikely to see in wild: if application cannot allocate small data for internal structure, it will always fail on allocation for RAW image data. + WIN32/VisualStudio 2008/2010: fopen,fscanf and sscanf calls in Libraw_datastream code are changed to *_s (secure) ones. + Debug print removed from fatal error handler. + Mmaped I/O for dcraw_emu sample is turned on via -E switch now (because old -B switch is used for settng cropbox). * all client code should be recompiled due to structures size change * LibRaw 0.11-Beta1 2010-07-31 Alex Tutubalin * dcraw 9.04 (1.438) imported: changes in tiff metadata parser, fixed a typo in Canon A720 model name * small patch in Sony ARW2 unpacking code to make valgrind happy * LibRaw 0.10.0-Beta3. 2010-07-05 Alex Tutubalin * dcraw 9.03 (1.437) imported: + New cameras: Canon SX20, Nikon D3s, Olympus E-P2, Panasoni DMC-GF1, Samsung EX1, Sony A450 + Color data changed for some cameras * LibRaw 0.10.0-Beta2. 2010-06-06 Alex Tutubalin * dcraw 9.01 (1.434) imported: + Separate black levels for each color channel. + New cameras: Canon 550D, Casio EX-Z1050, Fuji HS10/HS11, Kodak Z981, Panasonic G2 and G10, Phase One P65, Samsung NX-10 and WB550, Sony NEX-3 and NEX-5. + Fixed file descriptor leak in dark frame subtraction processing * Fixed dcraw 9.01's bug in DNG black level processing * Preliminary support for Sony A450 camera. * New command-line switch -h in mem_image sample (half_size support) * Some patches by Johannes Hanika (darktable author): + OpenMP speedup for PPG-interpolation + green_matching - suppress of 'color maze' on cameras with different green channel sensitivity. This option is turns on by filed with same name in imgdata.params * all client code should be recompiled due to structures size change * LibRaw::free() is now public instead of private. * LibRaw 0.10.0-Beta1. 2010-05-15 Alex Tutubalin * Fixed bug in 8-bit RAW processing code * LibRaw 0.9.1-Release 2010-04-26 Alex Tutubalin * OpenMP support: OpenMP is possible under MinGW (untested) * LibRaw 0.9.0-Release 2010-04-21 Alex Tutubalin * Finally fixed inconsistency in Fuji files processing * New COLOR(row,col) call to get bayer color index in image[] array * Old FC() call is deprecated and will be removed in future releases * unprocessed_raw sample switched to COLOR() call * LibRaw 0.9.0-Beta5 2010-04-10 Alex Tutubalin * Fixed bug in unpacking DNG files made from Fuji RAFs. * LibRaw 0.9.0-Beta4 2010-04-09 Alex Tutubalin * Fixed typecast error (problem reported only on gcc 4.2.1/32bit) in CRW files processing. * C++ API call LibRaw::adjust_maximum() is now deprecated and de-documented, use params.adjust_maximum_thr instead (on by default) * C-API call libraw_adjust_maximum() removed. * New postprocessing parameter params.adjust_maximum_thr This parameter replaces LibRaw::adjust_maximum(), but more flexible Defaults are reasonable (0.75, same as in old adjust_maximum), look into documentation for more details. * Removed last OpenMP warning * dcraw_emu's -c parameter now wants numeric (float) argument. This value is assigned to params.adjust_maximum_thr. Use -c 0.0 for dcraw compatibility. * all client code should be recompiled due to structures size change * LibRaw 0.9.0-Beta3 2010-03-29 Alex Tutubalin * Fixed a bug in channel_maximum[] calculation for Panasonic cameras. * channel_maximum[] data now calculated for ALL cameras. * OpenMP warnings suppressed. * Documented the -c command-line switch for dcraw_emu sample. * Removed extra messages from dcraw_emu sample. * LibRaw 0.9.0-Beta2 2010-03-28 Alex Tutubalin New licensing: * Triple licensing (selected by LibRaw user): + LGPL 2.1 (http://www.gnu.org/licenses/lgpl-2.1.html) + CDDL 1.0 (http://www.opensource.org/licenses/cddl1.txt) + LibRaw Software License (27 March 2010 version) (http://www.libraw.org/data/LICENSE.LibRaw.pdf) * There is no separate LibRaw-Lite and LibRaw-Commercial versions, only single LibRaw. Current LibRaw-Lite and LibRaw-Commercial users should switch to LibRaw without loss of functionality. It is possible to change licensig too (e.g. from LGPL to CDDL for LibRaw-Lite users and from LibRaw License to LGPL or CDDL for LibRaw-Commercial users). * No Foveon support :( It is not possible to get good color from Foveon sensors with *any* converter. So, there is no need to support these cameras. Dcraw's Foveon-processing code is too strict licensed (GPL), so we choose to drop it. New Features: * New data field colordata.channel_maximum[4] - per channel data maximum (calculated for most cameras, 0 for others). * New call LibRaw::adjust_maximum() (and libraw_adjust_maximum() in C API). This call changes hardcoded colordata.maximum value to calculated at unpack stage. This helps suppress false color in highlights (magenta clouds and so). * New command line parameter -c for dcraw_emu sample. Calls adjust_maximum() for each processed file. * all client code should be recompiled due to structures size change * LibRaw 0.9.0-Beta1 2010-02-06 Alex Tutubalin * Fixed ambiguity in pow/sqrt calls (to make Sun C++ compiler happy) * OpenMP is not supported under MS Visual Studio * Masked a bug in RIFF format parser * LibRaw 0.8.6 2009-12-30 Alex Tutubalin * Fixed bug in simple_dcraw sample parameters processing * Imported dcraw 8.99 (1.432): + New cameras: Canon: 1D mk IV, Canon S90; Casio Z750, Nikon D3S, Pentax K-x, Sony A-500/550, Fuji S200EXR + New color data for Canon G11 and Sony A850 + Changes in Canon sRAW processing + Changes in Kodak metadata processing + Changes in uncompressed Fuji files processing (FinePix S5xxx) * LibRaw 0.8.5 2009-11-21 Alex Tutubalin + Fixed a bug in processing of uncompressed Phase One files * LibRaw 0.8.4 2009-10-24 Alex Tutubalin + Imported dcraw 8.98/1.431: * New Cameras: Canon 7D, Panasonic GF1, Sony A850 and A380, Casio Z850, Nikon D300s + changes in libraw_datastream.h to make compilers more happy * LibRaw 0.8.3 2009-09-02 Alex Tutubalin + Fixed bug in Hasselblad .3FR unpacking code * Imported dcraw 8.97/1.428: Nikon D3000 image width fix * LibRaw 0.8.2 2009-08-31 Alex Tutubalin + Enum LibRaw_thumbnail_formats (LIBRAW_IMAGE_*) values changed to match values in enum LibRaw_image_formats (LIBRAW_THUMBNAIL_*). You need to recompile all sources using these constants. 2009-08-30 Alex Tutubalin * Imported dcraw 8.97/1.427: + new cameras: Canon A470, Canon G11 (without color data), Nikon D3000, Olympus E-P1, Panasonic DMC-FZ35/FZ38 + some changes in decoding code. * Fixes for Microsoft Visual C++ 6.0 compatibility * C-API dcraw_make_mem_thumb() call finally exported in API * LibRaw 0.8.1 2009-08-24 Alex Tutubalin * Imported dcraw 8.96/1.426 + New cameras: Casio EX-Z60 and EX-Z75, Kodak Z980, Nikon D5000, Olympus X200, D560Z,C350Z,E620, Pentax K7, Sony A330. + New color data for many cameras + Generalized unpacker code for Canon and Casio P&S cameras * LibRaw 0.8.0-Release 2009-08-13 Alex Tutubalin * RAW files larger than 2Gb are supported on: - Unix (all supported: FreeBSD, MacOS X, Linux) - Windows (with C runtime version >= 8.0) * bzero replaced with memset to make Solaris users happy * All applications on 32-bit systems should be recompiled due to data structures size changes. * Minor fixes in windows makefile * LibRaw 0.8.0-Beta5 2009-07-21 Alex Tutubalin * Imported dcraw 8.95 (1.425): + new huffman tree code + New cameras supported: AGFAPHOTO DC-833m, Casio EX-S20, Phase One P65, Samsung S850 + Removed hardcoded white-balance data for many P&S cameras. It is recommended to set params.use_camera_wb to 1 for safe WB. * Fixes for Nikon D5000 files: no pink stripe at right side of frame * C-wrapper: added missed calls libraw_dcraw_make_mem_image libraw_dcraw_ make_mem_thumb * Minor fixes to make non-gcc compilers more happy * Internal structures changed, full recompilation of all client code is needed. * LibRaw 0.8.0-Beta4 2009-06-08 Alex Tutubalin * Fixes: gamma curve processing was not performed in dcraw_write_mem_image() * Fixes: gamma curve processing was not performed for Kodak thumbnails * LibRaw 0.8.0-Beta3 2009-06-05 Alex Tutubalin * Fixes in documentation: params.gamm[] described more precisely * Fixes in version number, 0.8-beta1 was mistakenly 0.0.0-beta1 * LibRaw 0.8.0-Beta2 2009-06-04 Alex Tutubalin * Imported dcraw 8.94 (1.423): + New camera support: Canon: SX1, 500D/Rebel T1i, A570, A590, SX110 Kodak Z1015, Motorola PIXL, Olympus E30, Panasonic DMC-GH1 + Improved color data for Nikon D3X + New gamma curve model + Many changes in RAW unpacking code + Canon cameras: black level is not subtracted if set params.document_mode > 1 * API changed: params.gamma_16bit field removed. Gamma curve is set via params.gamm[0]/gamm[1] values (see documentation and samples for details) * LibRaw::identify() splitted to avoid MS VS2008 bug (too many nested blocks) * Samples: dcraw_emu and mem_image samples supports new dcraw 16bit/gamma semantics: -6: set 16 bit output -4: set 16 bit output and linear gamma curve and no auto brighness * LibRaw 0.8.0-Beta1 2009-04-28 Alex Tutubalin * Identify sample renamed to raw-identify (name conflict with ImageMagic) * Copyright notice changes * Many compiler warnings removed 2009-04-07 Alex Tutubalin * More accurate types conversion in libraw_datastream.h * New postprocessing parameter auto_bright_thr: set portion of clipped pixels for auto brightening code (instead of dcraw-derived hardcoded 1%) * -U option for dcraw_emu sample sets auto_bright_thr parameter * all client code should be recompiled due to structures size change * LibRaw 0.7.2-Release 2009-03-22 Alex Tutubalin * Fixed typo in OpenMP support code * MinGW support * dcraw source is included in distribution * LibRaw 0.7.1-Release 2009-03-15 Alex Tutubalin * Fuji SuperCCD RAWs: color channels unshuffled on RAW read stage (moved from postprocessing stage) * LibRaw 0.7.0-Release 2009-03-13 Alex Tutubalin * dcraw 8.93/1.421 imported: + more accurate pentax dSLR support + fixes in Kodak 620x/720x identification + faster identification procedure for some formats. * LibRaw 0.7.0-Beta5 2009-03-08 Alex Tutubalin * dcraw 8.92/1.420 imported: + user-specified gamma curve + Pentax K2000/Km support + Changes in Canon sRAW processing (support for 5D2 fw 1.07) * all client code should be recompiled * LibRaw 0.7.0-Beta4 2009-02-13 Alex Tutubalin * bugfix: 4channels sample finally subtracts black by default * dcraw 8.91/1.419 imported: + fixes in RIFF files parsing * LibRaw 0.7.0-Beta3 2009-02-12 Alex Tutubalin * Black level was not calculated for Canon RAWs in some filtering modes * 4channels sample prints calculated black level (scaled if autoscaling used). Also output file names for this sample now includes color channel name (R/G/B/G2 or C/M/Y/G) * LibRaw 0.7.0-Beta2 2009-02-09 Alex Tutubalin * New sample 4channels: splits RAW color channels into four separate TIFFs * LibRaw 0.7.0-Beta1 2009-02-07 Alex Tutubalin * Fixed bug in external jpeg metadata reading code. * Cleaned some C++ warnings * dcraw 8.91/1.418 imported + Hasselblad V96C support * You need to clean and recompile client code which uses LibRaw_*_datastream classes. * LibRaw 0.7.0-Alpha6 2009-01-30 Alex Tutubalin * New data input framework is created. It is possible now to easyly implement your own data input interface for LibRaw (e.g. for reading RAW data from network data stream) * All older programs using previous LibRaw versions are compatible at source code level. * LibRaw can read RAW data from memory buffer via new LibRaw::open_buffer() API call (implemented on top of new input framework). This call used in sample application dcraw_emu and simple_dcraw (with -B command-line switch) to test new API. * Error handling callback functions now can be called with NULL filename passed (if underlying data stream object does not know file name). So, client error handling callbacks should work with NULL filename. * All client code should be recompiled * Imported dcraw 8.90/1.417: + Support for loading White Balance data from Sony ARW files edited with Sony IDC software. * LibRaw 0.7.0-Alpha5 2009-01-17 Alex Tutubalin * Raw filtering mode LIBRAW_FILTERING_NOPOSTPROCESS has renamed to LIBRAW_FILTERING_NORAWCURVE for better reflect its purpose. This filtering_mode bit turns off tone curve applying on RAW data on bayer-pattern cameras with raw tone curve: + Adobe DNG (only RAW with bayer pattern) + Nikon compressed NEF + Some Kodak cameras + Sony A700/A900 (tone curve applied to 8-bit raws) * unprocessed_raw sample: added command-line key -N, this key turns on LIBRAW_FILTERING_NORAWCURVE filtering mode. * New scheme of Fuji RAW processing (introduced in 0.7-Alpha3) supports DNG files generated from Fuji RAF. * Imported dcraw 8.90/1.416: + better support for Samsung S85 + fixed possible integer overflow in wavelet denoising code * LibRaw 0.7.0-Alpha4 2009-01-14 Alex Tutubalin * Black mask extraction supported for all files with bayer data (one component per pixel). Black mask data not avaliable for multi-component data (Foveon, Canon sRAW, Sinar 4-shot, Kodak YCC/YRGB). * Black level subtraction can be turned off for all bayer cameras (added support for PhaseOne backs). * Fujifilm camera processing model changed: + RAW data is extracted without 45-degree rotation + dcraw-compatible rotation is performed on postptocessing stage + it is possible to rotate RAW data without postprocessing by LibRaw::rotate_fuji_raw() call. * New filtering mode setting: LIBRAW_FILTERING_NOPOSTPROCESS This bits turns off RAW tone curve processing based on tone curve readed from RAW metadata. This mode supported only for PhaseOne backs now (to be supported on all relevant cameras in nearest future releases) * Black level data (got from RAW data) are stored for PhaseOne backs. * Black level subtraction bug (derived from dcraw) fixed for PhaseOne files. * Fixed processing of -s parameter for dcraw_emu sample * Parameter -s N (select shot number) added to unprocessed_raw sample. * Imported dcraw 8.90/1.414: + changes in QuickTake 100 metadata processing + changes in external jpeg processing code + Samsung S85 support * All client code should be recompiled * LibRaw 0.7.0-Alpha3 released 2009-01-10 Alex Tutubalin * Fixed bug in add_masked_borders: crash if output dimensions is already larger than raw dimensions * Fixed out of bounds in samples/unprocessed_raw.cpp for files with non-square pixels * LibRaw 0.7.0-Alpha2 released 2009-01-08 Alex Tutubalin * Fixed bug in 0.7.0-a0: black frame size has not reset, so in batch processing there is an error in black frame size for files without black frame. * Implemented reading of black/masked pixels data for near all cameras with masked pixels, exclding: + Canon sRAW, Leaf (MOS), Sinar 4-shot - more than one color component in black frame (redesign of black frame data structures required). + Fuji SuperCCD: need to design right methods of extraction (should we rotate and resize black pixels as active ones??) * Tested for most dSLR data formats with masked pixels: 7 of 9 untested formats are from old P&S cameras. * New call LibRaw::unpack_function_name() returns unpack function name (useful for testers only) * New identify sample parameters (useful for test-suite builders to check test coverage): -u - print unpack function name -f - print masked frame size These parameters works only for identify run without -v parameter * Imported dcraw 8.89/1.411 + changes in Panasonic FZ50 files parsing * LibRaw 0.7.0-Alpha1 released 2009-01-05 Alex Tutubalin * It is possible to turn off RAW data filtration (black level subtraction, zero pixels averaging): + supported on all cameras except Foveon and Phase One + filtraction controlled by new parameter "filtering_mode" + it is possible to expand API by filtering procedures built for specific camera model. * Black border (masked pixels) extraction: + API (data structures) for storing black mask. + Black mask extraction supported only for limited list of data formats: - Canon .CRW, .CR2 (with exception of sRAW),A600, A5 - Adobe DNG (both converted RAW and native DNG) - Nikon NEF (compressed only) this list to be expanded in future LibRaw versions * New call add_masked_borders_to_bitmap makes full bitmap 'masked border' + image * Usage sample for functionality listed above: samples/unprocessed_raw * Imported dcraw 8.89/1.410: + fixed bugs in Hasselblad .fff decoding + fixes in Imacon metadata decoding * Documentation changes * All client code should be recompiled * LibRaw 0.7.0-Alpha0 2009-01-01 Alex Tutubalin * Fixed a bug (filedescriptor and buffer memory leak) in thumbnail extraction when called before metadata analysis. Thanks to Albert Astalis Cid. * LibRaw 0.6.4 Release 2008-12-11 Alex Tutubalin * Imported new edition of dcraw 8.89 (version 1.409) * Nikon NEF decoding changed * LibRaw 0.6.3 Release 2008-12-03 Alex Tutubalin * fixed bug in Panasonic .RW2 processing (only for thread-safe version, single-threaded version was not affected) * All client code should be recompiled * LibRaw 0.6.2 Release 2008-12-03 Alex Tutubalin * Imported dcraw 8.89 (version 1.407) * New cameras: Canon G10 & 5D Mk2, Leaf AFi 7, Leica D-LUX4, Panasonic FX150 & G1, Fujifilm IS Pro, * Changed camera support (color conversion tables): Canon 50D, Nikon D90 & P6000, Panasonic LX3 & FZ28, Sony A900 * LibRaw 0.6.2 beta 2008-09-25 Alex Tutubalin * Added new data field float LibRaw::imgdata.color.cam_xyz[4][3]. This field contains constant table (different for each camera) for Camera RGB->XYZ conversion. * All client code should be recompiled * LibRaw 0.6.1 Release 2008-09-18 Alex Tutubalin * dcraw 8.88 imported: - new cameras (Canon 50D, Sony A900, Nikon D90 & P6000, Panasonic LX3 FZ28) - new method of black point subtraction for Canon cameras, preliminary banding supression. * Stack memory usage lowered (some thread data moved to dynamic memory) * some patches for MSVC compatibility * LibRaw 0.6.0 Release 2008-09-16 Alex Tutubalin * Enum definitions changed to make gcc -pedantic happy * Compiler/preprocessor flags does not affects LibRaw class field set (i.e. structure for thread local storage is always allocated) * Default library compilation mode (i.e. sources imported in another project) is thread-safe 2008-09-14 Alex Tutubalin * OpenMP support for most CPU consuming steps of processing: ahd_interpolation. wavelet_denoise 10-30% speed-up of full processing pipe on 2-core CPU OpenMP supported only on gcc (Linux/FreeBSD and Mac OS X) * LibRaw 0.6.0-Beta-1 2008-09-10 Alex Tutubalin * All set_**handler accepts additional void* pointer, which should point to callback private data. This pointer passed to user callback when it called. * LibRaw 0.6.0-alpha5 * All client code should be recompiled 2008-09-10 Alex Tutubalin * New processing stages in enum LibRaw_progress: LIBRAW_PROGRESS_BAD_PIXELS LIBRAW_PROGRESS_DARK_FRAME (reserved stages LIBRAW_PROGRESS_RESERVED_PRE1-PRE2 has removed) * libraw_strprogress() - convert progress code into string * Added progress/cancellation user callbacks + new fatal error code: CANCELLED_BY_CALLBACK + sample usage in samples/dcraw_emu.cpp (try run it with -v -v -v opts) * LibRaw 0.6.0-alpha4 * All client code should be recompiled 2008-09-08 Alex Tutubalin * ICC-profiles support (same as in dcraw) + input/output profiles (specified as path to 'icc' file or 'embed' for embedded input profile) + additional warnings + LCMS library used * support of bad pixel map (caller should specify path to bad pixel file in dcraw-compatible format) * dark frame subtraction support (caller should supply path to 16-bit PGM map). samples/simple_dcraw.cpp - -4 option added for dark frame file generation * support of bad pixeld map (dcraw-compatible format) * the dcraw_emu sample supports all new features (ICC, dark frame, bad pixels) * libraw/libraw_version.h, defines, calls and macros for version checks: + LibRaw::version(), LibRaw::versionNumber(), LIBRAW_CHECK_VERSION() * List of supported cameras: + LibRaw::cameraCount() + LibRaw::cameraList() * fixed error in adjust_sizes_info_only * documentation changes * LibRaw 0.6.0-alpha3 2008-09-07 Alex Tutubalin * samples/mem_image.c - bitwise equal output with dcraw -4 (PPMs outputted with network byte order) * LibRaw 0.6.0-alpha2 2008-09-06 Alex Tutubalin * Added calls dcraw_make_mem_image and dcraw_make_mem_image: + functions (and supporting code) + documentation changed + new sample code samples/mem_image.cpp * Added processing parameter LibRaw::imgdata.params.gamma_16bit (set to 1 to make gamma correction for 16-bit output) * LibRaw 0.6.0-alpha1 2008-08-28 Alex Tutubalin * dcraw 1.404 (8.87) imported: - 6 new cameras supported (Canon 1000D, A720, SD300; Nikon D700, Oly E-520,Kodak C603) * Licensing changed to GPL v2 2008-05-02 Alex Tutubalin * mmap/malloc+read IO-layer removed due to no performance gain. FILE I/O returned 2008-05-02 Alex Tutubalin * dcraw 1.403 imported - changes in ljpeg decompression (index values cut to 12 bit) - changes in parse_foveon() jpeg thumbnail extraction * LibRaw 0.5.3 released 2008-04-24 Alex Tutubalin * Linux build of samples/identify fixed * documentation editorial * LibRaw 0.5.2 released 2008-04-21 Alex Tutubalin * All documentation translated to English * English changelog started :) * minor bug (include path) fixed in samples/half_mt * LibRaw 0.5.1 released diff --git a/core/libs/rawengine/libraw/README b/core/libs/rawengine/libraw/README index 6ede1b600a..d23b2ea08a 100644 --- a/core/libs/rawengine/libraw/README +++ b/core/libs/rawengine/libraw/README @@ -1,27 +1,27 @@ ====================== LibRaw ============================== == Library for reading and processing of RAW digicam images == LibRaw is a library for reading RAW files from digital photo cameras (CRW/CR2, NEF, RAF, DNG, MOS, KDC, DCR, etc, virtually all RAW formats are supported). It pays special attention to correct retrieval of data required for subsequent RAW conversion. The library is intended for embedding in RAW converters, data analyzers, and other programs using RAW files as the initial data. -LibRaw library, Copyright (C) 2008-2017 LibRaw LLC (info@libraw.org) +LibRaw library, Copyright (C) 2008-2018 LibRaw LLC (info@libraw.org) The library includes source code from dcraw.c, Dave Coffin's raw photo decoder Copyright 1997-2016 by Dave Coffin, dcoffin a cybercom o net LibRaw is distributed for free under two different licenses: * GNU Lesser General Public License, version 2.1 * COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 You may use one of these licensing modes and switch between them. If you modify LibRaw source and made your changes public, you should accept both two licensing modes for your changes/additions. diff --git a/core/libs/rawengine/libraw/README.demosaic-packs b/core/libs/rawengine/libraw/README.demosaic-packs deleted file mode 100644 index e91d644e39..0000000000 --- a/core/libs/rawengine/libraw/README.demosaic-packs +++ /dev/null @@ -1,46 +0,0 @@ -======================= LibRaw demosaic pack(s) =============================== - -There are many good interpolation (demosaic) methods implemented in open-source -world. - -Unfortunately, some of these methods are distributed under the terms of -different versions of GNU General Public License (GPL). So it is not possible -to include implementation of these demosaics into the LibRaw distribution -because LibRaw is distributed under more liberal licenses (LGPL and CDDL). - -Of course, it is possible to distribute these demosaic methods in separate -packages and use within LibRaw under following conditions: - - * LibRaw is used under the terms of LGPL license which is GPL-compatible - * Resulting product (which uses LibRaw AND LibRaw-demosaic-pack) is licensed - under GPL2+ (for GPL2 demosaic-pack) or GPL3+ (if demosaic-pack-GPL3 is used). - -For now demosaic packs are available via GitHub only: - - 1) LibRaw demosaic pack GPL2+ - GitHub URL: git://github.com/LibRaw/LibRaw-demosaic-pack-GPL2.git - - This pack includes these demosaic implementations: - - * AFD and LMMSE implementations from PerfectRaw by Manuel Llorens - * VCD, Modified AHD, post-demosaic refinemend and median - filters by Paul Lee - - 2) LibRaw demosaic pack GPL3+ - GitHub URL: git://github.com/LibRaw/LibRaw-demosaic-pack-GPL3.git - - This pack includes AMaZe interpolation by Emil Martinec. - -== How To Use (developer only!) === - -1. Get LibRaw-0.12... and unpack it in some folder. - -2. Checkout one or both demosaic pack(s) in the same folder (NOT within LibRaw folder). - -3. Check Makefile settings: -CFLAGS_DP1 and CFLAGS_DP2 should point to demosaic pack(s) folder(s) -CFLAGS should have -DLIBRAW_DEMOSAIC_PACK_GPL2/-DLIBRAW_DEMOSAIC_PACK_GPL3 setting - -4. Just run make. - -./configure stuff is not supported with demosaic-pack(s) for now. diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL2/COPYRIGHT b/core/libs/rawengine/libraw/demosaic-pack-GPL2/COPYRIGHT deleted file mode 100644 index 89aea5a63b..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL2/COPYRIGHT +++ /dev/null @@ -1,22 +0,0 @@ - -VCD, Modified AHD, post-demosaic refinemend and median filters are from -'Modified DCRAW' Copyright 2009 Paul Lee -(http://sites.google.com/site/demosaicalgorithms/modified-dcraw) - -dcraw.c -- Dave Coffin's raw photo decoder, -dcraw.c is copyright 1997-2010 by Dave Coffin, dcoffin a cybercom o net. - -AFD and LMMSE implementations are taken from dcraw.c from PerfectRaw ver. 0.65. -PerfectRaw source contains no explicit Copyright information, so - 1) (likely) these programs are Copyright 2009 Manuel Llorens - 2) GNU General Public License version 2 or later assumed because some files - in same folder have this copying notice. - -dcraw.c -- Dave Coffin's raw photo decoder, -dcraw.c is copyright 1997-2010 by Dave Coffin, dcoffin a cybercom o net. - - -LibRaw adaptation and integration Copyright (C) 2010 Christos Stamatopoulos. - - - diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL2/Changelog b/core/libs/rawengine/libraw/demosaic-pack-GPL2/Changelog deleted file mode 100644 index 683cd77c46..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL2/Changelog +++ /dev/null @@ -1,17 +0,0 @@ -2011-01-10 Alex Tutubalin - * pragma omp changed in median filter -2010-12-20 Alex Tutubalin - * Fixed crash on Sigma DPx files in Foveon code -2010-12-05 Alex Tutubalin - * foveon processing code from dcraw - -2010-11-27 Alex Tutubalin - * fixed bug with allocation size in lmmse_interpolate - * changed malloc to calloc to make valgrind happy with uninitialized - values - -2010-11-20 Alex Tutubalin - * OpenMP with LIBRAW_USE_OPENMP - -2010-11-15 Alex Tutubalin - * Initial revision diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL2/LICENSE.txt b/core/libs/rawengine/libraw/demosaic-pack-GPL2/LICENSE.txt deleted file mode 100644 index d159169d10..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL2/LICENSE.txt +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL2/README b/core/libs/rawengine/libraw/demosaic-pack-GPL2/README deleted file mode 100644 index 4c630668b3..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL2/README +++ /dev/null @@ -1,13 +0,0 @@ -** LibRaw-demosaic-pack-GPL2 ** - -This folder contains additional demosaic/image correction methods for -LibRaw (http://www.libraw.org). - -You need LibRaw RAW processing library to use program/algorithm found in this -folder. - -LibRaw can be downloaded from LibRaw origin site: http://www.libraw.org/download -or from GitHub (git://github.com/LibRaw/LibRaw.git) - -Look into README.demosaic-packs in LibRaw distribution for more details. - diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL2/afd_interpolate_pl.c b/core/libs/rawengine/libraw/demosaic-pack-GPL2/afd_interpolate_pl.c deleted file mode 100644 index f882bb0cab..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL2/afd_interpolate_pl.c +++ /dev/null @@ -1,320 +0,0 @@ -/* This file was taken from PerfectRaw ver. 0.65 - on May 14, 2010, taking dcraw ver.8.88/rev.1.405 - as basis. - http://dl.dropbox.com/u/602348/perfectRAW%200.65%20source%20code.zip - - As PerfectRaw source code was published, the release under - GPL Version 2 or later option could be applied, so this file - is taken under this premise. -*/ - -/* -Adaptive Filtered Demosaicking interpolation is adapted from -the work of Lian Naixiang, Chang Lanlan and Prof. Tan Yap Peng. -*/ - - -#define FC_BK(row,col) \ - (filters_bk >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3) - -#define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} } -void CLASS afd_interpolate_pl(int afd_passes, int clip_on) -{ - int row, col, rr, cc, rr1, cc1, c, d, ii, jj, ba, lum_iter; - int p12, p13, p14, p21, p22, p23, p24, p25; - int p41, p42, p43, p44, p45, p52, p53, p54; - float (*pix)[4], (*dimage)[4], (*w)[4], *glut; - double v0, v1, v2, dG, dC0, dC1, dC2, dC3, dC4, temp; - double ws, w0, w1, w2, w3, dt; - clock_t t1, t2; -#ifdef DCRAW_VERBOSE - if (verbose) { - fprintf(stderr,_("AFD interpolation with pattern matching...\n")); - fprintf(stderr,_("\tafd_passes, clip_on = %d, %d\n"),afd_passes,clip_on); } -#endif - t1 = clock(); - - // allocate work with boundary - ba = 6; - rr1 = height + 2*ba; - cc1 = width + 2*ba; - - // Set up working arrays - dimage = (float (*)[4])calloc(rr1*cc1, sizeof *dimage); - w = (float (*)[4])calloc((int)((1+rr1*cc1)/2),sizeof *w); - - // copy CFA values and apply gamma correction - glut = (float *)calloc(65536,sizeof *glut); - for (ii=0; ii < 65536; ii++) { - v0 = (float)ii / 65535.0; - glut[ii] = (v0 <= 0.0031308 ? v0*12.92 : 1.055*pow(v0,1./2.4) - 0.055); } - // - for (rr=0; rr < rr1; rr++) - for (cc=0, row=rr-ba; cc < cc1; cc++) { - col = cc - ba; - ii = rr*cc1 + cc; - c = FC(rr,cc); - if ((row >= 0) & (row < height) & (col >= 0) & (col < width)) - dimage[ii][c] = glut[image[row*width+col][c]]; - else - dimage[ii][c] = 0; } - // - free(glut); - - // Set up indices - p12 = -2*cc1-1; p13 = p12+1; p14 = p13+1; - p21 = -cc1-2; p22 = p21+1; p23 = p22+1; p24 = p23+1; p25 = p24+1; - p41 = cc1-2; p42 = p41+1; p43 = p42+1; p44 = p43+1; p45 = p44+1; - p52 = 2*cc1-1; p53 = p52+1; p54 = p53+1; - - // Low pass filtering to extract luminance at GREEN pixels - for (rr=2; rr < rr1-2; rr++) - for (cc=2+(FC(rr,3)&1), c=FC(rr,cc+1); cc < cc1-2; cc+=2) { - pix = dimage + rr*cc1+cc; - d = 2 - c; - v0 = (pix[p12][c] + pix[p14][c] + pix[p21][d] + pix[p25][d] + - pix[p41][d] + pix[p45][d] + pix[p52][c] + pix[p54][c] - - 2.0*(pix[p13][1] + pix[ -2][1] + pix[ 2][1] + pix[p53][1]) - - 4.0*(pix[p22][1] + pix[p24][1] + pix[p42][1] + pix[p44][1]) - + 6.0*(pix[p23][d] + pix[ -1][c] + pix[ 1][c] + pix[p43][d]) - + 56.0*pix[0][1]) / 64.0; - if (clip_on) v0 = LIM(v0,0.0,1.0); - pix[0][3] = v0; } - // Compute adapative weighting matrix - for (ii=0, rr=2; rr < rr1-2; rr++) - for (cc=2+(FC(rr,2)&1), c=FC(rr,cc); cc < cc1-2; cc+=2, ii++) { - pix = dimage + rr*cc1+cc; - v0 = pix[0][c]; - // horizontal - dG = pix[1][1] - pix[-1][1]; - if (dG < 0) dG = -dG; - v1 = v0 - pix[ -2][c]; - if (v1 < 0) v1 = -v1; - v2 = v0 - pix[ 2][c]; - if (v2 < 0) v2 = -v2; - w0 = 1.0/(1.0 + v1 + dG); - w2 = 1.0/(1.0 + v2 + dG); - // vertical - dG = pix[p43][1] - pix[p23][1]; - if (dG < 0) dG = -dG; - v1 = v0 - pix[p13][c]; - if (v1 < 0) v1 = -v1; - v2 = v0 - pix[p53][c]; - if (v2 < 0) v2 = -v2; - w1 = 1.0/(1.0 + v1 + dG); - w3 = 1.0/(1.0 + v2 + dG); - // - ws = w0 + w1 + w2 + w3; - w[ii][0] = w0/ws; - w[ii][1] = w1/ws; - w[ii][2] = w2/ws; - w[ii][3] = w3/ws; } - // Calculate initial red/blue at GREEN pixels with bilinear - for (rr=1; rr < rr1-1; rr++) - for (cc=1+(FC(rr,2)&1), c=FC(rr,cc+1); cc < cc1-1; cc+=2) { - pix = dimage + rr*cc1+cc; - pix[0][c] = 0.5*(pix[ -1][c] + pix[ 1][c]); - c = 2 - c; - pix[0][c] = 0.5*(pix[p23][c] + pix[p43][c]); - c = 2 - c; } - for (lum_iter=0; lum_iter < afd_passes; lum_iter++) { - // Estimate luminance at RED/BLUE pixels - for (ii=0, rr=2; rr < rr1-2; rr++) - for (cc=2+(FC(rr,2)&1), c=FC(rr,cc); cc < cc1-2; cc+=2, ii++) { - pix = dimage + rr*cc1+cc; - v0 = pix[0][c] + - w[ii][0]*(pix[ -1][3] - pix[ -1][c]) + - w[ii][2]*(pix[ 1][3] - pix[ 1][c]) + - w[ii][1]*(pix[p23][3] - pix[p23][c]) + - w[ii][3]*(pix[p43][3] - pix[p43][c]); - if (clip_on) v0 = LIM(v0,0.0,1.0); - pix[0][3] = v0; } - // Interpolote red/blue pixels on BLUE/RED pixel locations - // using pattern regcognition on (r-L or b-L) - for (rr=1; rr < rr1-1; rr++) - for (cc=1+(FC(rr,1)&1), c=2-FC(rr,cc); cc < cc1-1; cc+=2) { - pix = dimage + rr*cc1+cc; - dC1 = pix[p22][c] - pix[p22][3]; - dC2 = pix[p24][c] - pix[p24][3]; - dC3 = pix[p42][c] - pix[p42][3]; - dC4 = pix[p44][c] - pix[p44][3]; - dC0 = 0.25*(dC1 + dC2 + dC3 + dC4); - jj = (dC1 > dC0) + (dC2 > dC0) + (dC3 > dC0) + (dC4 > dC0); - if (jj == 3 || jj == 1) { - // edge-corner pattern: median of colorr differential values - PIX_SORT(dC1,dC2); - PIX_SORT(dC3,dC4); - PIX_SORT(dC1,dC3); - PIX_SORT(dC2,dC4); - dC0 = 0.5*(dC2 + dC3); } - else { - // stripe pattern: average along diagonal - v1 = pix[p22][c] - pix[p44][c]; - if (v1 < 0) v1 = -v1; - v2 = pix[p24][c] - pix[p42][c]; - if (v2 < 0) v2 = -v2; - dC0 = (v1 < v2 ? 0.5*(dC1 + dC4) : 0.5*(dC2 + dC3)); } - v0 = pix[0][3] + dC0; - if (clip_on) v0 = LIM(v0,0.0,1.0); - pix[0][c] = v0; } - // Interpolote red/blue pixels on GREEN pixel locations - // using pattern regcognition on (r-L or b-L) - for (rr=1; rr < rr1-1; rr++) - for (cc=1+(FC(rr,2)&1), c=FC(rr,cc+1); cc < cc1-1; cc+=2) { - pix = dimage + rr*cc1+cc; - for (ii=0; ii < 2; c=2-c, ii++) { - dC1 = pix[p23][c] - pix[p23][3]; - dC2 = pix[ -1][c] - pix[ -1][3]; - dC3 = pix[ 1][c] - pix[ 1][3]; - dC4 = pix[p43][c] - pix[p43][3]; - dC0 = 0.25*(dC1 + dC2 + dC3 + dC4); - jj = (dC1 > dC0) + (dC2 > dC0) + (dC3 > dC0) + (dC4 > dC0); - if (jj == 3 || jj == 1) { - // edge-corner pattern: median of color differential values - PIX_SORT(dC1,dC2); - PIX_SORT(dC3,dC4); - PIX_SORT(dC1,dC3); - PIX_SORT(dC2,dC4); - dC0 = 0.5*(dC2 + dC3); } - else { - // stripe pattern: average along diagonal - v1 = pix[p23][c] - pix[p43][c]; - if (v1 < 0) v1 = -v1; - v2 = pix[ -1][c] - pix[ 1][c]; - if (v2 < 0) v2 = -v2; - dC0 = (v1 < v2 ? 0.5*(dC1 + dC4) : 0.5*(dC2 + dC3)); } - v0 = pix[0][3] + dC0; - if (clip_on) v0 = LIM(v0,0.0,1.0); - pix[0][c] = v0; } - } - } - free(w); - - // Interpolate green pixels at RED/BLUE - for (rr=2; rr < rr1-2; rr++) - for (cc=2+(FC(rr,2)&1), c=2-FC(rr,cc); cc < cc1-2; cc+=2) { - pix = dimage + rr*cc1+cc; - // green - pix[0][1] = pix[0][3] + 0.25*(pix[ -1][1] - pix[ -1][3] + - pix[ 1][1] - pix[ 1][3] + - pix[p23][1] - pix[p23][3] + - pix[p43][1] - pix[p43][3]); } - - // copy result back to image matrix - for (row=0; row < height; row++) - for (col=0, rr=row+ba; col < width; col++) { - cc = col+ba; - c = FC(row,col); - pix = dimage + rr*cc1+cc; - ii = row*width + col; - for (jj=0; jj < 3; jj++) - if (jj != c) { - v0 = pix[0][jj]; - v1 = (v0 <= 0.04045 ? v0/12.92 : pow((v0 + 0.055)/1.055,2.4)); - image[ii][jj] = CLIP((int)(65535.0*v1 + 0.5)); } } - free(dimage); - - // Done - t2 = clock(); - dt = ((double)(t2-t1)) / CLOCKS_PER_SEC; -#ifdef DCRAW_VERBOSE - if (verbose) fprintf(stderr,_("\telapsed time = %5.3fs\n"),dt); -#endif -} - -//void CLASS afd_noise_filter_pl() -//{ -// int i,c,row,col; -// int shrinked; -// float mean,std_dev; -// float noise_attenuation; -// ushort value; -// int offset; -// ushort (*img)[4], *lum; -// -// if (half_size) return; -// shrinked=0; -// if (shrink){ -// shrinked=shrink; -// unshrink_image(); -// } -// -// img = (ushort (*)[4]) calloc (height*width, sizeof *img); -// merror(img,"afd_noise_filter_pl"); -// memcpy(img,image,height*width*sizeof *img); -// -// // preinterpolate -// filters_bk=filters; -// 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); -// // interpolate -// afd_interpolate_pl(2,1); -// -// // Get luminance -// lum = (ushort *)calloc(width*height,sizeof *lum); -// for(i=0;i 0.008856 ? pow((double)r,1/3.0) : 7.787*r + 16/116.0; - } - for (i=0; i < 3; i++) - for (j=0; j < colors; j++) - for (xyz_cam[i][j] = k=0; k < 3; k++) - xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i]; - - border_interpolate(6); - buffer = (char *) malloc (26*TS*TS); /* 1664 kB */ - merror (buffer, "ahd_interpolate()"); - rgb = (ushort(*)[TS][TS][3]) buffer; - lab = (short (*)[TS][TS][3])(buffer + 12*TS*TS); - homo = (char (*)[TS][TS]) (buffer + 24*TS*TS); - - for (top=3; top < height-6; top += TS-7) - for (left=3; left < width-6; left += TS-7) { - - /* Interpolate green horizontally and vertically: */ - for (row = top; row < top+TS && row < height-3; row++) { - col = left + (FC(row,left) & 1); - for (c = FC(row,col); col < left+TS && col < width-3; 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) >> 2; - if (val < 0 || val > 65535) { - val = (pix[-3][1] + pix[3][1] + - 18*(2*pix[0][c] - pix[-2][c] - pix[2][c]) + - 63*(pix[-1][1] + pix[1][1]) + 64) >> 7; - if (val < 0 || val > 65535) { - val = (4*(pix[-1][1] + pix[1][1]) + - 2*pix[0][c]-pix[-2][c]-pix[2][c] + 4) >> 3; - if (val < 0 || val > 65535) - val = (pix[-1][1] + pix[1][1] + 1) >> 1; }} - rgb[0][row-top][col-left][1] = val; - val = ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2 - - pix[-2*width][c] - pix[2*width][c] + 2) >> 2; - if (val < 0 || val > 65535) { - val = (pix[-3*width][1] + pix[3*width][1] + - 18*(2*pix[0][c] - pix[-2*width][c] - pix[2*width][c]) + - 63*(pix[-width][1] + pix[width][1]) + 64) >> 7; - if (val < 0 || val > 65535) { - val = (4*(pix[-width][1] + pix[width][1]) + - 2*pix[0][c]-pix[-2*width][c]-pix[2*width][c] + 4) >> 3; - if (val < 0 || val > 65535) - val = (pix[-width][1] + pix[width][1] + 1) >> 1; }} - rgb[1][row-top][col-left][1] = val; - } - } - /* Interpolate red and blue, and convert to CIELab: */ - for (d=0; d < 2; d++) - for (row=top+1; row < top+TS-1 && row < height-4; row++) - for (col=left+1; col < left+TS-1 && col < width-4; 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) >> 1); - if (val < 0 || val > 65535) - val = (pix[-1][2-c] + pix[1][2-c] + 1) >> 1; - rix[0][2-c] = val; - val = pix[0][1] + (( pix[-width][c] + pix[width][c] - - rix[-TS][1] - rix[TS][1] + 1) >> 1); - if (val < 0 || val > 65535) - val = (pix[-width][c] + pix[width][c] + 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] + 2) >> 2); - if (val < 0 || val > 65535) - val = (pix[-width-1][c] + pix[-width+1][c] + - pix[ width-1][c] + pix[ width+1][c] + 2) >> 2; } - rix[0][c] = val; - c = FC(row,col); - rix[0][c] = pix[0][c]; - xyz[0] = xyz[1] = xyz[2] = 0.5; - FORCC { - xyz[0] += xyz_cam[0][c] * rix[0][c]; - xyz[1] += xyz_cam[1][c] * rix[0][c]; - xyz[2] += xyz_cam[2][c] * rix[0][c]; - } - xyz[0] = cbrt[CLIP((int) xyz[0])]; - xyz[1] = cbrt[CLIP((int) xyz[1])]; - xyz[2] = cbrt[CLIP((int) xyz[2])]; - lix[0][0] = 64 * (116 * xyz[1] - 16); - lix[0][1] = 64 * 500 * (xyz[0] - xyz[1]); - lix[0][2] = 64 * 200 * (xyz[1] - xyz[2]); - } - /* Build homogeneity maps from the CIELab images: */ - memset (homo, 0, 2*TS*TS); - for (row=top+2; row < top+TS-2 && row < height-5; row++) { - tr = row-top; - for (col=left+2; col < left+TS-2 && col < width-5; 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-6; row++) { - tr = row-top; - for (col=left+3; col < left+TS-3 && col < width-6; 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) >> 1; - } - } - } - free (buffer); - -} -#undef TS diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL2/ahd_partial_interpolate.c b/core/libs/rawengine/libraw/demosaic-pack-GPL2/ahd_partial_interpolate.c deleted file mode 100644 index e3ee7f8db8..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL2/ahd_partial_interpolate.c +++ /dev/null @@ -1,200 +0,0 @@ -/* This file was taken from modified dcraw published by Paul Lee - on January 23, 2009, taking dcraw ver.8.90/rev.1.417 - as basis. - http://sites.google.com/site/demosaicalgorithms/modified-dcraw - - As modified dcraw source code was published, the release under - GPL Version 2 or later option could be applied, so this file - is taken under this premise. -*/ - -/* - Copyright (C) 2009 Paul Lee - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - - -/* -Adaptive Homogeneity-Directed interpolation is based on -the work of Keigo Hirakawa, Thomas Parks, and Paul Lee. -*/ -#define TS 256 /* Tile Size */ - -void CLASS ahd_partial_interpolate(int threshold_value) -{ - int i, j, k, top, left, row, col, tr, tc, c, d, val, hm[2]; - int h_cnt, v_cnt, indx; - ushort (*pix)[4], (*rix)[3]; - static const int dir[4] = { -1, 1, -TS, TS }; - unsigned ldiff[2][4], abdiff[2][4], leps, abeps; - float r, cbrt[0x10000], xyz[3], xyz_cam[3][4]; - ushort (*rgb)[TS][TS][3]; - short (*lab)[TS][TS][3], (*lix)[3]; - char (*homo)[TS][TS], *buffer; - -#ifdef DCRAW_VERBOSE - if (verbose) fprintf (stderr,_("\tAHD partial interpolation...")); -#endif - h_cnt = v_cnt = 0; - - for (i=0; i < 0x10000; i++) { - r = i / 65535.0; - cbrt[i] = r > 0.008856 ? pow((double)r,1/3.0) : 7.787*r + 16/116.0; - } - for (i=0; i < 3; i++) - for (j=0; j < colors; j++) - for (xyz_cam[i][j] = k=0; k < 3; k++) - xyz_cam[i][j] += xyz_rgb[i][k] * rgb_cam[k][j] / d65_white[i]; - - buffer = (char *) malloc (26*TS*TS); /* 1664 kB */ - merror (buffer, "ahd_interpolate()"); - rgb = (ushort(*)[TS][TS][3]) buffer; - lab = (short (*)[TS][TS][3])(buffer + 12*TS*TS); - homo = (char (*)[TS][TS]) (buffer + 24*TS*TS); - - for (top=3; top < height-6; top += TS-7) - for (left=3; left < width-6; left += TS-7) { - - /* Interpolate green horizontally and vertically: */ - for (row = top; row < top+TS && row < height-3; row++) { - col = left + (FC(row,left) & 1); - for (c = FC(row,col); col < left+TS && col < width-3; 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) >> 2; - if (val < 0 || val > 65535) { - val = (pix[-3][1] + pix[3][1] + - 18*(2*pix[0][c] - pix[-2][c] - pix[2][c]) + - 63*(pix[-1][1] + pix[1][1]) + 64) >> 7; - if (val < 0 || val > 65535) { - val = (4*(pix[-1][1] + pix[1][1]) + - 2*pix[0][c]-pix[-2][c]-pix[2][c] + 4) >> 3; - if (val < 0 || val > 65535) - val = (pix[-1][1] + pix[1][1] + 1) >> 1; }} - rgb[0][row-top][col-left][1] = val; - val = ((pix[-width][1] + pix[0][c] + pix[width][1]) * 2 - - pix[-2*width][c] - pix[2*width][c] + 2) >> 2; - if (val < 0 || val > 65535) { - val = (pix[-3*width][1] + pix[3*width][1] + - 18*(2*pix[0][c] - pix[-2*width][c] - pix[2*width][c]) + - 63*(pix[-width][1] + pix[width][1]) + 64) >> 7; - if (val < 0 || val > 65535) { - val = (4*(pix[-width][1] + pix[width][1]) + - 2*pix[0][c]-pix[-2*width][c]-pix[2*width][c] + 4) >> 3; - if (val < 0 || val > 65535) - val = (pix[-width][1] + pix[width][1] + 1) >> 1; }} - rgb[1][row-top][col-left][1] = val; - } - } - /* Interpolate red and blue, and convert to CIELab: */ - for (d=0; d < 2; d++) - for (row=top+1; row < top+TS-1 && row < height-4; row++) - for (col=left+1; col < left+TS-1 && col < width-4; 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) >> 1); - if (val < 0 || val > 65535) - val = (pix[-1][2-c] + pix[1][2-c] + 1) >> 1; - rix[0][2-c] = val; - val = pix[0][1] + (( pix[-width][c] + pix[width][c] - - rix[-TS][1] - rix[TS][1] + 1) >> 1); - if (val < 0 || val > 65535) - val = (pix[-width][c] + pix[width][c] + 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] + 2) >> 2); - if (val < 0 || val > 65535) - val = (pix[-width-1][c] + pix[-width+1][c] + - pix[ width-1][c] + pix[ width+1][c] + 2) >> 2; } - rix[0][c] = val; - c = FC(row,col); - rix[0][c] = pix[0][c]; - xyz[0] = xyz[1] = xyz[2] = 0.5; - FORCC { - xyz[0] += xyz_cam[0][c] * rix[0][c]; - xyz[1] += xyz_cam[1][c] * rix[0][c]; - xyz[2] += xyz_cam[2][c] * rix[0][c]; - } - xyz[0] = cbrt[CLIP((int) xyz[0])]; - xyz[1] = cbrt[CLIP((int) xyz[1])]; - xyz[2] = cbrt[CLIP((int) xyz[2])]; - lix[0][0] = 64 * (116 * xyz[1] - 16); - lix[0][1] = 64 * 500 * (xyz[0] - xyz[1]); - lix[0][2] = 64 * 200 * (xyz[1] - xyz[2]); - } - /* Build homogeneity maps from the CIELab images: */ - memset (homo, 0, 2*TS*TS); - for (row=top+2; row < top+TS-2 && row < height-5; row++) { - tr = row-top; - for (col=left+2; col < left+TS-2 && col < width-5; 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-6; row++) { - tr = row-top; - for (col=left+3; col < left+TS-3 && col < width-6; col++) { - tc = col-left; - indx = row*width+col; - 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]+threshold_value) <= hm[1]) { - v_cnt++; - FORC3 image[indx][c] = rgb[1][tr][tc][c]; - } - else if ((hm[1]+threshold_value) <= hm[0]) { - h_cnt++; - FORC3 image[indx][c] = rgb[0][tr][tc][c]; - } - } - } - } - free (buffer); -#ifdef DCRAW_VERBOSE - if (verbose) { - fprintf (stderr,_(" H, V = %4.2f, %4.2f (%%)\n"), - 100*(double)h_cnt/(double)(h_cnt+v_cnt), - 100*(double)v_cnt/(double)(h_cnt+v_cnt)); - } -#endif -} -#undef TS - diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL2/dcraw_foveon.c b/core/libs/rawengine/libraw/demosaic-pack-GPL2/dcraw_foveon.c deleted file mode 100644 index fa03759b68..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL2/dcraw_foveon.c +++ /dev/null @@ -1,944 +0,0 @@ -/* - dcraw.c -- Dave Coffin's raw photo decoder - Copyright 1997-2013 by Dave Coffin, dcoffin a cybercom o net - - This is a command-line ANSI C program to convert raw photos from - any digital camera on any computer running any operating system. - - No license is required to download and use dcraw.c. However, - to lawfully redistribute dcraw, you must either (a) offer, at - no extra charge, full source code* for all executable files - containing RESTRICTED functions, (b) distribute this code under - the GPL Version 2 or later, (c) remove all RESTRICTED functions, - re-implement them, or copy them from an earlier, unrestricted - Revision of dcraw.c, or (d) purchase a license from the author. - - The functions that process Foveon images have been RESTRICTED - since Revision 1.237. All other code remains free for all uses. - - *If you have not modified dcraw.c in any way, a link to my - homepage qualifies as "full source code". - - $Revision: 1.456 $ - $Date: 2013/06/16 18:01:08 $ - */ - -#define getbits(n) getbithuff(n,0) - -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 (×tamp)); -#endif - } - fseek (ifp, save, SEEK_SET); - } -} - - -/* 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) { -#ifdef LIBRAW_LIBRARY_BUILD - throw LIBRAW_EXCEPTION_DECODE_RAW; -#else - fprintf (stderr,_("%s: decoder table overflow\n"), ifname); - longjmp (failure, 2); -#endif - } - if (code) - for (i=0; i < size; i++) - if (huff[i] == code) { - cur->leaf = i; - return; - } - if ((len = code >> 27) > 26) return; - code = (len+1) << 27 | (code & 0x3ffffff) << 1; - - cur->branch[0] = free_decode; - foveon_decoder (size, code); - cur->branch[1] = free_decode; - foveon_decoder (size, code+1); -} - -#ifdef LIBRAW_LIBRARY_BUILD -#define T imgdata.thumbnail -#define ID libraw_internal_data.internal_data - -void LibRaw::foveon_thumb_loader (void) -{ - unsigned bwide, row, col, bitbuf=0, bit=1, c, i; - struct decode *dindex; - short pred[3]; - - if(T.thumb) free(T.thumb); - T.thumb = NULL; - - bwide = get4(); - if (bwide > 0) - { - if (bwide < (unsigned)T.twidth*3) return; - T.thumb = (char*)malloc(3*T.twidth * T.theight); - merror (T.thumb, "foveon_thumb()"); - char *buf = (char*)malloc(bwide); - merror (buf, "foveon_thumb()"); - for (row=0; row < T.theight; row++) - { - ID.input->read(buf, 1, bwide); - memmove(T.thumb+(row*T.twidth*3),buf,T.twidth*3); - } - free(buf); - T.tlength = 3*T.twidth * T.theight; - T.tformat = LIBRAW_THUMBNAIL_BITMAP; - return; - } - else - { - foveon_decoder (256, 0); - T.thumb = (char*)malloc(3*T.twidth * T.theight); - char *bufp = T.thumb; - merror (T.thumb, "foveon_thumb()"); - for (row=0; row < T.theight; row++) - { - memset (pred, 0, sizeof pred); - if (!bit) get4(); - for (bit=col=0; col < T.twidth; col++) - for(c=0;c<3;c++) - { - for (dindex=first_decode; dindex->branch[0]; ) - { - if ((bit = (bit-1) & 31) == 31) - for (i=0; i < 4; i++) - bitbuf = (bitbuf << 8) + ID.input->get_char(); - dindex = dindex->branch[bitbuf >> bit & 1]; - } - pred[c] += dindex->leaf; - (*bufp++)=pred[c]; - } - } - T.tformat = LIBRAW_THUMBNAIL_BITMAP; - T.tlength = 3*T.twidth * T.theight; - } - return; -} -#endif - -void CLASS foveon_thumb() -{ - unsigned bwide, row, col, bitbuf=0, bit=1, c, i; - char *buf; - struct decode *dindex; - short pred[3]; - - bwide = get4(); - fprintf (ofp, "P6\n%d %d\n255\n", thumb_width, thumb_height); - if (bwide > 0) { - if (bwide < thumb_width*3) return; - buf = (char *) malloc (bwide); - merror (buf, "foveon_thumb()"); - for (row=0; row < thumb_height; row++) { - fread (buf, 1, bwide, ifp); - fwrite (buf, 3, thumb_width, ofp); - } - free (buf); - return; - } - foveon_decoder (256, 0); - - for (row=0; row < thumb_height; row++) { - memset (pred, 0, sizeof pred); - if (!bit) get4(); - for (bit=col=0; col < thumb_width; col++) - FORC3 { - for (dindex=first_decode; dindex->branch[0]; ) { - if ((bit = (bit-1) & 31) == 31) - for (i=0; i < 4; i++) - bitbuf = (bitbuf << 8) + fgetc(ifp); - dindex = dindex->branch[bitbuf >> bit & 1]; - } - pred[c] += dindex->leaf; - fputc (pred[c], ofp); - } - } -} - -void CLASS foveon_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++) { -#ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); -#endif - 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[1024], 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++) { -#ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); -#endif - 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[1024], 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) { -#ifdef LIBRAW_LIBRARY_BUILD - if(wide>32767 || high > 32767 || wide*high > 20000000) - { - throw LIBRAW_EXCEPTION_IO_CORRUPT; - } -#endif - 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 *t_curve; - unsigned i, size; - double x; - - if (!filt) filt = 0.8; - size = 4*M_PI*max / filt; - if (size == UINT_MAX) size--; - t_curve = (short *) calloc (size+1, sizeof *t_curve); - merror (t_curve, "foveon_make_curve()"); - t_curve[0] = size; - for (i=0; i < size; i++) { - x = i*filt/max/4; - t_curve[i+1] = (cos(x)+1)/2 * tanh(i*filt/mul) * mul + 0.5; - } - return t_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 *t_curve, int i) -{ - if (abs(i) >= t_curve[0]) return 0; - return i < 0 ? -t_curve[1-i] : t_curve[1+i]; -} - -#ifdef LIBRAW_LIBRARY_BUILD -#ifdef image -#undef image -#endif -#define image ((short(*)[4]) imgdata.image) -#else -#define image ((short (*)[4]) image) -#endif - -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], *t_curve[8], (*t_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 (*t_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 (t_curve, color_dq, div, cfilt); - FORC3 chroma_dq[c] /= 3; - foveon_make_curves (t_curve+3, chroma_dq, div, cfilt); - FORC3 dsum += chroma_dq[c] / div[c]; - t_curve[6] = foveon_make_curve (dsum, dsum, cfilt); - t_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); - - t_black = (float (*)[3]) calloc (height, sizeof *t_black); - for (row=0; row < height; row++) { - for (i=0; i < 6; i++) - ddft[0][0][i] = ddft[1][0][i] + - row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]); - FORC3 t_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 (t_black, t_black+8, sizeof *t_black*8); - memcpy (t_black+height-11, t_black+height-22, 11*sizeof *t_black); - memcpy (last, t_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]) - t_black[row][c] = (last[0][c] > last[2][c]) ? last[0][c]:last[2][c]; - } else - if (last[1][c] < last[2][c]) - t_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], t_black[row+1], sizeof last[2]); - } - FORC3 t_black[row][c] = (last[0][c] + last[1][c])/2; - FORC3 t_black[0][c] = (t_black[1][c] + t_black[3][c])/2; - - val = 1 - exp(-1/24.0); - memcpy (fsum, t_black, sizeof fsum); - for (row=1; row < height; row++) - FORC3 fsum[c] += t_black[row][c] = - (t_black[row][c] - t_black[row-1][c])*val + t_black[row-1][c]; - memcpy (last[0], t_black[height-1], sizeof last[0]); - FORC3 fsum[c] /= height; - for (row = height; row--; ) - FORC3 last[0][c] = t_black[row][c] = - (t_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 t_black[row][c] += fsum[c]/2 + total[c]/(total[3]*100.0); - - for (row=0; row < height; row++) { - for (i=0; i < 6; i++) - ddft[0][0][i] = ddft[1][0][i] + - row / (height-1.0) * (ddft[2][0][i] - ddft[1][0][i]); - pix = image[row*width]; - memcpy (prev, pix, sizeof prev); - frow = row / (height-1.0) * (dim[2]-1); - if ((irow = frow) == dim[2]-1) irow--; - frow -= irow; - for (i=0; i < dim[1]; i++) - FORC3 sgrow[i][c] = sgain[ irow *dim[1]+i][c] * (1-frow) + - sgain[(irow+1)*dim[1]+i][c] * frow; - for (col=0; col < width; col++) { - FORC3 { - diff = pix[c] - prev[c]; - prev[c] = pix[c]; - ipix[c] = pix[c] + floor ((diff + (diff*diff >> 14)) * cfilt - - ddft[0][c][1] - ddft[0][c][0] * ((float) col/width - 0.5) - - t_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 (t_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 (t_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 (t_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 (t_curve[c], pix[c]); - sum = (pix[0]+pix[1]+pix[1]+pix[2]) >> 2; - FORC3 pix[c] -= foveon_apply_curve (t_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 */ - t_shrink = (short (*)[3]) calloc ((width/4) * (height/4), sizeof *t_shrink); - merror (t_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) - t_shrink[row*(width/4)+col][c] = ipix[c] >> 4; - else - t_shrink[row*(width/4)+col][c] = - (t_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] = - (t_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 (t_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 (t_shrink); - free (smrow[6]); - for (i=0; i < 8; i++) - free (t_curve[i]); - - /* Trim off the black border */ - if (~cropbox[2] && ~cropbox[3]) - { - // Image already cropped, do nothing - int crop[4],c; - for(int c=0;c<4;c++) - { - crop[c] = cropbox[c]; - if(crop[c]<0) - crop[c]=0; - } - if(crop[0]>=width-1) crop[0] = width - 2; - if(crop[1]>=height-1) crop[1] = height-2; - if(crop[0]+crop[2] >= width) crop[2] = width-crop[0]; - if(crop[1]+crop[3] >= height) crop[3] = height-crop[1]; - active[0] = crop[0]; - active[1] = crop[1]; - active[2] = crop[0]+crop[2]; - active[3] = crop[1]+crop[3]; - } - else - { - 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 -#ifdef LIBRAW_LIBRARY_BUILD -#define image (imgdata.image) -#endif - -/* RESTRICTED code ends here */ - diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL2/es_median_filter.c b/core/libs/rawengine/libraw/demosaic-pack-GPL2/es_median_filter.c deleted file mode 100644 index ab124600a9..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL2/es_median_filter.c +++ /dev/null @@ -1,299 +0,0 @@ -/* This file was taken from modified dcraw published by Paul Lee - on January 23, 2009, taking dcraw ver.8.90/rev.1.417 - as basis. - http://sites.google.com/site/demosaicalgorithms/modified-dcraw - - As modified dcraw source code was published, the release under - GPL Version 2 or later option could be applied, so this file - is taken under this premise. -*/ - -/* - Copyright (C) 2009 Paul Lee - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - - -/* - Refinement process on demosaiced image with - edge-sensitive median filter and pattern recognition based update - Reference: Hybrid color filter array demosaicking for effective - artifact suppression, L. Chang and Y-P Tan, Journal of Electronic - Imaging 15(1) 013003 (Jan-Mar 2006) - -*/ -#define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} } -void CLASS es_median_filter() -{ - ushort (*pix)[4]; - int (*mf)[3], (*pc)[3], p[25], indx, row, col, c, d, temp, i, j; - int v0, v1, v2, edge_cnt, smooth_cnt, w1, w2; - int dC0, dC1, dC2, dC3, dC4, pass; - int p00, p01, p02, p03, p04, p05, p06, p07, p08, p09, - p15, p16, p17, p18, p19, p20, p21, p22, p23, p24; - double EA, T=1280; - w1 = width; - w2 = 2*w1; - p00 = -w2-2; p01 = -w2-1; p02 = -w2 ; p03 = -w2+1; p04 = -w2+2; - p05 = -w1-2; p06 = -w1-1; p07 = -w1 ; p08 = -w1+1; p09 = -w1+2; - p15 = w1-2; p16 = w1-1; p17 = w1 ; p18 = w1+1; p19 = w1+2; - p20 = w2-2; p21 = w2-1; p22 = w2 ; p23 = w2+1; p24 = w2+2; - /* Allocate buffer for 3x3 median filter */ - mf = (int (*)[3])calloc(width*height, sizeof *mf); - for (pass=1; pass <= es_med_passes; pass++) { -#ifdef DCRAW_VERBOSE - if (verbose) - fprintf (stderr,_("Edge-sensitive median filter pass %d...\n"), pass); -#endif - for (c=0; c < 3; c+=2) { -#ifdef DCRAW_VERBOSE - if (verbose) { - if (c == 0) - fprintf (stderr,_("\tR-G: 5x5 median filter + 3x3 Laplacian...")); - else - fprintf (stderr,_("\tB-G: 5x5 median filter + 3x3 Laplacian...")); } -#endif - /* Compute differential color plane */ - for (indx=0; indx < height*width; indx++) - mf[indx][c] = image[indx][c] - image[indx][1]; - /* Apply 3x3 median fileter */ -/* for (row=1; row < height-1; row++) */ -/* for (col=1; col < width-1; col++) { */ -/* pc = mf + row*width+col; */ -/* /\* Assign 3x3 differential color values *\/ */ -/* p[0] = pc[p06][c]; p[1] = pc[p07][c]; p[2] = pc[p08][c]; */ -/* p[3] = pc[ -1][c]; p[4] = pc[ 0][c]; p[5] = pc[ 1][c]; */ -/* p[6] = pc[p16][c]; p[7] = pc[p17][c]; p[8] = pc[p18][c]; */ -/* /\* Sort for median of 9 values *\/ */ -/* PIX_SORT(p[1],p[2]); PIX_SORT(p[4], p[5]); PIX_SORT(p[7],p[8]); */ -/* PIX_SORT(p[0],p[1]); PIX_SORT(p[3], p[4]); PIX_SORT(p[6],p[7]); */ -/* PIX_SORT(p[1],p[2]); PIX_SORT(p[4], p[5]); PIX_SORT(p[7],p[8]); */ -/* PIX_SORT(p[0],p[3]); PIX_SORT(p[5], p[8]); PIX_SORT(p[4],p[7]); */ -/* PIX_SORT(p[3],p[6]); PIX_SORT(p[1], p[4]); PIX_SORT(p[2],p[5]); */ -/* PIX_SORT(p[4],p[7]); PIX_SORT(p[4], p[2]); PIX_SORT(p[6],p[4]); */ -/* PIX_SORT(p[4],p[2]); */ -/* pc[0][1] = p[4]; */ -/* } */ - /* Apply 5x5 median fileter */ -#ifdef LIBRAW_USE_OPENMP -#pragma omp parallel for private(row,col,pc,p) -#endif - for (row=2; row < height-2; row++) - for (col=2; col < width-2; col++) { - pc = mf + row*width+col; - /* Assign 5x5 differential color values */ - p[ 0] = pc[p00][c]; p[ 1] = pc[p01][c]; p[ 2] = pc[p02][c]; - p[ 3] = pc[p03][c]; p[ 4] = pc[p04][c]; p[ 5] = pc[p05][c]; - p[ 6] = pc[p06][c]; p[ 7] = pc[p07][c]; p[ 8] = pc[p08][c]; - p[ 9] = pc[p09][c]; p[10] = pc[ -2][c]; p[11] = pc[ -1][c]; - p[12] = pc[ 0][c]; p[13] = pc[ 1][c]; p[14] = pc[ 2][c]; - p[15] = pc[p15][c]; p[16] = pc[p16][c]; p[17] = pc[p17][c]; - p[18] = pc[p18][c]; p[19] = pc[p19][c]; p[20] = pc[p20][c]; - p[21] = pc[p21][c]; p[22] = pc[p22][c]; p[23] = pc[p23][c]; - p[24] = pc[p24][c]; - /* Sort for median of 25 values */ - PIX_SORT(p[ 0],p[ 1]); PIX_SORT(p[ 3],p[ 4]); PIX_SORT(p[ 2],p[ 4]); - PIX_SORT(p[ 2],p[ 3]); PIX_SORT(p[ 6],p[ 7]); PIX_SORT(p[ 5],p[ 7]); - PIX_SORT(p[ 5],p[ 6]); PIX_SORT(p[ 9],p[10]); PIX_SORT(p[ 8],p[10]); - PIX_SORT(p[ 8],p[ 9]); PIX_SORT(p[12],p[13]); PIX_SORT(p[11],p[13]); - PIX_SORT(p[11],p[12]); PIX_SORT(p[15],p[16]); PIX_SORT(p[14],p[16]); - PIX_SORT(p[14],p[15]); PIX_SORT(p[18],p[19]); PIX_SORT(p[17],p[19]); - PIX_SORT(p[17],p[18]); PIX_SORT(p[21],p[22]); PIX_SORT(p[20],p[22]); - PIX_SORT(p[20],p[21]); PIX_SORT(p[23],p[24]); PIX_SORT(p[ 2],p[ 5]); - PIX_SORT(p[ 3],p[ 6]); PIX_SORT(p[ 0],p[ 6]); PIX_SORT(p[ 0],p[ 3]); - PIX_SORT(p[ 4],p[ 7]); PIX_SORT(p[ 1],p[ 7]); PIX_SORT(p[ 1],p[ 4]); - PIX_SORT(p[11],p[14]); PIX_SORT(p[ 8],p[14]); PIX_SORT(p[ 8],p[11]); - PIX_SORT(p[12],p[15]); PIX_SORT(p[ 9],p[15]); PIX_SORT(p[ 9],p[12]); - PIX_SORT(p[13],p[16]); PIX_SORT(p[10],p[16]); PIX_SORT(p[10],p[13]); - PIX_SORT(p[20],p[23]); PIX_SORT(p[17],p[23]); PIX_SORT(p[17],p[20]); - PIX_SORT(p[21],p[24]); PIX_SORT(p[18],p[24]); PIX_SORT(p[18],p[21]); - PIX_SORT(p[19],p[22]); PIX_SORT(p[ 8],p[17]); PIX_SORT(p[ 9],p[18]); - PIX_SORT(p[ 0],p[18]); PIX_SORT(p[ 0],p[ 9]); PIX_SORT(p[10],p[19]); - PIX_SORT(p[ 1],p[19]); PIX_SORT(p[ 1],p[10]); PIX_SORT(p[11],p[20]); - PIX_SORT(p[ 2],p[20]); PIX_SORT(p[ 2],p[11]); PIX_SORT(p[12],p[21]); - PIX_SORT(p[ 3],p[21]); PIX_SORT(p[ 3],p[12]); PIX_SORT(p[13],p[22]); - PIX_SORT(p[ 4],p[22]); PIX_SORT(p[ 4],p[13]); PIX_SORT(p[14],p[23]); - PIX_SORT(p[ 5],p[23]); PIX_SORT(p[ 5],p[14]); PIX_SORT(p[15],p[24]); - PIX_SORT(p[ 6],p[24]); PIX_SORT(p[ 6],p[15]); PIX_SORT(p[ 7],p[16]); - PIX_SORT(p[ 7],p[19]); PIX_SORT(p[13],p[21]); PIX_SORT(p[15],p[23]); - PIX_SORT(p[ 7],p[13]); PIX_SORT(p[ 7],p[15]); PIX_SORT(p[ 1],p[ 9]); - PIX_SORT(p[ 3],p[11]); PIX_SORT(p[ 5],p[17]); PIX_SORT(p[11],p[17]); - PIX_SORT(p[ 9],p[17]); PIX_SORT(p[ 4],p[10]); PIX_SORT(p[ 6],p[12]); - PIX_SORT(p[ 7],p[14]); PIX_SORT(p[ 4],p[ 6]); PIX_SORT(p[ 4],p[ 7]); - PIX_SORT(p[12],p[14]); PIX_SORT(p[10],p[14]); PIX_SORT(p[ 6],p[ 7]); - PIX_SORT(p[10],p[12]); PIX_SORT(p[ 6],p[10]); PIX_SORT(p[ 6],p[17]); - PIX_SORT(p[12],p[17]); PIX_SORT(p[ 7],p[17]); PIX_SORT(p[ 7],p[10]); - PIX_SORT(p[12],p[18]); PIX_SORT(p[ 7],p[12]); PIX_SORT(p[10],p[18]); - PIX_SORT(p[12],p[20]); PIX_SORT(p[10],p[20]); PIX_SORT(p[10],p[12]); - pc[0][1] = p[12]; - } - /* Apply 3x3 Laplacian fileter */ - edge_cnt = smooth_cnt = 0; - for (row=1; row < height-1; row++) - for (col=1; col < width-1; col++) { - pc = mf + row*width+col; - EA = 0.8182*(pc[-w1][1]+pc[-1][1]+pc[1][1]+pc[w1][1])-3.6364*pc[0][1]+ - 0.0909*(pc[-w1-1][1]+pc[-w1+1][1]+pc[w1-1][1]+pc[w1+1][1]); - if (EA > T || EA < -T) { - pc[0][c] = -9999999; - edge_cnt++; } - else { - pc[0][c] = pc[0][1]; - smooth_cnt++; } - } -#ifdef DCRAW_VERBOSE - if (verbose) - fprintf (stderr,_(" edge = %5.2f (%%)\n"), - 100.*(double)(edge_cnt)/(double)(edge_cnt+smooth_cnt)); -#endif - } - /* Make sure we don't mess up with edges */ - for (row=1; row < height-1; row++) - for (col=1; col < width-1; col++) { - pc = mf + row*width+col; - if (pc[0][0] == -9999999 || pc[0][2] == -9999999) - pc[0][0] = pc[0][2] = -9999999; - } - /* Now median(R-G) and median(B-G) are computed */ - /* red/blue at GREEN pixel locations */ - for (row=1; row < height-1; row++) - for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) { - indx = row*width+col; - for (i=0; i < 2; c=2-c, i++) - if (mf[indx][c] != -9999999) { - v0 = image[indx][1]+mf[indx][c]; - image[indx][c] = CLIP(v0); } - } - /* red/blue at BLUE/RED pixel locations */ - for (row=2; row < height-2; row++) - for (col=2+(FC(row,2) & 1), c=2-FC(row,col); col < width-2; col+=2) { - indx = row*width+col; - if (mf[indx][c] != -9999999) { - v0 = image[indx][1]+mf[indx][c]; - image[indx][c] = CLIP(v0); } - } - /* green at RED/BLUE location */ - for (row=1; row < height-1; row++) - for (col=1+(FC(row,1) & 1), c=FC(row,col); col < width-3; col+=2) { - indx = row*width+col; - d = 2 - c; - if (mf[indx][c] != -9999999) { - if (mf[indx][d] != -9999999) - v0 = (image[indx][c]-mf[indx][c]+image[indx][d]-mf[indx][d]+1) >> 1; - else - v0 = (image[indx][c]-mf[indx][c]+image[indx][1]+1) >> 1; } - else { - if (mf[indx][d] != -9999999) - v0 = (image[indx][d]-mf[indx][d]+image[indx][1]+1) >> 1; - else - v0 = image[indx][1]; } - image[indx][1] = CLIP(v0); - } - /* Update interpolated pixels after differential median filter */ -#ifdef DCRAW_VERBOSE - if (verbose) fprintf (stderr,_("\tUpdate R,G,B...")); -#endif - /* Update red & blue at GREEN by averaging color differential values */ - for (row=1; row < height-1; row++) - for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) { - indx = row*width+col; - pix = image + indx; - if (mf[indx][c] != -9999999) { - v0 = (pix[-1][c]+pix[1][c]+2*pix[0][1]-pix[-1][1]-pix[1][1]+1) >> 1; - pix[0][c] = CLIP(v0); } - c = 2 - c; - if (mf[indx][c] != -9999999) { - v0 = (pix[-w1][c]+pix[w1][c]+2*pix[0][1]-pix[-w1][1]-pix[w1][1]+1) >> 1; - pix[0][c] = CLIP(v0); } - c = 2 - c; - } - /* Update red/blue at BLUE/RED pixels by pattern recognition */ - for (row=1; row < height-1; row++) - for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < width-1; col+=2) { - indx = row*width+col; - if (mf[indx][c] != -9999999) { - pix = image + indx; - dC1 = pix[-w1-1][1]-pix[-w1-1][c]; - dC2 = pix[-w1+1][1]-pix[-w1+1][c]; - dC3 = pix[ w1-1][1]-pix[ w1-1][c]; - dC4 = pix[ w1+1][1]-pix[ w1+1][c]; - dC0 = dC1 + dC2 + dC3 + dC4; - dC1 <<= 2; - dC2 <<= 2; - dC3 <<= 2; - dC4 <<= 2; - j = (dC1 > dC0) + (dC2 > dC0) + (dC3 > dC0) + (dC4 > dC0); - if (j == 3 || j == 1) { - /* edge-corner pattern: median of color differential values */ - PIX_SORT(dC1,dC2); - PIX_SORT(dC3,dC4); - PIX_SORT(dC1,dC3); - PIX_SORT(dC2,dC4); - dC0 = dC2 + dC3; } - else { - /* stripe pattern: average along diagonal */ - v1 = ABS(pix[-w1-1][c]-pix[w1+1][c]); - v2 = ABS(pix[-w1+1][c]-pix[w1-1][c]); - if (v1 < v2) - dC0 = dC1 + dC4; - else - dC0 = dC2 + dC3; } - v0 = (((int)(pix[0][1]) << 3) - dC0 + 4) >> 3; - pix[0][c] = CLIP(v0); } - } - /* Update green at RED/BLUE pixels by pattern recognition */ - for (row=1; row < height-1; row++) - for (col=1+(FC(row,1) & 1), c=FC(row,col); col < width-1; col+=2) { - indx = row*width+col; - if (mf[indx][c] != -9999999) { - pix = image + indx; - dC1 = pix[-w1][c]-pix[-w1][1]; - dC2 = pix[ -1][c]-pix[ -1][1]; - dC3 = pix[ 1][c]-pix[ 1][1]; - dC4 = pix[ w1][c]-pix[ w1][1]; - dC0 = dC1 + dC2 + dC3 + dC4; - dC1 <<= 2; - dC2 <<= 2; - dC3 <<= 2; - dC4 <<= 2; - j = (dC1 > dC0) + (dC2 > dC0) + (dC3 > dC0) + (dC4 > dC0); - if (j == 3 || j == 1) { - /* edge-corner pattern: median of color differential values */ - PIX_SORT(dC1,dC2); - PIX_SORT(dC3,dC4); - PIX_SORT(dC1,dC3); - PIX_SORT(dC2,dC4); - dC0 = dC2 + dC3; } - else { - /* stripe pattern: average along diagonal */ - v1 = ABS(pix[-w1][1]-pix[w1][1]); - v2 = ABS(pix[ -1][1]-pix[ 1][1]); - if (v1 < v2) - dC0 = dC1 + dC4; - else - dC0 = dC2 + dC3; } - v0 = (((int)(pix[0][c]) << 3) - dC0 + 4) >> 3; - pix[0][1] = CLIP(v0); - } - } -#ifdef DCRAW_VERBOSE - if (verbose) fprintf (stderr,_("\n")); -#endif - } - /* Free buffer */ - free(mf); -} -#undef PIX_SORT diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL2/lmmse_interpolate.c b/core/libs/rawengine/libraw/demosaic-pack-GPL2/lmmse_interpolate.c deleted file mode 100644 index d6fe4b968f..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL2/lmmse_interpolate.c +++ /dev/null @@ -1,278 +0,0 @@ -/* This file was taken from PerfectRaw ver. 0.65 published - in 2010, taking dcraw ver.8.88/rev.1.405 - as basis. - http://dl.dropbox.com/u/602348/perfectRAW%200.65%20source%20code.zip - - As PerfectRaw source code was published, the release under - GPL Version 2 or later option could be applied, so this file - is taken under this premise. -*/ - -// LSMME demosaicing algorithm -// L. Zhang and X. Wu, -// Color demosaicking via directional linear minimum mean square-error -// estimation, IEEE Trans. on Image Processing, vol. 14, pp. 2167-2178, -// Dec. 2005. -#define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} } -void CLASS lmmse_interpolate(int gamma_apply) -{ - ushort (*pix)[4]; - int row, col, c, d, w1, w2, w3, w4, ii, ba, rr1, cc1, rr, cc, pass; - float h0, h1, h2, h3, h4, hs; - float p1, p2, p3, p4, p5, p6, p7, p8, p9, temp; - float Y, v0, mu, vx, vn, xh, vh, xv, vv; - float (*rix)[6], (*qix)[6]; - float (*glut); - char *buffer; - clock_t t1, t2; - double dt; -#ifdef DCRAW_VERBOSE - if (verbose) fprintf(stderr,_("LMMSE interpolation...\n")); -#endif - t1 = clock(); - // allocate work with boundary - ba = 10; - rr1 = height + 2*ba; - cc1 = width + 2*ba; - if (gamma_apply) - buffer = (char *)calloc(rr1*cc1*6*sizeof(float)+65536*sizeof(float),1); - else - buffer = (char *)calloc(rr1*cc1*6*sizeof(float),1); - merror(buffer,"lmmse_interpolate()"); - qix = (float (*)[6])buffer; - if (gamma_apply) { - glut = (float *)(buffer + rr1*cc1*24); - for (ii=0; ii < 65536; ii++) { - v0 = (float)ii / 65535.0; - if (v0 <= 0.0031308) - glut[ii] = v0*12.92; - else - glut[ii] = 1.055*pow((double)v0,1./2.4) - 0.055; } } - // indices - w1 = cc1; - w2 = 2*w1; - w3 = 3*w1; - w4 = 4*w1; - // define low pass filter (sigma=2, L=4) - h0 = 1.0; - h1 = exp( -1.0/8.0); - h2 = exp( -4.0/8.0); - h3 = exp( -9.0/8.0); - h4 = exp(-16.0/8.0); - hs = h0 + 2.0*(h1 + h2 + h3 + h4); - h0 /= hs; - h1 /= hs; - h2 /= hs; - h3 /= hs; - h4 /= hs; - // copy CFA values - for (rr=0; rr < rr1; rr++) - for (cc=0, row=rr-ba; cc < cc1; cc++) { - col = cc - ba; - rix = qix + rr*cc1 + cc; - if ((row >= 0) & (row < height) & (col >= 0) & (col < width)) - if (gamma_apply) - rix[0][4] = glut[image[row*width+col][FC(row,col)]]; - else - rix[0][4] = (double)image[row*width+col][FC(row,col)]/65535.0; - else - rix[0][4] = 0; } - // G-R(B) - for (rr=2; rr < rr1-2; rr++) { - // G-R(B) at R(B) location - for (cc=2+(FC(rr,2)&1); cc < cc1-2; cc+=2) { - rix = qix + rr*cc1 + cc; - // v0 = 0.25R + 0.25B, Y = 0.25R + 0.5B + 0.25B - v0 = 0.0625*(rix[-w1-1][4]+rix[-w1+1][4]+rix[w1-1][4]+rix[w1+1][4]) + - 0.25*rix[0][4]; - // horizontal - rix[0][0] = -0.25*(rix[ -2][4] + rix[ 2][4]) - + 0.5*(rix[ -1][4] + rix[0][4] + rix[ 1][4]); - Y = v0 + 0.5*rix[0][0]; - if (rix[0][4] > 1.75*Y) - rix[0][0] = ULIM(rix[0][0],rix[ -1][4],rix[ 1][4]); - else - rix[0][0] = LIM(rix[0][0],0.0,1.0); - rix[0][0] -= rix[0][4]; - // vertical - rix[0][1] = -0.25*(rix[-w2][4] + rix[w2][4]) - + 0.5*(rix[-w1][4] + rix[0][4] + rix[w1][4]); - Y = v0 + 0.5*rix[0][1]; - if (rix[0][4] > 1.75*Y) - rix[0][1] = ULIM(rix[0][1],rix[-w1][4],rix[w1][4]); - else - rix[0][1] = LIM(rix[0][1],0.0,1.0); - rix[0][1] -= rix[0][4]; } - // G-R(B) at G location - for (cc=2+(FC(rr,3)&1); cc < cc1-2; cc+=2) { - rix = qix + rr*cc1 + cc; - rix[0][0] = 0.25*(rix[ -2][4] + rix[ 2][4]) - - 0.5*(rix[ -1][4] + rix[0][4] + rix[ 1][4]); - rix[0][1] = 0.25*(rix[-w2][4] + rix[w2][4]) - - 0.5*(rix[-w1][4] + rix[0][4] + rix[w1][4]); - rix[0][0] = LIM(rix[0][0],-1.0,0.0) + rix[0][4]; - rix[0][1] = LIM(rix[0][1],-1.0,0.0) + rix[0][4]; - } } - // apply low pass filter on differential colors - for (rr=4; rr < rr1-4; rr++) - for (cc=4; cc < cc1-4; cc++) { - rix = qix + rr*cc1 + cc; - rix[0][2] = h0*rix[0][0] + - h1*(rix[ -1][0] + rix[ 1][0]) + h2*(rix[ -2][0] + rix[ 2][0]) + - h3*(rix[ -3][0] + rix[ 3][0]) + h4*(rix[ -4][0] + rix[ 4][0]); - rix[0][3] = h0*rix[0][1] + - h1*(rix[-w1][1] + rix[w1][1]) + h2*(rix[-w2][1] + rix[w2][1]) + - h3*(rix[-w3][1] + rix[w3][1]) + h4*(rix[-w4][1] + rix[w4][1]); } - // interpolate G-R(B) at R(B) - for (rr=4; rr < rr1-4; rr++) - for (cc=4+(FC(rr,4)&1); cc < cc1-4; cc+=2) { - rix = qix + rr*cc1 + cc; - // horizontal - mu = (rix[-4][2] + rix[-3][2] + rix[-2][2] + rix[-1][2] + rix[0][2]+ - rix[ 1][2] + rix[ 2][2] + rix[ 3][2] + rix[ 4][2]) / 9.0; - p1 = rix[-4][2] - mu; - p2 = rix[-3][2] - mu; - p3 = rix[-2][2] - mu; - p4 = rix[-1][2] - mu; - p5 = rix[ 0][2] - mu; - p6 = rix[ 1][2] - mu; - p7 = rix[ 2][2] - mu; - p8 = rix[ 3][2] - mu; - p9 = rix[ 4][2] - mu; - vx = 1e-7+p1*p1+p2*p2+p3*p3+p4*p4+p5*p5+p6*p6+p7*p7+p8*p8+p9*p9; - p1 = rix[-4][0] - rix[-4][2]; - p2 = rix[-3][0] - rix[-3][2]; - p3 = rix[-2][0] - rix[-2][2]; - p4 = rix[-1][0] - rix[-1][2]; - p5 = rix[ 0][0] - rix[ 0][2]; - p6 = rix[ 1][0] - rix[ 1][2]; - p7 = rix[ 2][0] - rix[ 2][2]; - p8 = rix[ 3][0] - rix[ 3][2]; - p9 = rix[ 4][0] - rix[ 4][2]; - vn = 1e-7+p1*p1+p2*p2+p3*p3+p4*p4+p5*p5+p6*p6+p7*p7+p8*p8+p9*p9; - xh = (rix[0][0]*vx + rix[0][2]*vn)/(vx + vn); - vh = vx*vn/(vx + vn); - // vertical - mu = (rix[-w4][3] + rix[-w3][3] + rix[-w2][3] + rix[-w1][3] + rix[0][3]+ - rix[ w1][3] + rix[ w2][3] + rix[ w3][3] + rix[ w4][3]) / 9.0; - p1 = rix[-w4][3] - mu; - p2 = rix[-w3][3] - mu; - p3 = rix[-w2][3] - mu; - p4 = rix[-w1][3] - mu; - p5 = rix[ 0][3] - mu; - p6 = rix[ w1][3] - mu; - p7 = rix[ w2][3] - mu; - p8 = rix[ w3][3] - mu; - p9 = rix[ w4][3] - mu; - vx = 1e-7+p1*p1+p2*p2+p3*p3+p4*p4+p5*p5+p6*p6+p7*p7+p8*p8+p9*p9; - p1 = rix[-w4][1] - rix[-w4][3]; - p2 = rix[-w3][1] - rix[-w3][3]; - p3 = rix[-w2][1] - rix[-w2][3]; - p4 = rix[-w1][1] - rix[-w1][3]; - p5 = rix[ 0][1] - rix[ 0][3]; - p6 = rix[ w1][1] - rix[ w1][3]; - p7 = rix[ w2][1] - rix[ w2][3]; - p8 = rix[ w3][1] - rix[ w3][3]; - p9 = rix[ w4][1] - rix[ w4][3]; - vn = 1e-7+p1*p1+p2*p2+p3*p3+p4*p4+p5*p5+p6*p6+p7*p7+p8*p8+p9*p9; - xv = (rix[0][1]*vx + rix[0][3]*vn)/(vx + vn); - vv = vx*vn/(vx + vn); - // interpolated G-R(B) - rix[0][4] = (xh*vv + xv*vh)/(vh + vv); } - // copy CFA values - for (rr=0; rr < rr1; rr++) - for (cc=0, row=rr-ba; cc < cc1; cc++) { - col=cc-ba; - rix = qix + rr*cc1 + cc; - c = FC(rr,cc); - if ((row >= 0) & (row < height) & (col >= 0) & (col < width)) - if (gamma_apply) - rix[0][c] = glut[image[row*width+col][c]]; - else - rix[0][c] = (double)image[row*width+col][c]/65535.0; - else - rix[0][c] = 0; - if (c != 1) rix[0][1] = rix[0][c] + rix[0][4]; } - // bilinear interpolation for R/B - // interpolate R/B at G location - for (rr=1; rr < rr1-1; rr++) - for (cc=1+(FC(rr,2)&1), c=FC(rr,cc+1); cc < cc1-1; cc+=2) { - rix = qix + rr*cc1 + cc; - rix[0][c] = rix[0][1] - + 0.5*(rix[ -1][c] - rix[ -1][1] + rix[ 1][c] - rix[ 1][1]); - c = 2 - c; - rix[0][c] = rix[0][1] - + 0.5*(rix[-w1][c] - rix[-w1][1] + rix[w1][c] - rix[w1][1]); - c = 2 - c; } - // interpolate R/B at B/R location - for (rr=1; rr < rr1-1; rr++) - for (cc=1+(FC(rr,1)&1), c=2-FC(rr,cc); cc < cc1-1; cc+=2) { - rix = qix + rr*cc1 + cc; - rix[0][c] = rix[0][1] - + 0.25*(rix[-w1][c] - rix[-w1][1] + rix[ -1][c] - rix[ -1][1]+ - rix[ 1][c] - rix[ 1][1] + rix[ w1][c] - rix[ w1][1]); } - // median filter - for (pass=1; pass <= 3; pass++) { - for (c=0; c < 3; c+=2) { - // Compute median(R-G) and median(B-G) - d = c + 3; - for (ii=0; ii < rr1*cc1; ii++) qix[ii][d] = qix[ii][c] - qix[ii][1]; - // Apply 3x3 median fileter - for (rr=1; rr < rr1-1; rr++) - for (cc=1; cc < cc1-1; cc++) { - rix = qix + rr*cc1 + cc; - // Assign 3x3 differential color values - p1 = rix[-w1-1][d]; p2 = rix[-w1][d]; p3 = rix[-w1+1][d]; - p4 = rix[ -1][d]; p5 = rix[ 0][d]; p6 = rix[ 1][d]; - p7 = rix[ w1-1][d]; p8 = rix[ w1][d]; p9 = rix[ w1+1][d]; - // Sort for median of 9 values - PIX_SORT(p2,p3); PIX_SORT(p5,p6); PIX_SORT(p8,p9); - PIX_SORT(p1,p2); PIX_SORT(p4,p5); PIX_SORT(p7,p8); - PIX_SORT(p2,p3); PIX_SORT(p5,p6); PIX_SORT(p8,p9); - PIX_SORT(p1,p4); PIX_SORT(p6,p9); PIX_SORT(p5,p8); - PIX_SORT(p4,p7); PIX_SORT(p2,p5); PIX_SORT(p3,p6); - PIX_SORT(p5,p8); PIX_SORT(p5,p3); PIX_SORT(p7,p5); - PIX_SORT(p5,p3); - rix[0][4] = p5; } - for (ii=0; ii < rr1*cc1; ii++) qix[ii][d] = qix[ii][4]; } - // red/blue at GREEN pixel locations - for (rr=0; rr < rr1; rr++) - for (cc=(FC(rr,1)&1), c=FC(rr,cc+1); cc < cc1; cc+=2) { - rix = qix + rr*cc1 + cc; - rix[0][0] = rix[0][1] + rix[0][3]; - rix[0][2] = rix[0][1] + rix[0][5]; } - // red/blue and green at BLUE/RED pixel locations - for (rr=0; rr < rr1; rr++) - for (cc=(FC(rr,0)&1), c=2-FC(rr,cc), d=c+3; cc < cc1; cc+=2) { - rix = qix + rr*cc1 + cc; - rix[0][c] = rix[0][1] + rix[0][d]; - rix[0][1] = 0.5*(rix[0][0] - rix[0][3] + rix[0][2] - rix[0][5]); } } - // copy result back to image matrix - for (row=0; row < height; row++) - for (col=0, rr=row+ba; col < width; col++) { - cc = col+ba; - pix = image + row*width + col; - rix = qix + rr*cc1 + cc; - c = FC(row,col); - if (gamma_apply) { - for (ii=0; ii < 3; ii++) - if (ii != c) { - v0 = rix[0][ii]; - if (v0 <= 0.04045) - v0 /= 12.92; - else - v0 = pow((v0 + 0.055)/1.055,2.4); - pix[0][ii] = CLIP((int)(65535.0*v0 + 0.5)); } } - else - for (ii=0; ii < 3; ii++) - if (ii != c) - pix[0][ii] = CLIP((int)(65535.0*rix[0][ii] + 0.5)); - } - // Done - free(buffer); - t2 = clock(); - dt = ((double)(t2-t1)) / CLOCKS_PER_SEC; -#ifdef DCRAW_VERBOSE - if (verbose) fprintf(stderr,_("\telapsed time = %5.3fs\n"),dt); -#endif -} diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL2/median_filter_new.c b/core/libs/rawengine/libraw/demosaic-pack-GPL2/median_filter_new.c deleted file mode 100644 index 1d724268e1..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL2/median_filter_new.c +++ /dev/null @@ -1,113 +0,0 @@ -/* This file was taken from modified dcraw published by Paul Lee - on January 23, 2009, taking dcraw ver.8.90/rev.1.417 - as basis. - http://sites.google.com/site/demosaicalgorithms/modified-dcraw - - As modified dcraw source code was published, the release under - GPL Version 2 or later option could be applied, so this file - is taken under this premise. -*/ - -/* - Copyright (C) 2009 Paul Lee - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - - -/* - differential median filter -*/ -#define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} } -void CLASS median_filter_new() -{ - int (*mf)[3], (*pc)[3], p[9], indx, row, col, c, d, temp, i, v0, pass; - int p11, p12, p13, p31, p32, p33; - p11 = -width-1; - p12 = p11+1; - p13 = p12+1; - p31 = width-1; - p32 = p31+1; - p33 = p32+1; - /* Allocate buffer for 3x3 median filter */ - mf = (int (*)[3]) calloc(width*height, sizeof *mf); - for (pass=1; pass <= med_passes; pass++) { -#ifdef DCRAW_VERBOSE - if (verbose) - fprintf (stderr,_("3x3 differential median filter pass %d...\n"), pass); -#endif - for (c=0; c < 3; c+=2) { - /* Compute median(R-G) and median(B-G) */ - for (indx=0; indx < height*width; indx++) - mf[indx][c] = image[indx][c] - image[indx][1]; - /* Apply 3x3 median fileter */ -#ifdef LIBRAW_USE_OPENMP -#pragma omp parallel for private(row,col,pc,p) -#endif - for (row=1; row < height-1; row++) - for (col=1; col < width-1; col++) { - pc = mf + row*width+col; - /* Assign 3x3 differential color values */ - p[0] = pc[p11][c]; p[1] = pc[p12][c]; p[2] = pc[p13][c]; - p[3] = pc[ -1][c]; p[4] = pc[ 0][c]; p[5] = pc[ 1][c]; - p[6] = pc[p31][c]; p[7] = pc[p32][c]; p[8] = pc[p33][c]; - /* Sort for median of 9 values */ - PIX_SORT(p[1],p[2]); PIX_SORT(p[4], p[5]); PIX_SORT(p[7],p[8]); - PIX_SORT(p[0],p[1]); PIX_SORT(p[3], p[4]); PIX_SORT(p[6],p[7]); - PIX_SORT(p[1],p[2]); PIX_SORT(p[4], p[5]); PIX_SORT(p[7],p[8]); - PIX_SORT(p[0],p[3]); PIX_SORT(p[5], p[8]); PIX_SORT(p[4],p[7]); - PIX_SORT(p[3],p[6]); PIX_SORT(p[1], p[4]); PIX_SORT(p[2],p[5]); - PIX_SORT(p[4],p[7]); PIX_SORT(p[4], p[2]); PIX_SORT(p[6],p[4]); - PIX_SORT(p[4],p[2]); - pc[0][1] = p[4]; - } - for (row=1; row < height-1; row++) - for (col=1; col < width-1; col++) { - pc = mf + row*width+col; - pc[0][c] = pc[0][1]; } - } - - /* red/blue at GREEN pixel locations */ - for (row=1; row < height-1; row++) - for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) { - indx = row*width+col; - for (i=0; i < 2; c=2-c, i++) { - v0 = image[indx][1]+mf[indx][c]; - image[indx][c] = CLIP(v0); - } - } - - /* red/blue at BLUE/RED pixel locations */ - for (row=2; row < height-2; row++) - for (col=2+(FC(row,2) & 1), c=2-FC(row,col); col < width-2; col+=2) { - indx = row*width+col; - v0 = image[indx][1]+mf[indx][c]; - image[indx][c] = CLIP(v0); - } - - /* green at RED/BLUE location */ - for (row=1; row < height-1; row++) - for (col=1+(FC(row,1) & 1), c=FC(row,col); col < width-3; col+=2) { - indx = row*width+col; - d = 2 - c; - v0 = (image[indx][c]-mf[indx][c]+image[indx][d]-mf[indx][d]+1) >> 1; - image[indx][1] = CLIP(v0); - } - } - - /* Free buffer */ - free(mf); -} -#undef PIX_SORT diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL2/refinement.c b/core/libs/rawengine/libraw/demosaic-pack-GPL2/refinement.c deleted file mode 100644 index e92593ec19..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL2/refinement.c +++ /dev/null @@ -1,107 +0,0 @@ -/* This file was taken from modified dcraw published by Paul Lee - on January 23, 2009, taking dcraw ver.8.90/rev.1.417 - as basis. - http://sites.google.com/site/demosaicalgorithms/modified-dcraw - - As modified dcraw source code was published, the release under - GPL Version 2 or later option could be applied, so this file - is taken under this premise. -*/ - -/* - Copyright (C) 2009 Paul Lee - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - - -/* - Refinement based on EECI demosaicing algorithm by L. Chang and Y.P. Tan -*/ -void CLASS refinement() -{ - ushort (*pix)[4]; - int row, col, indx, c, i, d, w1, w2, v0; - double dL, dR, dU, dD, dt; - clock_t t1, t2; - -#ifdef DCRAW_VERBOSE - if (verbose) fprintf(stderr,_("Post-demosaic refinement...")); -#endif - t1 = clock(); - w1 = width; - w2 = 2*w1; - - /* Reinforce interpolated green pixels on RED/BLUE pixel locations */ - for (row=2; row < height-2; row++) - for (col=2+(FC(row,2) & 1), c=FC(row,col); col < width-2; col+=2) { - indx = row*width+col; - pix = image + indx; - dL = 1.0/(1.0+ABS(pix[ -2][c]-pix[0][c])+ABS(pix[ 1][1]-pix[ -1][1])); - dR = 1.0/(1.0+ABS(pix[ 2][c]-pix[0][c])+ABS(pix[ 1][1]-pix[ -1][1])); - dU = 1.0/(1.0+ABS(pix[-w2][c]-pix[0][c])+ABS(pix[w1][1]-pix[-w1][1])); - dD = 1.0/(1.0+ABS(pix[ w2][c]-pix[0][c])+ABS(pix[w1][1]-pix[-w1][1])); - v0 = (int)((double)pix[0][c] + 0.5 + - ((double)(pix[ -1][1]-pix[ -1][c])*dL + - (double)(pix[ 1][1]-pix[ 1][c])*dR + - (double)(pix[-w1][1]-pix[-w1][c])*dU + - (double)(pix[ w1][1]-pix[ w1][c])*dD ) / (dL+dR+dU+dD)); - pix[0][1] = CLIP(v0); - } - - /* Reinforce interpolated red/blue pixels on GREEN pixel locations */ - for (row=2; row < height-2; row++) - for (col=2+(FC(row,3) & 1), c=FC(row,col+1); col < width-2; col+=2) { - indx = row*width+col; - pix = image + indx; - for (i=0; i < 2; c=2-c, i++) { - dL = 1.0/(1.0+ABS(pix[ -2][1]-pix[0][1])+ABS(pix[ 1][c]-pix[ -1][c])); - dR = 1.0/(1.0+ABS(pix[ 2][1]-pix[0][1])+ABS(pix[ 1][c]-pix[ -1][c])); - dU = 1.0/(1.0+ABS(pix[-w2][1]-pix[0][1])+ABS(pix[w1][c]-pix[-w1][c])); - dD = 1.0/(1.0+ABS(pix[ w2][1]-pix[0][1])+ABS(pix[w1][c]-pix[-w1][c])); - v0 = (int)((double)pix[0][1] + 0.5 - - ((double)(pix[ -1][1]-pix[ -1][c])*dL + - (double)(pix[ 1][1]-pix[ 1][c])*dR + - (double)(pix[-w1][1]-pix[-w1][c])*dU + - (double)(pix[ w1][1]-pix[ w1][c])*dD ) / (dL+dR+dU+dD)); - pix[0][c] = CLIP(v0); - } - } - - /* Reinforce integrated red/blue pixels on BLUE/RED pixel locations */ - for (row=2; row < height-2; row++) - for (col=2+(FC(row,2) & 1), c=2-FC(row,col); col < width-2; col+=2) { - indx = row*width+col; - pix = image + indx; - d = 2 - c; - dL = 1.0/(1.0+ABS(pix[ -2][d]-pix[0][d])+ABS(pix[ 1][1]-pix[ -1][1])); - dR = 1.0/(1.0+ABS(pix[ 2][d]-pix[0][d])+ABS(pix[ 1][1]-pix[ -1][1])); - dU = 1.0/(1.0+ABS(pix[-w2][d]-pix[0][d])+ABS(pix[w1][1]-pix[-w1][1])); - dD = 1.0/(1.0+ABS(pix[ w2][d]-pix[0][d])+ABS(pix[w1][1]-pix[-w1][1])); - v0 = (int)((double)pix[0][1] + 0.5 - - ((double)(pix[ -1][1]-pix[ -1][c])*dL + - (double)(pix[ 1][1]-pix[ 1][c])*dR + - (double)(pix[-w1][1]-pix[-w1][c])*dU + - (double)(pix[ w1][1]-pix[ w1][c])*dD ) / (dL+dR+dU+dD)); - pix[0][c] = CLIP(v0); - } - - /* Done */ - t2 = clock(); - dt = ((double)(t2-t1)) / CLOCKS_PER_SEC; -#ifdef DCRAW_VERBOSE - if (verbose) fprintf(stderr,_("\telapsed time = %5.3fs\n"),dt); -#endif -} diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL2/vcd_interpolate.c b/core/libs/rawengine/libraw/demosaic-pack-GPL2/vcd_interpolate.c deleted file mode 100644 index b0183f6627..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL2/vcd_interpolate.c +++ /dev/null @@ -1,352 +0,0 @@ -/* This file was taken from modified dcraw published by Paul Lee - on January 23, 2009, taking dcraw ver.8.90/rev.1.417 - as basis. - http://sites.google.com/site/demosaicalgorithms/modified-dcraw - - As modified dcraw source code was published, the release under - GPL Version 2 or later option could be applied, so this file - is taken under this premise. -*/ - -/* -Color Demosaicing Using Variance of Color Differences -by K.H Chung and Y.H Chan -*/ -#define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} } - -/* -Christos : -If ahd == 0 then its just VCD -*/ - -void CLASS vcd_interpolate(int ahd_cutoff) -{ - int row, col, indx, c, d, i, j; - ushort (*pix)[4]; - int w1, w2, w3, w4, w5, w6, v0, v1, v2, v3, v4, LH, LV, var_dir; - int AHD_cnt, LH_cnt, LV_cnt, varH_cnt, varV_cnt, varD_cnt, T_cnt; - int dC0, dC1, dC2, dC3, dC4, temp; - double e, T, d1, d3, d5, d7, d9, varH, varV, varD, var0; - clock_t t1, t2; - double dt; -#ifdef DCRAW_VERBOSE - if (verbose) fprintf(stderr,_("VCD interpolation...\n")); -#endif - t1 = clock(); - /* assume VCD's T value is based on gamma=2.22 test images */ - T = 2; - AHD_cnt = LH_cnt = LV_cnt = varH_cnt = varV_cnt = varD_cnt = 0; - w1 = width; - w2 = 2*w1; - w3 = 3*w1; - w4 = 4*w1; - w5 = 5*w1; - w6 = 6*w1; - border_interpolate(6); - - /* run AHD interpolation on Green channel with threshold */ - if (ahd_cutoff > 0) ahd_partial_interpolate(ahd_cutoff); - - /* Interpolate green pixels on red/blue pixel locations */ - for (row=6; row < height-6; row++) - for (col=6+(FC(row,6) & 1), c=FC(row,col); col < width-6; col+=2) { - indx = row*width+col; - pix = image + indx; - d = 2 - c; - if (image[indx][1] > 0) { - var_dir = 4; - AHD_cnt++; } - else { - /* LH: Eq.(6) */ - LH = - ABS(pix[-2-w2][c]-pix[-w2][c]) + ABS(pix[-w2][c]-pix[2-w2][c]) + - ABS(pix[-2 ][c]-pix[ 0][c]) + ABS(pix[ 0][c]-pix[2 ][c]) + - ABS(pix[-2+w2][c]-pix[ w2][c]) + ABS(pix[ w2][c]-pix[2+w2][c]) + - ABS(pix[-2-w1][1]-pix[-w1][1]) + ABS(pix[-w1][1]-pix[2-w1][1]) + - ABS(pix[-2+w1][1]-pix[ w1][1]) + ABS(pix[ w1][1]-pix[2+w1][1]) + - ABS(pix[-1-w2][1]-pix[-w2][c]) + ABS(pix[-w2][c]-pix[1-w2][1]) + - ABS(pix[-1 ][1]-pix[ 0][c]) + ABS(pix[ 0][c]-pix[1 ][1]) + - ABS(pix[-1+w2][1]-pix[ w2][c]) + ABS(pix[ w2][c]-pix[1+w2][1]) + - ABS(pix[-1-w1][d]-pix[-w1][1]) + ABS(pix[-w1][1]-pix[1-w1][d]) + - ABS(pix[-1+w1][d]-pix[ w1][1]) + ABS(pix[ w1][1]-pix[1+w1][d]); - /* LV: Eq.(7) */ - LV = - ABS(pix[-2-w2][c]-pix[-2][c]) + ABS(pix[-2][c]-pix[-2+w2][c]) + - ABS(pix[ -w2][c]-pix[ 0][c]) + ABS(pix[ 0][c]-pix[ w2][c]) + - ABS(pix[ 2-w2][c]-pix[ 2][c]) + ABS(pix[ 2][c]-pix[ 2+w2][c]) + - ABS(pix[-1-w2][1]-pix[-1][1]) + ABS(pix[-1][1]-pix[-1+w2][1]) + - ABS(pix[ 1-w2][1]-pix[ 1][1]) + ABS(pix[ 1][1]-pix[ 1+w2][1]) + - ABS(pix[-2-w1][1]-pix[-2][c]) + ABS(pix[-2][c]-pix[-2+w1][1]) + - ABS(pix[ -w1][1]-pix[ 0][c]) + ABS(pix[ 0][c]-pix[ w1][1]) + - ABS(pix[ 2-w1][1]-pix[ 2][c]) + ABS(pix[ 2][c]-pix[ 2+w1][1]) + - ABS(pix[-1-w1][d]-pix[-1][1]) + ABS(pix[-1][1]-pix[-1+w1][d]) + - ABS(pix[ 1-w1][d]-pix[ 1][1]) + ABS(pix[ 1][1]-pix[ 1+w1][d]); - /* e: Eq.(8) */ - e = (double)(LH) / (double)(LV); - if (e < 1) e = 1.0/e; - /* g: Eq.(9)~(10) */ - if (e > T) { - if (LH < LV) { - var_dir = 1; - LH_cnt++; } - else { - var_dir = 2; - LV_cnt++; } - } - /* varH, varV, varD: Eq. (11)~(18) */ - else { - /* varH: Eq.(11) */ - d1 = (double)(pix[-6][c]-2*(pix[-5][1]-pix[-4][c]+pix[-3][1])+pix[-2][c])/65535.0; - d3 = (double)(pix[-4][c]-2*(pix[-3][1]-pix[-2][c]+pix[-1][1])+pix[ 0][c])/65535.0; - d5 = (double)(pix[-2][c]-2*(pix[-1][1]-pix[ 0][c]+pix[ 1][1])+pix[ 2][c])/65535.0; - d7 = (double)(pix[ 0][c]-2*(pix[ 1][1]-pix[ 2][c]+pix[ 3][1])+pix[ 4][c])/65535.0; - d9 = (double)(pix[ 2][c]-2*(pix[ 3][1]-pix[ 4][c]+pix[ 5][1])+pix[ 6][c])/65535.0; - /* variance assuming d2 =(d1+d3)/2, d4=(d3+d5)/2, and etc */ - varH = - d1*(18*d1 - 3*d3 - 12*d5 - 12*d7 - 9*d9) + - d3*(19*d3 - 7*d5 - 16*d7 - 12*d9) + - d5*(19*d5 - 7*d7 - 12*d9) + - d7*(19*d7 - 3*d9) + - 18*d9*d9; - var_dir = 1; - var0 = varH; - /* varV: Eq.(12) */ - d1 = (double)(pix[-w6][c]-2*(pix[-w5][1]-pix[-w4][c]+pix[-w3][1])+pix[-w2][c])/65535.0; - d3 = (double)(pix[-w4][c]-2*(pix[-w3][1]-pix[-w2][c]+pix[-w1][1])+pix[ 0][c])/65535.0; - d5 = (double)(pix[-w2][c]-2*(pix[-w1][1]-pix[ 0][c]+pix[ w1][1])+pix[ w2][c])/65535.0; - d7 = (double)(pix[ 0][c]-2*(pix[ w1][1]-pix[ w2][c]+pix[ w3][1])+pix[ w4][c])/65535.0; - d9 = (double)(pix[ w2][c]-2*(pix[ w3][1]-pix[ w4][c]+pix[ w5][1])+pix[ w6][c])/65535.0; - varV = - d1*(18*d1 - 3*d3 - 12*d5 - 12*d7 - 9*d9) + - d3*(19*d3 - 7*d5 - 16*d7 - 12*d9) + - d5*(19*d5 - 7*d7 - 12*d9) + - d7*(19*d7 - 3*d9) + - 18*d9*d9; - if (varV < var0) { - var_dir = 2; - var0 = varV; } - /* varD: Eq.(17) */ - d1 = (double)(4*pix[-4 ][c]+pix[-4-w2][c]+pix[-6][c]+pix[-2 ][c]+pix[-4+w2][c] - -2*(pix[-4-w1][1]+pix[-5 ][1]+pix[-3][1]+pix[-4+w1][1]))/65535.0; - d3 = (double)(4*pix[-2 ][c]+pix[-2-w2][c]+pix[-4][c]+pix[ 0 ][c]+pix[-2+w2][c] - -2*(pix[-2-w1][1]+pix[-3 ][1]+pix[-1][1]+pix[-2+w1][1]))/65535.0; - d5 = (double)(4*pix[ 0 ][c]+pix[ -w2][c]+pix[-2][c]+pix[ 2 ][c]+pix[ w2][c] - -2*(pix[ -w1][1]+pix[-1 ][1]+pix[ 1][1]+pix[ w1][1]))/65535.0; - d7 = (double)(4*pix[ 2 ][c]+pix[ 2-w2][c]+pix[ 0][c]+pix[ 4 ][c]+pix[ 2+w2][c] - -2*(pix[ 2-w1][1]+pix[ 1 ][1]+pix[ 3][1]+pix[ 2+w1][1]))/65535.0; - d9 = (double)(4*pix[ 4 ][c]+pix[ 4-w2][c]+pix[ 2][c]+pix[ 6 ][c]+pix[ 4+w2][c] - -2*(pix[ 4-w1][1]+pix[ 3 ][1]+pix[ 5][1]+pix[ 4+w1][1]))/65535.0; - varD = - d1*(18*d1 - 3*d3 - 12*d5 - 12*d7 - 9*d9) + - d3*(19*d3 - 7*d5 - 16*d7 - 12*d9) + - d5*(19*d5 - 7*d7 - 12*d9) + - d7*(19*d7 - 3*d9) + - 18*d9*d9; - /* d5 stays same */ - d1 = (double)(4*pix[-w4][c]+pix[-w6 ][c]+pix[-w4-2][c]+pix[-w4+2][c]+pix[-w2][c] - -2*(pix[-w5][1]+pix[-w4-1][1]+pix[-w4+1][1]+pix[-w3 ][1]))/65535.0; - d3 = (double)(4*pix[-w2][c]+pix[-w4 ][c]+pix[-w2-2][c]+pix[-w2+2][c]+pix[ 0][c] - -2*(pix[-w3][1]+pix[-w2-1][1]+pix[-w2+1][1]+pix[-w1 ][1]))/65535.0; - d7 = (double)(4*pix[ w2][c]+pix[ 0][c]+pix[ w2-2][c]+pix[ w2+2][c]+pix[ w4][c] - -2*(pix[ w1][1]+pix[ w2-1][1]+pix[ w2+1][1]+pix[ w3 ][1]))/65535.0; - d9 = (double)(4*pix[ w4][c]+pix[ w2 ][c]+pix[ w4-2][c]+pix[ w4+2][c]+pix[ w6][c] - -2*(pix[ w3][1]+pix[ w4-1][1]+pix[ w4+1][1]+pix[ w5 ][1]))/65535.0; - varD += - d1*(18*d1 - 3*d3 - 12*d5 - 12*d7 - 9*d9) + - d3*(19*d3 - 7*d5 - 16*d7 - 12*d9) + - d5*(19*d5 - 7*d7 - 12*d9) + - d7*(19*d7 - 3*d9) + - 18*d9*d9; - /* scale varD to equalize to varH and varV */ - varD /= 8.0; - if (varD < var0) var_dir = 3; - /* Eq.(18) */ - if (var_dir == 1) - varH_cnt++; - else if (var_dir == 2) - varV_cnt++; - else if (var_dir == 3) - varD_cnt++; - } - } - /* limit values within surrounding green values - for overshooted pixel values, revert to linear interpolation */ - if (var_dir == 1) { - /* Eq.(3) - Horizontal */ - v0 = - (2*(pix[ -1][1]+pix[0][c]+pix[ 1][1])-pix[ -2][c]-pix[ 2][c]+2) >> 2; - v1 = pix[-1][1]; - v2 = pix[ 1][1]; - PIX_SORT(v1,v2); - /* +- 50% range */ - v3 = MAX(2*v1 - v2,0); - v4 = MIN(2*v2 - v1,65535); - if (v0 < v3 || v0 > v4) { - v0 = (pix[-3][1] + pix[3][1] + - 18*(2*pix[0][c] - pix[-2][c] - pix[2][c]) + - 63*(pix[-1][1] + pix[1][1]) + 64) >> 7; - if (v0 < v3 || v0 > v4) { - v0 = (4*(v1 + v2) + 2*pix[0][c]-pix[-2][c]-pix[2][c] + 4) >> 3; - /* Bi-linear if anti-aliasing overshoots */ - if (v0 < v3 || v0 > v4) v0 = (v1 + v2 + 1) >> 1; } } - } - else if (var_dir == 2) { - /* Eq.(4) - Vertical */ - v0 = - (2*(pix[-w1][1]+pix[0][c]+pix[w1][1])-pix[-w2][c]-pix[w2][c]+2) >> 2; - v1 = pix[-w1][1]; - v2 = pix[ w1][1]; - PIX_SORT(v1,v2); - /* +- 50% range */ - v3 = MAX(2*v1 - v2,0); - v4 = MIN(2*v2 - v1,65535); - if (v0 < v3 || v0 > v4) { - v0 = (pix[-w3][1] + pix[w3][1] + - 18*(2*pix[0][c] - pix[-w2][c] - pix[w2][c]) + - 63*(pix[-w1][1] + pix[w1][1]) + 64) >> 7; - if (v0 < v3 || v0 > v4) { - v0 = (4*(v1 + v2) + 2*pix[0][c]-pix[-w2][c]-pix[w2][c] + 4) >> 3; - /* Bi-linear if anti-aliasing overshoots */ - if (v0 < v3 || v0 > v4) v0 = (v1 + v2 + 1) >> 1; }} - } - else if (var_dir == 3) { - /* Eq.(5) - Diagonal */ - v0 = 2*(pix[ -1][1]+pix[0][c]+pix[ 1][1])-pix[ -2][c]-pix[ 2][c]+2; - v0 += 2*(pix[-w1][1]+pix[0][c]+pix[w1][1])-pix[-w2][c]-pix[w2][c]+2; - v0 >>= 3; - v1 = MIN(MIN(pix[-1][1],pix[1][1]),MIN(pix[-w1][1],pix[w1][1])); - v2 = MAX(MAX(pix[-1][1],pix[1][1]),MAX(pix[-w1][1],pix[w1][1])); - v3 = MAX(2*v1 - v2,0); - v4 = MIN(2*v2 - v1,65535); - if (v0 < v3 || v0 > v4) - v0 = (pix[-w1][1] + pix[ -1][1] + pix[ 1][1] + pix[w1][1] + 2) >> 2; - } - else if (var_dir == 4) { - v0 = pix[0][1]; - } - pix[0][1] = v0; - } - - /* - Interpolote red/blue pixels on BLUE/RED pixel locations - using pattern regcognition on differential color plane - */ - for (row=1; row < height-1; row++) - for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < width-1; col+=2) { - indx = row*width+col; - pix = image + indx; - if (pix[0][c] == 0) { - dC1 = pix[-w1-1][1]-pix[-w1-1][c]; - dC2 = pix[-w1+1][1]-pix[-w1+1][c]; - dC3 = pix[ w1-1][1]-pix[ w1-1][c]; - dC4 = pix[ w1+1][1]-pix[ w1+1][c]; - dC0 = dC1 + dC2 + dC3 + dC4; - dC1 <<= 2; - dC2 <<= 2; - dC3 <<= 2; - dC4 <<= 2; - j = (dC1 > dC0) + (dC2 > dC0) + (dC3 > dC0) + (dC4 > dC0); - if (j == 3 || j == 1) { - /* edge-corner pattern: median of color differential values */ - PIX_SORT(dC1,dC2); - PIX_SORT(dC3,dC4); - PIX_SORT(dC1,dC3); - PIX_SORT(dC2,dC4); - dC0 = dC2 + dC3; } - else { - /* stripe pattern: average along diagonal */ - v1 = ABS(pix[-w1-1][c]-pix[w1+1][c]); - v2 = ABS(pix[-w1+1][c]-pix[w1-1][c]); - if (v1 < v2) - dC0 = dC1 + dC4; - else if (v1 > v2) - dC0 = dC2 + dC3; - else - dC0 <<= 1; } - v0 = (((int)(pix[0][1]) << 3) - dC0 + 4) >> 3; - /* apply anti-aliasing if overshoot */ - if (v0 < 0 || v0 > 65535) - v0 = (pix[-w1-1][c]+pix[-w1+1][c]+pix[w1-1][c]+pix[w1+1][c]+2) >> 2; - pix[0][c] = v0; - } - } - /* - Interpolote red/blue pixels on GREEN pixel locations - using pattern regcognition on differential color plane - */ - for (row=1; row < height-1; row++) - for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) { - indx = row*width+col; - pix = image + indx; - for (i=0; i < 2; c=2-c, i++) { - if (pix[0][c] == 0) { - dC1 = pix[-w1][1]-pix[-w1][c]; - dC2 = pix[ -1][1]-pix[ -1][c]; - dC3 = pix[ 1][1]-pix[ 1][c]; - dC4 = pix[ w1][1]-pix[ w1][c]; - dC0 = dC1 + dC2 + dC3 + dC4; - dC1 <<= 2; - dC2 <<= 2; - dC3 <<= 2; - dC4 <<= 2; - j = (dC1 > dC0) + (dC2 > dC0) + (dC3 > dC0) + (dC4 > dC0); - if (j == 3 || j == 1) { - /* edge-corner pattern: median of color differential values */ - PIX_SORT(dC1,dC2); - PIX_SORT(dC3,dC4); - PIX_SORT(dC1,dC3); - PIX_SORT(dC2,dC4); - dC0 = dC2 + dC3; } - else { - /* stripe pattern: average along diagonal */ - v1 = ABS(pix[-w1][c]-pix[w1][c]); - v2 = ABS(pix[ -1][c]-pix[ 1][c]); - if (v1 < v2) - dC0 = dC1 + dC4; - else if (v1 > v2) - dC0 = dC2 + dC3; - else - dC0 <<= 1; } - v0 = (((int)(pix[0][1]) << 3) - dC0 + 4) >> 3; - /* apply anti-aliasing if overshoot */ - if (v0 < 0 || v0 > 65535) { - if (i == 0) - v0 = (pix[ -1][c]+pix[ 1][c]+1) >> 1; - else - v0 = (pix[-w1][c]+pix[w1][c]+1) >> 1; } - pix[0][c] = v0; - } - } - } - - /* Compute statistics */ -#ifdef DCRAW_VERBOSE - if (verbose) { - if (ahd_cutoff > 0) { - T_cnt = AHD_cnt + LH_cnt + LV_cnt + varH_cnt + varV_cnt + varD_cnt; - fprintf (stderr, - _("\tAHD, LH, LV, varH, varV varD = %4.2f, %4.2f, %4.2f, %4.2f, %4.2f, %4.2f (%%)\n"), - 100*(double)AHD_cnt/(double)T_cnt, - 100*(double)LH_cnt/(double)T_cnt, - 100*(double)LV_cnt/(double)T_cnt, - 100*(double)varH_cnt/(double)T_cnt, - 100*(double)varV_cnt/(double)T_cnt, - 100*(double)varD_cnt/(double)T_cnt); } - else { - T_cnt = LH_cnt + LV_cnt + varH_cnt + varV_cnt + varD_cnt; - fprintf (stderr, - _("\tLH, LV, varH, varV varD = %4.2f, %4.2f, %4.2f, %4.2f, %4.2f (%%)\n"), - 100*(double)LH_cnt/(double)T_cnt, - 100*(double)LV_cnt/(double)T_cnt, - 100*(double)varH_cnt/(double)T_cnt, - 100*(double)varV_cnt/(double)T_cnt, - 100*(double)varD_cnt/(double)T_cnt); } - } - - /* Done */ - t2 = clock(); - dt = ((double)(t2-t1)) / CLOCKS_PER_SEC; - if (verbose) fprintf(stderr,_("\telapsed time = %5.3fs\n"),dt); -#endif -} -#undef PIX_SORT diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL3/CA_correct_RT.cc b/core/libs/rawengine/libraw/demosaic-pack-GPL3/CA_correct_RT.cc deleted file mode 100644 index 1380f52aec..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL3/CA_correct_RT.cc +++ /dev/null @@ -1,899 +0,0 @@ -//////////////////////////////////////////////////////////////// -// -// Chromatic Aberration Auto-correction -// -// copyright (c) 2008-2010 Emil Martinec -// -// -// code dated: November 26, 2010 -// -// CA_correct_RT.cc is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -#define TS 256 // Tile size -//#define polyord 6 // max order of fit monomial -//#define numpar 36 // number of fit parameters = SQR(polyord) - -#define PIX_SORT(a,b) { if ((a)>(b)) {temp=(a);(a)=(b);(b)=temp;} } - -/*#define ushort UshORt - typedef unsigned char uchar; - typedef unsigned short ushort;*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define SQR(x) ((x)*(x)) -#define ABS(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31)) -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#define LIM(x,min,max) MAX(min,MIN(x,max)) -#define ULIM(x,y,z) ((y) < (z) ? LIM(x,y,z) : LIM(x,z,y)) -#define CLIP(x) LIM(x,0,65535) -//#define SWAP(a,b) { a ^= b; a ^= (b ^= a); } - - - -//////////////////////////////////////////////////////////////// -//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -int LinEqSolve2(int nDim, float* pfMatr, float* pfVect, float* pfSolution) -{ -//============================================================================== -// return 1 if system not solving, 0 if system solved -// nDim - system dimension -// pfMatr - matrix with coefficients -// pfVect - vector with free members -// pfSolution - vector with system solution -// pfMatr becames trianglular after function call -// pfVect changes after function call -// -// Developer: Henry Guennadi Levkin -// -//============================================================================== - - float fMaxElem; - float fAcc; - - int i, j, k, m; - - for(k=0; k<(nDim-1); k++) {// base row of matrix - // search of line with max element - fMaxElem = fabs( pfMatr[k*nDim + k] ); - m = k; - for (i=k+1; i=0; k--) { - pfSolution[k] = pfVect[k]; - for(i=(k+1); iheight) {rrmax=height-top;} else {rrmax=rr1;} - if (right>width) {ccmax=width-left;} else {ccmax=cc1;} - - for (rr=rrmin; rr < rrmax; rr++) - for (row=rr+top, cc=ccmin; cc < ccmax; cc++) { - col = cc+left; - c = FC(rr,cc); - indx=row*width+col; - indx1=rr*TS+cc; - //rgb[indx1][c] = (rawData[row][col])/65535.0f; - rgb[indx1][c] = image[indx][c]/65535.0f;//for dcraw implementation - } - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //fill borders - if (rrmin>0) { - for (rr=0; rr0) { - for (rr=rrmin; rr0 && ccmin>0) { - for (rr=0; rr0 && ccmax0) { - for (rr=0; rr-1 && row-1 && col0.8*clip_pt || Gtmp[indx]>0.8*clip_pt) continue; - - //in linear interpolation, color differences are a quadratic function of interpolation position; - //solve for the interpolation position that minimizes color difference variance over the tile - - //vertical - gdiff=0.3125*(rgb[indx+TS][1]-rgb[indx-TS][1])+0.09375*(rgb[indx+TS+1][1]-rgb[indx-TS+1][1]+rgb[indx+TS-1][1]-rgb[indx-TS-1][1]); - deltgrb=(rgb[indx][c]-rgb[indx][1])-0.5*((rgb[indx-v4][c]-rgb[indx-v4][1])+(rgb[indx+v4][c]-rgb[indx+v4][1])); - - gradwt=fabs(0.25*rbhpfv[indx]+0.125*(rbhpfv[indx+2]+rbhpfv[indx-2]) );//*(grblpfv[indx-v2]+grblpfv[indx+v2])/(eps+0.1*grblpfv[indx-v2]+rblpfv[indx-v2]+0.1*grblpfv[indx+v2]+rblpfv[indx+v2]); - if (gradwt>eps) { - coeff[0][0][c] += gradwt*deltgrb*deltgrb; - coeff[0][1][c] += gradwt*gdiff*deltgrb; - coeff[0][2][c] += gradwt*gdiff*gdiff; - areawt[0][c]++; - } - - //horizontal - gdiff=0.3125*(rgb[indx+1][1]-rgb[indx-1][1])+0.09375*(rgb[indx+1+TS][1]-rgb[indx-1+TS][1]+rgb[indx+1-TS][1]-rgb[indx-1-TS][1]); - deltgrb=(rgb[indx][c]-rgb[indx][1])-0.5*((rgb[indx-4][c]-rgb[indx-4][1])+(rgb[indx+4][c]-rgb[indx+4][1])); - - gradwt=fabs(0.25*rbhpfh[indx]+0.125*(rbhpfh[indx+v2]+rbhpfh[indx-v2]) );//*(grblpfh[indx-2]+grblpfh[indx+2])/(eps+0.1*grblpfh[indx-2]+rblpfh[indx-2]+0.1*grblpfh[indx+2]+rblpfh[indx+2]); - if (gradwt>eps) { - coeff[1][0][c] += gradwt*deltgrb*deltgrb; - coeff[1][1][c] += gradwt*gdiff*deltgrb; - coeff[1][2][c] += gradwt*gdiff*gdiff; - areawt[1][c]++; - } - - // In Mathematica, - // f[x_]=Expand[Total[Flatten[ - // ((1-x) RotateLeft[Gint,shift1]+x RotateLeft[Gint,shift2]-cfapad)^2[[dv;;-1;;2,dh;;-1;;2]]]]]; - // extremum = -.5Coefficient[f[x],x]/Coefficient[f[x],x^2] - } - for (c=0; c<3; c+=2){ - for (j=0; j<2; j++) {// vert/hor - //printf("hblock %d vblock %d j %d c %d areawt %d \n",hblock,vblock,j,c,areawt[j][c]); - //printf("hblock %d vblock %d j %d c %d areawt %d ",hblock,vblock,j,c,areawt[j][c]); - - if (areawt[j][c]>0 && coeff[j][2][c]>eps2) { - CAshift[j][c]=coeff[j][1][c]/coeff[j][2][c]; - blockwt[vblock*hblsz+hblock]= areawt[j][c];//*coeff[j][2][c]/(eps+coeff[j][0][c]) ; - } else { - CAshift[j][c]=17.0; - blockwt[vblock*hblsz+hblock]=0; - } - //if (c==0 && j==0) printf("vblock= %d hblock= %d denom= %f areawt= %d \n",vblock,hblock,coeff[j][2][c],areawt[j][c]); - - //printf("%f \n",CAshift[j][c]); - - //data structure = CAshift[vert/hor][color] - //j=0=vert, 1=hor - - - offset[j][c]=floor(CAshift[j][c]); - //offset gives NW corner of square containing the min; j=0=vert, 1=hor - - if (fabs(CAshift[j][c])<2.0) { - blockave[j][c] += CAshift[j][c]; - blocksqave[j][c] += SQR(CAshift[j][c]); - blockdenom[j][c] += 1; - } - }//vert/hor - }//color - - - - /* CAshift[j][c] are the locations - that minimize color difference variances; - This is the approximate _optical_ location of the R/B pixels */ - - for (c=0; c<3; c+=2) { - //evaluate the shifts to the location that minimizes CA within the tile - blockshifts[(vblock)*hblsz+hblock][c][0]=(CAshift[0][c]); //vert CA shift for R/B - blockshifts[(vblock)*hblsz+hblock][c][1]=(CAshift[1][c]); //hor CA shift for R/B - //data structure: blockshifts[blocknum][R/B][v/h] - //if (c==0) printf("vblock= %d hblock= %d blockshiftsmedian= %f \n",vblock,hblock,blockshifts[(vblock)*hblsz+hblock][c][0]); - } - - // if(plistener) plistener->setProgress(0.5*fabs((float)top/height)); - - } - } - //end of diagnostic pass - - for (j=0; j<2; j++) - for (c=0; c<3; c+=2) { - if (blockdenom[j][c]) { - blockvar[j][c] = blocksqave[j][c]/blockdenom[j][c]-SQR(blockave[j][c]/blockdenom[j][c]); - } else { -#ifdef DCRAW_VERBOSE - fprintf (stderr,"blockdenom vanishes \n"); -#endif - return; - } - } -#ifdef DCRAW_VERBOSE - - if (verbose) fprintf (stderr,"tile variances %f %f %f %f \n",blockvar[0][0],blockvar[1][0],blockvar[0][2],blockvar[1][2] ); -#endif - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - //now prepare for CA correction pass - //first, fill border blocks of blockshift array - for (vblock=1; vblock4.0*blockvar[0][c] || SQR(blockshifts[(vblock)*hblsz+hblock][c][1])>4.0*blockvar[1][c]) continue; - numblox[c] += 1; - for (dir=0; dir<2; dir++) { - for (i=0; iheight) {rrmax=height-top;} else {rrmax=rr1;} - if (right>width) {ccmax=width-left;} else {ccmax=cc1;} - - - for (rr=rrmin; rr < rrmax; rr++) - for (row=rr+top, cc=ccmin; cc < ccmax; cc++) { - col = cc+left; - c = FC(rr,cc); - indx=row*width+col; - indx1=rr*TS+cc; - //rgb[indx1][c] = image[indx][c]/65535.0f; - //rgb[indx1][c] = (rawData[row][col])/65535.0f; - rgb[indx1][c] = image[indx][c]/65535.0f;//for dcraw implementation - - if ((c&1)==0) rgb[indx1][1] = Gtmp[indx]; - } - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //fill borders - if (rrmin>0) { - for (rr=0; rr0) { - for (rr=rrmin; rr0 && ccmin>0) { - for (rr=0; rr0 && ccmax0) { - for (rr=0; rr-1 && row-1 && col0) { - GRBdir[0][c] = 1; - } else { - GRBdir[0][c] = -1; - } - if (blockshifts[(vblock)*hblsz+hblock][c][1]>0) { - GRBdir[1][c] = 1; - } else { - GRBdir[1][c] = -1; - } - - } - - - for (rr=4; rr < rr1-4; rr++) - for (cc=4+(FC(rr,2)&1), c = FC(rr,cc); cc < cc1-4; cc+=2) { - //perform CA correction using color ratios or color differences - - Ginthfloor=(1-shifthfrac[c])*rgb[(rr+shiftvfloor[c])*TS+cc+shifthfloor[c]][1]+(shifthfrac[c])*rgb[(rr+shiftvfloor[c])*TS+cc+shifthceil[c]][1]; - Ginthceil=(1-shifthfrac[c])*rgb[(rr+shiftvceil[c])*TS+cc+shifthfloor[c]][1]+(shifthfrac[c])*rgb[(rr+shiftvceil[c])*TS+cc+shifthceil[c]][1]; - //Gint is blinear interpolation of G at CA shift point - Gint=(1-shiftvfrac[c])*Ginthfloor+(shiftvfrac[c])*Ginthceil; - - //determine R/B at grid points using color differences at shift point plus interpolated G value at grid point - //but first we need to interpolate G-R/G-B to grid points... - grbdiff[(rr)*TS+cc]=Gint-rgb[(rr)*TS+cc][c]; - gshift[(rr)*TS+cc]=Gint; - } - - for (rr=8; rr < rr1-8; rr++) - for (cc=8+(FC(rr,2)&1), c = FC(rr,cc), indx=rr*TS+cc; cc < cc1-8; cc+=2, indx+=2) { - - //if (rgb[indx][c]>clip_pt || Gtmp[indx]>clip_pt) continue; - - grbdiffold = rgb[indx][1]-rgb[indx][c]; - - //interpolate color difference from optical R/B locations to grid locations - //gradient weights using difference from G at CA shift points and G at grid points -p[0]=1/(eps+fabs(rgb[indx][1]-gshift[indx])); -p[1]=1/(eps+fabs(rgb[indx][1]-gshift[indx-2*GRBdir[1][c]])); -p[2]=1/(eps+fabs(rgb[indx][1]-gshift[(rr-2*GRBdir[0][c])*TS+cc])); - p[3]=1/(eps+fabs(rgb[indx][1]-gshift[(rr-2*GRBdir[0][c])*TS+cc-2*GRBdir[1][c]])); -grbdiffint = (p[0]*grbdiff[indx]+p[1]*grbdiff[indx-2*GRBdir[1][c]]+ p[2]*grbdiff[(rr-2*GRBdir[0][c])*TS+cc]+p[3]*grbdiff[(rr-2*GRBdir[0][c])*TS+cc-2*GRBdir[1][c]])/(p[0]+p[1]+p[2]+p[3]); - //now determine R/B at grid points using interpolated color differences and interpolated G value at grid point -if (fabs(grbdiffold)>fabs(grbdiffint) ) { -rgb[indx][c]=rgb[indx][1]-grbdiffint; -} - - - //if color difference interpolation overshot the correction, just desaturate - if (grbdiffold*grbdiffint<0) { - rgb[indx][c]=rgb[indx][1]-0.5*(grbdiffold+grbdiffint); - } - } - - // copy CA corrected results back to image matrix - for (rr=border; rr < rr1-border; rr++) - for (row=rr+top, cc=border+(FC(rr,2)&1); cc < cc1-border; cc+=2) { - col = cc + left; - indx = row*width + col; - c = FC(row,col); - - //rawData[row][col] = CLIP((int)(65535.0f*rgb[(rr)*TS+cc][c] + 0.5f)); - image[indx][c] = CLIP((int)(65535.0*rgb[(rr)*TS+cc][c] + 0.5));//for dcraw implementation - - } - - //if(plistener) plistener->setProgress(0.5+0.5*fabs((float)top/height)); - - } - - // clean up - free(buffer); - free(Gtmp); - free(buffer1); - t2 = clock(); - dt = ((double)(t2-t1)) / CLOCKS_PER_SEC; -#ifdef DCRAW_VERBOSE - if (verbose) { - fprintf(stderr,_("elapsed time = %5.3fs\n"),dt); - /* fprintf(stderr,_(" MAIN = %5.3fs\n"), - (double)t2_main/CLOCKS_PER_SEC); */ - } -#endif - - -#undef TS -//#undef border -//#undef border2 -#undef PIX_SORT -#undef SQR - -} - - - diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL3/COPYRIGHT b/core/libs/rawengine/libraw/demosaic-pack-GPL3/COPYRIGHT deleted file mode 100644 index 8a459fa8e8..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL3/COPYRIGHT +++ /dev/null @@ -1,15 +0,0 @@ - -AMaZE demosaic algorithm (Aliasing Minimization and Zipper Elimination) -copyright (c) 2008-2010 Emil Martinec -incorporating ideas of Luis Sanz Rodrigues and Paul Lee - -amaze_interpolate_RT.cc is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. See LICENSE.txt for details. - - -LibRaw adaptation and integration Copyright (C) 2010 Christos Stamatopoulos. - - - diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL3/Changelog b/core/libs/rawengine/libraw/demosaic-pack-GPL3/Changelog deleted file mode 100644 index 4c8699a0d7..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL3/Changelog +++ /dev/null @@ -1,26 +0,0 @@ -2011-02-05 Alex Tutubalin - * green_equilibrate is disabled in half_size mode -2011-01-13 Alex Tutubalin - * removed exposure correction code due to instability - -2011-01-10 Alex Tutubalin - * OpenMP for green equilibration - * Expocorrection before interpolation by Jackues Desmis - -2010-12-20 Alex Tutubalin - * Green equilibration, CFA pixel cleaning and CFA line denoise by - Emil Martinec. Code adaped to LibRaw by Jacques Desmis - -2010-12-13 Alex Tutubalin - * Imported new AMaZE and CA_correct code provided by Jacques Desmis - -2010-11-27 Alex Tutubalin - * malloc changed to calloc to make valgrind happy with - uninitialized values - -2010-11-20 Alex Tutubalin - * Imported actual AMaZE implementation from RawTherapee - * OpenMP with LIBRAW_USE_OPENMP - -2010-11-15 Alex Tutubalin - * Initial revision diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL3/LICENSE.txt b/core/libs/rawengine/libraw/demosaic-pack-GPL3/LICENSE.txt deleted file mode 100644 index 94a9ed024d..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL3/LICENSE.txt +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL3/README b/core/libs/rawengine/libraw/demosaic-pack-GPL3/README deleted file mode 100644 index 2914f6fc1f..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL3/README +++ /dev/null @@ -1,13 +0,0 @@ -** LibRaw-demosaic-pack-GPL3 ** - -This folder contains additional demosaic/image correction methods for -LibRaw (http://www.libraw.org). - -You need LibRaw RAW processing library to use program/algorithm found in this -folder. - -LibRaw can be downloaded from LibRaw origin site: http://www.libraw.org/download -or from GitHub (git://github.com/LibRaw/LibRaw.git) - -Look into README.demosaic-packs in LibRaw distribution for more details. - diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL3/amaze_demosaic_RT.cc b/core/libs/rawengine/libraw/demosaic-pack-GPL3/amaze_demosaic_RT.cc deleted file mode 100644 index d6891ae122..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL3/amaze_demosaic_RT.cc +++ /dev/null @@ -1,1042 +0,0 @@ -//////////////////////////////////////////////////////////////// -// -// AMaZE demosaic algorithm -// (Aliasing Minimization and Zipper Elimination) -// -// copyright (c) 2008-2010 Emil Martinec -// -// incorporating ideas of Luis Sanz Rodrigues and Paul Lee -// -// code dated: May 27, 2010 -// -// amaze_interpolate_RT.cc is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -//////////////////////////////////////////////////////////////// - - -#define TS 512 // Tile size; the image is processed in square tiles to lower memory requirements and facilitate multi-threading -// #define CLASS - -//void RawImageSource::amaze_demosaic_RT() { - -#define SQR(x) ((x)*(x)) - //#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 HCLIP(x) MIN(clip_pt,x) //modifEmil - - - - - // local variables -void CLASS amaze_demosaic_RT() { - double dt; - clock_t t1, t2; - - - float clip_pt =MIN(MIN(pre_mul[0],pre_mul[1]),pre_mul[2]); - - int winx=0, winy=0,winw=width, winh=height; - - //offset of R pixel within a Bayer quartet - int ex, ey; - - //shifts of pointer value to access pixels in vertical and diagonal directions - static const int v1=TS, v2=2*TS, v3=3*TS, p1=-TS+1, p2=-2*TS+2, p3=-3*TS+3, m1=TS+1, m2=2*TS+2, m3=3*TS+3; - - //neighborhood of a pixel - static const int nbr[5] = {-v2,-2,2,v2,0}; - - //tolerance to avoid dividing by zero - static const float eps=1e-5, epssq=1e-10; //tolerance to avoid dividing by zero - - //adaptive ratios threshold - static const float arthresh=0.75; - //nyquist texture test threshold - static const float nyqthresh=0.5; - //diagonal interpolation test threshold - static const float pmthresh=0.25; - //factors for bounding interpolation in saturated regions - static const float lbd=1.0, ubd=1.0; //lbd=0.66, ubd=1.5 alternative values; - - //gaussian on 5x5 quincunx, sigma=1.2 - static const float gaussodd[4] = {0.14659727707323927f, 0.103592713382435f, 0.0732036125103057f, 0.0365543548389495f}; - //gaussian on 5x5, sigma=1.2 - static const float gaussgrad[6] = {0.07384411893421103f, 0.06207511968171489f, 0.0521818194747806f, \ - 0.03687419286733595f, 0.03099732204057846f, 0.018413194161458882f}; - //gaussian on 3x3, sigma =0.7 - static const float gauss1[3] = {0.3376688223162362f, 0.12171198028231786f, 0.04387081413862306f}; - //gaussian on 5x5 alt quincunx, sigma=1.5 - static const float gausseven[2] = {0.13719494435797422f, 0.05640252782101291f}; - //guassian on quincunx grid - static const float gquinc[4] = {0.169917f, 0.108947f, 0.069855f, 0.0287182f}; - - volatile double progress = 0.0; -#ifdef DCRAW_VERBOSE - if (verbose) printf ("AMaZE interpolation v20b OMP[E.Martinec]\n"); -#endif - t1 = clock(); - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -//#pragma omp parallel -#if defined (LIBRAW_USE_OPENMP) -#pragma omp parallel -#endif - - -{ - //position of top/left corner of the tile - int top, left; - // beginning of storage block for tile - char *buffer; - // rgb values - float (*rgb)[3]; - // horizontal gradient - float (*delh); - // vertical gradient - float (*delv); - // square of delh - float (*delhsq); - // square of delv - float (*delvsq); - // gradient based directional weights for interpolation - float (*dirwts)[2]; - // vertically interpolated color differences G-R, G-B - float (*vcd); - // horizontally interpolated color differences - float (*hcd); - // alternative vertical interpolation - float (*vcdalt); - // alternative horizontal interpolation - float (*hcdalt); - // square of vcd - float (*vcdsq); - // square of hcd - float (*hcdsq); - // square of average color difference - float (*cddiffsq); - // weight to give horizontal vs vertical interpolation - float (*hvwt); - // final interpolated color difference - float (*Dgrb)[2]; - // gradient in plus (NE/SW) direction - float (*delp); - // gradient in minus (NW/SE) direction - float (*delm); - // diagonal interpolation of R+B - float (*rbint); - // horizontal curvature of interpolated G (used to refine interpolation in Nyquist texture regions) - float (*Dgrbh2); - // vertical curvature of interpolated G - float (*Dgrbv2); - // difference between up/down interpolations of G - float (*dgintv); - // difference between left/right interpolations of G - float (*dginth); - // diagonal (plus) color difference R-B or G1-G2 - float (*Dgrbp1); - // diagonal (minus) color difference R-B or G1-G2 - float (*Dgrbm1); - // square of diagonal color difference - float (*Dgrbpsq1); - // square of diagonal color difference - float (*Dgrbmsq1); - // tile raw data - float (*cfa); - // relative weight for combining plus and minus diagonal interpolations - float (*pmwt); - // interpolated color difference R-B in plus direction - float (*rbp); - // interpolated color difference R-B in minus direction - float (*rbm); - - // nyquist texture flag 1=nyquist, 0=not nyquist - int (*nyquist); - - - // assign working space - buffer = (char *) malloc((34*sizeof(float)+sizeof(int))*TS*TS); - //merror(buffer,"amaze_interpolate()"); - //memset(buffer,0,(34*sizeof(float)+sizeof(int))*TS*TS); - // rgb array - rgb = (float (*)[3]) buffer; //pointers to array - delh = (float (*)) (buffer + 3*sizeof(float)*TS*TS); - delv = (float (*)) (buffer + 4*sizeof(float)*TS*TS); - delhsq = (float (*)) (buffer + 5*sizeof(float)*TS*TS); - delvsq = (float (*)) (buffer + 6*sizeof(float)*TS*TS); - dirwts = (float (*)[2]) (buffer + 7*sizeof(float)*TS*TS); - vcd = (float (*)) (buffer + 9*sizeof(float)*TS*TS); - hcd = (float (*)) (buffer + 10*sizeof(float)*TS*TS); - vcdalt = (float (*)) (buffer + 11*sizeof(float)*TS*TS); - hcdalt = (float (*)) (buffer + 12*sizeof(float)*TS*TS); - vcdsq = (float (*)) (buffer + 13*sizeof(float)*TS*TS); - hcdsq = (float (*)) (buffer + 14*sizeof(float)*TS*TS); - cddiffsq = (float (*)) (buffer + 15*sizeof(float)*TS*TS); - hvwt = (float (*)) (buffer + 16*sizeof(float)*TS*TS); - Dgrb = (float (*)[2]) (buffer + 17*sizeof(float)*TS*TS); - delp = (float (*)) (buffer + 19*sizeof(float)*TS*TS); - delm = (float (*)) (buffer + 20*sizeof(float)*TS*TS); - rbint = (float (*)) (buffer + 21*sizeof(float)*TS*TS); - Dgrbh2 = (float (*)) (buffer + 22*sizeof(float)*TS*TS); - Dgrbv2 = (float (*)) (buffer + 23*sizeof(float)*TS*TS); - dgintv = (float (*)) (buffer + 24*sizeof(float)*TS*TS); - dginth = (float (*)) (buffer + 25*sizeof(float)*TS*TS); - Dgrbp1 = (float (*)) (buffer + 26*sizeof(float)*TS*TS); - Dgrbm1 = (float (*)) (buffer + 27*sizeof(float)*TS*TS); - Dgrbpsq1 = (float (*)) (buffer + 28*sizeof(float)*TS*TS); - Dgrbmsq1 = (float (*)) (buffer + 29*sizeof(float)*TS*TS); - cfa = (float (*)) (buffer + 30*sizeof(float)*TS*TS); - pmwt = (float (*)) (buffer + 31*sizeof(float)*TS*TS); - rbp = (float (*)) (buffer + 32*sizeof(float)*TS*TS); - rbm = (float (*)) (buffer + 33*sizeof(float)*TS*TS); - - nyquist = (int (*)) (buffer + 34*sizeof(int)*TS*TS); - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - /*double dt; - clock_t t1, t2; - - clock_t t1_init, t2_init = 0; - clock_t t1_vcdhcd, t2_vcdhcd = 0; - clock_t t1_cdvar, t2_cdvar = 0; - clock_t t1_nyqtest, t2_nyqtest = 0; - clock_t t1_areainterp, t2_areainterp = 0; - clock_t t1_compare, t2_compare = 0; - clock_t t1_diag, t2_diag = 0; - clock_t t1_chroma, t2_chroma = 0;*/ - - - // start - //if (verbose) fprintf (stderr,_("AMaZE interpolation ...\n")); - //t1 = clock(); - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - //if (plistener) { - // plistener->setProgressStr ("AMaZE Demosaicing..."); - // plistener->setProgress (0.0); -// } - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - //determine GRBG coset; (ey,ex) is the offset of the R subarray - if (FC(0,0)==1) {//first pixel is G - if (FC(0,1)==0) {ey=0; ex=1;} else {ey=1; ex=0;} - } else {//first pixel is R or B - if (FC(0,0)==0) {ey=0; ex=0;} else {ey=1; ex=1;} - } - /* - int omp_get_nested(void); - omp_set_nested(1); - omp_set_num_threads(4); - omp_set_dynamic(9); -*/ -#if defined (LIBRAW_USE_OPENMP) - -#pragma omp for schedule(dynamic) nowait -#endif - for (top=winy-16; top < winy+height; top += TS-32) - for (left=winx-16; left < winx+width; left += TS-32) { - //location of tile bottom edge - int bottom = MIN( top+TS,winy+height+16); - //location of tile right edge - int right = MIN(left+TS, winx+width+16); - //tile width (=TS except for right edge of image) - int rr1 = bottom - top; - //tile height (=TS except for bottom edge of image) - int cc1 = right - left; - - //tile vars - //counters for pixel location in the image - int row, col; - //min and max row/column in the tile - int rrmin, rrmax, ccmin, ccmax; - //counters for pixel location within the tile - int rr, cc; - //color index 0=R, 1=G, 2=B - int c; - //pointer counters within the tile - int indx, indx1; - //direction counter for nbrs[] - int dir; - //dummy indices - int i, j; - // +1 or -1 - int sgn; - - //color ratios in up/down/left/right directions - float cru, crd, crl, crr; - //adaptive weights for vertical/horizontal/plus/minus directions - float vwt, hwt, pwt, mwt; - //vertical and horizontal G interpolations - float Gintv, Ginth; - //G interpolated in vert/hor directions using adaptive ratios - float guar, gdar, glar, grar; - //G interpolated in vert/hor directions using Hamilton-Adams method - float guha, gdha, glha, grha; - //interpolated G from fusing left/right or up/down - float Ginthar, Ginthha, Gintvar, Gintvha; - //color difference (G-R or G-B) variance in up/down/left/right directions - float Dgrbvvaru, Dgrbvvard, Dgrbhvarl, Dgrbhvarr; - //gradients in various directions - float gradp, gradm, gradv, gradh, gradpm, gradhv; - //color difference variances in vertical and horizontal directions - float vcdvar, hcdvar, vcdvar1, hcdvar1, hcdaltvar, vcdaltvar; - //adaptive interpolation weight using variance of color differences - float varwt; - //adaptive interpolation weight using difference of left-right and up-down G interpolations - float diffwt; - //alternative adaptive weight for combining horizontal/vertical interpolations - float hvwtalt; - //temporary variables for combining interpolation weights at R and B sites - float vo, ve; - //interpolation of G in four directions - float gu, gd, gl, gr; - //variance of G in vertical/horizontal directions - float gvarh, gvarv; - - //Nyquist texture test - float nyqtest; - //accumulators for Nyquist texture interpolation - float sumh, sumv, sumsqh, sumsqv, areawt; - - //color ratios in diagonal directions - float crse, crnw, crne, crsw; - //color differences in diagonal directions - float rbse, rbnw, rbne, rbsw; - //adaptive weights for combining diagonal interpolations - float wtse, wtnw, wtsw, wtne; - //alternate weight for combining diagonal interpolations - float pmwtalt; - //variance of R-B in plus/minus directions - float rbvarp, rbvarm; - - - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - // rgb from input CFA data - // rgb values should be floating point number between 0 and 1 - // after white balance multipliers are applied - // a 16 pixel border is added to each side of the image - - // bookkeeping for borders - if (top(winy+height)) {rrmax=winy+height-top;} else {rrmax=rr1;} - if (right>(winx+width)) {ccmax=winx+width-left;} else {ccmax=cc1;} - - for (rr=rrmin; rr < rrmax; rr++) - for (row=rr+top, cc=ccmin; cc < ccmax; cc++) { - col = cc+left; - c = FC(rr,cc); - indx1=rr*TS+cc; - //rgb[indx1][c] = (rawData[row][col])/65535.0f; - indx=row*width+col; - rgb[indx1][c] = image[indx][c]/65535.0f;//for dcraw implementation - - cfa[indx1] = rgb[indx1][c]; - } - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - //fill borders - if (rrmin>0) { - for (rr=0; rr<16; rr++) - for (cc=ccmin; cc0) { - for (rr=rrmin; rr0 && ccmin>0) { - for (rr=0; rr<16; rr++) - for (cc=0; cc<16; cc++) { - c=FC(rr,cc); - //rgb[(rr)*TS+cc][c] = (rawData[winy+32-rr][winx+32-cc])/65535.0f; - rgb[(rr)*TS+cc][c] = (rgb[(32-rr)*TS+(32-cc)][c]);//for dcraw implementation - cfa[(rr)*TS+cc] = rgb[(rr)*TS+cc][c]; - } - } - if (rrmax0 && ccmax0) { - for (rr=0; rr<16; rr++) - for (cc=0; cc<16; cc++) { - c=FC(rr,cc); - //rgb[(rrmax+rr)*TS+cc][c] = (rawData[(winy+height-rr-2)][(winx+32-cc)])/65535.0f; - rgb[(rrmax+rr)*TS+cc][c] = (image[(height-rr-2)*width+(32-cc)][c])/65535.0f;//for dcraw implementation - cfa[(rrmax+rr)*TS+cc] = rgb[(rrmax+rr)*TS+cc][c]; - } - } - - //end of border fill - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - for (rr=1; rr < rr1-1; rr++) - for (cc=1, indx=(rr)*TS+cc; cc < cc1-1; cc++, indx++) { - - delh[indx] = fabs(cfa[indx+1]-cfa[indx-1]); - delv[indx] = fabs(cfa[indx+v1]-cfa[indx-v1]); - delhsq[indx] = SQR(delh[indx]); - delvsq[indx] = SQR(delv[indx]); - delp[indx] = fabs(cfa[indx+p1]-cfa[indx-p1]); - delm[indx] = fabs(cfa[indx+m1]-cfa[indx-m1]); - - } - - for (rr=2; rr < rr1-2; rr++) - for (cc=2,indx=(rr)*TS+cc; cc < cc1-2; cc++, indx++) { - - dirwts[indx][0] = eps+delv[indx+v1]+delv[indx-v1]+delv[indx];//+fabs(cfa[indx+v2]-cfa[indx-v2]); - //vert directional averaging weights - dirwts[indx][1] = eps+delh[indx+1]+delh[indx-1]+delh[indx];//+fabs(cfa[indx+2]-cfa[indx-2]); - //horizontal weights - - if (FC(rr,cc)&1) { - //for later use in diagonal interpolation - //Dgrbp1[indx]=2*cfa[indx]-(cfa[indx-p1]+cfa[indx+p1]); - //Dgrbm1[indx]=2*cfa[indx]-(cfa[indx-m1]+cfa[indx+m1]); - Dgrbpsq1[indx]=(SQR(cfa[indx]-cfa[indx-p1])+SQR(cfa[indx]-cfa[indx+p1])); - Dgrbmsq1[indx]=(SQR(cfa[indx]-cfa[indx-m1])+SQR(cfa[indx]-cfa[indx+m1])); - } - } - - //t2_init += clock()-t1_init; - // end of tile initialization - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - //interpolate vertical and horizontal color differences - //t1_vcdhcd = clock(); - - for (rr=4; rr 0.8*clip_pt || Gintvha > 0.8*clip_pt || Ginthha > 0.8*clip_pt) { - //use HA if highlights are (nearly) clipped - guar=guha; gdar=gdha; glar=glha; grar=grha; - vcd[indx]=vcdalt[indx]; hcd[indx]=hcdalt[indx]; - } - - //differences of interpolations in opposite directions - dgintv[indx]=MIN(SQR(guha-gdha),SQR(guar-gdar)); - dginth[indx]=MIN(SQR(glha-grha),SQR(glar-grar)); - - //dgintv[indx]=SQR(guar-gdar); - //dginth[indx]=SQR(glar-grar); - - //vcdsq[indx] = SQR(vcd[indx]); - //hcdsq[indx] = SQR(hcd[indx]); - //cddiffsq[indx] = SQR(vcd[indx]-hcd[indx]); - } - //t2_vcdhcd += clock() - t1_vcdhcd; - - //t1_cdvar = clock(); - for (rr=4; rr0) { - if (3*hcd[indx] > (Ginth+cfa[indx])) { - hcd[indx]=-ULIM(Ginth,cfa[indx-1],cfa[indx+1])+cfa[indx]; - } else { - hwt = 1-3*hcd[indx]/(eps+Ginth+cfa[indx]); - hcd[indx]=hwt*hcd[indx] + (1-hwt)*(-ULIM(Ginth,cfa[indx-1],cfa[indx+1])+cfa[indx]); - } - } - if (vcd[indx]>0) { - if (3*vcd[indx] > (Gintv+cfa[indx])) { - vcd[indx]=-ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])+cfa[indx]; - } else { - vwt = 1-3*vcd[indx]/(eps+Gintv+cfa[indx]); - vcd[indx]=vwt*vcd[indx] + (1-vwt)*(-ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])+cfa[indx]); - } - } - - if (Ginth > clip_pt) hcd[indx]=-ULIM(Ginth,cfa[indx-1],cfa[indx+1])+cfa[indx];//for RT implementation - if (Gintv > clip_pt) vcd[indx]=-ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])+cfa[indx]; - //if (Ginth > pre_mul[c]) hcd[indx]=-ULIM(Ginth,cfa[indx-1],cfa[indx+1])+cfa[indx];//for dcraw implementation - //if (Gintv > pre_mul[c]) vcd[indx]=-ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])+cfa[indx]; - - } else {//R or B site - - Ginth = hcd[indx]+cfa[indx];//interpolated G - Gintv = vcd[indx]+cfa[indx]; - - if (hcd[indx]<0) { - if (3*hcd[indx] < -(Ginth+cfa[indx])) { - hcd[indx]=ULIM(Ginth,cfa[indx-1],cfa[indx+1])-cfa[indx]; - } else { - hwt = 1+3*hcd[indx]/(eps+Ginth+cfa[indx]); - hcd[indx]=hwt*hcd[indx] + (1-hwt)*(ULIM(Ginth,cfa[indx-1],cfa[indx+1])-cfa[indx]); - } - } - if (vcd[indx]<0) { - if (3*vcd[indx] < -(Gintv+cfa[indx])) { - vcd[indx]=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])-cfa[indx]; - } else { - vwt = 1+3*vcd[indx]/(eps+Gintv+cfa[indx]); - vcd[indx]=vwt*vcd[indx] + (1-vwt)*(ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])-cfa[indx]); - } - } - - if (Ginth > clip_pt) hcd[indx]=ULIM(Ginth,cfa[indx-1],cfa[indx+1])-cfa[indx];//for RT implementation - if (Gintv > clip_pt) vcd[indx]=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])-cfa[indx]; - //if (Ginth > pre_mul[c]) hcd[indx]=ULIM(Ginth,cfa[indx-1],cfa[indx+1])-cfa[indx];//for dcraw implementation - //if (Gintv > pre_mul[c]) vcd[indx]=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1])-cfa[indx]; - } - - - vcdsq[indx] = SQR(vcd[indx]); - hcdsq[indx] = SQR(hcd[indx]); - cddiffsq[indx] = SQR(vcd[indx]-hcd[indx]); - } - - for (rr=6; rr0 && fabs(0.5-diffwt)0) {nyquist[indx]=1;}//nyquist=1 for nyquist region - } - - for (rr=8; rr4) nyquist[indx]=1; - //or not - if (areawt<4) nyquist[indx]=0; - } - - //t2_nyqtest += clock() - t1_nyqtest; - // end of Nyquist test - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // in areas of Nyquist texture, do area interpolation - //t1_areainterp = clock(); - for (rr=8; rr0.5) Dgrb[indx][0]=vcd[indx]; - rgb[indx][1] = cfa[indx] + Dgrb[indx][0];//evaluate G (finally!) - - //local curvature in G (preparation for nyquist refinement step) - if (nyquist[indx]) { - Dgrbh2[indx] = SQR(rgb[indx][1] - 0.5*(rgb[indx-1][1]+rgb[indx+1][1])); - Dgrbv2[indx] = SQR(rgb[indx][1] - 0.5*(rgb[indx-v1][1]+rgb[indx+v1][1])); - } else { - Dgrbh2[indx] = Dgrbv2[indx] = 0; - } - } - - //end of standard interpolation - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // refine Nyquist areas using G curvatures - - for (rr=8; rr clip_pt) rbp[indx]=ULIM(rbp[indx],cfa[indx-p1],cfa[indx+p1]);//for RT implementation - if (rbm[indx] > clip_pt) rbm[indx]=ULIM(rbm[indx],cfa[indx-m1],cfa[indx+m1]); - //c=2-FC(rr,cc);//for dcraw implementation - //if (rbp[indx] > pre_mul[c]) rbp[indx]=ULIM(rbp[indx],cfa[indx-p1],cfa[indx+p1]); - //if (rbm[indx] > pre_mul[c]) rbm[indx]=ULIM(rbm[indx],cfa[indx-m1],cfa[indx+m1]); - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - //rbint[indx] = 0.5*(cfa[indx] + (rbp*rbvarm+rbm*rbvarp)/(rbvarp+rbvarm));//this is R+B, interpolated - } - - - - for (rr=10; rr clip_pt) Ginth=ULIM(Ginth,cfa[indx-1],cfa[indx+1]);//for RT implementation - if (Gintv > clip_pt) Gintv=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1]); - //c=FC(rr,cc);//for dcraw implementation - //if (Ginth > pre_mul[c]) Ginth=ULIM(Ginth,cfa[indx-1],cfa[indx+1]); - //if (Gintv > pre_mul[c]) Gintv=ULIM(Gintv,cfa[indx-v1],cfa[indx+v1]); - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - rgb[indx][1] = Ginth*(1-hvwt[indx]) + Gintv*hvwt[indx]; - //rgb[indx][1] = 0.5*(rgb[indx][1]+0.25*(rgb[indx-v1][1]+rgb[indx+v1][1]+rgb[indx-1][1]+rgb[indx+1][1])); - Dgrb[indx][0] = rgb[indx][1]-cfa[indx]; - - //rgb[indx][2-FC(rr,cc)]=2*rbint[indx]-cfa[indx]; - } - //end of diagonal interpolation correction - //t2_diag += clock() - t1_diag; - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - //t1_chroma = clock(); - //fancy chrominance interpolation - //(ey,ex) is location of R site - for (rr=13-ey; rr -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define SQRF(x) (((float)x)*((float)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) - -void CLASS cfa_impulse_gauss(float lclean, float cclean) -{ - double dt; - clock_t t1, t2; - int winx=0, winy=0,winw=width, winh=height; - - int compt=0, compt10=0,compt50=0,compt250=0,compt500=0,comptmax=0; - static const int border=8; - int rayo=1,i,d; - int compte1=0; - static const float eps1=1e-10; - -#ifdef DCRAW_VERBOSE - if (verbose) fprintf (stderr,_("CFA impulse-hot and gaussian denoise [E.Martinec +JD] g:%1.4f br:%1.4f\n"), lclean,cclean); -#endif - t1 = clock(); - border_interpolate(16); - float noisevar=SQRF(lclean); - float noisevarbr=SQRF(cclean); - -#pragma omp parallel -{ - int top,left; - char *buffer; // TS*TS*20 - float (*rgb)[3]; // TS*TS*12 - float (*lpf); // TS*TS*4 - float (*hpf); // TS*TS*4 - - // assign working space - buffer = (char *) calloc((4*sizeof(float)+sizeof(int))*TS*TS,1); - - // rgb array - rgb = (float (*)[3]) buffer; //pointers to rows of array - lpf = (float (*)) (buffer + 3*sizeof(float)*TS*TS); - hpf = (float (*)) (buffer + 4*sizeof(float)*TS*TS); - - //This is stuff from AMaZE, hope it makes sense here - - // Fill border pixels -// border_interpolate(16); - // Fill G interpolated values with border interpolation and input values - // Main algorithm: Tile loop - -#if defined (LIBRAW_USE_OPENMP) -#pragma omp for schedule(dynamic) nowait -#endif - for (top=0; top < winh-16; top += TS-32) - for (left=0; left < winw-16; left += TS-32) { - - int bottom = MIN( top+TS,winh); - int right = MIN(left+TS, winw); - int rr1 = bottom - top; - int cc1 = right - left; - - int rr,cc; - int c; - int row, col; - int indx; - float hfvar[3]; - float gin, g[8]; - float norm; - float wtdsum; - int dir,dirwt; - float rbin,rb[8],hfnbrave; - float v1; - /* t1_main = clock(); */ - // rgb from input CFA data - /* rgb values should be floating point number between 0 and 1 - after white balance multipliers are applied */ - for (rr=0; rr < rr1; rr++) - for (row=rr+top, cc=0; cc < cc1; cc++) { - col = cc+left; - c = FC(rr,cc); - //if(info!=0) img[row*width+col][c]=image[row*width+col][c]; - rgb[rr*TS+cc][c] = image[row*width+col][c]/65535.0f; - } - for (c=0; c<3; c++){hfvar[c]=0.0f;} - - //The cleaning algorithm starts here - - for (rr=2; rr < rr1-1; rr++) - for (cc=2; cc < cc1-1; cc++) { - c = FC(rr,cc); - if (c==1) { - //G pixel neighbor average (nearest neighbors on quincunx grid) - gin=rgb[(rr)*TS+cc][c]; - g[0]=rgb[(rr-2)*TS+cc][c]; - g[1]=rgb[(rr-1)*TS+cc-1][c]; - g[2]=rgb[(rr-1)*TS+cc+1][c]; - g[3]=rgb[(rr)*TS+cc-2][c]; - g[4]=rgb[(rr)*TS+cc+2][c]; - g[5]=rgb[(rr+1)*TS+cc-1][c]; - g[6]=rgb[(rr+1)*TS+cc+1][c]; - g[7]=rgb[(rr+2)*TS+cc][c]; - //evaluate directional weighted sum of neighbors - norm=0.0f; - wtdsum=0.0f; - for (dir=0; dir<8; dir++){ - dirwt=1/(SQRF(gin-g[dir])+noisevar+eps1);//JD - norm+=dirwt; - wtdsum+=g[dir]*dirwt; - } - wtdsum=wtdsum/norm; - //low pass and high pass filters from sum and difference - lpf[(rr)*TS+cc]=(gin+wtdsum)/2; - hpf[(rr)*TS+cc]=(gin-wtdsum)/2; - hfvar[c]=hfvar[c]+SQRF(hpf[(rr)*TS+cc]);//running total for variance - } - else { - - //R or B pixel neighbor average - rbin=rgb[(rr)*TS+cc][c]; - rb[0]=rgb[(rr-2)*TS+cc-2][c]; - rb[1]=rgb[(rr-2)*TS+cc][c]; - rb[2]=rgb[(rr-2)*TS+cc+2][c]; - rb[3]=rgb[(rr)*TS+cc-2][c]; - rb[4]=rgb[(rr)*TS+cc+2][c]; - rb[5]=rgb[(rr+2)*TS+cc-2][c]; - rb[6]=rgb[(rr+2)*TS+cc][c]; - rb[7]=rgb[(rr+2)*TS+cc+2][c]; - //evaluate directional weights - norm=0.0f; - wtdsum=0.0f; - for (dir=0; dir<8; dir++) - { - dirwt=1/(SQRF(rbin-rb[dir])+noisevarbr+eps1);//JD - norm+=dirwt; - wtdsum+=rb[dir]*dirwt; - } - wtdsum=wtdsum/norm; - //low pass and high pass filters from sum and difference - lpf[(rr)*TS+cc]=(rbin+wtdsum)/2; - hpf[(rr)*TS+cc]=(rbin-wtdsum)/2; - hfvar[c]=hfvar[c]+SQRF(hpf[(rr)*TS+cc]);//running total for variance - } - //end initialization - } - //normalize high frequency variances of color channels - hfvar[1]=hfvar[1]/(0.5f*(rr1-4)*(cc1-4)); - hfvar[0]=hfvar[0]/(0.25f*(rr1-4)*(cc1-4)); - hfvar[2]=hfvar[2]/(0.25f*(rr1-4)*(cc1-4)); - //now smooth the cfa data - for (rr=4; rr < rr1-3; rr++) - for (cc=4; cc < cc1-3; cc++) { - c = FC(rr,cc); - - if (c==1) { - //G pixel high freq neighbor average from closest eight neighbors - hfnbrave=0.125f*(hpf[(rr-2)*TS+cc]+hpf[(rr-1)*TS+cc-1]+hpf[(rr-1)*TS+cc+1]+hpf[(rr)*TS+cc-2]+ \ - hpf[(rr)*TS+cc+2]+hpf[(rr+1)*TS+cc-1]+hpf[(rr+1)*TS+cc+1]+hpf[(rr+2)*TS+cc]); - } - else { - //R or B pixel high freq neighbor average from closest eight neighbors - - hfnbrave=0.125f*(hpf[(rr-2)*TS+cc-2]+hpf[(rr-2)*TS+cc]+hpf[(rr-2)*TS+cc+2]+hpf[(rr)*TS+cc-2]+ \ - hpf[(rr)*TS+cc+2]+hpf[(rr+2)*TS+cc-2]+hpf[(rr+2)*TS+cc]+hpf[(rr+2)*TS+cc+2]); - } - /* smooth high frequencies if they are much more than tile variance, using Wiener filter */ - hpf[(rr)*TS+cc]=hpf[(rr)*TS+cc]*hfvar[c]/(SQRF(hpf[(rr)*TS+cc]-hfnbrave)+hfvar[c]); - /* reconstruct cfa data */ - rgb[(rr)*TS+cc][c]=lpf[(rr)*TS+cc]+hpf[(rr)*TS+cc]; - } - - // copy smoothed results back to image matrix; - for (rr=border; rr < rr1-border; rr++) - for (row=rr+top, cc=border; cc < cc1-border; cc++) { - col = cc + left; - indx = row*width + col; - c = FC(row,col); - v1 = rgb[(rr)*TS+cc][c]; - // modif JD - /* if(c==1 && noisevar==0) image[indx][c]=img[indx][c]; - else if (c==0 && noisevarbr==0) image[indx][c]=img[indx][c]; - else if (c==2 && noisevarbr==0) image[indx][c]=img[indx][c]; - else */ - image[indx][c] = CLIP((int)(65535.0f*v1 + 0.5f)); - /* if(info!=0) { - if(abs(image[indx][c]-img[indx][c]) < 5) compt++; - else if(abs(image[indx][c]-img[indx][c]) < 50) compt10++; - else if(abs(image[indx][c]-img[indx][c]) < 500) compt50++; - else if(abs(image[indx][c]-img[indx][c]) < 2500) compt250++; - else if(abs(image[indx][c]-img[indx][c]) < 5000) compt500++; - else if(abs(image[indx][c]-img[indx][c]) >= 5000) comptmax++;} - */ - } - //free(buffer); - } - // clean up - free(buffer); - } - //JD - //free(img); -// if (info!=0) { printf("DeltaRGB < 5=%i 50=%i 500=%i 2500=%i 5000=%i >5000=%i\n",compt,compt10,compt50,compt250,compt500,comptmax);} - // done - t2 = clock(); - dt = ((double)(t2-t1)) / CLOCKS_PER_SEC; -#ifdef DCRAW_VERBOSE - if (verbose) { - fprintf(stderr,_("done in = %5.3fs\n"),dt); - /* fprintf(stderr,_(" MAIN = %5.3fs\n"), - (double)t2_main/CLOCKS_PER_SEC); */ - } -#endif - -} -//} -#undef TS -#undef TA diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL3/cfa_linedn_new.c b/core/libs/rawengine/libraw/demosaic-pack-GPL3/cfa_linedn_new.c deleted file mode 100644 index fc8004a28a..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL3/cfa_linedn_new.c +++ /dev/null @@ -1,221 +0,0 @@ -// CFA line denoise by DCT filtering -// copyright Emil Martinec -// all rights reserved -// 3/12/2010 and november 2010 -#define TS 256 // Tile size -//modified by Jacques Desmis - december 2010 -//#define CLASS - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "shrtdct_float.c" - - -#define SQRF(x) (((float)x)*((float)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) - -void CLASS cfa_linedn(float linenoise){ - double dt; - clock_t t1, t2; - - float eps=1e-5; //tolerance to avoid dividing by zero - const float clip_pt = (1.0 / MIN(MIN(pre_mul[0],pre_mul[1]),pre_mul[2])); // for highlights - const float gauss[5] = {0.20416368871516755, 0.18017382291138087, 0.1238315368057753, 0.0662822452863612, 0.02763055063889883}; - const float rolloff[8] = {0, 0.135335, 0.249352, 0.411112, 0.606531, 0.800737, 0.945959, 1}; //gaussian with sigma=3 - const float window[8] = {0, .25, .75, 1, 1, .75, .25, 0}; //sine squared - float aarr[4][8][8], *bbrr[4][8], **dctblock[4]; - for (int j=0; j<4; j++) { - for (int i = 0; i < 8; i++) - bbrr[j][i] = aarr[j][i]; - dctblock[j] = bbrr[j]; - } -#ifdef DCRAW_VERBOSE - if (verbose) fprintf (stderr,_("CFA line denoise v2b OMP [E.Martinec] %1.4f \n"), linenoise); -#endif - t1 = clock(); - - float noisevar=SQRF(3*linenoise); // _noise_ (as a fraction of saturation) is input to the algorithm -#pragma omp parallel -{ - char *buffer; // TS*TS*16 - float (*cfain); // TS*TS*4 - float (*cfablur); // TS*TS*4 - float (*cfadiff); // TS*TS*4 - float (*cfadn); // TS*TS*4 - - - - - // assign working space - buffer = (char *) calloc((3*sizeof(float)+sizeof(int))*TS*TS,1);// 16 - cfain = (float (*)) buffer; //pointers to rows of array - cfablur = (float (*)) (buffer + sizeof(float)*TS*TS); //4 - cfadiff = (float (*)) (buffer + 2*sizeof(float)*TS*TS);//8 - cfadn = (float (*)) (buffer + 3*sizeof(float)*TS*TS);//12 - - - // Main algorithm: Tile loop -#if defined (LIBRAW_USE_OPENMP) -#pragma omp for schedule(dynamic) nowait -#endif - for (int top=0; top < height-16; top += TS-32) - for (int left=0; left < width-16; left += TS-32) { - int bottom = MIN( top+TS,height); - int right = MIN(left+TS, width); - int rr1 = bottom - top; - int cc1 = right - left; - int numrows = bottom - top; - int numcols = right - left; - // load CFA data - /* rgb values should be floating point number between 0 and 1 - after white balance multipliers are applied; - data should be in linear gamma space */ - for (int rr=0; rr < rr1; rr++) - for (int cc=0, row=rr+top; cc < cc1; cc++) { - int col = cc+left; - int c = FC(rr,cc); - cfain[(rr)*TS+cc] = image[row*width+col][c]/65535.0; - } - //pad the block to a multiple of 16 on both sides - if (cc1 < TS) { - int indx=cc1 % 16; - for (int i=0; i<(16-indx); i++) - for (int rr=0; rr(linehvar[0]+linehvar[1])) {//horizontal lines - for (int i=1; i<8; i++) { - dctblock[0][0][i] *= 0.5*(noisefactor[0][i][1]+noisefactor[1][i][1]);//or should we use MIN??? - dctblock[1][0][i] *= 0.5*(noisefactor[0][i][1]+noisefactor[1][i][1]);//or should we use MIN??? - } - } - if (4*noisevar>(linehvar[2]+linehvar[3])) {//horizontal lines - for (int i=1; i<8; i++) { - dctblock[2][0][i] *= 0.5*(noisefactor[2][i][1]+noisefactor[3][i][1]);//or should we use MIN??? - dctblock[3][0][i] *= 0.5*(noisefactor[2][i][1]+noisefactor[3][i][1]);//or should we use MIN??? - } - } - //vertical lines - if (4*noisevar>(linevvar[0]+linevvar[2])) {//vertical lines - for (int i=1; i<8; i++) { - dctblock[0][i][0] *= 0.5*(noisefactor[0][i][0]+noisefactor[2][i][0]);//or should we use MIN??? - dctblock[2][i][0] *= 0.5*(noisefactor[0][i][0]+noisefactor[2][i][0]);//or should we use MIN??? - } - } - if (4*noisevar>(linevvar[1]+linevvar[3])) {//vertical lines - for (int i=1; i<8; i++) { - dctblock[1][i][0] *= 0.5*(noisefactor[1][i][0]+noisefactor[3][i][0]);//or should we use MIN??? - dctblock[3][i][0] *= 0.5*(noisefactor[1][i][0]+noisefactor[3][i][0]);//or should we use MIN??? - } - } - for (int ey=0; ey<2; ey++) // (ex,ey) specify RGGB subarray - for (int ex=0; ex<2; ex++) { - ddct8x8s(1, dctblock[2*ey+ex]); //inverse DCT - - for (int i=0; i<8; i++) - for (int j=0; j<8; j++) { - cfadn[(rr+2*i+ey)*TS+cc+2*j+ex] += window[i]*window[j]*dctblock[2*ey+ex][i][j]; - } - } - } - } - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - // copy smoothed results back to image matrix - for (int rr=16; rr < rr1-16; rr++) - for (int cc=16,row=rr+top; cc < cc1-16; cc++) { - int col = cc + left; - int indx = row*width + col; - int c = FC(row,col); - if (image[indx][c] <65535*0.8*clip_pt && cfadn[(rr)*TS+cc]<0.8*clip_pt) - image[indx][c] = CLIP((int)(65535*cfadn[(rr)*TS+cc]+ 0.5)); } - } - - // clean up - free(buffer); - } - // done - t2 = clock(); - dt = ((double)(t2-t1)) / CLOCKS_PER_SEC; -#ifdef DCRAW_VERBOSE - if (verbose) { - fprintf(stderr,_("elapsed time = %5.3fs\n"),dt); - } -#endif - -} -#undef TS -//#undef TA diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL3/green_equi.c b/core/libs/rawengine/libraw/demosaic-pack-GPL3/green_equi.c deleted file mode 100644 index 356138f59e..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL3/green_equi.c +++ /dev/null @@ -1,218 +0,0 @@ -// CFA pixel cleaning via directional average -// by Emil Martinec -// 2/18/2010 -#define TS 256 // Tile size -//modification OMP J.Desmis - december 2010 -//#define CLASS -/*#define ushort UshORt -typedef unsigned char uchar; - typedef unsigned short ushort;*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define SQR(x) ((x)*(x)) - - -void CLASS green_equilibrate(float thresh)//for dcraw implementation -{ - // local variables - static const int border=8; - static const int border2=16; - static const int v1=TS, v2=2*TS, v3=3*TS, /*v4=4*TS,*/ p1=-TS+1, p2=-2*TS+2, p3=-3*TS+3, m1=TS+1, m2=2*TS+2, m3=3*TS+3; - -//+ int height=H, width=W; //for RT only - int top, left; - - if(half_size) return; - - int verbose=1; - - static const float eps=1.0; //tolerance to avoid dividing by zero - //static const float thresh=0.03; //threshold for performing green equilibration; max percentage difference of G1 vs G2 - // G1-G2 differences larger than this will be assumed to be Nyquist texture, and left untouched - static const float diffthresh=0.25; //threshold for texture, not to be equilibrated - - double dt; - clock_t t1, t2; - - //clock_t t1_main, t2_main = 0; - - // start -#ifdef DCRAW_VERBOSE - if (verbose) fprintf(stderr,_("Green equilibration v1 OMP [E.Martinec] %1.3f...\n"),thresh); -#endif - - - - t1 = clock(); -#if defined (LIBRAW_USE_OPENMP) -#pragma omp parallel -#endif -{ - int top,left; - char *buffer; // TS*TS*16 - float (*cfa); // TS*TS*4 - float (*checker); // TS*TS*4 - float (*gvar); // TS*TS*4 - float (*gdiffv); // TS*TS*4 - float (*gdiffh); // TS*TS*4 - - /* assign working space */ - buffer = (char *) calloc((5*sizeof(float)+sizeof(int))*TS*TS,1); - //merror(buffer,"green_equil()"); - memset(buffer,0,5*sizeof(float)*TS*TS); - - cfa = (float (*)) buffer; - checker = (float (*)) (buffer + sizeof(float)*TS*TS); - gvar = (float (*)) (buffer + 2*sizeof(float)*TS*TS); - gdiffv = (float (*)) (buffer + 3*sizeof(float)*TS*TS); - gdiffh = (float (*)) (buffer + 4*sizeof(float)*TS*TS); - - - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - // Fill G interpolated values with border interpolation and input values - // Main algorithm: Tile loop -//#pragma omp parallel for shared(image,height,width) private(top,left) schedule(dynamic) -#if defined (LIBRAW_USE_OPENMP) -#pragma omp for schedule(dynamic) nowait -#endif - for (top=0; top < height-border; top += TS-border2) - for (left=0; left < width-border; left += TS-border2) { - int bottom = MIN( top+TS,height); - int right = MIN(left+TS, width); - int numrows = bottom - top; - int numcols = right - left; - - int row, col; - int rr, cc, c, indx; - int vote1, vote2; - - float val1; - - float gin, gse, gsw, gne, gnw, wtse, wtsw, wtne, wtnw; - float gu, gd, gl, gr; - float mcorr, pcorr; - float ginterp; - float diffvarh, diffvarv, hvwt; - // rgb from input CFA data - /* rgb values should be floating point number between 0 and 1 - after white balance multipliers are applied */ - for (rr=0; rr < numrows; rr++) - for (row=rr+top, cc=0; cc < numcols; cc++) { - col = cc+left; - cfa[rr*TS+cc] = image[row*width+col][FC(row,col)];//for dcraw implementation -// cfa[rr*TS+cc] = ri->data[row][col]; - } - - //The green equilibration algorithm starts here - - for (rr=2; rr < numrows-2; rr++) - //for (cc=3-(FC(rr,2)&1), indx=rr*TS+cc; cc < numcols-2; cc+=2, indx+=2) { - for (indx=rr*TS+2; indx < rr*TS+numcols-2; indx++) { - - if (FC(rr,indx)&1) { - pcorr = (cfa[indx+p1]-cfa[indx])*(cfa[indx-p1]-cfa[indx]); - mcorr = (cfa[indx+m1]-cfa[indx])*(cfa[indx-m1]-cfa[indx]); - - if (pcorr>0 && mcorr>0) {checker[indx]=1;} else {checker[indx]=0;} - - //checker[indx]=1;//test what happens if we always interpolate - } else { - gu=cfa[indx-v1]+0.5*(cfa[indx]-cfa[indx-v2]); - gd=cfa[indx+v1]+0.5*(cfa[indx]-cfa[indx+v2]); - gl=cfa[indx-1]+0.5*(cfa[indx]-cfa[indx-2]); - gr=cfa[indx+1]+0.5*(cfa[indx]-cfa[indx+2]); - - gdiffh[indx] = SQR((gl-gr)/(eps+gl+gr)); - gdiffv[indx] = SQR((gu-gd)/(eps+gu+gd)); - - //gvar[indx] = 0.25*(gu*gu+gd*gd+gl*gl+gr*gr)-SQR(0.25*(gu+gd+gl+gr)); - } - } - - - - //now smooth the cfa data - for (rr=6; rr < numrows-6; rr++) - for (cc=7-(FC(rr,2)&1), indx=rr*TS+cc; cc < numcols-6; cc+=2, indx+=2) { - if (checker[indx]) { - - diffvarh = eps+(gdiffh[indx-v1]+gdiffh[indx-1]+gdiffh[indx+1]+gdiffh[indx+v1]); - diffvarv = eps+(gdiffv[indx-v1]+gdiffv[indx-1]+gdiffv[indx+1]+gdiffv[indx+v1]); - hvwt = fabs(diffvarv-diffvarh)/(diffvarv+diffvarh); - - - vote1=(checker[indx-v2]+checker[indx-2]+checker[indx+2]+checker[indx+v2]); - vote2=(checker[indx-m1]+checker[indx+p1]+checker[indx-p1]+checker[indx+m1]); - if (vote1>0 && vote2>0 && hvwt 0.125*(gvar[indx-1]+gvar[indx+1]+gvar[indx-v1]+gvar[indx+v1])) &&*/ ((ginterp-gin) < thresh*(ginterp+gin)) ) { - cfa[indx]=0.5*(ginterp+gin); - } - - } - } - } - - // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - - // copy smoothed results back to image matrix - for (rr=border; rr < numrows-border; rr++) - for (row=rr+top, cc=border+1-(FC(rr,2)&1), indx=rr*TS+cc; cc < numcols-border; cc+=2, indx+=2) { - if (cfa[indx]<1) continue; - col = cc + left; - c = FC(row,col); - image[row*width + col][c] = CLIP((int)(cfa[indx] + 0.5)); //for dcraw implementation - //ri->data[row][col] = CLIP((int)(cfa[indx] + 0.5)); - } - - // clean up - //} - - } - free(buffer); - - - //done - } - t2 = clock(); - dt = ((double)(t2-t1)) / CLOCKS_PER_SEC; -#ifdef DCRAW_VERBOSE - - if (verbose) { - fprintf(stderr,_("elapsed time = %5.3fs\n"),dt); - } -#endif - -} -#undef TS diff --git a/core/libs/rawengine/libraw/demosaic-pack-GPL3/shrtdct_float.c b/core/libs/rawengine/libraw/demosaic-pack-GPL3/shrtdct_float.c deleted file mode 100644 index 5d8ab33ae7..0000000000 --- a/core/libs/rawengine/libraw/demosaic-pack-GPL3/shrtdct_float.c +++ /dev/null @@ -1,175 +0,0 @@ -/* -Short Discrete Cosine Transform - data length :8x8 - method :row-column, radix 4 FFT -functions - ddct8x8s : 8x8 DCT -function prototypes - void ddct8x8s(int isgn, float **a); -*/ - - -/* --------- 8x8 DCT (Discrete Cosine Transform) / Inverse of DCT -------- - [definition] - Normalized 8x8 IDCT - C[k1][k2] = (1/4) * sum_j1=0^7 sum_j2=0^7 - a[j1][j2] * s[j1] * s[j2] * - cos(pi*j1*(k1+1/2)/8) * - cos(pi*j2*(k2+1/2)/8), 0<=k1<8, 0<=k2<8 - (s[0] = 1/sqrt(2), s[j] = 1, j > 0) - Normalized 8x8 DCT - C[k1][k2] = (1/4) * s[k1] * s[k2] * sum_j1=0^7 sum_j2=0^7 - a[j1][j2] * - cos(pi*(j1+1/2)*k1/8) * - cos(pi*(j2+1/2)*k2/8), 0<=k1<8, 0<=k2<8 - (s[0] = 1/sqrt(2), s[j] = 1, j > 0) - [usage] - - ddct8x8s(1, a); - - ddct8x8s(-1, a); - [parameters] - a[0...7][0...7] :input/output data (double **) - output data - a[k1][k2] = C[k1][k2], 0<=k1<8, 0<=k2<8 -*/ - - -/* Cn_kR = sqrt(2.0/n) * cos(pi/2*k/n) */ -/* Cn_kI = sqrt(2.0/n) * sin(pi/2*k/n) */ -/* Wn_kR = cos(pi/2*k/n) */ -/* Wn_kI = sin(pi/2*k/n) */ -#define C8_1R 0.49039264020161522456 -#define C8_1I 0.09754516100806413392 -#define C8_2R 0.46193976625564337806 -#define C8_2I 0.19134171618254488586 -#define C8_3R 0.41573480615127261854 -#define C8_3I 0.27778511650980111237 -#define C8_4R 0.35355339059327376220 -#define W8_4R 0.70710678118654752440 - - -void ddct8x8s(int isgn, float **a) -{ - int j; - float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; - float xr, xi; - - if (isgn < 0) { - for (j = 0; j <= 7; j++) { - x0r = a[0][j] + a[7][j]; - x1r = a[0][j] - a[7][j]; - x0i = a[2][j] + a[5][j]; - x1i = a[2][j] - a[5][j]; - x2r = a[4][j] + a[3][j]; - x3r = a[4][j] - a[3][j]; - x2i = a[6][j] + a[1][j]; - x3i = a[6][j] - a[1][j]; - xr = x0r + x2r; - xi = x0i + x2i; - a[0][j] = C8_4R * (xr + xi); - a[4][j] = C8_4R * (xr - xi); - xr = x0r - x2r; - xi = x0i - x2i; - a[2][j] = C8_2R * xr - C8_2I * xi; - a[6][j] = C8_2R * xi + C8_2I * xr; - xr = W8_4R * (x1i - x3i); - x1i = W8_4R * (x1i + x3i); - x3i = x1i - x3r; - x1i += x3r; - x3r = x1r - xr; - x1r += xr; - a[1][j] = C8_1R * x1r - C8_1I * x1i; - a[7][j] = C8_1R * x1i + C8_1I * x1r; - a[3][j] = C8_3R * x3r - C8_3I * x3i; - a[5][j] = C8_3R * x3i + C8_3I * x3r; - } - for (j = 0; j <= 7; j++) { - x0r = a[j][0] + a[j][7]; - x1r = a[j][0] - a[j][7]; - x0i = a[j][2] + a[j][5]; - x1i = a[j][2] - a[j][5]; - x2r = a[j][4] + a[j][3]; - x3r = a[j][4] - a[j][3]; - x2i = a[j][6] + a[j][1]; - x3i = a[j][6] - a[j][1]; - xr = x0r + x2r; - xi = x0i + x2i; - a[j][0] = C8_4R * (xr + xi); - a[j][4] = C8_4R * (xr - xi); - xr = x0r - x2r; - xi = x0i - x2i; - a[j][2] = C8_2R * xr - C8_2I * xi; - a[j][6] = C8_2R * xi + C8_2I * xr; - xr = W8_4R * (x1i - x3i); - x1i = W8_4R * (x1i + x3i); - x3i = x1i - x3r; - x1i += x3r; - x3r = x1r - xr; - x1r += xr; - a[j][1] = C8_1R * x1r - C8_1I * x1i; - a[j][7] = C8_1R * x1i + C8_1I * x1r; - a[j][3] = C8_3R * x3r - C8_3I * x3i; - a[j][5] = C8_3R * x3i + C8_3I * x3r; - } - } else { - for (j = 0; j <= 7; j++) { - x1r = C8_1R * a[1][j] + C8_1I * a[7][j]; - x1i = C8_1R * a[7][j] - C8_1I * a[1][j]; - x3r = C8_3R * a[3][j] + C8_3I * a[5][j]; - x3i = C8_3R * a[5][j] - C8_3I * a[3][j]; - xr = x1r - x3r; - xi = x1i + x3i; - x1r += x3r; - x3i -= x1i; - x1i = W8_4R * (xr + xi); - x3r = W8_4R * (xr - xi); - xr = C8_2R * a[2][j] + C8_2I * a[6][j]; - xi = C8_2R * a[6][j] - C8_2I * a[2][j]; - x0r = C8_4R * (a[0][j] + a[4][j]); - x0i = C8_4R * (a[0][j] - a[4][j]); - x2r = x0r - xr; - x2i = x0i - xi; - x0r += xr; - x0i += xi; - a[0][j] = x0r + x1r; - a[7][j] = x0r - x1r; - a[2][j] = x0i + x1i; - a[5][j] = x0i - x1i; - a[4][j] = x2r - x3i; - a[3][j] = x2r + x3i; - a[6][j] = x2i - x3r; - a[1][j] = x2i + x3r; - } - for (j = 0; j <= 7; j++) { - x1r = C8_1R * a[j][1] + C8_1I * a[j][7]; - x1i = C8_1R * a[j][7] - C8_1I * a[j][1]; - x3r = C8_3R * a[j][3] + C8_3I * a[j][5]; - x3i = C8_3R * a[j][5] - C8_3I * a[j][3]; - xr = x1r - x3r; - xi = x1i + x3i; - x1r += x3r; - x3i -= x1i; - x1i = W8_4R * (xr + xi); - x3r = W8_4R * (xr - xi); - xr = C8_2R * a[j][2] + C8_2I * a[j][6]; - xi = C8_2R * a[j][6] - C8_2I * a[j][2]; - x0r = C8_4R * (a[j][0] + a[j][4]); - x0i = C8_4R * (a[j][0] - a[j][4]); - x2r = x0r - xr; - x2i = x0i - xi; - x0r += xr; - x0i += xi; - a[j][0] = x0r + x1r; - a[j][7] = x0r - x1r; - a[j][2] = x0i + x1i; - a[j][5] = x0i - x1i; - a[j][4] = x2r - x3i; - a[j][3] = x2r + x3i; - a[j][6] = x2i - x3r; - a[j][1] = x2i + x3r; - } - } -} - diff --git a/core/libs/rawengine/libraw/internal/aahd_demosaic.cpp b/core/libs/rawengine/libraw/internal/aahd_demosaic.cpp index f5b58ca503..17e7472628 100644 --- a/core/libs/rawengine/libraw/internal/aahd_demosaic.cpp +++ b/core/libs/rawengine/libraw/internal/aahd_demosaic.cpp @@ -1,703 +1,708 @@ /* -*- C++ -*- * File: aahd_demosaic.cpp * Copyright 2013 Anton Petrusevich * Created: Wed May 15, 2013 * * This code is licensed under one of two licenses as you choose: * * 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 * (See file LICENSE.LGPL provided in LibRaw distribution archive for details). * * 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 * (See file LICENSE.CDDL provided in LibRaw distribution archive for details). * */ typedef ushort ushort3[3]; typedef int int3[3]; #ifndef Pnw #define Pnw (-1-nr_width) #define Pn (-nr_width) #define Pne (+1-nr_width) #define Pe (+1) #define Pse (+1+nr_width) #define Ps (+nr_width) #define Psw (-1+nr_width) #define Pw (-1) #endif struct AAHD { int nr_height, nr_width; static const int nr_margin = 4; static const int Thot = 4; static const int Tdead = 4; static const int OverFraction = 8; ushort3 *rgb_ahd[2]; int3 *yuv[2]; char *ndir, *homo[2]; ushort channel_maximum[3], channels_max; ushort channel_minimum[3]; static const float yuv_coeff[3][3]; static float gammaLUT[0x10000]; float yuv_cam[3][3]; LibRaw &libraw; enum { HVSH = 1, HOR = 2, VER = 4, HORSH = HOR | HVSH, VERSH = VER | HVSH, HOT = 8 }; static inline float calc_dist(int c1, int c2) throw () { return c1 > c2 ? (float) c1 / c2 : (float) c2 / c1; } int inline Y(ushort3 &rgb) throw () { return yuv_cam[0][0] * rgb[0] + yuv_cam[0][1] * rgb[1] + yuv_cam[0][2] * rgb[2]; } int inline U(ushort3 &rgb) throw () { return yuv_cam[1][0] * rgb[0] + yuv_cam[1][1] * rgb[1] + yuv_cam[1][2] * rgb[2]; } int inline V(ushort3 &rgb) throw () { return yuv_cam[2][0] * rgb[0] + yuv_cam[2][1] * rgb[1] + yuv_cam[2][2] * rgb[2]; } inline int nr_offset(int row, int col) throw () { return (row * nr_width + col); } ~AAHD(); AAHD(LibRaw &_libraw); void make_ahd_greens(); void make_ahd_gline(int i); void make_ahd_rb(); void make_ahd_rb_hv(int i); void make_ahd_rb_last(int i); void evaluate_ahd(); void combine_image(); void hide_hots(); void refine_hv_dirs(); void refine_hv_dirs(int i, int js); void refine_ihv_dirs(int i); void illustrate_dirs(); void illustrate_dline(int i); }; const float AAHD::yuv_coeff[3][3] = { // YPbPr // { // 0.299f, // 0.587f, // 0.114f }, // { // -0.168736, // -0.331264f, // 0.5f }, // { // 0.5f, // -0.418688f, // -0.081312f } // // Rec. 2020 // Y'= 0,2627R' + 0,6780G' + 0,0593B' // U = (B-Y)/1.8814 = (-0,2627R' - 0,6780G' + 0.9407B) / 1.8814 = -0.13963R - 0.36037G + 0.5B // V = (R-Y)/1.4647 = (0.7373R - 0,6780G - 0,0593B) / 1.4647 = 0.5R - 0.4629G - 0.04049B { +0.2627f, +0.6780f, +0.0593f }, { -0.13963f, -0.36037f, +0.5f }, { +0.5034f, -0.4629f, -0.0405f } }; float AAHD::gammaLUT[0x10000] = { -1.f }; AAHD::AAHD(LibRaw& _libraw) : libraw(_libraw) { nr_height = libraw.imgdata.sizes.iheight + nr_margin * 2; nr_width = libraw.imgdata.sizes.iwidth + nr_margin * 2; rgb_ahd[0] = (ushort3*) calloc(nr_height * nr_width, (sizeof(ushort3) * 2 + sizeof(int3) * 2 + 3)); + if(!rgb_ahd[0]) + throw LIBRAW_EXCEPTION_ALLOC; + rgb_ahd[1] = rgb_ahd[0] + nr_height * nr_width; yuv[0] = (int3 *) (rgb_ahd[1] + nr_height * nr_width); yuv[1] = yuv[0] + nr_height * nr_width; ndir = (char*) (yuv[1] + nr_height * nr_width); homo[0] = ndir + nr_height * nr_width; homo[1] = homo[0] + nr_height * nr_width; channel_maximum[0] = channel_maximum[1] = channel_maximum[2] = 0; channel_minimum[0] = libraw.imgdata.image[0][0]; channel_minimum[1] = libraw.imgdata.image[0][1]; channel_minimum[2] = libraw.imgdata.image[0][2]; int iwidth = libraw.imgdata.sizes.iwidth; for (int i = 0; i < 3; ++i) for (int j = 0; j < 3; ++j) { yuv_cam[i][j] = 0; for (int k = 0; k < 3; ++k) yuv_cam[i][j] += yuv_coeff[i][k] * libraw.imgdata.color.rgb_cam[k][j]; } if (gammaLUT[0] < -0.1f) { float r; for (int i = 0; i < 0x10000; i++) { r = (float) i / 0x10000; gammaLUT[i] = 0x10000 * (r < 0.0181 ? 4.5f * r : 1.0993f * pow(r, 0.45f) - .0993f); } } for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { int col_cache[48]; for (int j = 0; j < 48; ++j) { int c = libraw.COLOR(i, j); if (c == 3) c = 1; col_cache[j] = c; } int moff = nr_offset(i + nr_margin, nr_margin); for (int j = 0; j < iwidth; ++j, ++moff) { int c = col_cache[j % 48]; unsigned short d = libraw.imgdata.image[i * iwidth + j][c]; if (d != 0) { if (channel_maximum[c] < d) channel_maximum[c] = d; if (channel_minimum[c] > d) channel_minimum[c] = d; rgb_ahd[1][moff][c] = rgb_ahd[0][moff][c] = d; } } } channels_max = MAX(MAX(channel_maximum[0], channel_maximum[1]), channel_maximum[2]); } void AAHD::hide_hots() { int iwidth = libraw.imgdata.sizes.iwidth; for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { int js = libraw.COLOR(i, 0) & 1; int kc = libraw.COLOR(i, js); /* * js -- Ð½Ð°Ñ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ñ…-координата, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¿Ð¾Ð¿Ð°Ð´Ð°ÐµÑ‚ мимо извеÑтного зелёного * kc -- извеÑтный цвет в точке Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ */ int moff = nr_offset(i + nr_margin, nr_margin + js); for (int j = js; j < iwidth; j += 2, moff += 2) { ushort3 *rgb = &rgb_ahd[0][moff]; int c = rgb[0][kc]; if ((c > rgb[2 * Pe][kc] && c > rgb[2 * Pw][kc] && c > rgb[2 * Pn][kc] && c > rgb[2 * Ps][kc] && c > rgb[Pe][1] && c > rgb[Pw][1] && c > rgb[Pn][1] && c > rgb[Ps][1]) || (c < rgb[2 * Pe][kc] && c < rgb[2 * Pw][kc] && c < rgb[2 * Pn][kc] && c < rgb[2 * Ps][kc] && c < rgb[Pe][1] && c < rgb[Pw][1] && c < rgb[Pn][1] && c < rgb[Ps][1])) { int chot = c >> Thot; int cdead = c << Tdead; int avg = 0; for (int k = -2; k < 3; k += 2) for (int m = -2; m < 3; m += 2) if (m == 0 && k == 0) continue; else avg += rgb[nr_offset(k, m)][kc]; avg /= 8; if (chot > avg || cdead < avg) { ndir[moff] |= HOT; int dh = ABS(rgb[2 * Pw][kc] - rgb[2 * Pe][kc]) + ABS(rgb[Pw][1] - rgb[Pe][1]) + ABS(rgb[Pw][1] - rgb[Pe][1] + rgb[2 * Pe][kc] - rgb[2 * Pw][kc]); int dv = ABS(rgb[2 * Pn][kc] - rgb[2 * Ps][kc]) + ABS(rgb[Pn][1] - rgb[Ps][1]) + ABS(rgb[Pn][1] - rgb[Ps][1] + rgb[2 * Ps][kc] - rgb[2 * Pn][kc]); int d; if (dv > dh) d = Pw; else d = Pn; rgb_ahd[1][moff][kc] = rgb[0][kc] = (rgb[+2 * d][kc] + rgb[-2 * d][kc]) / 2; } } } js ^= 1; moff = nr_offset(i + nr_margin, nr_margin + js); for (int j = js; j < iwidth; j += 2, moff += 2) { ushort3 *rgb = &rgb_ahd[0][moff]; int c = rgb[0][1]; if ((c > rgb[2 * Pe][1] && c > rgb[2 * Pw][1] && c > rgb[2 * Pn][1] && c > rgb[2 * Ps][1] && c > rgb[Pe][kc] && c > rgb[Pw][kc] && c > rgb[Pn][kc ^ 2] && c > rgb[Ps][kc ^ 2]) || (c < rgb[2 * Pe][1] && c < rgb[2 * Pw][1] && c < rgb[2 * Pn][1] && c < rgb[2 * Ps][1] && c < rgb[Pe][kc] && c < rgb[Pw][kc] && c < rgb[Pn][kc ^ 2] && c < rgb[Ps][kc ^ 2])) { int chot = c >> Thot; int cdead = c << Tdead; int avg = 0; for (int k = -2; k < 3; k += 2) for (int m = -2; m < 3; m += 2) if (k == 0 && m == 0) continue; else avg += rgb[nr_offset(k, m)][1]; avg /= 8; if (chot > avg || cdead < avg) { ndir[moff] |= HOT; int dh = ABS(rgb[2 * Pw][1] - rgb[2 * Pe][1]) + ABS(rgb[Pw][kc] - rgb[Pe][kc]) + ABS(rgb[Pw][kc] - rgb[Pe][kc] + rgb[2 * Pe][1] - rgb[2 * Pw][1]); int dv = ABS(rgb[2 * Pn][1] - rgb[2 * Ps][1]) + ABS(rgb[Pn][kc ^ 2] - rgb[Ps][kc ^ 2]) + ABS( rgb[Pn][kc ^ 2] - rgb[Ps][kc ^ 2] + rgb[2 * Ps][1] - rgb[2 * Pn][1]); int d; if (dv > dh) d = Pw; else d = Pn; rgb_ahd[1][moff][1] = rgb[0][1] = (rgb[+2 * d][1] + rgb[-2 * d][1]) / 2; } } } } } const static double xyz_rgb[3][3] = { { 0.412453, 0.357580, 0.180423 }, { 0.212671, 0.715160, 0.072169 }, { 0.019334, 0.119193, 0.950227 } }; const static float d65_white[3] = { 0.950456f, 1.0f, 1.088754f }; void AAHD::evaluate_ahd() { int hvdir[4] = { Pw, Pe, Pn, Ps }; /* * YUV * */ for (int d = 0; d < 2; ++d) { for (int i = 0; i < nr_width * nr_height; ++i) { ushort3 rgb; for (int c = 0; c < 3; ++c) { rgb[c] = gammaLUT[rgb_ahd[d][i][c]]; } yuv[d][i][0] = Y(rgb); yuv[d][i][1] = U(rgb); yuv[d][i][2] = V(rgb); } } /* */ /* * Lab * float r, cbrt[0x10000], xyz[3], xyz_cam[3][4]; for (int i = 0; i < 0x10000; i++) { r = i / 65535.0; cbrt[i] = r > 0.008856 ? pow((double) r, (double) (1 / 3.0)) : 7.787 * r + 16 / 116.0; } for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) { xyz_cam[i][j] = 0; for (int k = 0; k < 3; k++) xyz_cam[i][j] += xyz_rgb[i][k] * libraw.imgdata.color.rgb_cam[k][j] / d65_white[i]; } for (int d = 0; d < 2; ++d) for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { int moff = nr_offset(i + nr_margin, nr_margin); for (int j = 0; j < libraw.imgdata.sizes.iwidth; j++, ++moff) { xyz[0] = xyz[1] = xyz[2] = 0.5; for (int c = 0; c < 3; c++) { xyz[0] += xyz_cam[0][c] * rgb_ahd[d][moff][c]; xyz[1] += xyz_cam[1][c] * rgb_ahd[d][moff][c]; xyz[2] += xyz_cam[2][c] * rgb_ahd[d][moff][c]; } xyz[0] = cbrt[CLIP((int) xyz[0])]; xyz[1] = cbrt[CLIP((int) xyz[1])]; xyz[2] = cbrt[CLIP((int) xyz[2])]; yuv[d][moff][0] = 64 * (116 * xyz[1] - 16); yuv[d][moff][1] = 64 * 500 * (xyz[0] - xyz[1]); yuv[d][moff][2] = 64 * 200 * (xyz[1] - xyz[2]); } } * Lab */ for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { int moff = nr_offset(i + nr_margin, nr_margin); for (int j = 0; j < libraw.imgdata.sizes.iwidth; j++, ++moff) { int3 *ynr; float ydiff[2][4]; int uvdiff[2][4]; for (int d = 0; d < 2; ++d) { ynr = &yuv[d][moff]; for (int k = 0; k < 4; k++) { ydiff[d][k] = ABS(ynr[0][0] - ynr[hvdir[k]][0]); uvdiff[d][k] = SQR(ynr[0][1] - ynr[hvdir[k]][1]) + SQR(ynr[0][2] - ynr[hvdir[k]][2]); } } float yeps = MIN(MAX(ydiff[0][0], ydiff[0][1]), MAX(ydiff[1][2], ydiff[1][3])); int uveps = MIN(MAX(uvdiff[0][0], uvdiff[0][1]), MAX(uvdiff[1][2], uvdiff[1][3])); for (int d = 0; d < 2; d++) { ynr = &yuv[d][moff]; for (int k = 0; k < 4; k++) if (ydiff[d][k] <= yeps && uvdiff[d][k] <= uveps) { homo[d][moff + hvdir[k]]++; if (k / 2 == d) { // еÑли в Ñонаправленном направлении интеполÑции Ñледующие точки так же гомогенны, учтём их тоже for (int m = 2; m < 4; ++m) { int hvd = m * hvdir[k]; if (ABS(ynr[0][0] - ynr[hvd][0]) < yeps && SQR(ynr[0][1] - ynr[hvd][1]) + SQR(ynr[0][2] - ynr[hvd][2]) < uveps) { homo[d][moff + hvd]++; } else break; } } } } } } for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { int moff = nr_offset(i + nr_margin, nr_margin); for (int j = 0; j < libraw.imgdata.sizes.iwidth; j++, ++moff) { char hm[2]; for (int d = 0; d < 2; d++) { hm[d] = 0; char *hh = &homo[d][moff]; for (int hx = -1; hx < 2; hx++) for (int hy = -1; hy < 2; hy++) hm[d] += hh[nr_offset(hy, hx)]; } char d = 0; if (hm[0] != hm[1]) { if (hm[1] > hm[0]) { d = VERSH; } else { d = HORSH; } } else { int3 *ynr = &yuv[1][moff]; int gv = SQR(2 * ynr[0][0] - ynr[Pn][0] - ynr[Ps][0]); gv += SQR(2 * ynr[0][1] - ynr[Pn][1] - ynr[Ps][1]) + SQR(2 * ynr[0][2] - ynr[Pn][2] - ynr[Ps][2]); ynr = &yuv[1][moff + Pn]; gv += (SQR(2 * ynr[0][0] - ynr[Pn][0] - ynr[Ps][0]) + SQR(2 * ynr[0][1] - ynr[Pn][1] - ynr[Ps][1]) + SQR(2 * ynr[0][2] - ynr[Pn][2] - ynr[Ps][2])) / 2; ynr = &yuv[1][moff + Ps]; gv += (SQR(2 * ynr[0][0] - ynr[Pn][0] - ynr[Ps][0]) + SQR(2 * ynr[0][1] - ynr[Pn][1] - ynr[Ps][1]) + SQR(2 * ynr[0][2] - ynr[Pn][2] - ynr[Ps][2])) / 2; ynr = &yuv[0][moff]; int gh = SQR(2 * ynr[0][0] - ynr[Pw][0] - ynr[Pe][0]); gh += SQR(2 * ynr[0][1] - ynr[Pw][1] - ynr[Pe][1]) + SQR(2 * ynr[0][2] - ynr[Pw][2] - ynr[Pe][2]); ynr = &yuv[0][moff + Pw]; gh += (SQR(2 * ynr[0][0] - ynr[Pw][0] - ynr[Pe][0]) + SQR(2 * ynr[0][1] - ynr[Pw][1] - ynr[Pe][1]) + SQR(2 * ynr[0][2] - ynr[Pw][2] - ynr[Pe][2])) / 2; ynr = &yuv[0][moff + Pe]; gh += (SQR(2 * ynr[0][0] - ynr[Pw][0] - ynr[Pe][0]) + SQR(2 * ynr[0][1] - ynr[Pw][1] - ynr[Pe][1]) + SQR(2 * ynr[0][2] - ynr[Pw][2] - ynr[Pe][2])) / 2; if (gv > gh) d = HOR; else d = VER; } ndir[moff] |= d; } } } void AAHD::combine_image() { for (int i = 0, i_out = 0; i < libraw.imgdata.sizes.iheight; ++i) { int moff = nr_offset(i + nr_margin, nr_margin); for (int j = 0; j < libraw.imgdata.sizes.iwidth; j++, ++moff, ++i_out) { if (ndir[moff] & HOT) { int c = libraw.COLOR(i, j); rgb_ahd[1][moff][c] = rgb_ahd[0][moff][c] = libraw.imgdata.image[i_out][c]; } if (ndir[moff] & VER) { libraw.imgdata.image[i_out][0] = rgb_ahd[1][moff][0]; libraw.imgdata.image[i_out][3] = libraw.imgdata.image[i_out][1] = rgb_ahd[1][moff][1]; libraw.imgdata.image[i_out][2] = rgb_ahd[1][moff][2]; } else { libraw.imgdata.image[i_out][0] = rgb_ahd[0][moff][0]; libraw.imgdata.image[i_out][3] = libraw.imgdata.image[i_out][1] = rgb_ahd[0][moff][1]; libraw.imgdata.image[i_out][2] = rgb_ahd[0][moff][2]; } } } } void AAHD::refine_hv_dirs() { for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { refine_hv_dirs(i, i & 1); } for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { refine_hv_dirs(i, (i & 1) ^ 1); } for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { refine_ihv_dirs(i); } } void AAHD::refine_ihv_dirs(int i) { int iwidth = libraw.imgdata.sizes.iwidth; int moff = nr_offset(i + nr_margin, nr_margin); for (int j = 0; j < iwidth; j++, ++moff) { if (ndir[moff] & HVSH) continue; int nv = (ndir[moff + Pn] & VER) + (ndir[moff + Ps] & VER) + (ndir[moff + Pw] & VER) + (ndir[moff + Pe] & VER); int nh = (ndir[moff + Pn] & HOR) + (ndir[moff + Ps] & HOR) + (ndir[moff + Pw] & HOR) + (ndir[moff + Pe] & HOR); nv /= VER; nh /= HOR; if ((ndir[moff] & VER) && nh > 3) { ndir[moff] &= ~VER; ndir[moff] |= HOR; } if ((ndir[moff] & HOR) && nv > 3) { ndir[moff] &= ~HOR; ndir[moff] |= VER; } } } void AAHD::refine_hv_dirs(int i, int js) { int iwidth = libraw.imgdata.sizes.iwidth; int moff = nr_offset(i + nr_margin, nr_margin + js); for (int j = js; j < iwidth; j += 2, moff += 2) { int nv = (ndir[moff + Pn] & VER) + (ndir[moff + Ps] & VER) + (ndir[moff + Pw] & VER) + (ndir[moff + Pe] & VER); int nh = (ndir[moff + Pn] & HOR) + (ndir[moff + Ps] & HOR) + (ndir[moff + Pw] & HOR) + (ndir[moff + Pe] & HOR); bool codir = (ndir[moff] & VER) ? ((ndir[moff + Pn] & VER) || (ndir[moff + Ps] & VER)) : ((ndir[moff + Pw] & HOR) || (ndir[moff + Pe] & HOR)); nv /= VER; nh /= HOR; if ((ndir[moff] & VER) && (nh > 2 && !codir)) { ndir[moff] &= ~VER; ndir[moff] |= HOR; } if ((ndir[moff] & HOR) && (nv > 2 && !codir)) { ndir[moff] &= ~HOR; ndir[moff] |= VER; } } } /* * вычиÑление недоÑтающих зелёных точек. */ void AAHD::make_ahd_greens() { for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { make_ahd_gline(i); } } void AAHD::make_ahd_gline(int i) { int iwidth = libraw.imgdata.sizes.iwidth; int js = libraw.COLOR(i, 0) & 1; int kc = libraw.COLOR(i, js); /* * js -- Ð½Ð°Ñ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ñ…-координата, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¿Ð¾Ð¿Ð°Ð´Ð°ÐµÑ‚ мимо извеÑтного зелёного * kc -- извеÑтный цвет в точке Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ */ int hvdir[2] = { Pe, Ps }; for (int d = 0; d < 2; ++d) { int moff = nr_offset(i + nr_margin, nr_margin + js); for (int j = js; j < iwidth; j += 2, moff += 2) { ushort3 *cnr; cnr = &rgb_ahd[d][moff]; int h1 = 2 * cnr[-hvdir[d]][1] - int(cnr[-2 * hvdir[d]][kc] + cnr[0][kc]); int h2 = 2 * cnr[+hvdir[d]][1] - int(cnr[+2 * hvdir[d]][kc] + cnr[0][kc]); int h0 = (h1 + h2) / 4; int eg = cnr[0][kc] + h0; int min = MIN(cnr[-hvdir[d]][1], cnr[+hvdir[d]][1]); int max = MAX(cnr[-hvdir[d]][1], cnr[+hvdir[d]][1]); min -= min / OverFraction; max += max / OverFraction; if (eg < min) eg = min - sqrt(float(min - eg)); else if (eg > max) eg = max + sqrt(float(eg - max)); if (eg > channel_maximum[1]) eg = channel_maximum[1]; else if (eg < channel_minimum[1]) eg = channel_minimum[1]; cnr[0][1] = eg; } } } /* * Ð¾Ñ‚Ð»Ð°Ð´Ð¾Ñ‡Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ */ void AAHD::illustrate_dirs() { for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { illustrate_dline(i); } } void AAHD::illustrate_dline(int i) { int iwidth = libraw.imgdata.sizes.iwidth; for (int j = 0; j < iwidth; j++) { int x = j + nr_margin; int y = i + nr_margin; rgb_ahd[1][nr_offset(y, x)][0] = rgb_ahd[1][nr_offset(y, x)][1] = rgb_ahd[1][nr_offset(y, x)][2] = rgb_ahd[0][nr_offset(y, x)][0] = rgb_ahd[0][nr_offset(y, x)][1] = rgb_ahd[0][nr_offset(y, x)][2] = 0; int l = ndir[nr_offset(y, x)] & HVSH; l /= HVSH; if (ndir[nr_offset(y, x)] & VER) rgb_ahd[1][nr_offset(y, x)][0] = l * channel_maximum[0] / 4 + channel_maximum[0] / 4; else rgb_ahd[0][nr_offset(y, x)][2] = l * channel_maximum[2] / 4 + channel_maximum[2] / 4; } } void AAHD::make_ahd_rb_hv(int i) { int iwidth = libraw.imgdata.sizes.iwidth; int js = libraw.COLOR(i, 0) & 1; int kc = libraw.COLOR(i, js); js ^= 1; // Ð½Ð°Ñ‡Ð°Ð»ÑŒÐ½Ð°Ñ ÐºÐ¾Ð¾Ñ€Ð´Ð¸Ð½Ð°Ñ‚Ð° зелёного int hvdir[2] = { Pe, Ps }; // интерполÑÑ†Ð¸Ñ Ð²ÐµÑ€Ñ‚Ð¸ÐºÐ°Ð»ÑŒÐ½Ñ‹Ñ… вертикально и горизонтальных горизонтально for (int j = js; j < iwidth; j += 2) { int x = j + nr_margin; int y = i + nr_margin; int moff = nr_offset(y, x); for (int d = 0; d < 2; ++d) { ushort3 *cnr; cnr = &rgb_ahd[d][moff]; int c = kc ^ (d << 1); // цвет ÑоответÑвенного направлениÑ, Ð´Ð»Ñ Ð³Ð¾Ñ€Ð¸Ð·Ð¾Ð½Ñ‚Ð°Ð»ÑŒÐ½Ð¾Ð³Ð¾ c = kc, Ð´Ð»Ñ Ð²ÐµÑ€Ñ‚Ð¸ÐºÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ c=kc^2 int h1 = cnr[-hvdir[d]][c] - cnr[-hvdir[d]][1]; int h2 = cnr[+hvdir[d]][c] - cnr[+hvdir[d]][1]; int h0 = (h1 + h2) / 2; int eg = cnr[0][1] + h0; // int min = MIN(cnr[-hvdir[d]][c], cnr[+hvdir[d]][c]); // int max = MAX(cnr[-hvdir[d]][c], cnr[+hvdir[d]][c]); // min -= min / OverFraction; // max += max / OverFraction; // if (eg < min) // eg = min - sqrt(min - eg); // else if (eg > max) // eg = max + sqrt(eg - max); if (eg > channel_maximum[c]) eg = channel_maximum[c]; else if (eg < channel_minimum[c]) eg = channel_minimum[c]; cnr[0][c] = eg; } } } void AAHD::make_ahd_rb() { for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { make_ahd_rb_hv(i); } for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { make_ahd_rb_last(i); } } void AAHD::make_ahd_rb_last(int i) { int iwidth = libraw.imgdata.sizes.iwidth; int js = libraw.COLOR(i, 0) & 1; int kc = libraw.COLOR(i, js); /* * js -- Ð½Ð°Ñ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ñ…-координата, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¿Ð¾Ð¿Ð°Ð´Ð°ÐµÑ‚ мимо извеÑтного зелёного * kc -- извеÑтный цвет в точке Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ */ int dirs[2][3] = { { Pnw, Pn, Pne }, { Pnw, Pw, Psw } }; int moff = nr_offset(i + nr_margin, nr_margin); for (int j = 0; j < iwidth; j++) { for (int d = 0; d < 2; ++d) { ushort3 *cnr; cnr = &rgb_ahd[d][moff + j]; int c = kc ^ 2; if ((j & 1) != js) { // точка зелёного, Ð´Ð»Ñ Ð²ÐµÑ€Ñ‚Ð¸ÐºÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ð½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð½ÑƒÐ¶ÐµÐ½ альтернативный Ñтрочному цвет c ^= d << 1; } int bh, bk; int bgd = 0; for (int k = 0; k < 3; ++k) for (int h = 0; h < 3; ++h) { // градиент зелёного Ð¿Ð»ÑŽÑ Ð³Ñ€Ð°Ð´Ð¸ÐµÐ½Ñ‚ {r,b} int gd = ABS(2 * cnr[0][1] - (cnr[+dirs[d][k]][1] + cnr[-dirs[d][h]][1])) + ABS(cnr[+dirs[d][k]][c] - cnr[-dirs[d][h]][c]) / 4 + ABS( cnr[+dirs[d][k]][c] - cnr[+dirs[d][k]][1] + cnr[-dirs[d][h]][1] - cnr[-dirs[d][h]][c]) / 4; if (bgd == 0 || gd < bgd) { bgd = gd; bh = h; bk = k; } } int h1 = cnr[+dirs[d][bk]][c] - cnr[+dirs[d][bk]][1]; int h2 = cnr[-dirs[d][bh]][c] - cnr[-dirs[d][bh]][1]; int eg = cnr[0][1] + (h1 + h2) / 2; // int min = MIN(cnr[+dirs[d][bk]][c], cnr[-dirs[d][bh]][c]); // int max = MAX(cnr[+dirs[d][bk]][c], cnr[-dirs[d][bh]][c]); // min -= min / OverFraction; // max += max / OverFraction; // if (eg < min) // eg = min - sqrt(min - eg); // else if (eg > max) // eg = max + sqrt(eg - max); if (eg > channel_maximum[c]) eg = channel_maximum[c]; else if (eg < channel_minimum[c]) eg = channel_minimum[c]; cnr[0][c] = eg; } } } AAHD::~AAHD() { free(rgb_ahd[0]); } void LibRaw::aahd_interpolate() { +#ifdef DCRAW_VERBOSE printf("AAHD interpolating\n"); +#endif AAHD aahd(*this); aahd.hide_hots(); aahd.make_ahd_greens(); aahd.make_ahd_rb(); aahd.evaluate_ahd(); aahd.refine_hv_dirs(); // aahd.illustrate_dirs(); aahd.combine_image(); } diff --git a/core/libs/rawengine/libraw/internal/dcraw_common.cpp b/core/libs/rawengine/libraw/internal/dcraw_common.cpp index bac101358f..29cc72fae0 100644 --- a/core/libs/rawengine/libraw/internal/dcraw_common.cpp +++ b/core/libs/rawengine/libraw/internal/dcraw_common.cpp @@ -1,16125 +1,20265 @@ /* - Copyright 2008-2017 LibRaw LLC (info@libraw.org) + Copyright 2008-2018 LibRaw LLC (info@libraw.org) LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). This file is generated from Dave Coffin's dcraw.c dcraw.c -- Dave Coffin's raw photo decoder Copyright 1997-2010 by Dave Coffin, dcoffin a cybercom o net Look into dcraw homepage (probably http://cybercom.net/~dcoffin/dcraw/) for more information */ #include #define CLASS LibRaw:: #include "libraw/libraw_types.h" #define LIBRAW_LIBRARY_BUILD #define LIBRAW_IO_REDEFINED #include "libraw/libraw.h" #include "internal/defines.h" #include "internal/var_defines.h" -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); +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); } + +#if !defined(__FreeBSD__) static size_t local_strnlen(const char *s, size_t n) { const char *p = (const char *)memchr(s, 0, n); - return(p ? p-s : n); + return (p ? p - s : n); } /* add OS X version check here ?? */ -#define strnlen(a,b) local_strnlen(a,b) +#define strnlen(a, b) local_strnlen(a, b) +#endif + +#ifdef LIBRAW_LIBRARY_BUILD +static int Fuji_wb_list1[] = {LIBRAW_WBI_FineWeather, LIBRAW_WBI_Shade, LIBRAW_WBI_FL_D, + LIBRAW_WBI_FL_L, LIBRAW_WBI_FL_W, LIBRAW_WBI_Tungsten}; +static int nFuji_wb_list1 = sizeof(Fuji_wb_list1) / sizeof(int); +static int FujiCCT_K[31] = {2500, 2550, 2650, 2700, 2800, 2850, 2950, 3000, 3100, 3200, 3300, + 3400, 3600, 3700, 3800, 4000, 4200, 4300, 4500, 4800, 5000, 5300, + 5600, 5900, 6300, 6700, 7100, 7700, 8300, 9100, 10000}; +static int Fuji_wb_list2[] = {LIBRAW_WBI_Auto, 0, LIBRAW_WBI_Custom, 6, LIBRAW_WBI_FineWeather, 1, + LIBRAW_WBI_Shade, 8, LIBRAW_WBI_FL_D, 10, LIBRAW_WBI_FL_L, 11, + LIBRAW_WBI_FL_W, 12, LIBRAW_WBI_Tungsten, 2, LIBRAW_WBI_Underwater, 35, + LIBRAW_WBI_Ill_A, 82, LIBRAW_WBI_D65, 83}; +static int nFuji_wb_list2 = sizeof(Fuji_wb_list2) / sizeof(int); + +static int Oly_wb_list1[] = {LIBRAW_WBI_Shade, LIBRAW_WBI_Cloudy, LIBRAW_WBI_FineWeather, + LIBRAW_WBI_Tungsten, LIBRAW_WBI_Sunset, LIBRAW_WBI_FL_D, + LIBRAW_WBI_FL_N, LIBRAW_WBI_FL_W, LIBRAW_WBI_FL_WW}; + +static int Oly_wb_list2[] = {LIBRAW_WBI_Auto, + 0, + LIBRAW_WBI_Tungsten, + 3000, + 0x100, + 3300, + 0x100, + 3600, + 0x100, + 3900, + LIBRAW_WBI_FL_W, + 4000, + 0x100, + 4300, + LIBRAW_WBI_FL_D, + 4500, + 0x100, + 4800, + LIBRAW_WBI_FineWeather, + 5300, + LIBRAW_WBI_Cloudy, + 6000, + LIBRAW_WBI_FL_N, + 6600, + LIBRAW_WBI_Shade, + 7500, + LIBRAW_WBI_Custom1, + 0, + LIBRAW_WBI_Custom2, + 0, + LIBRAW_WBI_Custom3, + 0, + LIBRAW_WBI_Custom4, + 0}; + +static int Pentax_wb_list1[] = {LIBRAW_WBI_Daylight, LIBRAW_WBI_Shade, LIBRAW_WBI_Cloudy, LIBRAW_WBI_Tungsten, + LIBRAW_WBI_FL_D, LIBRAW_WBI_FL_N, LIBRAW_WBI_FL_W, LIBRAW_WBI_Flash}; + +static int Pentax_wb_list2[] = {LIBRAW_WBI_Daylight, LIBRAW_WBI_Shade, LIBRAW_WBI_Cloudy, + LIBRAW_WBI_Tungsten, LIBRAW_WBI_FL_D, LIBRAW_WBI_FL_N, + LIBRAW_WBI_FL_W, LIBRAW_WBI_Flash, LIBRAW_WBI_FL_L}; +static int nPentax_wb_list2 = sizeof(Pentax_wb_list2) / sizeof(int); -#ifdef LIBRAW_LIBRARY_BUILD static int stread(char *buf, size_t len, LibRaw_abstract_datastream *fp) { if(len>0) { int r = fp->read(buf, len, 1); buf[len - 1] = 0; return r; } else return 0; } -#define stmread(buf,maxlen,fp) stread(buf,MIN(maxlen,sizeof(buf)),fp) +#define stmread(buf, maxlen, fp) stread(buf, MIN(maxlen, sizeof(buf)), fp) #endif -#ifndef __GLIBC__ -char *my_memmem (char *haystack, size_t haystacklen, - char *needle, size_t needlelen) +#if !defined(__GLIBC__) && !defined(__FreeBSD__) +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)) + if (!memcmp(c, needle, needlelen)) return c; return 0; } #define memmem my_memmem -char *my_strcasestr (char *haystack, const char *needle) +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 -#define strbuflen(buf) strnlen(buf,sizeof(buf)-1) +#define strbuflen(buf) strnlen(buf, sizeof(buf) - 1) -ushort CLASS sget2 (uchar *s) +ushort CLASS sget2(uchar *s) { - if (order == 0x4949) /* "II" means little-endian */ + if (order == 0x4949) /* "II" means little-endian */ return s[0] | s[1] << 8; - else /* "MM" means big-endian */ + else /* "MM" means big-endian */ return s[0] << 8 | s[1]; } // DNG was written by: -#define CameraDNG 1 -#define AdobeDNG 2 +#define nonDNG 0 +#define CameraDNG 1 +#define AdobeDNG 2 #ifdef LIBRAW_LIBRARY_BUILD -static int getwords(char *line, char *words[], int maxwords,int maxlen) +static int getwords(char *line, char *words[], int maxwords, int maxlen) { - line[maxlen-1] = 0; + line[maxlen - 1] = 0; char *p = line; int nwords = 0; - while(1) + while (1) { - while(isspace(*p)) p++; - if(*p == '\0') return nwords; + while (isspace(*p)) + p++; + if (*p == '\0') + return nwords; words[nwords++] = p; - while(!isspace(*p) && *p != '\0') p++; - if(*p == '\0') return nwords; + while (!isspace(*p) && *p != '\0') + p++; + if (*p == '\0') + return nwords; *p++ = '\0'; - if(nwords >= maxwords) return nwords; + if (nwords >= maxwords) + return nwords; } } -static ushort saneSonyCameraInfo(uchar a, uchar b, uchar c, uchar d, uchar e, uchar f){ - if ((a >> 4) > 9) return 0; - else if ((a & 0x0f) > 9) return 0; - else if ((b >> 4) > 9) return 0; - else if ((b & 0x0f) > 9) return 0; - else if ((c >> 4) > 9) return 0; - else if ((c & 0x0f) > 9) return 0; - else if ((d >> 4) > 9) return 0; - else if ((d & 0x0f) > 9) return 0; - else if ((e >> 4) > 9) return 0; - else if ((e & 0x0f) > 9) return 0; - else if ((f >> 4) > 9) return 0; - else if ((f & 0x0f) > 9) return 0; -return 1; +static ushort saneSonyCameraInfo(uchar a, uchar b, uchar c, uchar d, uchar e, uchar f) +{ + if ((a >> 4) > 9) + return 0; + else if ((a & 0x0f) > 9) + return 0; + else if ((b >> 4) > 9) + return 0; + else if ((b & 0x0f) > 9) + return 0; + else if ((c >> 4) > 9) + return 0; + else if ((c & 0x0f) > 9) + return 0; + else if ((d >> 4) > 9) + return 0; + else if ((d & 0x0f) > 9) + return 0; + else if ((e >> 4) > 9) + return 0; + else if ((e & 0x0f) > 9) + return 0; + else if ((f >> 4) > 9) + return 0; + else if ((f & 0x0f) > 9) + return 0; + return 1; } -static ushort bcd2dec(uchar data){ - if ((data >> 4) > 9) return 0; - else if ((data & 0x0f) > 9) return 0; - else return (data >> 4) * 10 + (data & 0x0f); +static ushort bcd2dec(uchar data) +{ + if ((data >> 4) > 9) + return 0; + else if ((data & 0x0f) > 9) + return 0; + else + return (data >> 4) * 10 + (data & 0x0f); } -static uchar SonySubstitution[257] = "\x00\x01\x32\xb1\x0a\x0e\x87\x28\x02\xcc\xca\xad\x1b\xdc\x08\xed\x64\x86\xf0\x4f\x8c\x6c\xb8\xcb\x69\xc4\x2c\x03\x97\xb6\x93\x7c\x14\xf3\xe2\x3e\x30\x8e\xd7\x60\x1c\xa1\xab\x37\xec\x75\xbe\x23\x15\x6a\x59\x3f\xd0\xb9\x96\xb5\x50\x27\x88\xe3\x81\x94\xe0\xc0\x04\x5c\xc6\xe8\x5f\x4b\x70\x38\x9f\x82\x80\x51\x2b\xc5\x45\x49\x9b\x21\x52\x53\x54\x85\x0b\x5d\x61\xda\x7b\x55\x26\x24\x07\x6e\x36\x5b\x47\xb7\xd9\x4a\xa2\xdf\xbf\x12\x25\xbc\x1e\x7f\x56\xea\x10\xe6\xcf\x67\x4d\x3c\x91\x83\xe1\x31\xb3\x6f\xf4\x05\x8a\x46\xc8\x18\x76\x68\xbd\xac\x92\x2a\x13\xe9\x0f\xa3\x7a\xdb\x3d\xd4\xe7\x3a\x1a\x57\xaf\x20\x42\xb2\x9e\xc3\x8b\xf2\xd5\xd3\xa4\x7e\x1f\x98\x9c\xee\x74\xa5\xa6\xa7\xd8\x5e\xb0\xb4\x34\xce\xa8\x79\x77\x5a\xc1\x89\xae\x9a\x11\x33\x9d\xf5\x39\x19\x65\x78\x16\x71\xd2\xa9\x44\x63\x40\x29\xba\xa0\x8f\xe4\xd6\x3b\x84\x0d\xc2\x4e\x58\xdd\x99\x22\x6b\xc9\xbb\x17\x06\xe5\x7d\x66\x43\x62\xf6\xcd\x35\x90\x2e\x41\x8d\x6d\xaa\x09\x73\x95\x0c\xf1\x1d\xde\x4c\x2f\x2d\xf7\xd1\x72\xeb\xef\x48\xc7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"; - -ushort CLASS sget2Rev(uchar *s) // specific to some Canon Makernotes fields, where they have endian in reverse +static uchar SonySubstitution[257] = + "\x00\x01\x32\xb1\x0a\x0e\x87\x28\x02\xcc\xca\xad\x1b\xdc\x08\xed\x64\x86\xf0\x4f\x8c\x6c\xb8\xcb\x69\xc4\x2c\x03" + "\x97\xb6\x93\x7c\x14\xf3\xe2\x3e\x30\x8e\xd7\x60\x1c\xa1\xab\x37\xec\x75\xbe\x23\x15\x6a\x59\x3f\xd0\xb9\x96\xb5" + "\x50\x27\x88\xe3\x81\x94\xe0\xc0\x04\x5c\xc6\xe8\x5f\x4b\x70\x38\x9f\x82\x80\x51\x2b\xc5\x45\x49\x9b\x21\x52\x53" + "\x54\x85\x0b\x5d\x61\xda\x7b\x55\x26\x24\x07\x6e\x36\x5b\x47\xb7\xd9\x4a\xa2\xdf\xbf\x12\x25\xbc\x1e\x7f\x56\xea" + "\x10\xe6\xcf\x67\x4d\x3c\x91\x83\xe1\x31\xb3\x6f\xf4\x05\x8a\x46\xc8\x18\x76\x68\xbd\xac\x92\x2a\x13\xe9\x0f\xa3" + "\x7a\xdb\x3d\xd4\xe7\x3a\x1a\x57\xaf\x20\x42\xb2\x9e\xc3\x8b\xf2\xd5\xd3\xa4\x7e\x1f\x98\x9c\xee\x74\xa5\xa6\xa7" + "\xd8\x5e\xb0\xb4\x34\xce\xa8\x79\x77\x5a\xc1\x89\xae\x9a\x11\x33\x9d\xf5\x39\x19\x65\x78\x16\x71\xd2\xa9\x44\x63" + "\x40\x29\xba\xa0\x8f\xe4\xd6\x3b\x84\x0d\xc2\x4e\x58\xdd\x99\x22\x6b\xc9\xbb\x17\x06\xe5\x7d\x66\x43\x62\xf6\xcd" + "\x35\x90\x2e\x41\x8d\x6d\xaa\x09\x73\x95\x0c\xf1\x1d\xde\x4c\x2f\x2d\xf7\xd1\x72\xeb\xef\x48\xc7\xf8\xf9\xfa\xfb" + "\xfc\xfd\xfe\xff"; + +ushort CLASS sget2Rev(uchar *s) // specific to some Canon Makernotes fields, where they have endian in reverse { - if (order == 0x4d4d) /* "II" means little-endian, and we reverse to "MM" - big endian */ - return s[0] | s[1] << 8; - else /* "MM" means big-endian... */ - return s[0] << 8 | s[1]; + if (order == 0x4d4d) /* "II" means little-endian, and we reverse to "MM" - big endian */ + return s[0] | s[1] << 8; + else /* "MM" means big-endian... */ + return s[0] << 8 | s[1]; } #endif ushort CLASS get2() { - uchar str[2] = { 0xff,0xff }; - fread (str, 1, 2, ifp); + uchar str[2] = {0xff, 0xff}; + fread(str, 1, 2, ifp); return sget2(str); } -unsigned CLASS sget4 (uchar *s) +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); + 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(); -} +unsigned CLASS getint(int type) { return type == 3 ? get2() : get4(); } -float CLASS int_to_float (int i) +float CLASS int_to_float(int i) { - union { int i; float f; } u; + union { + int i; + float f; + } u; u.i = i; return u.f; } -double CLASS getreal (int type) +double CLASS getreal(int type) { - union { char c[8]; double d; } u,v; + union { + char c[8]; + double d; + } u, v; int i, rev; - switch (type) { - case 3: return (unsigned short) get2(); - case 4: return (unsigned int) get4(); - case 5: - u.d = (unsigned int) get4(); - v.d = (unsigned int)get4(); - return u.d / (v.d ? v.d : 1); - case 8: return (signed short) get2(); - case 9: return (signed int) get4(); - case 10: - u.d = (signed int) get4(); - v.d = (signed int)get4(); - return u.d / (v.d?v.d:1); - 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); + switch (type) + { + case 3: + return (unsigned short)get2(); + case 4: + return (unsigned int)get4(); + case 5: + u.d = (unsigned int)get4(); + v.d = (unsigned int)get4(); + return u.d / (v.d ? v.d : 1); + case 8: + return (signed short)get2(); + case 9: + return (signed int)get4(); + case 10: + u.d = (signed int)get4(); + v.d = (signed int)get4(); + return u.d / (v.d ? v.d : 1); + 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, unsigned count) +void CLASS read_shorts(ushort *pixel, unsigned count) { - if (fread (pixel, 2, count, ifp) < count) derror(); + if (fread(pixel, 2, count, ifp) < count) + derror(); if ((order == 0x4949) == (ntohs(0x1234) == 0x1234)) - swab ((char*)pixel, (char*)pixel, count*2); + swab((char *)pixel, (char *)pixel, count * 2); } -void CLASS cubic_spline (const int *x_, const int *y_, const int len) +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++) { + 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 = 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]; + 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]); + 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 = 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--) { + 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 (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++) { + 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; + 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)); + curve[i] = y_out < 0.0 ? 0 : (y_out >= 1.0 ? 65535 : (ushort)(y_out * 65535.0 + 0.5)); } - free (A); + free(A); } -void CLASS canon_600_fixed_wb (int temp) +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 } }; + {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; + float frac = 0; - for (lo=4; --lo; ) - if (*mul[lo] <= temp) break; - for (hi=0; hi < 3; hi++) - if (*mul[hi] >= temp) break; + 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]); + 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 CLASS canon_600_color(int ratio[2], int mar) { - int clipped=0, target, miss; + int clipped = 0, target, miss; - if (flash_used) { + 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; + { + 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; } + { + ratio[1] = -50; + clipped = 1; + } if (ratio[1] > 307) - { ratio[1] = 307; clipped = 1; } + { + 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; + 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; + 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 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); + 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]; + 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: ; + 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]); + 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; + 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 (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; + 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; + uchar data[1120], *dp; ushort *pix; int irow, row; - for (irow=row=0; irow < height; irow++) { + for (irow = row = 0; irow < height; irow++) + { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - 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 ); + 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[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 ); + pix[7] = (dp[8] << 2) + (dp[9] >> 6); } - if ((row+=2) > height) row = 1; + 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 } }; + static const short mul[4][2] = {{1141, 1145}, {1128, 1109}, {1178, 1149}, {1128, 1109}}; - for (row=0; row < height; row++) - { + for (row = 0; row < height; row++) + { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - for (col=0; col < width; col++) { - if ((val = BAYER(row,col) - black) < 0) val = 0; + 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; - } + 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; + 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) +unsigned CLASS getbithuff(int nbits, ushort *huff) { #ifdef LIBRAW_NOTHREADS - static unsigned bitbuf=0; - static int vbits=0, reset=0; + static unsigned bitbuf = 0; + static int vbits = 0, reset = 0; #else #define bitbuf tls->getbits.bitbuf -#define vbits tls->getbits.vbits -#define reset tls->getbits.reset +#define vbits tls->getbits.vbits +#define reset tls->getbits.reset #endif unsigned c; - if (nbits > 25) return 0; + 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; + 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) { + c = bitbuf << (32 - vbits) >> (32 - nbits); + if (huff) + { vbits -= huff[c] >> 8; - c = (uchar) huff[c]; - } else + c = (uchar)huff[c]; + } + else vbits -= nbits; - if (vbits < 0) derror(); + if (vbits < 0) + derror(); return c; #ifndef LIBRAW_NOTHREADS #undef bitbuf #undef vbits #undef reset #endif } -#define getbits(n) getbithuff(n,0) -#define gethuff(h) getbithuff(*h,h+1) +#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 + 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) +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()"); + 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; + 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); -} +ushort *CLASS make_decoder(const uchar *source) { return make_decoder_ref(&source); } -void CLASS crw_init_tables (unsigned table, ushort *huff[2]) +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 }, + {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]); + {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; + 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; + 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]; + int block, diffbuf[64], leaf, len, diff, carry = 0, pnum = 0, base[2]; - crw_init_tables (tiff_compress, huff); + 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); + if (!lowbits) + maximum = 0x3ff; + fseek(ifp, 540 + lowbits * raw_height * raw_width / 4, SEEK_SET); zero_after_ff = 1; getbits(-1); #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - for (row=0; row < raw_height; row+=8) { + for (row = 0; row < raw_height; row += 8) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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; - } + 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); } - fseek (ifp, save, SEEK_SET); } - } #ifdef LIBRAW_LIBRARY_BUILD - } catch (...) { - FORC(2) free (huff[c]); + } + catch (...) + { + FORC(2) free(huff[c]); throw; } #endif - FORC(2) free (huff[c]); + FORC(2) free(huff[c]); } -int CLASS ljpeg_start (struct jhead *jh, int info_only) +int CLASS ljpeg_start(struct jhead *jh, int info_only) { ushort c, tag, len; int cnt = 0; uchar data[0x10000]; const uchar *dp; - memset (jh, 0, sizeof *jh); + memset(jh, 0, sizeof *jh); jh->restart = INT_MAX; - if ((fgetc(ifp),fgetc(ifp)) != 0xd8) return 0; - do { - if(feof(ifp)) return 0; - if(cnt++ > 1024) return 0; // 1024 tags limit - if (!fread (data, 2, 2, ifp)) return 0; - tag = data[0] << 8 | data[1]; + if ((fgetc(ifp), fgetc(ifp)) != 0xd8) + return 0; + do + { + if (feof(ifp)) + return 0; + if (cnt++ > 1024) + return 0; // 1024 tags limit + if (!fread(data, 2, 2, ifp)) + return 0; + 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: // start of frame; lossless, Huffman - jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3; - case 0xffc1: - case 0xffc0: - jh->algo = tag & 0xff; - 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: // define Huffman tables - if (info_only) break; - for (dp = data; dp < data+len && !((c = *dp++) & -20); ) - jh->free[c] = jh->huff[c] = make_decoder_ref (&dp); - break; - case 0xffda: // start of scan - jh->psv = data[1+data[0]*2]; - jh->bits -= data[3+data[0]*2] & 15; - break; - case 0xffdb: - FORC(64) jh->quant[c] = data[c*2+1] << 8 | data[c*2+2]; - break; - case 0xffdd: - jh->restart = data[0] << 8 | data[1]; + if (tag <= 0xff00) + return 0; + fread(data, 1, len, ifp); + switch (tag) + { + case 0xffc3: // start of frame; lossless, Huffman + jh->sraw = ((data[7] >> 4) * (data[7] & 15) - 1) & 3; + case 0xffc1: + case 0xffc0: + jh->algo = tag & 0xff; + 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: // define Huffman tables + if (info_only) + break; + for (dp = data; dp < data + len && !((c = *dp++) & -20);) + jh->free[c] = jh->huff[c] = make_decoder_ref(&dp); + break; + case 0xffda: // start of scan + jh->psv = data[1 + data[0] * 2]; + jh->bits -= data[3 + data[0] * 2] & 15; + break; + case 0xffdb: + FORC(64) jh->quant[c] = data[c * 2 + 1] << 8 | data[c * 2 + 2]; + break; + case 0xffdd: + jh->restart = data[0] << 8 | data[1]; } } while (tag != 0xffda); - if (jh->bits > 16 || jh->clrs > 6 || - !jh->bits || !jh->high || !jh->wide || !jh->clrs) return 0; - if (info_only) return 1; - if (!jh->huff[0]) return 0; - FORC(19) 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()"); + if (jh->bits > 16 || jh->clrs > 6 || !jh->bits || !jh->high || !jh->wide || !jh->clrs) + return 0; + if (info_only) + return 1; + if (!jh->huff[0]) + return 0; + FORC(19) 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) +void CLASS ljpeg_end(struct jhead *jh) { int c; - FORC4 if (jh->free[c]) free (jh->free[c]); - free (jh->row); + FORC4 if (jh->free[c]) free(jh->free[c]); + free(jh->row); } -int CLASS ljpeg_diff (ushort *huff) +int CLASS ljpeg_diff(ushort *huff) { int len, diff; - if(!huff) + if (!huff) #ifdef LIBRAW_LIBRARY_BUILD throw LIBRAW_EXCEPTION_IO_CORRUPT; #else - longjmp (failure, 2); + longjmp(failure, 2); #endif - len = gethuff(huff); if (len == 16 && (!dng_version || dng_version >= 0x1010000)) return -32768; diff = getbits(len); - if ((diff & (1 << (len-1))) == 0) + if ((diff & (1 << (len - 1))) == 0) diff -= (1 << len) - 1; return diff; } -ushort * CLASS ljpeg_row (int jrow, struct jhead *jh) +ushort *CLASS ljpeg_row(int jrow, struct jhead *jh) { - int col, c, diff, pred, spred=0; - ushort mark=0, *row[3]; + 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)); + 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]); + 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]++; + 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, jhigh, jrow, jcol, val, jidx, i, j, row=0, col=0; + int jwide, jhigh, jrow, jcol, val, jidx, i, j, row = 0, col = 0; struct jhead jh; ushort *rp; - if (!ljpeg_start (&jh, 0)) return; + if (!ljpeg_start(&jh, 0)) + return; - if(jh.wide<1 || jh.high<1 || jh.clrs<1 || jh.bits <1) + if (jh.wide < 1 || jh.high < 1 || jh.clrs < 1 || jh.bits < 1) #ifdef LIBRAW_LIBRARY_BUILD throw LIBRAW_EXCEPTION_IO_CORRUPT; #else - longjmp (failure, 2); + longjmp(failure, 2); #endif jwide = jh.wide * jh.clrs; jhigh = jh.high; - if(jh.clrs == 4 && jwide >= raw_width*2) jhigh *= 2; + if (jh.clrs == 4 && jwide >= raw_width * 2) + jhigh *= 2; #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - for (jrow=0; jrow < jh.high; jrow++) { + for (jrow = 0; jrow < jh.high; jrow++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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]*raw_height); - if ((j = i >= cr2_slice[0])) - i = cr2_slice[0]; - jidx -= i * (cr2_slice[1]*raw_height); - 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) -#ifdef LIBRAW_LIBRARY_BUILD - throw LIBRAW_EXCEPTION_IO_CORRUPT; + 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] * raw_height); + if ((j = i >= cr2_slice[0])) + i = cr2_slice[0]; + jidx -= i * (cr2_slice[1] * raw_height); + 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) +#ifdef LIBRAW_LIBRARY_BUILD + throw LIBRAW_EXCEPTION_IO_CORRUPT; #else - longjmp (failure, 3); + longjmp(failure, 3); #endif - if ((unsigned) row < raw_height) RAW(row,col) = val; - if (++col >= raw_width) - col = (row++,0); + if ((unsigned)row < raw_height) + RAW(row, col) = val; + if (++col >= raw_width) + col = (row++, 0); + } } - } #ifdef LIBRAW_LIBRARY_BUILD - } catch (...) { - ljpeg_end (&jh); + } + catch (...) + { + ljpeg_end(&jh); throw; } #endif - ljpeg_end (&jh); + 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; + 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; #ifdef LIBRAW_LIBRARY_BUILD int saved_w = width, saved_h = height; #endif char *cp; - if (!ljpeg_start (&jh, 0) || jh.clrs < 4) return; + if (!ljpeg_start(&jh, 0) || jh.clrs < 4) + return; jwide = (jh.wide >>= 1) * jh.clrs; - #ifdef LIBRAW_LIBRARY_BUILD - if(load_flags & 256) + if (load_flags & 256) { - width = raw_width; - height = raw_height; + width = raw_width; + height = raw_height; } - try { + try + { #endif - 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) { + 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) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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; + 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; #ifdef LIBRAW_LIBRARY_BUILD - if(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SRAW_NO_INTERPOLATE) + if (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SRAW_NO_INTERPOLATE) { - FORC (jh.clrs-2) - { - ip[col + (c >> 1)*width + (c & 1)][0] = rp[jcol+c]; - ip[col + (c >> 1)*width + (c & 1)][1] = ip[col + (c >> 1)*width + (c & 1)][2] = 8192; - } - ip[col][1] = rp[jcol+jh.clrs-2] - 8192; - ip[col][2] = rp[jcol+jh.clrs-1] - 8192; + FORC(jh.clrs - 2) + { + ip[col + (c >> 1) * width + (c & 1)][0] = rp[jcol + c]; + ip[col + (c >> 1) * width + (c & 1)][1] = ip[col + (c >> 1) * width + (c & 1)][2] = 8192; + } + ip[col][1] = rp[jcol + jh.clrs - 2] - 8192; + ip[col][2] = rp[jcol + jh.clrs - 1] - 8192; } - else if(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SRAW_NO_RGB) + else if (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SRAW_NO_RGB) { - FORC (jh.clrs-2) - ip[col + (c >> 1)*width + (c & 1)][0] = rp[jcol+c]; - ip[col][1] = rp[jcol+jh.clrs-2] - 8192; - ip[col][2] = rp[jcol+jh.clrs-1] - 8192; + FORC(jh.clrs - 2) + ip[col + (c >> 1) * width + (c & 1)][0] = rp[jcol + c]; + ip[col][1] = rp[jcol + jh.clrs - 2] - 8192; + ip[col][2] = rp[jcol + jh.clrs - 1] - 8192; } - else + else #endif { - 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; + 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; } + } } } - } #ifdef LIBRAW_LIBRARY_BUILD - } catch (...) { - ljpeg_end (&jh); - throw ; + } + catch (...) + { + ljpeg_end(&jh); + throw; } #endif #ifdef LIBRAW_LIBRARY_BUILD - if(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SRAW_NO_INTERPOLATE) - { - ljpeg_end (&jh); - maximum = 0x3fff; - height = saved_h; - width = saved_w; - return; - } + if (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SRAW_NO_INTERPOLATE) + { + ljpeg_end(&jh); + maximum = 0x3fff; + height = saved_h; + width = saved_w; + return; + } #endif #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - 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) { + 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) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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]; - } + 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-width][c] + ip[col+width][c] + 1) >> 1; - } + ip[col][c] = (ip[col - 1][c] + ip[col + 1][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; - } #ifdef LIBRAW_LIBRARY_BUILD - if(!(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SRAW_NO_RGB) ) + if (!(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SRAW_NO_RGB)) #endif - for ( ; rp < ip[0]; rp+=4) { + for (; rp < ip[0]; rp += 4) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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); - } -#ifdef LIBRAW_LIBRARY_BUILD - } catch (...) { - ljpeg_end (&jh); - throw ; + 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] = CLIP15(pix[c] * sraw_mul[c] >> 10); + } +#ifdef LIBRAW_LIBRARY_BUILD + } + catch (...) + { + ljpeg_end(&jh); + throw; } height = saved_h; width = saved_w; #endif - ljpeg_end (&jh); + ljpeg_end(&jh); maximum = 0x3fff; } -void CLASS adobe_copy_pixel (unsigned row, unsigned col, ushort **rp) +void CLASS adobe_copy_pixel(unsigned row, unsigned col, ushort **rp) { int c; - if (tiff_samples == 2 && shot_select) (*rp)++; - if (raw_image) { + if (tiff_samples == 2 && shot_select) + (*rp)++; + if (raw_image) + { + if (row < raw_height && col < raw_width) + RAW(row, col) = curve[**rp]; + *rp += tiff_samples; + } + else + { +#ifdef LIBRAW_LIBRARY_BUILD if (row < raw_height && col < raw_width) - RAW(row,col) = curve[**rp]; + FORC(tiff_samples) + image[row * raw_width + col][c] = curve[(*rp)[c]]; *rp += tiff_samples; - } else { +#else if (row < height && col < width) FORC(tiff_samples) - image[row*width+col][c] = curve[(*rp)[c]]; + image[row * width + col][c] = curve[(*rp)[c]]; *rp += tiff_samples; +#endif } - if (tiff_samples == 2 && shot_select) (*rp)--; + if (tiff_samples == 2 && shot_select) + (*rp)--; } -void CLASS ljpeg_idct (struct jhead *jh) +void CLASS ljpeg_idct(struct jhead *jh) { int c, i, j, len, skip, coef; float work[3][8][8]; - static float cs[106] = { 0 }; - static const uchar zigzag[80] = - { 0, 1, 8,16, 9, 2, 3,10,17,24,32,25,18,11, 4, 5,12,19,26,33, - 40,48,41,34,27,20,13, 6, 7,14,21,28,35,42,49,56,57,50,43,36, - 29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54, - 47,55,62,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63 }; + static float cs[106] = {0}; + static const uchar zigzag[80] = {0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, + 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, + 47, 55, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63}; if (!cs[0]) - FORC(106) cs[c] = cos((c & 31)*M_PI/16)/2; - memset (work, 0, sizeof work); - work[0][0][0] = jh->vpred[0] += ljpeg_diff (jh->huff[0]) * jh->quant[0]; - for (i=1; i < 64; i++ ) { - len = gethuff (jh->huff[16]); + FORC(106) cs[c] = cos((c & 31) * M_PI / 16) / 2; + memset(work, 0, sizeof work); + work[0][0][0] = jh->vpred[0] += ljpeg_diff(jh->huff[0]) * jh->quant[0]; + for (i = 1; i < 64; i++) + { + len = gethuff(jh->huff[16]); i += skip = len >> 4; - if (!(len &= 15) && skip < 15) break; + if (!(len &= 15) && skip < 15) + break; coef = getbits(len); - if ((coef & (1 << (len-1))) == 0) + if ((coef & (1 << (len - 1))) == 0) coef -= (1 << len) - 1; ((float *)work)[zigzag[i]] = coef * jh->quant[i]; } FORC(8) work[0][0][c] *= M_SQRT1_2; FORC(8) work[0][c][0] *= M_SQRT1_2; - for (i=0; i < 8; i++) - for (j=0; j < 8; j++) - FORC(8) work[1][i][j] += work[0][i][c] * cs[(j*2+1)*c]; - for (i=0; i < 8; i++) - for (j=0; j < 8; j++) - FORC(8) work[2][i][j] += work[1][c][j] * cs[(i*2+1)*c]; - - FORC(64) jh->idct[c] = CLIP(((float *)work[2])[c]+0.5); + for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) + FORC(8) work[1][i][j] += work[0][i][c] * cs[(j * 2 + 1) * c]; + for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) + FORC(8) work[2][i][j] += work[1][c][j] * cs[(i * 2 + 1) * c]; + + FORC(64) jh->idct[c] = CLIP(((float *)work[2])[c] + 0.5); } void CLASS lossless_dng_load_raw() { - unsigned save, trow=0, tcol=0, jwide, jrow, jcol, row, col, i, j; + unsigned save, trow = 0, tcol = 0, jwide, jrow, jcol, row, col, i, j; struct jhead jh; ushort *rp; - while (trow < raw_height) { + while (trow < raw_height) + { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif save = ftell(ifp); if (tile_length < INT_MAX) - fseek (ifp, get4(), SEEK_SET); - if (!ljpeg_start (&jh, 0)) break; + fseek(ifp, get4(), SEEK_SET); + if (!ljpeg_start(&jh, 0)) + break; jwide = jh.wide; - if (filters) jwide *= jh.clrs; - jwide /= MIN (is_raw, tiff_samples); + if (filters) + jwide *= jh.clrs; + jwide /= MIN(is_raw, tiff_samples); #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - switch (jh.algo) { + switch (jh.algo) + { case 0xc1: - jh.vpred[0] = 16384; - getbits(-1); - for (jrow=0; jrow+7 < jh.high; jrow += 8) { -#ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); -#endif - for (jcol=0; jcol+7 < jh.wide; jcol += 8) { - ljpeg_idct (&jh); - rp = jh.idct; - row = trow + jcol/tile_width + jrow*2; - col = tcol + jcol%tile_width; - for (i=0; i < 16; i+=2) - for (j=0; j < 8; j++) - adobe_copy_pixel (row+i, col+j, &rp); - } - } - break; + jh.vpred[0] = 16384; + getbits(-1); + for (jrow = 0; jrow + 7 < jh.high; jrow += 8) + { +#ifdef LIBRAW_LIBRARY_BUILD + checkCancel(); +#endif + for (jcol = 0; jcol + 7 < jh.wide; jcol += 8) + { + ljpeg_idct(&jh); + rp = jh.idct; + row = trow + jcol / tile_width + jrow * 2; + col = tcol + jcol % tile_width; + for (i = 0; i < 16; i += 2) + for (j = 0; j < 8; j++) + adobe_copy_pixel(row + i, col + j, &rp); + } + } + break; case 0xc3: - for (row=col=jrow=0; jrow < jh.high; jrow++) { + for (row = col = jrow = 0; jrow < jh.high; jrow++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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); + rp = ljpeg_row(jrow, &jh); + if(tiff_samples == 1 && jh.clrs > 1 && jh.clrs*jwide == raw_width) + for (jcol = 0; jcol < jwide*jh.clrs; jcol++) + { + adobe_copy_pixel(trow + row, tcol + col, &rp); + if (++col >= tile_width || col >= raw_width) + row += 1 + (col = 0); } - } + else + 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); + } + } } #ifdef LIBRAW_LIBRARY_BUILD - } catch (...) { - ljpeg_end (&jh); - throw ; + } + catch (...) + { + ljpeg_end(&jh); + throw; } #endif - fseek (ifp, save+4, SEEK_SET); + fseek(ifp, save + 4, SEEK_SET); if ((tcol += tile_width) >= raw_width) trow += tile_length + (tcol = 0); - ljpeg_end (&jh); + 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()"); + pixel = (ushort *)calloc(raw_width, tiff_samples * sizeof *pixel); + merror(pixel, "packed_dng_load_raw()"); #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - for (row=0; row < raw_height; row++) { + for (row = 0; row < raw_height; row++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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); + 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); } - for (rp=pixel, col=0; col < raw_width; col++) - adobe_copy_pixel (row, col, &rp); - } #ifdef LIBRAW_LIBRARY_BUILD - } catch (...) { - free (pixel); - throw ; + } + catch (...) + { + free(pixel); + throw; } #endif - free (pixel); + 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]; + ushort vpred[2][2] = {{0, 0}, {0, 0}}, hpred[2]; - fseek (ifp, meta_offset, SEEK_SET); + fseek(ifp, meta_offset, SEEK_SET); dep = (get2() + 12) & 15; - fseek (ifp, 12, SEEK_CUR); + 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; + 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); + fseek(ifp, data_offset, SEEK_SET); getbits(-1); - for (row=0; row < raw_height; row++) + for (row = 0; row < raw_height; row++) { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - 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(); + 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(); } } } #ifdef LIBRAW_LIBRARY_BUILD void CLASS nikon_coolscan_load_raw() { if(!image) throw LIBRAW_EXCEPTION_IO_CORRUPT; int bypp = tiff_bps <= 8 ? 1 : 2; int bufsize = width * 3 * bypp; if (tiff_bps <= 8) gamma_curve(1.0 / imgdata.params.coolscan_nef_gamma, 0., 1, 255); else - gamma_curve(1.0/imgdata.params.coolscan_nef_gamma,0.,1,65535); - fseek (ifp, data_offset, SEEK_SET); - unsigned char *buf = (unsigned char*)malloc(bufsize); + gamma_curve(1.0 / imgdata.params.coolscan_nef_gamma, 0., 1, 65535); + fseek(ifp, data_offset, SEEK_SET); + unsigned char *buf = (unsigned char *)malloc(bufsize); unsigned short *ubuf = (unsigned short *)buf; - for(int row = 0; row < raw_height; row++) - { - int red = fread (buf, 1, bufsize, ifp); - unsigned short (*ip)[4] = (unsigned short (*)[4]) image + row*width; - if(tiff_bps <= 8) - for(int col=0; col 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); + 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); + } + 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); #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - for (min=row=0; row < height; row++) { + for (min = row = 0; row < height; row++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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)]; + 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)]; + } } - } #ifdef LIBRAW_LIBRARY_BUILD - } catch (...) { - free (huff); + } + catch (...) + { + free(huff); throw; } #endif - free (huff); + free(huff); } void CLASS nikon_yuv_load_raw() { #ifdef LIBRAW_LIBRARY_BUILD - if(!image) + if (!image) throw LIBRAW_EXCEPTION_IO_CORRUPT; #endif int row, col, yuv[4], rgb[3], b, c; - UINT64 bitbuf=0; + UINT64 bitbuf = 0; float cmul[4]; - FORC4 { cmul[c] = cam_mul[c]>0.001f?cam_mul[c]:1.f; } - for (row=0; row < raw_height; row++) + FORC4 { cmul[c] = cam_mul[c] > 0.001f ? cam_mul[c] : 1.f; } + for (row = 0; row < raw_height; row++) { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - 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); + 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)] / cmul[c]; + 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)] / cmul[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 }; + const uchar often[] = {0x00, 0x55, 0xaa, 0xff}; - memset (histo, 0, sizeof histo); - fseek (ifp, -2000, SEEK_END); - for (i=0; i < 2000; i++) + 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++) + 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) + 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 { + static const struct + { int bits; char t_make[12], t_model[15]; } table[] = { - { 0x00, "Pentax", "Optio 33WR" }, - { 0x03, "Nikon", "E3200" }, - { 0x32, "Nikon", "E3700" }, - { 0x33, "Olympus", "C740UZ" } }; + {0x00, "Pentax", "Optio 33WR"}, {0x03, "Nikon", "E3200"}, {0x32, "Nikon", "E3700"}, {0x33, "Olympus", "C740UZ"}}; - fseek (ifp, 3072, SEEK_SET); - fread (dp, 1, 24, ifp); + fseek(ifp, 3072, SEEK_SET); + fread(dp, 1, 24, ifp); bits = (dp[8] & 3) << 4 | (dp[20] & 3); - for (i=0; i < sizeof table / sizeof *table; i++) - if (bits == table[i].bits) { - strcpy (make, table[i].t_make ); - strcpy (model, table[i].t_model); + for (i = 0; i < sizeof table / sizeof *table; i++) + if (bits == table[i].bits) + { + strcpy(make, table[i].t_make); + strcpy(model, table[i].t_model); } } /* Separates a Minolta DiMAGE Z2 from a Nikon E4300. */ int CLASS minolta_z2() { int i, nz; char tail[424]; - fseek (ifp, -sizeof tail, SEEK_END); - fread (tail, 1, sizeof tail, ifp); - for (nz=i=0; i < sizeof tail; i++) - if (tail[i]) nz++; + 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 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); + 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); + 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" }; + 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); + 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); + 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); + free(thumb); } void CLASS rollei_load_raw() { uchar pixel[10]; unsigned iten = 0, isix, i, buffer = 0, todo[16]; #ifdef LIBRAW_LIBRARY_BUILD if(raw_width > 32767 || raw_height > 32767) throw LIBRAW_EXCEPTION_IO_BADFILE; #endif unsigned maxpixel = raw_width*(raw_height+7); isix = raw_width * raw_height * 5 / 8; - while (fread (pixel, 1, 10, ifp) == 10) { + while (fread(pixel, 1, 10, ifp) == 10) + { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - 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 = 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 < 16; i += 2) + { + todo[i] = isix++; + todo[i + 1] = buffer >> (14 - i) * 5; } for (i = 0; i < 16; i += 2) if(todo[i] < maxpixel) raw_image[todo[i]] = (todo[i + 1] & 0x3ff); else derror(); } maximum = 0x3ff; } -int CLASS raw (unsigned row, unsigned col) -{ - return (row < raw_height && col < raw_width) ? RAW(row,col) : 0; -} +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) +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; + 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++) { + mrow = (float *)calloc(nc * wide, sizeof *mrow); + merror(mrow, "phase_one_flat_field()"); + for (y = 0; y < high; y++) + { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - 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) + { + 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]; + for (x = 0; x < wide; x++) + for (c = 0; c < nc; c += 2) + mrow[c * wide + x] += mrow[(c + 1) * wide + x]; } } - free (mrow); + free(mrow); } int 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]={NULL,NULL}; + 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] = {NULL, NULL}; ushort *xval[2]; int qmult_applied = 0, qlin_applied = 0; #ifdef LIBRAW_LIBRARY_BUILD if (!meta_length) #else if (half_size || !meta_length) #endif return 0; #ifdef DCRAW_VERBOSE - if (verbose) fprintf (stderr,_("Phase One correction...\n")); + if (verbose) + fprintf(stderr, _("Phase One correction...\n")); #endif - fseek (ifp, meta_offset, SEEK_SET); + fseek(ifp, meta_offset, SEEK_SET); order = get2(); - fseek (ifp, 6, SEEK_CUR); - fseek (ifp, meta_offset+get4(), SEEK_SET); - entries = get4(); get4(); + fseek(ifp, 6, SEEK_CUR); + fseek(ifp, meta_offset + get4(), SEEK_SET); + entries = get4(); + get4(); #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - while (entries--) { + while (entries--) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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++) - { + 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++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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] = 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[19], cf[19]; - 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]; - cf[18] = cx[18] = 65535; - cubic_spline(cx, cf, 19); - - for (row = (qr ? ph1.split_row : 0); - row < (qr ? raw_height : ph1.split_row); 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] = 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[19], cf[19]; + 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]; + cf[18] = cx[18] = 65535; + cubic_spline(cx, cf, 19); + + for (row = (qr ? ph1.split_row : 0); row < (qr ? raw_height : ph1.split_row); row++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - for (col = (qc ? ph1.split_col : 0); - col < (qc ? raw_width : ph1.split_col); col++) - RAW(row,col) = curve[RAW(row,col)]; + 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++) - { + } + 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++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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] = get4(); - for (qr = 0; qr < 2; qr++) - for (qc = 0; qc < 2; qc++) - for (i = 0; i < 7; i++) - lc[qr][qc][i] = 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) 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 = 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] = get4(); + for (qr = 0; qr < 2; qr++) + for (qc = 0; qc < 2; qc++) + for (i = 0; i < 7; i++) + lc[qr][qc][i] = 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)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++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - for (col = (qc ? ph1.split_col : 0); - col < (qc ? raw_width : ph1.split_col); col++) - RAW(row,col) = curve[RAW(row,col)]; + 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; } - qmult_applied = 1; - qlin_applied = 1; + fseek(ifp, save, SEEK_SET); } - 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++) + 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++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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); + 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]); } - free (yval[0]); - } #ifdef LIBRAW_LIBRARY_BUILD } catch (...) { - if(yval[0]) free(yval[0]); + if (yval[0]) + free(yval[0]); return LIBRAW_CANCELLED_BY_CALLBACK; } #endif return 0; } void CLASS phase_one_load_raw() { int a, b, i; ushort akey, bkey, t_mask; - fseek (ifp, ph1.key_off, SEEK_SET); + fseek(ifp, ph1.key_off, SEEK_SET); akey = get2(); bkey = get2(); - t_mask = ph1.format == 1 ? 0x5555:0x1354; + t_mask = ph1.format == 1 ? 0x5555 : 0x1354; #ifdef LIBRAW_LIBRARY_BUILD - if (ph1.black_col || ph1.black_row ) + if (ph1.black_col || ph1.black_row) + { + imgdata.rawdata.ph1_cblack = (short(*)[2])calloc(raw_height * 2, sizeof(ushort)); + merror(imgdata.rawdata.ph1_cblack, "phase_one_load_raw()"); + imgdata.rawdata.ph1_rblack = (short(*)[2])calloc(raw_width * 2, sizeof(ushort)); + merror(imgdata.rawdata.ph1_rblack, "phase_one_load_raw()"); + if (ph1.black_col) { - imgdata.rawdata.ph1_cblack = (short(*)[2])calloc(raw_height*2,sizeof(ushort)); - merror(imgdata.rawdata.ph1_cblack,"phase_one_load_raw()"); - imgdata.rawdata.ph1_rblack = (short(*)[2])calloc(raw_width*2,sizeof(ushort)); - merror(imgdata.rawdata.ph1_rblack,"phase_one_load_raw()"); - if (ph1.black_col) - { - fseek (ifp, ph1.black_col, SEEK_SET); - read_shorts ((ushort *)imgdata.rawdata.ph1_cblack[0], raw_height*2); - } - if (ph1.black_row) - { - fseek (ifp, ph1.black_row, SEEK_SET); - read_shorts ((ushort *) imgdata.rawdata.ph1_rblack[0], raw_width*2); - } - } + fseek(ifp, ph1.black_col, SEEK_SET); + read_shorts((ushort *)imgdata.rawdata.ph1_cblack[0], raw_height * 2); + } + if (ph1.black_row) + { + fseek(ifp, ph1.black_row, SEEK_SET); + read_shorts((ushort *)imgdata.rawdata.ph1_rblack[0], raw_width * 2); + } + } #endif - fseek (ifp, data_offset, SEEK_SET); - read_shorts (raw_image, raw_width*raw_height); + 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 & t_mask) | (b & ~t_mask); - raw_image[i+1] = (b & t_mask) | (a & ~t_mask); + 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 & t_mask) | (b & ~t_mask); + raw_image[i + 1] = (b & t_mask) | (a & ~t_mask); } } -unsigned CLASS ph1_bithuff (int nbits, ushort *huff) +unsigned CLASS ph1_bithuff(int nbits, ushort *huff) { #ifndef LIBRAW_NOTHREADS #define bitbuf tls->ph1_bits.bitbuf -#define vbits tls->ph1_bits.vbits +#define vbits tls->ph1_bits.vbits #else - static UINT64 bitbuf=0; - static int vbits=0; + static UINT64 bitbuf = 0; + static int vbits = 0; #endif unsigned c; if (nbits == -1) return bitbuf = vbits = 0; - if (nbits == 0) return 0; - if (vbits < nbits) { + if (nbits == 0) + return 0; + if (vbits < nbits) + { bitbuf = bitbuf << 32 | get4(); vbits += 32; } - c = bitbuf << (64-vbits) >> (64-nbits); - if (huff) { + c = bitbuf << (64 - vbits) >> (64 - nbits); + if (huff) + { vbits -= huff[c] >> 8; - return (uchar) huff[c]; + return (uchar)huff[c]; } vbits -= nbits; return c; #ifndef LIBRAW_NOTHREADS #undef bitbuf #undef vbits #endif } -#define ph1_bits(n) ph1_bithuff(n,0) -#define ph1_huff(h) ph1_bithuff(*h,h+1) +#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 }; + 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 (*c_black)[2], (*r_black)[2]; + short(*c_black)[2], (*r_black)[2]; #ifdef LIBRAW_LIBRARY_BUILD - if(ph1.format == 6) + if (ph1.format == 6) throw LIBRAW_EXCEPTION_IO_CORRUPT; #endif - 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++) + 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(); - c_black = (short (*)[2]) (offset + raw_height); - fseek (ifp, ph1.black_col, SEEK_SET); + c_black = (short(*)[2])(offset + raw_height); + fseek(ifp, ph1.black_col, SEEK_SET); if (ph1.black_col) - read_shorts ((ushort *) c_black[0], raw_height*2); + read_shorts((ushort *)c_black[0], raw_height * 2); r_black = c_black + raw_height; - fseek (ifp, ph1.black_row, SEEK_SET); + fseek(ifp, ph1.black_row, SEEK_SET); if (ph1.black_row) - read_shorts ((ushort *) r_black[0], raw_width*2); + read_shorts((ushort *)r_black[0], raw_width * 2); #ifdef LIBRAW_LIBRARY_BUILD // Copy data to internal copy (ever if not read) - if (ph1.black_col || ph1.black_row ) - { - imgdata.rawdata.ph1_cblack = (short(*)[2])calloc(raw_height*2,sizeof(ushort)); - merror(imgdata.rawdata.ph1_cblack,"phase_one_load_raw_c()"); - memmove(imgdata.rawdata.ph1_cblack,(ushort*)c_black[0],raw_height*2*sizeof(ushort)); - imgdata.rawdata.ph1_rblack = (short(*)[2])calloc(raw_width*2,sizeof(ushort)); - merror(imgdata.rawdata.ph1_rblack,"phase_one_load_raw_c()"); - memmove(imgdata.rawdata.ph1_rblack,(ushort*)r_black[0],raw_width*2*sizeof(ushort)); - } + if (ph1.black_col || ph1.black_row) + { + imgdata.rawdata.ph1_cblack = (short(*)[2])calloc(raw_height * 2, sizeof(ushort)); + merror(imgdata.rawdata.ph1_cblack, "phase_one_load_raw_c()"); + memmove(imgdata.rawdata.ph1_cblack, (ushort *)c_black[0], raw_height * 2 * sizeof(ushort)); + imgdata.rawdata.ph1_rblack = (short(*)[2])calloc(raw_width * 2, sizeof(ushort)); + merror(imgdata.rawdata.ph1_rblack, "phase_one_load_raw_c()"); + memmove(imgdata.rawdata.ph1_rblack, (ushort *)r_black[0], raw_width * 2 * sizeof(ushort)); + } #endif - for (i=0; i < 256; i++) - curve[i] = i*i / 3.969 + 0.5; + for (i = 0; i < 256; i++) + curve[i] = i * i / 3.969 + 0.5; #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - for (row=0; row < raw_height; row++) { + for (row = 0; row < raw_height; row++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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]]; - } + 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]]; + } #ifndef LIBRAW_LIBRARY_BUILD - for (col=0; col < raw_width; col++) { - int shift = ph1.format == 8? 0: 2; - i = (pixel[col] << shift) - ph1.t_black - + c_black[row][col >= ph1.split_col] - + r_black[col][row >= ph1.split_row]; - if (i > 0) RAW(row,col) = i; - } + for (col = 0; col < raw_width; col++) + { + int shift = ph1.format == 8 ? 0 : 2; + i = (pixel[col] << shift) - ph1.t_black + c_black[row][col >= ph1.split_col] + + r_black[col][row >= ph1.split_row]; + if (i > 0) + RAW(row, col) = i; + } #else - if(ph1.format == 8) - memmove(&RAW(row,0),&pixel[0],raw_width*2); + if (ph1.format == 8) + memmove(&RAW(row, 0), &pixel[0], raw_width * 2); else - for (col=0; col < raw_width; col++) - RAW(row,col) = pixel[col] << 2; + for (col = 0; col < raw_width; col++) + RAW(row, col) = pixel[col] << 2; #endif - } + } #ifdef LIBRAW_LIBRARY_BUILD - } catch(...) { - free (pixel); + } + catch (...) + { + free(pixel); throw; } #endif - free (pixel); + free(pixel); maximum = 0xfffc - ph1.t_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; + if (!ljpeg_start(&jh, 0)) + return; order = 0x4949; ph1_bits(-1); #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - 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++) { + 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++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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; + 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; + } } } - } #ifdef LIBRAW_LIBRARY_BUILD - } catch (...){ - free (back[4]); - ljpeg_end (&jh); + } + catch (...) + { + free(back[4]); + ljpeg_end(&jh); throw; } #endif - free (back[4]); - ljpeg_end (&jh); - if (image) mix_green = 1; + 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; + ushort *pixel = 0; + unsigned tile = 0, r, c, row, col; - if (!filters) { + if (!filters || !raw_image) + { #ifdef LIBRAW_LIBRARY_BUILD if(!image) throw LIBRAW_EXCEPTION_IO_CORRUPT; #endif - pixel = (ushort *) calloc (raw_width, sizeof *pixel); - merror (pixel, "leaf_hdr_load_raw()"); + pixel = (ushort *)calloc(raw_width, sizeof *pixel); + merror(pixel, "leaf_hdr_load_raw()"); } #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - FORC(tiff_samples) - for (r=0; r < raw_height; r++) { + FORC(tiff_samples) + for (r = 0; r < raw_height; r++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - if (r % tile_length == 0) { - fseek (ifp, data_offset + 4*tile++, SEEK_SET); - fseek (ifp, get4(), SEEK_SET); + 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 && c != shot_select) + continue; + if (filters && raw_image) + pixel = raw_image + r * raw_width; + read_shorts(pixel, raw_width); + if (!filters && image && (row = r - top_margin) < height) + for (col = 0; col < width; col++) + image[row * width + col][c] = pixel[col + left_margin]; } #ifdef LIBRAW_LIBRARY_BUILD - } catch (...) { - if(!filters) free(pixel); + } + catch (...) + { + if (!filters) + free(pixel); throw; } #endif - if (!filters) { + if (!filters) + { maximum = 0xffff; raw_color = 1; - free (pixel); + 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++) - { + int row, col, bits = 0; + while (1 << ++bits < maximum) + ; + read_shorts(raw_image, raw_width * raw_height); + fseek(ifp,-2,SEEK_CUR); // avoid EOF error + if (maximum < 0xffff || load_flags) + for (row = 0; row < raw_height; row++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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(); - } + 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 unpacked_load_raw_reversed() { - int row, col, bits=0; - while (1 << ++bits < maximum); - for (row=raw_height-1; row >= 0; row--) - { + int row, col, bits = 0; + while (1 << ++bits < maximum) + ; + for (row = raw_height - 1; row >= 0; row--) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - read_shorts (&raw_image[row*raw_width], raw_width); - 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(); - } + read_shorts(&raw_image[row * raw_width], raw_width); + 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); + 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; } #ifdef LIBRAW_LIBRARY_BUILD - else if(!image) + if (!image) throw LIBRAW_EXCEPTION_IO_CORRUPT; #endif - pixel = (ushort *) calloc (raw_width, sizeof *pixel); - merror (pixel, "sinar_4shot_load_raw()"); + pixel = (ushort *)calloc(raw_width, sizeof *pixel); + merror(pixel, "sinar_4shot_load_raw()"); #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - for (shot=0; shot < 4; shot++) { + for (shot = 0; shot < 4; shot++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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]; - } + 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]; + } + } } - } #ifdef LIBRAW_LIBRARY_BUILD - } catch (...) { + } + catch (...) + { free(pixel); throw; } #endif - free (pixel); + free(pixel); mix_green = 1; } void CLASS imacon_full_load_raw() { +#ifdef LIBRAW_LIBRARY_BUILD + if (!image) + throw LIBRAW_EXCEPTION_IO_CORRUPT; +#endif int row, col; - if (!image) return; - #ifdef LIBRAW_LIBRARY_BUILD - unsigned short *buf = (unsigned short *)malloc(width*3*sizeof(unsigned short)); - merror(buf,"imacon_full_load_raw"); + unsigned short *buf = (unsigned short *)malloc(width * 3 * sizeof(unsigned short)); + merror(buf, "imacon_full_load_raw"); #endif - for (row=0; row < height; row++) + for (row = 0; row < height; row++) { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); - read_shorts(buf,width*3); - unsigned short (*rowp)[4] = &image[row*width]; - for (col=0; col < width; col++) - { - rowp[col][0]=buf[col*3]; - rowp[col][1]=buf[col*3+1]; - rowp[col][2]=buf[col*3+2]; - rowp[col][3]=0; - } + read_shorts(buf, width * 3); + unsigned short(*rowp)[4] = &image[row * width]; + for (col = 0; col < width; col++) + { + rowp[col][0] = buf[col * 3]; + rowp[col][1] = buf[col * 3 + 1]; + rowp[col][2] = buf[col * 3 + 2]; + rowp[col][3] = 0; + } #else - for (col=0; col < width; col++) - read_shorts (image[row*width+col], 3); + for (col = 0; col < width; col++) + read_shorts(image[row * width + col], 3); #endif } #ifdef LIBRAW_LIBRARY_BUILD free(buf); #endif } void CLASS packed_load_raw() { - int vbits=0, bwide, rbits, bite, half, irow, row, col, val, i; - UINT64 bitbuf=0; + 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; + 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++) { + half = (raw_height + 1) >> 1; + for (irow = 0; irow < raw_height; irow++) + { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif 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); + 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); } } if(feof(ifp)) throw LIBRAW_EXCEPTION_IO_EOF; - 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); + 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(); + 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; } } #ifdef LIBRAW_LIBRARY_BUILD ushort raw_stride; -void CLASS parse_broadcom () { +void CLASS parse_broadcom() +{ -/* This structure is at offset 0xb0 from the 'BRCM' ident. */ - struct { + /* This structure is at offset 0xb0 from the 'BRCM' ident. */ + struct + { uint8_t umode[32]; uint16_t uwidth; uint16_t uheight; uint16_t padding_right; uint16_t padding_down; uint32_t unknown_block[6]; uint16_t transform; uint16_t format; uint8_t bayer_order; uint8_t bayer_format; } header; header.bayer_order = 0; - fseek (ifp, 0xb0 - 0x20, SEEK_CUR); - fread (&header, 1, sizeof(header), ifp); - raw_stride = ((((((header.uwidth + header.padding_right)*5)+3)>>2) + 0x1f)&(~0x1f)); + fseek(ifp, 0xb0 - 0x20, SEEK_CUR); + fread(&header, 1, sizeof(header), ifp); + raw_stride = ((((((header.uwidth + header.padding_right) * 5) + 3) >> 2) + 0x1f) & (~0x1f)); raw_width = width = header.uwidth; raw_height = height = header.uheight; - filters = 0x16161616; /* default Bayer order is 2, BGGR */ + filters = 0x16161616; /* default Bayer order is 2, BGGR */ - switch (header.bayer_order) { - case 0: /* RGGB */ - filters = 0x94949494; - break; - case 1: /* GBRG */ - filters = 0x49494949; - break; - case 3: /* GRBG */ - filters = 0x61616161; - break; + switch (header.bayer_order) + { + case 0: /* RGGB */ + filters = 0x94949494; + break; + case 1: /* GBRG */ + filters = 0x49494949; + break; + case 3: /* GRBG */ + filters = 0x61616161; + break; } } -void CLASS broadcom_load_raw() { +void CLASS broadcom_load_raw() +{ uchar *data, *dp; int rev, row, col, c; rev = 3 * (order == 0x4949); - data = (uchar *) malloc (raw_stride*2); - merror (data, "broadcom_load_raw()"); + data = (uchar *)malloc(raw_stride * 2); + merror(data, "broadcom_load_raw()"); - for (row=0; row < raw_height; row++) { - if (fread (data+raw_stride, 1, raw_stride, ifp) < raw_stride) derror(); - FORC(raw_stride) data[c] = data[raw_stride+(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); + for (row = 0; row < raw_height; row++) + { + if (fread(data + raw_stride, 1, raw_stride, ifp) < raw_stride) + derror(); + FORC(raw_stride) data[c] = data[raw_stride + (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); + free(data); } #endif void CLASS nokia_load_raw() { - uchar *data, *dp; + uchar *data, *dp; int rev, dwide, row, col, c; - double sum[]={0,0}; + double sum[] = {0, 0}; rev = 3 * (order == 0x4949); dwide = (raw_width * 5 + 1) / 4; - data = (uchar *) malloc (dwide*2); - merror (data, "nokia_load_raw()"); + data = (uchar *)malloc(dwide * 2); + merror(data, "nokia_load_raw()"); #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - for (row=0; row < raw_height; row++) { + for (row = 0; row < raw_height; row++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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); - } + 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); + } #ifdef LIBRAW_LIBRARY_BUILD - } catch (...){ - free (data); + } + catch (...) + { + free(data); throw; } #endif - free (data); + free(data); maximum = 0x3ff; - if (strncmp(make,"OmniVision",10)) 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 (strncmp(make, "OmniVision", 10)) + 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; + if (sum[1] > sum[0]) + filters = 0x4b4b4b4b; } void CLASS android_tight_load_raw() { uchar *data, *dp; int bwide, row, col, c; - bwide = -(-5*raw_width >> 5) << 3; - data = (uchar *) malloc (bwide); - merror (data, "android_tight_load_raw()"); - for (row=0; row < raw_height; row++) { - if (fread (data, 1, bwide, ifp) < bwide) derror(); - 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); + bwide = -(-5 * raw_width >> 5) << 3; + data = (uchar *)malloc(bwide); + merror(data, "android_tight_load_raw()"); + for (row = 0; row < raw_height; row++) + { + if (fread(data, 1, bwide, ifp) < bwide) + derror(); + 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); } void CLASS android_loose_load_raw() { uchar *data, *dp; int bwide, row, col, c; - UINT64 bitbuf=0; + UINT64 bitbuf = 0; - bwide = (raw_width+5)/6 << 3; - data = (uchar *) malloc (bwide); - merror (data, "android_loose_load_raw()"); - for (row=0; row < raw_height; row++) { - if (fread (data, 1, bwide, ifp) < bwide) derror(); - for (dp=data, col=0; col < raw_width; dp+=8, col+=6) { - FORC(8) bitbuf = (bitbuf << 8) | dp[c^7]; - FORC(6) RAW(row,col+c) = (bitbuf >> c*10) & 0x3ff; + bwide = (raw_width + 5) / 6 << 3; + data = (uchar *)malloc(bwide); + merror(data, "android_loose_load_raw()"); + for (row = 0; row < raw_height; row++) + { + if (fread(data, 1, bwide, ifp) < bwide) + derror(); + for (dp = data, col = 0; col < raw_width; dp += 8, col += 6) + { + FORC(8) bitbuf = (bitbuf << 8) | dp[c ^ 7]; + FORC(6) RAW(row, col + c) = (bitbuf >> c * 10) & 0x3ff; } } - free (data); + free(data); } void CLASS canon_rmf_load_raw() { int row, col, bits, orow, ocol, c; #ifdef LIBRAW_LIBRARY_BUILD - int *words = (int*)malloc(sizeof(int)*(raw_width/3+1)); - merror(words,"canon_rmf_load_raw"); + int *words = (int *)malloc(sizeof(int) * (raw_width / 3 + 1)); + merror(words, "canon_rmf_load_raw"); #endif - for (row=0; row < raw_height; row++) + for (row = 0; row < raw_height; row++) { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); - fread(words,sizeof(int),raw_width/3,ifp); - for (col=0; col < raw_width-2; col+=3) + fread(words, sizeof(int), raw_width / 3, ifp); + for (col = 0; col < raw_width - 2; col += 3) + { + bits = words[col / 3]; + FORC3 { - bits = words[col/3]; - 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]; + 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]; } + } #else - for (col=0; col < raw_width-2; col+=3) { + 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]; + 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]; } } #endif } #ifdef LIBRAW_LIBRARY_BUILD free(words); #endif maximum = curve[0x3ff]; } -unsigned CLASS pana_bits (int nbits) +unsigned CLASS pana_data(int nb, unsigned *bytes) { #ifndef LIBRAW_NOTHREADS -#define buf tls->pana_bits.buf -#define vbits tls->pana_bits.vbits +#define vpos tls->pana_data.vpos +#define buf tls->pana_data.buf #else - static uchar buf[0x4000]; - static int vbits; + static uchar buf[0x4002]; + static int vpos; #endif int byte; - if (!nbits) return vbits=0; - if (!vbits) { - fread (buf+load_flags, 1, 0x4000-load_flags, ifp); - fread (buf, 1, load_flags, ifp); + if (!nb && !bytes) + return vpos = 0; + + if (!vpos) + { + fread(buf + load_flags, 1, 0x4000 - load_flags, ifp); + fread(buf, 1, load_flags, ifp); + } + + if (pana_encoding == 5) + { + for (byte = 0; byte < 16; byte++) + { + bytes[byte] = buf[vpos++]; + vpos &= 0x3FFF; + } + } + else + { + vpos = (vpos - nb) & 0x1ffff; + byte = vpos >> 3 ^ 0x3ff0; + return (buf[byte] | buf[byte + 1] << 8) >> (vpos & 7) & ~((~0u) << nb); } - vbits = (vbits - nbits) & 0x1ffff; - byte = vbits >> 3 ^ 0x3ff0; - return (buf[byte] | buf[byte+1] << 8) >> (vbits & 7) & ~((~0u) << nbits); + return 0; #ifndef LIBRAW_NOTHREADS +#undef vpos #undef buf -#undef vbits #endif } void CLASS panasonic_load_raw() { - int row, col, i, j, sh=0, pred[2], nonz[2]; + int row, col, i, j, sh = 0, pred[2], nonz[2]; + unsigned bytes[16]; + ushort *raw_block_data; + int enc_blck_size = pana_bpp == 12 ? 10 : 9; - pana_bits(0); - for (row = 0; row < raw_height; row++) + pana_data(0, 0); + if (pana_encoding == 5) { + for (row = 0; row < raw_height; row++) + { + raw_block_data = raw_image + row * raw_width; + #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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] &= ~((~0u) << sh); - pred[i & 1] += j << sh; + for (col = 0; col < raw_width; col += enc_blck_size) + { + pana_data(0, bytes); + + if (pana_bpp == 12) + { + raw_block_data[col] = ((bytes[1] & 0xF) << 8) + bytes[0]; + raw_block_data[col + 1] = 16 * bytes[2] + (bytes[1] >> 4); + raw_block_data[col + 2] = ((bytes[4] & 0xF) << 8) + bytes[3]; + raw_block_data[col + 3] = 16 * bytes[5] + (bytes[4] >> 4); + raw_block_data[col + 4] = ((bytes[7] & 0xF) << 8) + bytes[6]; + raw_block_data[col + 5] = 16 * bytes[8] + (bytes[7] >> 4); + raw_block_data[col + 6] = ((bytes[10] & 0xF) << 8) + bytes[9]; + raw_block_data[col + 7] = 16 * bytes[11] + (bytes[10] >> 4); + raw_block_data[col + 8] = ((bytes[13] & 0xF) << 8) + bytes[12]; + raw_block_data[col + 9] = 16 * bytes[14] + (bytes[13] >> 4); + } + else if (pana_bpp == 14) + { + raw_block_data[col] = bytes[0] + ((bytes[1] & 0x3F) << 8); + raw_block_data[col + 1] = (bytes[1] >> 6) + 4 * (bytes[2]) + + ((bytes[3] & 0xF) << 10); + raw_block_data[col + 2] = (bytes[3] >> 4) + 16 * (bytes[4]) + + ((bytes[5] & 3) << 12); + raw_block_data[col + 3] = ((bytes[5] & 0xFC) >> 2) + (bytes[6] << 6); + raw_block_data[col + 4] = bytes[7] + ((bytes[8] & 0x3F) << 8); + raw_block_data[col + 5] = (bytes[8] >> 6) + 4 * bytes[9] + ((bytes[10] & 0xF) << 10); + raw_block_data[col + 6] = (bytes[10] >> 4) + 16 * bytes[11] + ((bytes[12] & 3) << 12); + raw_block_data[col + 7] = ((bytes[12] & 0xFC) >> 2) + (bytes[13] << 6); + raw_block_data[col + 8] = bytes[14] + ((bytes[15] & 0x3F) << 8); } } - 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 && row < height) - derror(); + } + } + else + { + for (row = 0; row < raw_height; row++) + { +#ifdef LIBRAW_LIBRARY_BUILD + checkCancel(); +#endif + 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_data(2, 0)); + if (nonz[i & 1]) + { + if ((j = pana_data(8, 0))) + { + if ((pred[i & 1] -= 0x80 << sh) < 0 || sh == 4) + pred[i & 1] &= ~((~0u) << sh); + pred[i & 1] += j << sh; + } + } + else if ((nonz[i & 1] = pana_data(8, 0)) || i > 11) + pred[i & 1] = nonz[i & 1] << 4 | pana_data(4, 0); + if ((RAW(row, col) = pred[col & 1]) > 4098 && col < width && row < height) + 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); + 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++) { + for (row = 0; row < height; row++) + { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - memset (acarry, 0, sizeof acarry); - for (col=0; col < raw_width; col++) { + 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++); + 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; + 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; + 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(); + 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++) { + for (irow = 0; irow < 1481; irow++) + { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - if (fread (pixel, 1, 768, ifp) < 768) derror(); + 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; + 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 t_curve[256] = - { 0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27, - 28,29,30,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,53, - 54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,74,75,76,77,78, - 79,80,81,82,83,84,86,88,90,92,94,97,99,101,103,105,107,110,112,114,116, - 118,120,123,125,127,129,131,134,136,138,140,142,144,147,149,151,153,155, - 158,160,162,164,166,168,171,173,175,177,179,181,184,186,188,190,192,195, - 197,199,201,203,205,208,210,212,214,216,218,221,223,226,230,235,239,244, - 248,252,257,261,265,270,274,278,283,287,291,296,300,305,309,313,318,322, - 326,331,335,339,344,348,352,357,361,365,370,374,379,383,387,392,396,400, - 405,409,413,418,422,426,431,435,440,444,448,453,457,461,466,470,474,479, - 483,487,492,496,500,508,519,531,542,553,564,575,587,598,609,620,631,643, - 654,665,676,687,698,710,721,732,743,754,766,777,788,799,810,822,833,844, - 855,866,878,889,900,911,922,933,945,956,967,978,989,1001,1012,1023 }; - int rb, row, col, sharp, val=0; + static const short gstep[16] = {-89, -60, -44, -32, -22, -15, -8, -2, 2, 8, 15, 22, 32, 44, 60, 89}; + static const short rstep[6][4] = {{-3, -1, 1, 3}, {-5, -1, 1, 5}, {-8, -2, 2, 8}, + {-13, -3, 3, 13}, {-19, -4, 4, 19}, {-28, -6, 6, 28}}; + static const short t_curve[256] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 88, 90, 92, 94, 97, 99, + 101, 103, 105, 107, 110, 112, 114, 116, 118, 120, 123, 125, 127, 129, 131, 134, 136, 138, 140, 142, 144, 147, + 149, 151, 153, 155, 158, 160, 162, 164, 166, 168, 171, 173, 175, 177, 179, 181, 184, 186, 188, 190, 192, 195, + 197, 199, 201, 203, 205, 208, 210, 212, 214, 216, 218, 221, 223, 226, 230, 235, 239, 244, 248, 252, 257, 261, + 265, 270, 274, 278, 283, 287, 291, 296, 300, 305, 309, 313, 318, 322, 326, 331, 335, 339, 344, 348, 352, 357, + 361, 365, 370, 374, 379, 383, 387, 392, 396, 400, 405, 409, 413, 418, 422, 426, 431, 435, 440, 444, 448, 453, + 457, 461, 466, 470, 474, 479, 483, 487, 492, 496, 500, 508, 519, 531, 542, 553, 564, 575, 587, 598, 609, 620, + 631, 643, 654, 665, 676, 687, 698, 710, 721, 732, 743, 754, 766, 777, 788, 799, 810, 822, 833, 844, 855, 866, + 878, 889, 900, 911, 922, 933, 945, 956, 967, 978, 989, 1001, 1012, 1023}; + int rb, row, col, sharp, val = 0; #ifdef LIBRAW_LIBRARY_BUILD if(width>640 || height > 480) throw LIBRAW_EXCEPTION_IO_CORRUPT; #endif - + getbits(-1); - memset (pixel, 0x80, sizeof pixel); - for (row=2; row < height+2; row++) { + memset(pixel, 0x80, sizeof pixel); + for (row = 2; row < height + 2; row++) + { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - 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); + 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; + 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 - 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 (rb = 0; rb < 2; rb++) + for (row = 2 + rb; row < height + 2; row += 2) { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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 (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 (row = 2; row < height + 2; row++) { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - 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 (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 (row = 0; row < height; row++) { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - for (col=0; col < width; col++) - RAW(row,col) = t_curve[pixel[row+2][col+2]]; + for (col = 0; col < width; col++) + RAW(row, col) = t_curve[pixel[row + 2][col + 2]]; } maximum = 0x3ff; } -#define radc_token(tree) ((signed char) getbithuff(8,huff[tree])) +#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 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 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) #ifdef __GNUC__ -# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) -# pragma GCC optimize("no-aggressive-loop-optimizations") -# endif +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) +#pragma GCC optimize("no-aggressive-loop-optimizations") +#endif #endif void CLASS kodak_radc_load_raw() { #ifdef LIBRAW_LIBRARY_BUILD // All kodak radc images are 768x512 - if(width>768 || raw_width>768 || height > 512 || raw_height>512 ) + if (width > 768 || raw_width > 768 || height > 512 || raw_height > 512) throw LIBRAW_EXCEPTION_IO_CORRUPT; #endif static const signed 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 - }; + 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) + 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]) - ((ushort *)huff)[s++] = src[i] << 8 | (uchar) src[i+1]; + ((ushort *)huff)[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); + FORC(256) huff[18][c] = (8 - s) << 8 | c >> s << s | 1 << (s - 1); getbits(-1); - for (i=0; i < sizeof(buf)/sizeof(short); i++) + for (i = 0; i < sizeof(buf) / sizeof(short); i++) ((short *)buf)[i] = 2048; - for (row=0; row < height; row+=4) { + for (row = 0; row < height; row += 4) + { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif FORC3 mul[c] = getbits(6); #ifdef LIBRAW_LIBRARY_BUILD - if(!mul[0] || !mul[1] || !mul[2]) + if (!mul[0] || !mul[1] || !mul[2]) throw LIBRAW_EXCEPTION_IO_CORRUPT; #endif - FORC3 { - val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c]; - s = val > 65564 ? 10:12; - x = ~((~0u) << (s-1)); - val <<= 12-s; - for (i=0; i < sizeof(buf[0])/sizeof(short); i++) - ((short *)buf[c])[i] = (((short *)buf[c])[i] * val + x) >> s; + FORC3 + { + val = ((0x1000000 / last[c] + 0x7ff) >> 12) * mul[c]; + s = val > 65564 ? 10 : 12; + x = ~((~0u) << (s - 1)); + val <<= 12 - s; + for (i = 0; i < sizeof(buf[0]) / sizeof(short); i++) + ((short *)buf[c])[i] = (((short *)buf[c])[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; - if(col>=0) - 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 (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(col>=0) + { + 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; + if(col>=0) + 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 (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++) + 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 - #ifndef LIBRAW_LIBRARY_BUILD METHODDEF(boolean) -fill_input_buffer (j_decompress_ptr cinfo) +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); + 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]; + JSAMPLE(*pixel)[3]; int row, col; - cinfo.err = jpeg_std_error (&jerr); - jpeg_create_decompress (&cinfo); - jpeg_stdio_src (&cinfo, ifp); + 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) { + 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_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); + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); maximum = 0xff << 1; } #else -struct jpegErrorManager { +struct jpegErrorManager +{ struct jpeg_error_mgr pub; }; -static void jpegErrorExit (j_common_ptr cinfo) +static void jpegErrorExit(j_common_ptr cinfo) { - jpegErrorManager* myerr = (jpegErrorManager*) cinfo->err; + jpegErrorManager *myerr = (jpegErrorManager *)cinfo->err; throw LIBRAW_EXCEPTION_DECODE_JPEG; } - // LibRaw's Kodak_jpeg_load_raw void CLASS kodak_jpeg_load_raw() { - if(data_size < 1) + if (data_size < 1) throw LIBRAW_EXCEPTION_DECODE_JPEG; int row, col; jpegErrorManager jerr; struct jpeg_decompress_struct cinfo; cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = jpegErrorExit; unsigned char *jpg_buf = (unsigned char *)malloc(data_size); - merror(jpg_buf,"kodak_jpeg_load_raw"); - unsigned char *pixel_buf = (unsigned char*) malloc(width*3); - jpeg_create_decompress (&cinfo); - merror(pixel_buf,"kodak_jpeg_load_raw"); + merror(jpg_buf, "kodak_jpeg_load_raw"); + unsigned char *pixel_buf = (unsigned char *)malloc(width * 3); + jpeg_create_decompress(&cinfo); + merror(pixel_buf, "kodak_jpeg_load_raw"); - fread(jpg_buf,data_size,1,ifp); - swab ((char*)jpg_buf, (char*)jpg_buf, data_size); + fread(jpg_buf, data_size, 1, ifp); + swab((char *)jpg_buf, (char *)jpg_buf, data_size); try - { - jpeg_mem_src(&cinfo, jpg_buf, data_size); - int rc = jpeg_read_header(&cinfo, TRUE); - if(rc!=1) - throw LIBRAW_EXCEPTION_DECODE_JPEG; + { + jpeg_mem_src(&cinfo, jpg_buf, data_size); + int rc = jpeg_read_header(&cinfo, TRUE); + if (rc != 1) + throw LIBRAW_EXCEPTION_DECODE_JPEG; - jpeg_start_decompress (&cinfo); - if ((cinfo.output_width != width ) || - (cinfo.output_height*2 != height ) || - (cinfo.output_components != 3 )) - { - throw LIBRAW_EXCEPTION_DECODE_JPEG; - } + jpeg_start_decompress(&cinfo); + if ((cinfo.output_width != width) || (cinfo.output_height * 2 != height) || (cinfo.output_components != 3)) + { + throw LIBRAW_EXCEPTION_DECODE_JPEG; + } - unsigned char *buf[1]; - buf[0] = pixel_buf; + unsigned char *buf[1]; + buf[0] = pixel_buf; - while (cinfo.output_scanline < cinfo.output_height) - { - checkCancel(); - row = cinfo.output_scanline * 2; - jpeg_read_scanlines (&cinfo, buf, 1); - unsigned char (*pixel)[3] = (unsigned char (*)[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]; - } - } + while (cinfo.output_scanline < cinfo.output_height) + { + checkCancel(); + row = cinfo.output_scanline * 2; + jpeg_read_scanlines(&cinfo, buf, 1); + unsigned char(*pixel)[3] = (unsigned char(*)[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]; + } } + } catch (...) - { - jpeg_finish_decompress (&cinfo); - jpeg_destroy_decompress (&cinfo); - free(jpg_buf); - free(pixel_buf); - throw; - } - jpeg_finish_decompress (&cinfo); - jpeg_destroy_decompress (&cinfo); + { + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + free(jpg_buf); + free(pixel_buf); + throw; + } + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); free(jpg_buf); free(pixel_buf); maximum = 0xff << 1; } #endif #ifndef LIBRAW_LIBRARY_BUILD -void CLASS gamma_curve (double pwr, double ts, int mode, int imax); +void CLASS gamma_curve(double pwr, double ts, int mode, int imax); #endif void CLASS lossy_dng_load_raw() { #ifdef LIBRAW_LIBRARY_BUILD - if(!image) + if (!image) throw LIBRAW_EXCEPTION_IO_CORRUPT; #endif 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; + 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); + if (meta_offset) + { + fseek(ifp, meta_offset, SEEK_SET); order = 0x4d4d; ntags = get4(); - while (ntags--) { - opcode = get4(); get4(); 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, (int)j); - cur[c][i] = tot*0xffff; + { + 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, (int)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); + } + 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); + fseek(ifp, get4(), SEEK_SET); #ifdef LIBRAW_LIBRARY_BUILD - if(libraw_internal_data.internal_data.input->jpeg_src(&cinfo) == -1) - { - jpeg_destroy_decompress(&cinfo); - throw LIBRAW_EXCEPTION_DECODE_JPEG; - } + if (libraw_internal_data.internal_data.input->jpeg_src(&cinfo) == -1) + { + jpeg_destroy_decompress(&cinfo); + throw LIBRAW_EXCEPTION_DECODE_JPEG; + } #else - jpeg_stdio_src (&cinfo, ifp); + jpeg_stdio_src(&cinfo, ifp); #endif - 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); + 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); #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - while (cinfo.output_scanline < cinfo.output_height && - (row = trow + cinfo.output_scanline) < height) { + while (cinfo.output_scanline < cinfo.output_height && (row = trow + cinfo.output_scanline) < height) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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_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]]; + } } - } #ifdef LIBRAW_LIBRARY_BUILD - } catch(...) { - jpeg_destroy_decompress (&cinfo); - throw; - } + } + catch (...) + { + jpeg_destroy_decompress(&cinfo); + throw; + } #endif - jpeg_abort_decompress (&cinfo); + jpeg_abort_decompress(&cinfo); if ((tcol += tile_width) >= raw_width) trow += tile_length + (tcol = 0); } - jpeg_destroy_decompress (&cinfo); + 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 }; + 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++) { + for (row = 0; row < height; row++) + { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - if (fread (pixel, 1, 848, ifp) < 848) derror(); + 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]; + 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()"); + pixel = (uchar *)calloc(raw_width, sizeof *pixel); + merror(pixel, "eight_bit_load_raw()"); #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - for (row=0; row < raw_height; row++) { + for (row = 0; row < raw_height; row++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - if (fread (pixel, 1, raw_width, ifp) < raw_width) derror(); - for (col=0; col < raw_width; col++) - RAW(row,col) = curve[pixel[col]]; - } + if (fread(pixel, 1, raw_width, ifp) < raw_width) + derror(); + for (col = 0; col < raw_width; col++) + RAW(row, col) = curve[pixel[col]]; + } #ifdef LIBRAW_LIBRARY_BUILD - } catch(...) { - free (pixel); + } + catch (...) + { + free(pixel); throw; } #endif - free (pixel); + free(pixel); maximum = curve[0xff]; } void CLASS kodak_c330_load_raw() { #ifdef LIBRAW_LIBRARY_BUILD - if(!image) + if (!image) throw LIBRAW_EXCEPTION_IO_CORRUPT; #endif 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()"); + pixel = (uchar *)calloc(raw_width, 2 * sizeof *pixel); + merror(pixel, "kodak_c330_load_raw()"); #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - for (row=0; row < height; row++) { + for (row = 0; row < height; row++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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)]; + 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)]; + } } - } #ifdef LIBRAW_LIBRARY_BUILD - } catch(...) { - free (pixel); + } + catch (...) + { + free(pixel); throw; } #endif - free (pixel); + free(pixel); maximum = curve[0xff]; } void CLASS kodak_c603_load_raw() { #ifdef LIBRAW_LIBRARY_BUILD - if(!image) + if (!image) throw LIBRAW_EXCEPTION_IO_CORRUPT; #endif 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()"); + pixel = (uchar *)calloc(raw_width, 3 * sizeof *pixel); + merror(pixel, "kodak_c603_load_raw()"); #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - for (row=0; row < height; row++) { + for (row = 0; row < height; row++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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)]; + 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)]; + } } - } #ifdef LIBRAW_LIBRARY_BUILD - } catch(...) { - free (pixel); + } + catch (...) + { + free(pixel); throw; } #endif - free (pixel); + 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 } }; + 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; + 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); + 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(); #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - for (row=0; row < raw_height; row++) { + for (row = 0; row < raw_height; row++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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; - } - } -#ifdef LIBRAW_LIBRARY_BUILD - } catch(...) { - free (pixel); + 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; + } + } +#ifdef LIBRAW_LIBRARY_BUILD + } + catch (...) + { + free(pixel); throw; } #endif - free (pixel); - FORC(2) free (huff[c]); + free(pixel); + FORC(2) free(huff[c]); } -int CLASS kodak_65000_decode (short *out, int bsize) +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; + 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) { + 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; + 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; + if ((bsize & 7) == 4) + { + bitbuf = fgetc(ifp) << 8; bitbuf += fgetc(ifp); bits = 16; } - for (i=0; i < bsize; i++) { + 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)); + if (bits < len) + { + for (j = 0; j < 32; j += 8) + bitbuf += (INT64)fgetc(ifp) << (bits + (j ^ 8)); bits += 32; } - diff = bitbuf & (0xffff >> (16-len)); + diff = bitbuf & (0xffff >> (16 - len)); bitbuf >>= len; bits -= len; - if ((diff & (1 << (len-1))) == 0) + if ((diff & (1 << (len - 1))) == 0) diff -= (1 << len) - 1; out[i] = diff; } return 0; } void CLASS kodak_65000_load_raw() { - short buf[272]; /* extra room for data stored w/o predictor */ + short buf[272]; /* 264 looks enough */ int row, col, len, pred[2], ret, i; - for (row=0; row < height; row++) + for (row = 0; row < height; row++) { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - for (col=0; col < width; col+=256) { + 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++) + len = MIN(256, width - col); + ret = kodak_65000_decode(buf, len); + for (i = 0; i < len; i++) { - int idx = ret ? buf[i] : (pred[i & 1] += buf[i]); - if(idx >=0 && idx <= 0xffff) - { - if ((RAW(row,col+i) = curve[idx]) >> 12) derror(); - } - else - derror(); + int idx = ret ? buf[i] : (pred[i & 1] += buf[i]); + if (idx >= 0 && idx < 0xffff) + { + if ((RAW(row, col + i) = curve[idx]) >> 12) + derror(); + } + else + derror(); } } } } void CLASS kodak_ycbcr_load_raw() { #ifdef LIBRAW_LIBRARY_BUILD - if(!image) + if (!image) throw LIBRAW_EXCEPTION_IO_CORRUPT; #endif short buf[384], *bp; int row, col, len, c, i, j, k, y[2][2], cb, cr, rgb[3]; ushort *ip; - if (!image) return; - unsigned int bits = (load_flags && load_flags > 9 && load_flags < 17)?load_flags:10; - for (row=0; row < height; row+=2) + unsigned int bits = (load_flags && load_flags > 9 && load_flags < 17) ? load_flags : 10; + for (row = 0; row < height; row += 2) { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - for (col=0; col < width; col+=128) { - len = MIN (128, width-col); - kodak_65000_decode (buf, len*3); + 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++) >> bits) derror(); - ip = image[(row+j)*width + col+i+k]; - FORC3 ip[c] = curve[LIM(y[j][k]+rgb[c], 0, 0xfff)]; - } + 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++) >> bits) + 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() { #ifdef LIBRAW_LIBRARY_BUILD - if(!image) + if (!image) throw LIBRAW_EXCEPTION_IO_CORRUPT; #endif short buf[768], *bp; - int row, col, len, c, i, rgb[3],ret; - ushort *ip=image[0]; + int row, col, len, c, i, rgb[3], ret; + ushort *ip = image[0]; - for (row=0; row < height; row++) + for (row = 0; row < height; row++) { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - for (col=0; col < width; col+=256) { - len = MIN (256, width-col); - ret = kodak_65000_decode (buf, len*3); - memset (rgb, 0, sizeof rgb); - for (bp=buf, i=0; i < len; i++, ip+=4) + for (col = 0; col < width; col += 256) + { + len = MIN(256, width - col); + ret = kodak_65000_decode(buf, len * 3); + memset(rgb, 0, sizeof rgb); + for (bp = buf, i = 0; i < len; i++, ip += 4) #ifdef LIBRAW_LIBRARY_BUILD - if(load_flags == 12) - { - FORC3 ip[c] = ret ? (*bp++) : (rgb[c] += *bp++); - } + if (load_flags == 12) + { + FORC3 ip[c] = ret ? (*bp++) : (rgb[c] += *bp++); + } else #endif FORC3 if ((ip[c] = ret ? (*bp++) : (rgb[c] += *bp++)) >> 12) derror(); } } } void CLASS kodak_thumb_load_raw() { #ifdef LIBRAW_LIBRARY_BUILD - if(!image) + if (!image) throw LIBRAW_EXCEPTION_IO_CORRUPT; #endif 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); + 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) +void CLASS sony_decrypt(unsigned *data, int len, int start, int key) { #ifndef LIBRAW_NOTHREADS #define pad tls->sony_decrypt.pad -#define p tls->sony_decrypt.p +#define p tls->sony_decrypt.p #else static unsigned pad[128], p; #endif - if (start) { - for (p=0; p < 4; 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[3] = pad[3] << 1 | (pad[0] ^ pad[2]) >> 31; + for (p = 4; p < 127; p++) + pad[p] = (pad[p - 4] ^ pad[p - 2]) << 1 | (pad[p - 3] ^ pad[p - 1]) >> 31; + for (p = 0; p < 127; p++) pad[p] = htonl(pad[p]); } while (len--) - { - *data++ ^= pad[p & 127] = pad[(p+1) & 127] ^ pad[(p+65) & 127]; - p++; - } + { + *data++ ^= pad[p & 127] = pad[(p + 1) & 127] ^ pad[(p + 65) & 127]; + p++; + } #ifndef LIBRAW_NOTHREADS #undef pad #undef p #endif } void CLASS sony_load_raw() { uchar head[40]; ushort *pixel; unsigned i, key, row, col; - fseek (ifp, 200896, SEEK_SET); - fseek (ifp, (unsigned) fgetc(ifp)*4 - 1, SEEK_CUR); + 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 *) head, 10, 1, key); - for (i=26; i-- > 22; ) + fseek(ifp, 164600, SEEK_SET); + fread(head, 1, 40, ifp); + sony_decrypt((unsigned *)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++) { + fseek(ifp, data_offset, SEEK_SET); + for (row = 0; row < raw_height; row++) + { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - pixel = raw_image + row*raw_width; - if (fread (pixel, 2, raw_width, ifp) < raw_width) derror(); - sony_decrypt ((unsigned *) pixel, raw_width/2, !row, key); - for (col=0; col < raw_width; col++) - if ((pixel[col] = ntohs(pixel[col])) >> 14) derror(); + pixel = raw_image + row * raw_width; + if (fread(pixel, 2, raw_width, ifp) < raw_width) + derror(); + sony_decrypt((unsigned *)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; + 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++) + for (n = i = 0; i < 18; i++) FORC(32768 >> (tab[i] >> 8)) huff[++n] = tab[i]; getbits(-1); - for (col = raw_width; col--; ) + for (col = raw_width; col--;) { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - 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; + 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()"); + data = (uchar *)malloc(raw_width + 1); + merror(data, "sony_arw2_load_raw()"); #ifdef LIBRAW_LIBRARY_BUILD - try { + try + { #endif - for (row=0; row < height; row++) { + for (row = 0; row < height; row++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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++); -#ifdef LIBRAW_LIBRARY_BUILD - /* flag checks if outside of loop */ - if(! (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SONYARW2_ALLFLAGS) // no flag set - || (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SONYARW2_DELTATOVALUE) - ) - { - 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; + 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++) + ; +#ifdef LIBRAW_LIBRARY_BUILD + /* flag checks if outside of loop */ + if (!(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SONYARW2_ALLFLAGS) // no flag set + || (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SONYARW2_DELTATOVALUE)) + { + 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; } } - else if(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SONYARW2_BASEONLY) + else if (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SONYARW2_BASEONLY) { - for (bit=30, i=0; i < 16; i++) - if (i == imax) pix[i] = max; - else if (i == imin) pix[i] = min; - else pix[i]=0; + for (bit = 30, i = 0; i < 16; i++) + if (i == imax) + pix[i] = max; + else if (i == imin) + pix[i] = min; + else + pix[i] = 0; } - else if(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SONYARW2_DELTAONLY) + else if (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SONYARW2_DELTAONLY) { - for (bit=30, i=0; i < 16; i++) - if (i == imax) pix[i] = 0; - else if (i == imin) pix[i] = 0; - else { - pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min; - if (pix[i] > 0x7ff) pix[i] = 0x7ff; + for (bit = 30, i = 0; i < 16; i++) + if (i == imax) + pix[i] = 0; + else if (i == imin) + pix[i] = 0; + else + { + pix[i] = ((sget2(dp + (bit >> 3)) >> (bit & 7) & 0x7f) << sh) + min; + if (pix[i] > 0x7ff) + pix[i] = 0x7ff; bit += 7; } } - else if(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SONYARW2_DELTAZEROBASE) + else if (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SONYARW2_DELTAZEROBASE) { - for (bit=30, i=0; i < 16; i++) - if (i == imax) pix[i] = 0; - else if (i == imin) pix[i] = 0; - else { - pix[i] = ((sget2(dp+(bit >> 3)) >> (bit & 7) & 0x7f) << sh); - if (pix[i] > 0x7ff) pix[i] = 0x7ff; + for (bit = 30, i = 0; i < 16; i++) + if (i == imax) + pix[i] = 0; + else if (i == imin) + pix[i] = 0; + else + { + pix[i] = ((sget2(dp + (bit >> 3)) >> (bit & 7) & 0x7f) << sh); + if (pix[i] > 0x7ff) + pix[i] = 0x7ff; bit += 7; } } #else /* unaltered dcraw processing */ - 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 (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; + } #endif #ifdef LIBRAW_LIBRARY_BUILD - if(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SONYARW2_DELTATOVALUE) + if (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SONYARW2_DELTATOVALUE) { - for (i=0; i < 16; i++, col+=2) - { - unsigned slope = pix[i] < 1001? 2 : curve[pix[i]<<1]-curve[(pix[i]<<1)-2]; - unsigned step = 1 << sh; - RAW(row,col)=curve[pix[i]<<1]>black+imgdata.params.sony_arw2_posterization_thr? - LIM(((slope*step*1000)/(curve[pix[i]<<1]-black)),0,10000):0; - } + for (i = 0; i < 16; i++, col += 2) + { + unsigned slope = pix[i] < 1001 ? 2 : curve[pix[i] << 1] - curve[(pix[i] << 1) - 2]; + unsigned step = 1 << sh; + RAW(row, col) = curve[pix[i] << 1] > black + imgdata.params.sony_arw2_posterization_thr + ? LIM(((slope * step * 1000) / (curve[pix[i] << 1] - black)), 0, 10000) + : 0; + } } - else + else { - for (i=0; i < 16; i++, col+=2) - RAW(row,col) = curve[pix[i] << 1]; + for (i = 0; i < 16; i++, col += 2) + RAW(row, col) = curve[pix[i] << 1]; } #else - for (i=0; i < 16; i++, col+=2) - RAW(row,col) = curve[pix[i] << 1] >> 2; + for (i = 0; i < 16; i++, col += 2) + RAW(row, col) = curve[pix[i] << 1] >> 2; #endif - col -= col & 1 ? 1:31; + col -= col & 1 ? 1 : 31; + } } - } #ifdef LIBRAW_LIBRARY_BUILD - } catch(...) { - free (data); + } + catch (...) + { + free(data); throw; } - if(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SONYARW2_DELTATOVALUE) - maximum=10000; + if (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SONYARW2_DELTATOVALUE) + maximum = 10000; #endif - free (data); + free(data); } void CLASS samsung_load_raw() { int row, col, c, i, dir, op[4], len[4]; #ifdef LIBRAW_LIBRARY_BUILD if(raw_width> 32768 || raw_height > 32768) // definitely too much for old samsung throw LIBRAW_EXCEPTION_IO_BADFILE; #endif unsigned maxpixels = raw_width*(raw_height+7); order = 0x4949; - for (row=0; row < raw_height; row++) { + for (row = 0; row < raw_height; row++) + { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - fseek (ifp, strip_offset+row*4, SEEK_SET); - fseek (ifp, data_offset+get4(), SEEK_SET); + 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) { + 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]++; + 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)]; unsigned idest = RAWINDEX(row, col + c); unsigned isrc = (dir ? RAWINDEX(row + (~c | -2), col + c) : col ? RAWINDEX(row, col + (c | -2)) : 0); if(idest < maxpixels && isrc < maxpixels) // less than zero is handled by unsigned conversion 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); else derror(); 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)); + 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]; + 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++) + 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 (row = 0; row < raw_height; row++) { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - 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(); + 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); + fseek(ifp, 9, SEEK_CUR); opt = fgetc(ifp); - init = (get2(),get2()); - for (row=0; row < raw_height; row++) { + init = (get2(), get2()); + for (row = 0; row < raw_height; row++) + { #ifdef LIBRAW_LIBRARY_BUILD checkCancel(); #endif - fseek (ifp, (data_offset-ftell(ifp)) & 15, SEEK_CUR); + fseek(ifp, (data_offset - ftell(ifp)) & 15, SEEK_CUR); ph1_bits(-1); - mag = 0; pmode = 7; - FORC(6) ((ushort *)lent)[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); + mag = 0; + pmode = 7; + FORC(6)((ushort *)lent)[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); + 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]; - } + 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; + 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) +#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) +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; + 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; + uchar diff, pred[] = {0, 0}; + ushort data = 0, range = 0; - fseek (ifp, seg[0][1]+1, SEEK_SET); + fseek(ifp, seg[0][1] + 1, SEEK_SET); getbits(-1); - if (seg[1][0] > raw_width*raw_height) - seg[1][0] = raw_width*raw_height; - for (pix=seg[0][0]; pix < seg[1][0]; pix++) { - for (s=0; s < 3; s++) { + if (seg[1][0] > raw_width * raw_height) + seg[1][0] = raw_width * raw_height; + 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; + carry = (nbits += carry + 1) < 1 ? nbits - 1 : 0; while (--nbits >= 0) - if ((data >> nbits & 0xff) == 0xff) break; + if ((data >> nbits & 0xff) == 0xff) + break; if (nbits > 0) - data = ((data & ((1 << (nbits-1)) - 1)) << 1) | - ((data + (((data & (1 << (nbits-1)))) << 1)) & ((~0u) << 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; + data = ((data & ((1 << (nbits - 1)) - 1)) << 1) | + ((data + (((data & (1 << (nbits - 1)))) << 1)) & ((~0u) << 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; + 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][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]++; + 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; #ifdef LIBRAW_LIBRARY_BUILD - if(pix>=raw_width*raw_height) + if (pix >= raw_width * raw_height) throw LIBRAW_EXCEPTION_IO_CORRUPT; #endif raw_image[pix] = pred[pix & 1] += diff; - if (!(pix & 1) && HOLE(pix / raw_width)) pix += 2; + 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); + 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); + smal_decode_segment(seg, 0); } -int CLASS median4 (int *p) +int CLASS median4(int *p) { int min, max, sum, i; min = max = sum = p[0]; - for (i=1; i < 4; i++) { + for (i = 1; i < 4; i++) + { sum += p[i]; - if (min > p[i]) min = p[i]; - if (max < p[i]) max = 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) +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); + 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); + fseek(ifp, 67, SEEK_SET); offset = get4(); - nseg = (uchar) fgetc(ifp); - fseek (ifp, offset, SEEK_SET); - for (i=0; i < nseg*2; i++) - ((unsigned *)seg)[i] = get4() + data_offset*(i & 1); - fseek (ifp, 78, SEEK_SET); + nseg = (uchar)fgetc(ifp); + fseek(ifp, offset, SEEK_SET); + for (i = 0; i < nseg * 2; i++) + ((unsigned *)seg)[i] = get4() + data_offset * (i & 1); + fseek(ifp, 78, SEEK_SET); holes = fgetc(ifp); - fseek (ifp, 88, SEEK_SET); + 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); + 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(); #ifndef LIBRAW_LIBRARY_BUILD - in = jas_stream_fopen (ifname, "rb"); + in = jas_stream_fopen(ifname, "rb"); #else - in = (jas_stream_t*)ifp->make_jas_stream(); - if(!in) - throw LIBRAW_EXCEPTION_DECODE_JPEG2000; + in = (jas_stream_t *)ifp->make_jas_stream(); + if (!in) + throw LIBRAW_EXCEPTION_DECODE_JPEG2000; #endif - jas_stream_seek (in, data_offset+20, SEEK_SET); - jimg = jas_image_decode (in, -1, 0); + jas_stream_seek(in, data_offset + 20, SEEK_SET); + jimg = jas_image_decode(in, -1, 0); #ifndef LIBRAW_LIBRARY_BUILD - if (!jimg) longjmp (failure, 3); + if (!jimg) + longjmp(failure, 3); #else - if(!jimg) - { - jas_stream_close (in); - throw LIBRAW_EXCEPTION_DECODE_JPEG2000; - } + if (!jimg) + { + jas_stream_close(in); + throw LIBRAW_EXCEPTION_DECODE_JPEG2000; + } #endif - 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()"); + 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()"); #ifdef LIBRAW_LIBRARY_BUILD bool fastexitflag = false; - try { + try + { #endif - FORC4 { + FORC4 + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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++) { + 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++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - 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); + 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 (row = 0; row < height; row++) + { #ifdef LIBRAW_LIBRARY_BUILD - checkCancel(); + checkCancel(); #endif - for (col=0; col < width; col++) - RAW(row,col) = curve[img[(row+1)*(width+2)+col+1]]; - } + for (col = 0; col < width; col++) + RAW(row, col) = curve[img[(row + 1) * (width + 2) + col + 1]]; + } #ifdef LIBRAW_LIBRARY_BUILD - } catch (...) { - fastexitflag=true; + } + catch (...) + { + fastexitflag = true; } #endif - free (img); - jas_matrix_destroy (jmat); - jas_image_destroy (jimg); - jas_stream_close (in); + free(img); + jas_matrix_destroy(jmat); + jas_image_destroy(jimg); + jas_stream_close(in); #ifdef LIBRAW_LIBRARY_BUILD - if(fastexitflag) + if (fastexitflag) throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK; #endif #endif } void CLASS crop_masked_pixels() { int row, col; unsigned #ifndef LIBRAW_LIBRARY_BUILD - r, raw_pitch = raw_width*2, - c, m, mblack[8], zero, val; + r, + raw_pitch = raw_width * 2, c, m, mblack[8], zero, val; #else - c, m, zero, val; + c, + m, zero, val; #define mblack imgdata.color.black_stat #endif #ifndef LIBRAW_LIBRARY_BUILD - if (load_raw == &CLASS phase_one_load_raw || - load_raw == &CLASS phase_one_load_raw_c) + 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); - } -#endif - if (mask[0][3] > 0) goto mask_set; - if (load_raw == &CLASS canon_load_raw || - load_raw == &CLASS lossless_jpeg_load_raw) { + 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); + } +#endif + 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: + 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][2] = mask[1][2] = top_margin + height; mask[0][3] += left_margin; - mask[1][1] += left_margin+width; + mask[1][1] += left_margin + width; mask[1][3] += raw_width; } - if (load_raw == &CLASS nokia_load_raw) { + if (load_raw == &CLASS nokia_load_raw) + { mask[0][2] = top_margin; mask[0][3] = width; } #ifdef LIBRAW_LIBRARY_BUILD - if (load_raw == &CLASS broadcom_load_raw) { + if (load_raw == &CLASS broadcom_load_raw) + { mask[0][2] = top_margin; mask[0][3] = width; } #endif 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_image[(row)*raw_pitch/2+(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; + 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_image[(row)*raw_pitch / 2 + (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; #ifndef LIBRAW_LIBRARY_BUILD canon_600_correct(); #endif - } else if (zero < mblack[4] && mblack[5] && mblack[6] && mblack[7]) { - FORC4 cblack[c] = mblack[c] / mblack[4+c]; + } + else if (zero < mblack[4] && mblack[5] && mblack[6] && mblack[7]) + { + FORC4 cblack[c] = mblack[c] / mblack[4 + c]; black = cblack[4] = cblack[5] = cblack[6] = 0; } } #ifdef LIBRAW_LIBRARY_BUILD #undef mblack #endif void CLASS remove_zeroes() { unsigned row, col, tot, n, r, c; #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES,0,2); + RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES, 0, 2); #endif - for (row=0; row < height; row++) - for (col=0; col < width; col++) - if (BAYER(row,col) == 0) { - tot = n = 0; - for (r = row-2; r <= row+2; r++) - for (c = col-2; c <= col+2; c++) - if (r < height && c < width && - FC(r,c) == FC(row,col) && BAYER(r,c)) - tot += (n++,BAYER(r,c)); - if (n) BAYER(row,col) = tot/n; + for (row = 0; row < height; row++) + for (col = 0; col < width; col++) + if (BAYER(row, col) == 0) + { + tot = n = 0; + for (r = row - 2; r <= row + 2; r++) + for (c = col - 2; c <= col + 2; c++) + if (r < height && c < width && FC(r, c) == FC(row, col) && BAYER(r, c)) + tot += (n++, BAYER(r, c)); + if (n) + BAYER(row, col) = tot / n; } #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES,1,2); + RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES, 1, 2); #endif } 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 } }; - -void CLASS gamma_curve (double pwr, double ts, int mode, int imax) + {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}}; + +void CLASS gamma_curve(double pwr, double ts, int mode, int imax) { int i; - double g[6], bnd[2]={0,0}, r; + 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]; + 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); + 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++) { + 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])))); + 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) +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++) + { + 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++) { + 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; + for (j = 0; j < 6; j++) + if(fabs(num)>0.00001f) + 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 (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]; + 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]) +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++) /* 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) */ + 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]; - if(num > 0.00001) - { - for (j=0; j < 3; j++) - cam_rgb[i][j] /= num; - pre_mul[i] = 1 / num; - } + if (num > 0.00001) + { + for (j = 0; j < 3; j++) + cam_rgb[i][j] /= num; + pre_mul[i] = 1 / num; + } else - { - for (j=0; j < 3; j++) - cam_rgb[i][j] = 0.0; - pre_mul[i] = 1.0; - } + { + for (j = 0; j < 3; j++) + cam_rgb[i][j] = 0.0; + pre_mul[i] = 1.0; + } } - pseudoinverse (cam_rgb, inverse, colors); - for (i=0; i < 3; i++) - for (j=0; j < colors; j++) + 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 + // 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++) { + 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; + 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); + 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++) + for (sq = 0; sq < NSQ; sq++) FORCC gmb_cam[sq][c] *= balance[c]; } - if (verbose) { - printf (" { \"%s %s\", %d,\n\t{", make, model, black); + 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 (" } },"); + 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) +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 = 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))]; + temp[i] = 2 * base[st * i] + base[st * (i - sc)] + base[st * (2 * size - 2 - (i + sc))]; } #if !defined(LIBRAW_USE_OPENMP) void CLASS wavelet_denoise() { - float *fimg=0, *temp, thold, mul[2], avg, diff; - int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast, blk[2]; + 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 }; + static const float noise[] = {0.8002, 0.2735, 0.1202, 0.0585, 0.0291, 0.0152, 0.0080, 0.0044}; #ifdef DCRAW_VERBOSE - if (verbose) fprintf (stderr,_("Wavelet denoising...\n")); + if (verbose) + fprintf(stderr, _("Wavelet denoising...\n")); #endif - while (maximum << scale < 0x10000) scale++; + 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++) + if ((size = iheight * iwidth) < 0x15550000) + fimg = (float *)malloc((size * 3 + iheight + iwidth) * sizeof *fimg); + merror(fimg, "wavelet_denoise()"); + temp = fimg + size * 3; + if ((nc = colors) == 3 && filters) + nc++; + FORC(nc) + { /* denoise R,G1,B,G3 individually */ + for (i = 0; i < size; i++) fimg[i] = 256 * sqrt((double)(image[i][c] << scale)); - for (hpass=lev=0; lev < 5; lev++) { - lpass = size*((lev & 1)+1); - for (row=0; row < iheight; row++) { - hat_transform (temp, fimg+hpass+row*iwidth, 1, iwidth, 1 << lev); - for (col=0; col < iwidth; col++) - fimg[lpass + row*iwidth + col] = temp[col] * 0.25; - } - for (col=0; col < iwidth; col++) { - hat_transform (temp, fimg+lpass+col, iwidth, iheight, 1 << lev); - for (row=0; row < iheight; row++) - fimg[lpass + row*iwidth + col] = temp[row] * 0.25; + 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]; + 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); + 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]; + 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); + 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((double)BAYER(row,col)) - avg; - if (diff < -thold) diff += thold; - else if (diff > thold) diff -= thold; - else diff = 0; - BAYER(row,col) = CLIP(SQR(avg+diff) + 0.5); + 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((double)BAYER(row, col)) - avg; + if (diff < -thold) + diff += thold; + else if (diff > thold) + diff -= thold; + else + diff = 0; + BAYER(row, col) = CLIP(SQR(avg + diff) + 0.5); } } } - free (fimg); + free(fimg); } #else /* LIBRAW_USE_OPENMP */ void CLASS wavelet_denoise() { - float *fimg=0, *temp, thold, mul[2], avg, diff; - int scale=1, size, lev, hpass, lpass, row, col, nc, c, i, wlast, blk[2]; + 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 }; + static const float noise[] = {0.8002, 0.2735, 0.1202, 0.0585, 0.0291, 0.0152, 0.0080, 0.0044}; #ifdef DCRAW_VERBOSE - if (verbose) fprintf (stderr,_("Wavelet denoising...\n")); + if (verbose) + fprintf(stderr, _("Wavelet denoising...\n")); #endif - while (maximum << scale < 0x10000) scale++; + 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++; + if ((size = iheight * iwidth) < 0x15550000) + fimg = (float *)malloc((size * 3 + iheight + iwidth) * sizeof *fimg); + merror(fimg, "wavelet_denoise()"); + temp = fimg + size * 3; + if ((nc = colors) == 3 && filters) + nc++; #ifdef LIBRAW_LIBRARY_BUILD -#pragma omp parallel default(shared) private(i,col,row,thold,lev,lpass,hpass,temp,c) firstprivate(scale,size) +#pragma omp parallel default(shared) private(i, col, row, thold, lev, lpass, hpass, temp, c) firstprivate(scale, size) #endif { - temp = (float*)malloc( (iheight + iwidth) * sizeof *fimg); - FORC(nc) { /* denoise R,G1,B,G3 individually */ + temp = (float *)malloc((iheight + iwidth) * sizeof *fimg); + FORC(nc) + { /* denoise R,G1,B,G3 individually */ #ifdef LIBRAW_LIBRARY_BUILD #pragma omp for #endif - for (i=0; i < size; i++) + for (i = 0; i < size; i++) fimg[i] = 256 * sqrt((double)(image[i][c] << scale)); - for (hpass=lev=0; lev < 5; lev++) { - lpass = size*((lev & 1)+1); + for (hpass = lev = 0; lev < 5; lev++) + { + lpass = size * ((lev & 1) + 1); #ifdef LIBRAW_LIBRARY_BUILD #pragma omp for #endif - for (row=0; row < iheight; row++) { - hat_transform (temp, fimg+hpass+row*iwidth, 1, iwidth, 1 << lev); - for (col=0; col < iwidth; col++) - fimg[lpass + row*iwidth + col] = temp[col] * 0.25; - } + for (row = 0; row < iheight; row++) + { + hat_transform(temp, fimg + hpass + row * iwidth, 1, iwidth, 1 << lev); + for (col = 0; col < iwidth; col++) + fimg[lpass + row * iwidth + col] = temp[col] * 0.25; + } #ifdef LIBRAW_LIBRARY_BUILD #pragma omp for #endif - for (col=0; col < iwidth; col++) { - hat_transform (temp, fimg+lpass+col, iwidth, iheight, 1 << lev); - for (row=0; row < iheight; row++) - fimg[lpass + row*iwidth + col] = temp[row] * 0.25; - } - thold = threshold * noise[lev]; + for (col = 0; col < iwidth; col++) + { + hat_transform(temp, fimg + lpass + col, iwidth, iheight, 1 << lev); + for (row = 0; row < iheight; row++) + fimg[lpass + row * iwidth + col] = temp[row] * 0.25; + } + thold = threshold * noise[lev]; #ifdef LIBRAW_LIBRARY_BUILD #pragma omp for #endif - for (i=0; i < size; i++) { - fimg[hpass+i] -= fimg[lpass+i]; - if (fimg[hpass+i] < -thold) fimg[hpass+i] += thold; - else if (fimg[hpass+i] > thold) fimg[hpass+i] -= thold; - else fimg[hpass+i] = 0; - if (hpass) fimg[i] += fimg[hpass+i]; - } - hpass = lpass; + for (i = 0; i < size; i++) + { + fimg[hpass + i] -= fimg[lpass + i]; + if (fimg[hpass + i] < -thold) + fimg[hpass + i] += thold; + else if (fimg[hpass + i] > thold) + fimg[hpass + i] -= thold; + else + fimg[hpass + i] = 0; + if (hpass) + fimg[i] += fimg[hpass + i]; + } + hpass = lpass; } #ifdef LIBRAW_LIBRARY_BUILD #pragma omp for #endif - for (i=0; i < size; i++) - image[i][c] = CLIP(SQR(fimg[i]+fimg[lpass+i])/0x10000); + for (i = 0; i < size; i++) + image[i][c] = CLIP(SQR(fimg[i] + fimg[lpass + i]) / 0x10000); } free(temp); } /* end omp parallel */ -/* the following loops are hard to parallize, no idea yes, - * problem is wlast which is carrying dependency - * second part should be easyer, but did not yet get it right. - */ - if (filters && colors == 3) { /* pull G1 and G3 closer together */ - for (row=0; row < 2; row++){ - mul[row] = 0.125 * pre_mul[FC(row+1,0) | 1] / pre_mul[FC(row,0) | 1]; - 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); + /* the following loops are hard to parallize, no idea yes, + * problem is wlast which is carrying dependency + * second part should be easyer, but did not yet get it right. + */ + if (filters && colors == 3) + { /* pull G1 and G3 closer together */ + for (row = 0; row < 2; row++) + { + mul[row] = 0.125 * pre_mul[FC(row + 1, 0) | 1] / pre_mul[FC(row, 0) | 1]; + 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((double)BAYER(row,col)) - avg; - if (diff < -thold) diff += thold; - else if (diff > thold) diff -= thold; - else diff = 0; - BAYER(row,col) = CLIP(SQR(avg+diff) + 0.5); + 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((double)BAYER(row, col)) - avg; + if (diff < -thold) + diff += thold; + else if (diff > thold) + diff -= thold; + else + diff = 0; + BAYER(row, col) = CLIP(SQR(avg + diff) + 0.5); } } } - free (fimg); + free(fimg); } #endif // green equilibration void CLASS green_matching() { - int i,j; - double m1,m2,c1,c2; - int o1_1,o1_2,o1_3,o1_4; - int o2_1,o2_2,o2_3,o2_4; - ushort (*img)[4]; + int i, j; + double m1, m2, c1, c2; + int o1_1, o1_2, o1_3, o1_4; + int o2_1, o2_2, o2_3, o2_4; + ushort(*img)[4]; const int margin = 3; int oj = 2, oi = 2; float f; const float thr = 0.01f; - if(half_size || shrink) return; - if(FC(oj, oi) != 3) oj++; - if(FC(oj, oi) != 3) oi++; - if(FC(oj, oi) != 3) oj--; - - img = (ushort (*)[4]) calloc (height*width, sizeof *image); - merror (img, "green_matching()"); - memcpy(img,image,height*width*sizeof *image); - - for(j=oj;j0xffff?0xffff:f; + f = image[j * width + i][3] * m1 / m2; + image[j * width + i][3] = f > 0xffff ? 0xffff : f; } } free(img); } 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; + ushort *img = 0, *pix; #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_SCALE_COLORS,0,2); + RUN_CALLBACK(LIBRAW_PROGRESS_SCALE_COLORS, 0, 2); #endif if (user_mul[0]) - memcpy (pre_mul, user_mul, sizeof pre_mul); - if (use_auto_wb || (use_camera_wb && cam_mul[0] == -1)) { - memset (dsum, 0, sizeof dsum); - bottom = MIN (greybox[1]+greybox[3], height); - right = MIN (greybox[0]+greybox[2], width); - for (row=greybox[1]; row < bottom; row += 8) - for (col=greybox[0]; col < right; col += 8) { - memset (sum, 0, sizeof sum); - for (y=row; y < row+8 && y < bottom; y++) - for (x=col; x < col+8 && x < right; x++) - FORC4 { - if (filters) { - c = 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: ; + 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]; + 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]++; - } -#ifdef LIBRAW_LIBRARY_BUILD - if(load_raw == &LibRaw::nikon_load_sraw) + 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++) { - // Nikon sRAW: camera WB already applied: - pre_mul[0]=pre_mul[1]=pre_mul[2]=pre_mul[3]=1.0; + c = FC(row, col); + if ((val = white[row][col] - cblack[c]) > 0) + sum[c] += val; + sum[c + 4]++; } +#ifdef LIBRAW_LIBRARY_BUILD + if (load_raw == &LibRaw::nikon_load_sraw) + { + // Nikon sRAW: camera WB already applied: + pre_mul[0] = pre_mul[1] = pre_mul[2] = pre_mul[3] = 1.0; + } else #endif - if (sum[0] && sum[1] && sum[2] && sum[3]) - FORC4 pre_mul[c] = (float) sum[c+4] / sum[c]; + 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); + memcpy(pre_mul, cam_mul, sizeof pre_mul); else - { + { #ifdef LIBRAW_LIBRARY_BUILD - imgdata.process_warnings |= LIBRAW_WARN_BAD_CAMERA_WB; + imgdata.process_warnings |= LIBRAW_WARN_BAD_CAMERA_WB; #endif #ifdef DCRAW_VERBOSE - fprintf (stderr,_("%s: Cannot use camera white balance.\n"), ifname); + fprintf(stderr, _("%s: Cannot use camera white balance.\n"), ifname); #endif - } + } } #ifdef LIBRAW_LIBRARY_BUILD // Nikon sRAW, daylight - if (load_raw == &LibRaw::nikon_load_sraw - && !use_camera_wb && !use_auto_wb - && cam_mul[0] > 0.001f && cam_mul[1] > 0.001f && cam_mul[2] > 0.001f ) - { - for(c=0;c<3;c++) - pre_mul[c]/=cam_mul[c]; + if (load_raw == &LibRaw::nikon_load_sraw && !use_camera_wb && !use_auto_wb && cam_mul[0] > 0.001f && + cam_mul[1] > 0.001f && cam_mul[2] > 0.001f) + { + for (c = 0; c < 3; c++) + pre_mul[c] /= cam_mul[c]; } #endif - if (pre_mul[1] == 0) pre_mul[1] = 1; - if (pre_mul[3] == 0) pre_mul[3] = colors < 4 ? pre_mul[1] : 1; + 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(); + if (threshold) + wavelet_denoise(); maximum -= black; - for (dmin=DBL_MAX, dmax=c=0; c < 4; c++) { + for (dmin = DBL_MAX, dmax = c = 0; c < 4; c++) + { if (dmin > pre_mul[c]) - dmin = pre_mul[c]; + dmin = pre_mul[c]; if (dmax < pre_mul[c]) - dmax = pre_mul[c]; + dmax = pre_mul[c]; } - if (!highlight) dmax = dmin; + if (!highlight) + dmax = dmin; FORC4 scale_mul[c] = (pre_mul[c] /= dmax) * 65535.0 / maximum; #ifdef DCRAW_VERBOSE - if (verbose) { - fprintf (stderr, - _("Scaling with darkness %d, saturation %d, and\nmultipliers"), dark, sat); - FORC4 fprintf (stderr, " %f", pre_mul[c]); - fputc ('\n', stderr); + if (verbose) + { + fprintf(stderr, _("Scaling with darkness %d, saturation %d, and\nmultipliers"), dark, sat); + FORC4 fprintf(stderr, " %f", pre_mul[c]); + fputc('\n', stderr); } #endif - 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]]; + 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; + size = iheight * iwidth; #ifdef LIBRAW_LIBRARY_BUILD scale_colors_loop(scale_mul); #else - for (i=0; i < size*4; i++) { - if (!(val = ((ushort *)image)[i])) continue; + for (i = 0; i < size * 4; i++) + { + if (!(val = ((ushort *)image)[i])) + continue; if (cblack[4] && cblack[5]) - val -= cblack[6 + i/4 / iwidth % cblack[4] * cblack[5] + - i/4 % iwidth % 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]; ((ushort *)image)[i] = CLIP(val); } #endif - if ((aber[0] != 1 || aber[2] != 1) && colors == 3) { + if ((aber[0] != 1 || aber[2] != 1) && colors == 3) + { #ifdef DCRAW_VERBOSE if (verbose) - fprintf (stderr,_("Correcting chromatic aberration...\n")); -#endif - for (c=0; c < 4; c+=2) { - if (aber[c] == 1) continue; - img = (ushort *) malloc (size * sizeof *img); - merror (img, "scale_colors()"); - for (i=0; i < size; i++) - img[i] = image[i][c]; - for (row=0; row < iheight; row++) { - ur = fr = (row - iheight*0.5) * aber[c] + iheight*0.5; - if (ur > iheight-2) continue; - fr -= ur; - for (col=0; col < iwidth; col++) { - uc = fc = (col - iwidth*0.5) * aber[c] + iwidth*0.5; - if (uc > iwidth-2) continue; - fc -= uc; - pix = img + ur*iwidth + uc; - image[row*iwidth+col][c] = - (pix[ 0]*(1-fc) + pix[ 1]*fc) * (1-fr) + - (pix[iwidth]*(1-fc) + pix[iwidth+1]*fc) * fr; - } + fprintf(stderr, _("Correcting chromatic aberration...\n")); +#endif + for (c = 0; c < 4; c += 2) + { + if (aber[c] == 1) + continue; + img = (ushort *)malloc(size * sizeof *img); + merror(img, "scale_colors()"); + for (i = 0; i < size; i++) + img[i] = image[i][c]; + for (row = 0; row < iheight; row++) + { + ur = fr = (row - iheight * 0.5) * aber[c] + iheight * 0.5; + if (ur > iheight - 2) + continue; + fr -= ur; + for (col = 0; col < iwidth; col++) + { + uc = fc = (col - iwidth * 0.5) * aber[c] + iwidth * 0.5; + if (uc > iwidth - 2) + continue; + fc -= uc; + pix = img + ur * iwidth + uc; + image[row * iwidth + col][c] = + (pix[0] * (1 - fc) + pix[1] * fc) * (1 - fr) + (pix[iwidth] * (1 - fc) + pix[iwidth + 1] * fc) * fr; + } } free(img); } } #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_SCALE_COLORS,1,2); + RUN_CALLBACK(LIBRAW_PROGRESS_SCALE_COLORS, 1, 2); #endif } void CLASS pre_interpolate() { - ushort (*img)[4]; + ushort(*img)[4]; int row, col, c; #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_PRE_INTERPOLATE,0,2); + RUN_CALLBACK(LIBRAW_PROGRESS_PRE_INTERPOLATE, 0, 2); #endif - if (shrink) { - if (half_size) { + 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; - } + 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); + } + 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) { + 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 (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 & 0x55555555U) << 1); } } - if (half_size) filters = 0; + if (half_size) + filters = 0; #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_PRE_INTERPOLATE,1,2); + RUN_CALLBACK(LIBRAW_PROGRESS_PRE_INTERPOLATE, 1, 2); #endif } -void CLASS border_interpolate (int border) +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]; + 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_loop(int code[16][16][32],int size) +void CLASS lin_interpolate_loop(int code[16][16][32], int size) { int row; - for (row=1; row < height-1; row++) + for (row = 1; row < height - 1; row++) + { + int col, *ip; + ushort *pix; + for (col = 1; col < width - 1; col++) { - int col,*ip; - ushort *pix; - for (col=1; col < width-1; col++) { - int i; - int sum[4]; - 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; - } + int i; + int sum[4]; + 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; } + } } void CLASS lin_interpolate() { - int code[16][16][32], size=16, *ip, sum[4]; + int code[16][16][32], size = 16, *ip, sum[4]; int f, c, x, y, row, col, shift, color; - #ifdef DCRAW_VERBOSE - if (verbose) fprintf (stderr,_("Bilinear interpolation...\n")); + if (verbose) + fprintf(stderr, _("Bilinear interpolation...\n")); #endif #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,0,3); + RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE, 0, 3); #endif - if (filters == 9) size = 6; + 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; - } + 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++ = sum[c]>0?256 / sum[c]:0; - } + if (c != f) + { + *ip++ = c; + *ip++ = sum[c] > 0 ? 256 / sum[c] : 0; + } } #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,1,3); + RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE, 1, 3); #endif - lin_interpolate_loop(code,size); + lin_interpolate_loop(code, size); #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,2,3); + RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE, 2, 3); #endif } /* This algorithm is officially called: "Interpolation using a Threshold-based variable number of gradients" described in http://scien.stanford.edu/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,-128, -1,-2,+0,-1,0,0x01, -1,-2,+1,-1,0,0x01, - -1,-2,+1,+0,1,0x01, -1,-1,-1,+1,0,-120, -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,-128, +0,-1,+0,+1,1,-120, +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,-128, - +1,-1,+1,+1,0,-120, +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]; + 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, -128, + -1, -2, +0, -1, 0, 0x01, -1, -2, +1, -1, 0, 0x01, -1, -2, +1, +0, 1, 0x01, -1, -1, -1, +1, 0, -120, + -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, -128, + +0, -1, +0, +1, 1, -120, +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, -128, + +1, -1, +1, +1, 0, -120, +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(); #ifdef DCRAW_VERBOSE - if (verbose) fprintf (stderr,_("VNG interpolation...\n")); + if (verbose) + fprintf(stderr, _("VNG interpolation...\n")); #endif - 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++) { + 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< gval[g]) gmin = gval[g]; - if (gmax < gval[g]) gmax = gval[g]; + 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; + 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++; - } + 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); + 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]; + 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]); + 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 dir[5] = {1, width, -1, -width, 1}; int row, col, diff[2], guess[2], c, d, i; - ushort (*pix)[4]; + ushort(*pix)[4]; border_interpolate(3); #ifdef DCRAW_VERBOSE - if (verbose) fprintf (stderr,_("PPG interpolation...\n")); + if (verbose) + fprintf(stderr, _("PPG interpolation...\n")); #endif /* Fill in the green layer with gradients and pattern recognition: */ #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,0,3); + RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE, 0, 3); #ifdef LIBRAW_USE_OPENMP #pragma omp parallel for default(shared) private(guess, diff, row, col, d, c, i, pix) schedule(static) #endif #endif - for (row=3; row < height-3; row++) - for (col=3+(FC(row,3) & 1), c=FC(row,col); col < width-3; col+=2) { - pix = image + row*width+col; - for (i=0; (d=dir[i]) > 0; i++) { - guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2 - - pix[-2*d][c] - pix[2*d][c]; - diff[i] = ( ABS(pix[-2*d][c] - pix[ 0][c]) + - ABS(pix[ 2*d][c] - pix[ 0][c]) + - ABS(pix[ -d][1] - pix[ d][1]) ) * 3 + - ( ABS(pix[ 3*d][1] - pix[ d][1]) + - ABS(pix[-3*d][1] - pix[-d][1]) ) * 2; + for (row = 3; row < height - 3; row++) + for (col = 3 + (FC(row, 3) & 1), c = FC(row, col); col < width - 3; col += 2) + { + pix = image + row * width + col; + for (i = 0; (d = dir[i]) > 0; i++) + { + guess[i] = (pix[-d][1] + pix[0][c] + pix[d][1]) * 2 - pix[-2 * d][c] - pix[2 * d][c]; + diff[i] = (ABS(pix[-2 * d][c] - pix[0][c]) + ABS(pix[2 * d][c] - pix[0][c]) + ABS(pix[-d][1] - pix[d][1])) * 3 + + (ABS(pix[3 * d][1] - pix[d][1]) + ABS(pix[-3 * d][1] - pix[-d][1])) * 2; } d = dir[i = diff[0] > diff[1]]; pix[0][1] = ULIM(guess[i] >> 2, pix[d][1], pix[-d][1]); } /* Calculate red and blue for each green pixel: */ #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,1,3); + RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE, 1, 3); #ifdef LIBRAW_USE_OPENMP #pragma omp parallel for default(shared) private(guess, diff, row, col, d, c, i, pix) schedule(static) #endif #endif - for (row=1; row < height-1; row++) - for (col=1+(FC(row,2) & 1), c=FC(row,col+1); col < width-1; col+=2) { - pix = image + row*width+col; - for (i=0; (d=dir[i]) > 0; c=2-c, i++) - pix[0][c] = CLIP((pix[-d][c] + pix[d][c] + 2*pix[0][1] - - pix[-d][1] - pix[d][1]) >> 1); + for (row = 1; row < height - 1; row++) + for (col = 1 + (FC(row, 2) & 1), c = FC(row, col + 1); col < width - 1; col += 2) + { + pix = image + row * width + col; + for (i = 0; (d = dir[i]) > 0; c = 2 - c, i++) + pix[0][c] = CLIP((pix[-d][c] + pix[d][c] + 2 * pix[0][1] - pix[-d][1] - pix[d][1]) >> 1); } /* Calculate blue for red pixels and vice versa: */ #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE,2,3); + RUN_CALLBACK(LIBRAW_PROGRESS_INTERPOLATE, 2, 3); #ifdef LIBRAW_USE_OPENMP #pragma omp parallel for default(shared) private(guess, diff, row, col, d, c, i, pix) schedule(static) #endif #endif - for (row=1; row < height-1; row++) - for (col=1+(FC(row,1) & 1), c=2-FC(row,col); col < width-1; col+=2) { - pix = image + row*width+col; - for (i=0; (d=dir[i]+dir[i+1]) > 0; i++) { - diff[i] = ABS(pix[-d][c] - pix[d][c]) + - ABS(pix[-d][1] - pix[0][1]) + - ABS(pix[ d][1] - pix[0][1]); - guess[i] = pix[-d][c] + pix[d][c] + 2*pix[0][1] - - pix[-d][1] - pix[d][1]; + 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); + pix[0][c] = CLIP(guess[diff[0] > diff[1]] >> 1); else - pix[0][c] = CLIP((guess[0]+guess[1]) >> 2); + pix[0][c] = CLIP((guess[0] + guess[1]) >> 2); } } -void CLASS cielab (ushort rgb[3], short lab[3]) +void CLASS cielab(ushort rgb[3], short lab[3]) { int c, i, j, k; float r, xyz[3]; #ifdef LIBRAW_NOTHREADS static float cbrt[0x10000], xyz_cam[3][4]; #else #define cbrt tls->ahd_data.cbrt #define xyz_cam tls->ahd_data.xyz_cam #endif - if (!rgb) { + if (!rgb) + { #ifndef LIBRAW_NOTHREADS - if(cbrt[0] < -1.0f) + if (cbrt[0] < -1.0f) #endif - for (i=0; i < 0x10000; i++) { - r = i / 65535.0; - cbrt[i] = r > 0.008856 ? pow(r,1.f/3.0f) : 7.787f*r + 16.f/116.0f; - } - 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]; + for (i = 0; i < 0x10000; i++) + { + r = i / 65535.0; + cbrt[i] = r > 0.008856 ? pow(r, 1.f / 3.0f) : 7.787f * r + 16.f / 116.0f; + } + 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 { + 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])]; + 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]); #ifndef LIBRAW_NOTHREADS #undef cbrt #undef xyz_cam #endif } -#define TS 512 /* Tile Size */ -#define fcol(row,col) xtrans[(row+6) % 6][(col+6) % 6] +#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) +void CLASS xtrans_interpolate(int passes) { int c, d, f, g, h, i, v, ng, row, col, top, left, mrow, mcol; + #ifdef LIBRAW_LIBRARY_BUILD - int cstat[4]={0,0,0,0}; + int cstat[4] = {0, 0, 0, 0}; #endif 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 }; + 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; + 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; #ifdef DCRAW_VERBOSE if (verbose) - fprintf (stderr,_("%d-pass X-Trans interpolation...\n"), passes); + fprintf(stderr, _("%d-pass X-Trans interpolation...\n"), passes); #endif #ifdef LIBRAW_LIBRARY_BUILD - if(width < TS || height < TS) - throw LIBRAW_EXCEPTION_IO_CORRUPT; // too small image - -/* Check against right pattern */ + if (width < TS || height < TS) + throw LIBRAW_EXCEPTION_IO_CORRUPT; // too small image + /* Check against right pattern */ for (row = 0; row < 6; row++) - for (col = 0; col < 6; col++) - cstat[fcol(row,col)]++; + for (col = 0; col < 6; col++) + cstat[fcol(row, col)]++; - if(cstat[0] < 6 || cstat[0]>10 || cstat[1]< 16 - || cstat[1]>24 || cstat[2]< 6 || cstat[2]>10 || cstat[3]) - throw LIBRAW_EXCEPTION_IO_CORRUPT; + if (cstat[0] < 6 || cstat[0] > 10 || cstat[1] < 16 || cstat[1] > 24 || cstat[2] < 6 || cstat[2] > 10 || cstat[3]) + throw LIBRAW_EXCEPTION_IO_CORRUPT; - // Init allhex table to unreasonable values - for(int i = 0; i < 3; i++) - for(int j = 0; j < 3; j++) - for(int k = 0; k < 2; k++) - for(int l = 0; l < 8; l++) - allhex[i][j][k][l]=32700; + // Init allhex table to unreasonable values + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + for (int k = 0; k < 2; k++) + for (int l = 0; l < 8; l++) + allhex[i][j][k][l] = 32700; #endif - - cielab (0,0); + 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)); - - int minv=0,maxv=0,minh=0,maxh=0; -/* 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]; - minv=MIN(v,minv); - maxv=MAX(v,maxv); - minh=MIN(v,minh); - maxh=MAX(v,maxh); - allhex[row][col][0][c^(g*2 & d)] = h + v*width; - allhex[row][col][1][c^(g*2 & d)] = h + v*TS; - } - } - -#ifdef LIBRAW_LIBRARY_BUILD - // Check allhex table initialization - for(int i = 0; i < 3; i++) - for(int j = 0; j < 3; j++) - for(int k = 0; k < 2; k++) - for(int l = 0; l < 8; l++) - if(allhex[i][j][k][l]>maxh+maxv*width+1 || allhex[i][j][k][l] maxh + maxv * width + 1 || allhex[i][j][k][l] < minh + minv * width - 1) + throw LIBRAW_EXCEPTION_IO_CORRUPT; int retrycount = 0; #endif - -/* 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; + /* 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; - } + 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) + 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--; + row--; #ifdef LIBRAW_LIBRARY_BUILD - if(retrycount++ > width*height) - throw LIBRAW_EXCEPTION_IO_CORRUPT; + if (retrycount++ > width * height) + throw LIBRAW_EXCEPTION_IO_CORRUPT; #endif - } - + } } } - 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< 1) - diff[d] += SQR (rix[i< 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; - } - } - } + 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]); + } -/* 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); - } - } + for (pass = 0; pass < passes; pass++) + { + if (pass == 1) + memcpy(rgb += 4, buffer, 4 * sizeof *rgb); -/* 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); - } - } + /* 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; + 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)); - } + /* 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]; - } + /* 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. */ #ifdef LIBRAW_LIBRARY_BUILD void CLASS ahd_interpolate_green_h_and_v(int top, int left, ushort (*out_rgb)[TS][TS][3]) { int row, col; int c, val; - ushort (*pix)[4]; - const int rowlimit = MIN(top+TS, height-2); - const int collimit = MIN(left+TS, width-2); + ushort(*pix)[4]; + const int rowlimit = MIN(top + TS, height - 2); + const int collimit = MIN(left + TS, width - 2); - for (row = top; row < rowlimit; row++) { - col = left + (FC(row,left) & 1); - for (c = FC(row,col); col < collimit; 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; - out_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; - out_rgb[1][row-top][col-left][1] = ULIM(val,pix[-width][1],pix[width][1]); + for (row = top; row < rowlimit; row++) + { + col = left + (FC(row, left) & 1); + for (c = FC(row, col); col < collimit; 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; + out_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; + out_rgb[1][row - top][col - left][1] = ULIM(val, pix[-width][1], pix[width][1]); } } } -void CLASS ahd_interpolate_r_and_b_in_rgb_and_convert_to_cielab(int top, int left, ushort (*inout_rgb)[TS][3], short (*out_lab)[TS][3]) +void CLASS ahd_interpolate_r_and_b_in_rgb_and_convert_to_cielab(int top, int left, ushort (*inout_rgb)[TS][3], + short (*out_lab)[TS][3]) { unsigned row, col; int c, val; - ushort (*pix)[4]; - ushort (*rix)[3]; - short (*lix)[3]; + ushort(*pix)[4]; + ushort(*rix)[3]; + short(*lix)[3]; float xyz[3]; - const unsigned num_pix_per_row = 4*width; - const unsigned rowlimit = MIN(top+TS-1, height-3); - const unsigned collimit = MIN(left+TS-1, width-3); + const unsigned num_pix_per_row = 4 * width; + const unsigned rowlimit = MIN(top + TS - 1, height - 3); + const unsigned collimit = MIN(left + TS - 1, width - 3); ushort *pix_above; ushort *pix_below; int t1, t2; - for (row = top+1; row < rowlimit; row++) { - pix = image + row*width + left; - rix = &inout_rgb[row-top][0]; - lix = &out_lab[row-top][0]; + for (row = top + 1; row < rowlimit; row++) + { + pix = image + row * width + left; + rix = &inout_rgb[row - top][0]; + lix = &out_lab[row - top][0]; - for (col = left+1; col < collimit; col++) { + for (col = left + 1; col < collimit; col++) + { pix++; pix_above = &pix[0][0] - num_pix_per_row; pix_below = &pix[0][0] + num_pix_per_row; rix++; lix++; c = 2 - FC(row, col); - if (c == 1) { - c = FC(row+1,col); - t1 = 2-c; - val = pix[0][1] + (( pix[-1][t1] + pix[1][t1] - - rix[-1][1] - rix[1][1] ) >> 1); + if (c == 1) + { + c = FC(row + 1, col); + t1 = 2 - c; + val = pix[0][1] + ((pix[-1][t1] + pix[1][t1] - rix[-1][1] - rix[1][1]) >> 1); rix[0][t1] = CLIP(val); - val = pix[0][1] + (( pix_above[c] + pix_below[c] - - rix[-TS][1] - rix[TS][1] ) >> 1); - } else { - t1 = -4+c; /* -4+c: pixel of color c to the left */ - t2 = 4+c; /* 4+c: pixel of color c to the right */ - val = rix[0][1] + (( pix_above[t1] + pix_above[t2] - + pix_below[t1] + pix_below[t2] - - rix[-TS-1][1] - rix[-TS+1][1] - - rix[+TS-1][1] - rix[+TS+1][1] + 1) >> 2); + val = pix[0][1] + ((pix_above[c] + pix_below[c] - rix[-TS][1] - rix[TS][1]) >> 1); + } + else + { + t1 = -4 + c; /* -4+c: pixel of color c to the left */ + t2 = 4 + c; /* 4+c: pixel of color c to the right */ + val = rix[0][1] + ((pix_above[t1] + pix_above[t2] + pix_below[t1] + pix_below[t2] - 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); + c = FC(row, col); rix[0][c] = pix[0][c]; - cielab(rix[0],lix[0]); + cielab(rix[0], lix[0]); } } } -void CLASS ahd_interpolate_r_and_b_and_convert_to_cielab(int top, int left, ushort (*inout_rgb)[TS][TS][3], short (*out_lab)[TS][TS][3]) +void CLASS ahd_interpolate_r_and_b_and_convert_to_cielab(int top, int left, ushort (*inout_rgb)[TS][TS][3], + short (*out_lab)[TS][TS][3]) { int direction; - for (direction = 0; direction < 2; direction++) { + for (direction = 0; direction < 2; direction++) + { ahd_interpolate_r_and_b_in_rgb_and_convert_to_cielab(top, left, inout_rgb[direction], out_lab[direction]); } } -void CLASS ahd_interpolate_build_homogeneity_map(int top, int left, short (*lab)[TS][TS][3], char (*out_homogeneity_map)[TS][2]) +void CLASS ahd_interpolate_build_homogeneity_map(int top, int left, short (*lab)[TS][TS][3], + char (*out_homogeneity_map)[TS][2]) { int row, col; int tr, tc; int direction; int i; - short (*lix)[3]; - short (*lixs[2])[3]; + short(*lix)[3]; + short(*lixs[2])[3]; short *adjacent_lix; unsigned ldiff[2][4], abdiff[2][4], leps, abeps; - static const int dir[4] = { -1, 1, -TS, TS }; - const int rowlimit = MIN(top+TS-2, height-4); - const int collimit = MIN(left+TS-2, width-4); + static const int dir[4] = {-1, 1, -TS, TS}; + const int rowlimit = MIN(top + TS - 2, height - 4); + const int collimit = MIN(left + TS - 2, width - 4); int homogeneity; - char (*homogeneity_map_p)[2]; + char(*homogeneity_map_p)[2]; - memset (out_homogeneity_map, 0, 2*TS*TS); + memset(out_homogeneity_map, 0, 2 * TS * TS); - for (row=top+2; row < rowlimit; row++) { - tr = row-top; + for (row = top + 2; row < rowlimit; row++) + { + tr = row - top; homogeneity_map_p = &out_homogeneity_map[tr][1]; - for (direction=0; direction < 2; direction++) { + for (direction = 0; direction < 2; direction++) + { lixs[direction] = &lab[direction][tr][1]; } - for (col=left+2; col < collimit; col++) { - tc = col-left; + for (col = left + 2; col < collimit; col++) + { + tc = col - left; homogeneity_map_p++; - for (direction=0; direction < 2; direction++) { + for (direction = 0; direction < 2; direction++) + { lix = ++lixs[direction]; - for (i=0; i < 4; i++) { - adjacent_lix = lix[dir[i]]; - ldiff[direction][i] = ABS(lix[0][0]-adjacent_lix[0]); - abdiff[direction][i] = SQR(lix[0][1]-adjacent_lix[1]) - + SQR(lix[0][2]-adjacent_lix[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 (direction=0; direction < 2; direction++) { - homogeneity = 0; - for (i=0; i < 4; i++) { - if (ldiff[direction][i] <= leps && abdiff[direction][i] <= abeps) { - homogeneity++; - } - } - homogeneity_map_p[0][direction] = homogeneity; + for (i = 0; i < 4; i++) + { + adjacent_lix = lix[dir[i]]; + ldiff[direction][i] = ABS(lix[0][0] - adjacent_lix[0]); + abdiff[direction][i] = SQR(lix[0][1] - adjacent_lix[1]) + SQR(lix[0][2] - adjacent_lix[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 (direction = 0; direction < 2; direction++) + { + homogeneity = 0; + for (i = 0; i < 4; i++) + { + if (ldiff[direction][i] <= leps && abdiff[direction][i] <= abeps) + { + homogeneity++; + } + } + homogeneity_map_p[0][direction] = homogeneity; } } } } -void CLASS ahd_interpolate_combine_homogeneous_pixels(int top, int left, ushort (*rgb)[TS][TS][3], char (*homogeneity_map)[TS][2]) +void CLASS ahd_interpolate_combine_homogeneous_pixels(int top, int left, ushort (*rgb)[TS][TS][3], + char (*homogeneity_map)[TS][2]) { int row, col; int tr, tc; int i, j; int direction; int hm[2]; int c; - const int rowlimit = MIN(top+TS-3, height-5); - const int collimit = MIN(left+TS-3, width-5); + const int rowlimit = MIN(top + TS - 3, height - 5); + const int collimit = MIN(left + TS - 3, width - 5); - ushort (*pix)[4]; - ushort (*rix[2])[3]; + ushort(*pix)[4]; + ushort(*rix[2])[3]; - for (row=top+3; row < rowlimit; row++) { - tr = row-top; - pix = &image[row*width+left+2]; - for (direction = 0; direction < 2; direction++) { + for (row = top + 3; row < rowlimit; row++) + { + tr = row - top; + pix = &image[row * width + left + 2]; + for (direction = 0; direction < 2; direction++) + { rix[direction] = &rgb[direction][tr][2]; } - for (col=left+3; col < collimit; col++) { - tc = col-left; + for (col = left + 3; col < collimit; col++) + { + tc = col - left; pix++; - for (direction = 0; direction < 2; direction++) { + for (direction = 0; direction < 2; direction++) + { rix[direction]++; } - for (direction=0; direction < 2; direction++) { + for (direction = 0; direction < 2; direction++) + { hm[direction] = 0; - for (i=tr-1; i <= tr+1; i++) { - for (j=tc-1; j <= tc+1; j++) { + for (i = tr - 1; i <= tr + 1; i++) + { + for (j = tc - 1; j <= tc + 1; j++) + { hm[direction] += homogeneity_map[i][j][direction]; } } } - if (hm[0] != hm[1]) { + if (hm[0] != hm[1]) + { memcpy(pix[0], rix[hm[1] > hm[0]][0], 3 * sizeof(ushort)); - } else { - FORC3 { - pix[0][c] = (rix[0][0][c] + rix[1][0][c]) >> 1; - } + } + else + { + FORC3 { pix[0][c] = (rix[0][0][c] + rix[1][0][c]) >> 1; } } } } } void CLASS ahd_interpolate() { int i, j, k, top, left; - float xyz_cam[3][4],r; + float xyz_cam[3][4], r; char *buffer; - ushort (*rgb)[TS][TS][3]; - short (*lab)[TS][TS][3]; - char (*homo)[TS][2]; + ushort(*rgb)[TS][TS][3]; + short(*lab)[TS][TS][3]; + char(*homo)[TS][2]; int terminate_flag = 0; - - cielab(0,0); + cielab(0, 0); border_interpolate(5); #ifdef LIBRAW_LIBRARY_BUILD #ifdef LIBRAW_USE_OPENMP -#pragma omp parallel private(buffer,rgb,lab,homo,top,left,i,j,k) shared(xyz_cam,terminate_flag) +#pragma omp parallel private(buffer, rgb, lab, homo, top, left, i, j, k) shared(xyz_cam, terminate_flag) #endif #endif { - buffer = (char *) malloc (26*TS*TS); /* 1664 kB */ - merror (buffer, "ahd_interpolate()"); - rgb = (ushort(*)[TS][TS][3]) buffer; - lab = (short (*)[TS][TS][3])(buffer + 12*TS*TS); - homo = (char (*)[TS][2]) (buffer + 24*TS*TS); + buffer = (char *)malloc(26 * TS * TS); /* 1664 kB */ + merror(buffer, "ahd_interpolate()"); + rgb = (ushort(*)[TS][TS][3])buffer; + lab = (short(*)[TS][TS][3])(buffer + 12 * TS * TS); + homo = (char(*)[TS][2])(buffer + 24 * TS * TS); #ifdef LIBRAW_LIBRARY_BUILD #ifdef LIBRAW_USE_OPENMP #pragma omp for schedule(dynamic) #endif #endif - for (top=2; top < height-5; top += TS-6){ + for (top = 2; top < height - 5; top += TS - 6) + { #ifdef LIBRAW_LIBRARY_BUILD #ifdef LIBRAW_USE_OPENMP - if(0== omp_get_thread_num()) + if (0 == omp_get_thread_num()) #endif - if(callbacks.progress_cb) { - int rr = (*callbacks.progress_cb)(callbacks.progresscb_data,LIBRAW_PROGRESS_INTERPOLATE,top-2,height-7); - if(rr) - terminate_flag = 1; - } + if (callbacks.progress_cb) + { + int rr = + (*callbacks.progress_cb)(callbacks.progresscb_data, LIBRAW_PROGRESS_INTERPOLATE, top - 2, height - 7); + if (rr) + terminate_flag = 1; + } #endif - for (left=2; !terminate_flag && (left < width-5); left += TS-6) { - ahd_interpolate_green_h_and_v(top, left, rgb); - ahd_interpolate_r_and_b_and_convert_to_cielab(top, left, rgb, lab); - ahd_interpolate_build_homogeneity_map(top, left, lab, homo); - ahd_interpolate_combine_homogeneous_pixels(top, left, rgb, homo); + for (left = 2; !terminate_flag && (left < width - 5); left += TS - 6) + { + ahd_interpolate_green_h_and_v(top, left, rgb); + ahd_interpolate_r_and_b_and_convert_to_cielab(top, left, rgb, lab); + ahd_interpolate_build_homogeneity_map(top, left, lab, homo); + ahd_interpolate_combine_homogeneous_pixels(top, left, rgb, homo); } } - free (buffer); + free(buffer); } #ifdef LIBRAW_LIBRARY_BUILD - if(terminate_flag) - throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK; + if (terminate_flag) + throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK; #endif } #else 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 }; + 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; + ushort(*rgb)[TS][TS][3], (*rix)[3], (*pix)[4]; + short(*lab)[TS][TS][3], (*lix)[3]; + char(*homo)[TS][TS], *buffer; #ifdef DCRAW_VERBOSE - if (verbose) fprintf (stderr,_("AHD interpolation...\n")); + if (verbose) + fprintf(stderr, _("AHD interpolation...\n")); #endif - cielab (0,0); + 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; - } + 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); + free(buffer); } #endif #undef TS void CLASS median_filter() { - ushort (*pix)[4]; + 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 }; + 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++) { + for (pass = 1; pass <= med_passes; pass++) + { #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_MEDIAN_FILTER,pass-1,med_passes); + RUN_CALLBACK(LIBRAW_PROGRESS_MEDIAN_FILTER, pass - 1, med_passes); #endif #ifdef DCRAW_VERBOSE if (verbose) - fprintf (stderr,_("Median filter pass %d...\n"), pass); + fprintf(stderr, _("Median filter pass %d...\n"), pass); #endif - for (c=0; c < 3; c+=2) { - for (pix = image; pix < image+width*height; pix++) - pix[0][3] = pix[0][c]; - for (pix = image+width; pix < image+width*(height-1); pix++) { - if ((pix-image+1) % width < 2) continue; - for (k=0, i = -width; i <= width; i += width) - for (j = i-1; j <= i+1; j++) - med[k++] = pix[j][3] - pix[j][1]; - for (i=0; i < sizeof opt; i+=2) - if (med[opt[i]] > med[opt[i+1]]) - SWAP (med[opt[i]] , med[opt[i+1]]); - pix[0][c] = CLIP(med[4] + pix[0][1]); + 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 } } }; + 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 ((unsigned)(colors - 3) > 1) + return; #ifdef DCRAW_VERBOSE - if (verbose) fprintf (stderr,_("Blending highlights...\n")); + if (verbose) + fprintf(stderr, _("Blending highlights...\n")); #endif #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS,0,2); + RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS, 0, 2); #endif - 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); + 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]); + 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; + chratio = sqrt(sum[1] / sum[0]); + for (c = 1; c < colors; c++) + lab[0][c] *= chratio; + FORCC for (cam[0][c] = j = 0; j < colors; j++) cam[0][c] += itrans[colors - 3][c][j] * lab[0][j]; + FORCC image[row * width + col][c] = cam[0][c] / colors; } #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS,1,2); + RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS, 1, 2); #endif } #define SCALE (4 >> shrink) void CLASS recover_highlights() { float *map, sum, wgt, grow; int hsat[4], count, spread, change, val, i; unsigned high, wide, mrow, mcol, row, col, kc, c, d, y, x; ushort *pixel; - static const signed char dir[8][2] = - { {-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1} }; + static const signed char dir[8][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 1}, {1, 0}, {1, -1}, {0, -1}}; #ifdef DCRAW_VERBOSE - if (verbose) fprintf (stderr,_("Rebuilding highlights...\n")); + if (verbose) + fprintf(stderr, _("Rebuilding highlights...\n")); #endif - grow = pow (2.0, 4-highlight); + grow = pow(2.0, 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; + for (kc = 0, c = 1; c < colors; c++) + if (pre_mul[kc] < pre_mul[c]) + kc = c; high = height / SCALE; - wide = width / SCALE; - map = (float *) calloc (high, wide*sizeof *map); - merror (map, "recover_highlights()"); - FORCC if (c != kc) { -#ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS,c-1,colors-1); -#endif - memset (map, 0, high*wide*sizeof *map); - for (mrow=0; mrow < high; mrow++) - for (mcol=0; mcol < wide; mcol++) { - sum = wgt = count = 0; - for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++) - for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) { - pixel = image[row*width+col]; - if (pixel[c] / hsat[c] == 1 && pixel[kc] > 24000) { - sum += pixel[c]; - wgt += pixel[kc]; - count++; - } - } - if (count == SCALE*SCALE) - map[mrow*wide+mcol] = sum / wgt; - } - for (spread = 32/grow; spread--; ) { - for (mrow=0; mrow < high; mrow++) - for (mcol=0; mcol < wide; mcol++) { - if (map[mrow*wide+mcol]) continue; - sum = count = 0; - for (d=0; d < 8; d++) { - y = mrow + dir[d][0]; - x = mcol + dir[d][1]; - if (y < high && x < wide && map[y*wide+x] > 0) { - sum += (1 + (d & 1)) * map[y*wide+x]; - count += 1 + (d & 1); - } - } - if (count > 3) - map[mrow*wide+mcol] = - (sum+grow) / (count+grow); - } - for (change=i=0; i < high*wide; i++) - if (map[i] < 0) { - map[i] = -map[i]; - change = 1; - } - if (!change) break; - } - for (i=0; i < high*wide; i++) - if (map[i] == 0) map[i] = 1; - for (mrow=0; mrow < high; mrow++) - for (mcol=0; mcol < wide; mcol++) { - for (row = mrow*SCALE; row < (mrow+1)*SCALE; row++) - for (col = mcol*SCALE; col < (mcol+1)*SCALE; col++) { - pixel = image[row*width+col]; - if (pixel[c] / hsat[c] > 1) { - val = pixel[kc] * map[mrow*wide+mcol]; - if (pixel[c] < val) pixel[c] = CLIP(val); - } - } + wide = width / SCALE; + map = (float *)calloc(high, wide * sizeof *map); + merror(map, "recover_highlights()"); + FORCC if (c != kc) + { +#ifdef LIBRAW_LIBRARY_BUILD + RUN_CALLBACK(LIBRAW_PROGRESS_HIGHLIGHTS, c - 1, colors - 1); +#endif + memset(map, 0, high * wide * sizeof *map); + for (mrow = 0; mrow < high; mrow++) + for (mcol = 0; mcol < wide; mcol++) + { + sum = wgt = count = 0; + for (row = mrow * SCALE; row < (mrow + 1) * SCALE; row++) + for (col = mcol * SCALE; col < (mcol + 1) * SCALE; col++) + { + pixel = image[row * width + col]; + if (pixel[c] / hsat[c] == 1 && pixel[kc] > 24000) + { + sum += pixel[c]; + wgt += pixel[kc]; + count++; + } + } + if (count == SCALE * SCALE) + map[mrow * wide + mcol] = sum / wgt; + } + for (spread = 32 / grow; spread--;) + { + for (mrow = 0; mrow < high; mrow++) + for (mcol = 0; mcol < wide; mcol++) + { + if (map[mrow * wide + mcol]) + continue; + sum = count = 0; + for (d = 0; d < 8; d++) + { + y = mrow + dir[d][0]; + x = mcol + dir[d][1]; + if (y < high && x < wide && map[y * wide + x] > 0) + { + sum += (1 + (d & 1)) * map[y * wide + x]; + count += 1 + (d & 1); + } + } + if (count > 3) + map[mrow * wide + mcol] = -(sum + grow) / (count + grow); + } + for (change = i = 0; i < high * wide; i++) + if (map[i] < 0) + { + map[i] = -map[i]; + change = 1; + } + if (!change) + break; + } + for (i = 0; i < high * wide; i++) + if (map[i] == 0) + map[i] = 1; + for (mrow = 0; mrow < high; mrow++) + for (mcol = 0; mcol < wide; mcol++) + { + for (row = mrow * SCALE; row < (mrow + 1) * SCALE; row++) + for (col = mcol * SCALE; col < (mcol + 1) * SCALE; col++) + { + pixel = image[row * width + col]; + if (pixel[c] / hsat[c] > 1) + { + val = pixel[kc] * map[mrow * wide + mcol]; + if (pixel[c] < val) + pixel[c] = CLIP(val); + } + } } } - free (map); -} -#undef SCALE - -void CLASS tiff_get (unsigned base, - unsigned *tag, unsigned *type, unsigned *len, unsigned *save) -{ - *tag = get2(); - *type = get2(); - *len = get4(); - *save = ftell(ifp) + 4; - if (*len * ("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); - } + free(map); } +#undef SCALE -static float powf_lim(float a, float b, float limup) +void CLASS tiff_get(unsigned base, unsigned *tag, unsigned *type, unsigned *len, unsigned *save) { - return (b>limup || b < -limup)?0.f:powf(a,b); +#ifdef LIBRAW_IOSPACE_CHECK + INT64 pos = ftell(ifp); + INT64 fsize = ifp->size(); + if(fsize < 12 || (fsize-pos) < 12) + throw LIBRAW_EXCEPTION_IO_EOF; +#endif + *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); } -static float libraw_powf64(float a, float b) + +void CLASS parse_thumb_note(int base, unsigned toff, unsigned tlen) { - return powf_lim(a,b,64.f); + 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); + } } +static float powf_lim(float a, float b, float limup) { return (b > limup || b < -limup) ? 0.f : powf(a, b); } +static float libraw_powf64l(float a, float b) { return powf_lim(a, b, 64.f); } #ifdef LIBRAW_LIBRARY_BUILD -static float my_roundf(float x) { +static float my_roundf(float x) +{ float t; - if (x >= 0.0) { + if (x >= 0.0) + { t = ceilf(x); - if (t - x > 0.5) t -= 1.0; + if (t - x > 0.5) + t -= 1.0; return t; - } else { + } + else + { t = ceilf(-x); - if (t + x > 0.5) t -= 1.0; + if (t + x > 0.5) + t -= 1.0; return -t; } } static float _CanonConvertAperture(ushort in) { - if ((in == (ushort)0xffe0) || (in == (ushort)0x7fff)) return 0.0f; - return libraw_powf64(2.0, in/64.0); + if ((in == (ushort)0xffe0) || (in == (ushort)0x7fff)) + return 0.0f; + return libraw_powf64l(2.0, in / 64.0); } -static float _CanonConvertEV (short in) +static float _CanonConvertEV(short in) { - short EV, Sign, Frac; - float Frac_f; - EV = in; - if (EV < 0) { - EV = -EV; - Sign = -1; - } else { - Sign = 1; - } - Frac = EV & 0x1f; - EV -= Frac; // remove fraction + short EV, Sign, Frac; + float Frac_f; + EV = in; + if (EV < 0) + { + EV = -EV; + Sign = -1; + } + else + { + Sign = 1; + } + Frac = EV & 0x1f; + EV -= Frac; // remove fraction - if (Frac == 0x0c) { // convert 1/3 and 2/3 codes - Frac_f = 32.0f / 3.0f; - } else if (Frac == 0x14) { - Frac_f = 64.0f / 3.0f; - } else Frac_f = (float) Frac; + if (Frac == 0x0c) + { // convert 1/3 and 2/3 codes + Frac_f = 32.0f / 3.0f; + } + else if (Frac == 0x14) + { + Frac_f = 64.0f / 3.0f; + } + else + Frac_f = (float)Frac; - return ((float)Sign * ((float)EV + Frac_f))/32.0f; + return ((float)Sign * ((float)EV + Frac_f)) / 32.0f; } -void CLASS setCanonBodyFeatures (unsigned id) - { - imgdata.lens.makernotes.CamID = id; - if ( - (id == 0x80000001) || // 1D - (id == 0x80000174) || // 1D2 - (id == 0x80000232) || // 1D2N - (id == 0x80000169) || // 1D3 - (id == 0x80000281) // 1D4 - ) - { - imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_APSH; - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Canon_EF; - } - else - if ( - (id == 0x80000167) || // 1Ds - (id == 0x80000188) || // 1Ds2 - (id == 0x80000215) || // 1Ds3 - (id == 0x80000269) || // 1DX - (id == 0x80000328) || // 1DX2 - (id == 0x80000324) || // 1DC - (id == 0x80000213) || // 5D - (id == 0x80000218) || // 5D2 - (id == 0x80000285) || // 5D3 - (id == 0x80000349) || // 5D4 - (id == 0x80000382) || // 5DS - (id == 0x80000401) || // 5DS R - (id == 0x80000302) // 6D - ) - { - imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_FF; - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Canon_EF; - } - else - if ( - (id == 0x80000331) || // M - (id == 0x80000355) || // M2 - (id == 0x80000374) || // M3 - (id == 0x80000384) || // M10 - (id == 0x80000394) // M5 - ) - { - imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_APSC; - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Canon_EF_M; - } - else - if ( - (id == 0x01140000) || // D30 - (id == 0x01668000) || // D60 - (id > 0x80000000) - ) - { - imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_APSC; - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Canon_EF; - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Unknown; - } - else - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; - } +unsigned CLASS setCanonBodyFeatures(unsigned id) +{ + if (id == 0x03740000) // EOS M3 + id = 0x80000374; + else if (id == 0x03840000) // EOS M10 + id = 0x80000384; + else if (id == 0x03940000) // EOS M5 + id = 0x80000394; + else if (id == 0x04070000) // EOS M6 + id = 0x80000407; + else if (id == 0x03980000) // EOS M100 + id = 0x80000398; - return; - } + imgdata.lens.makernotes.CamID = id; + if ((id == 0x80000001) || // 1D + (id == 0x80000174) || // 1D2 + (id == 0x80000232) || // 1D2N + (id == 0x80000169) || // 1D3 + (id == 0x80000281) // 1D4 + ) + { + imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_APSH; + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Canon_EF; + } + else if ((id == 0x80000167) || // 1Ds + (id == 0x80000188) || // 1Ds2 + (id == 0x80000215) || // 1Ds3 + (id == 0x80000269) || // 1DX + (id == 0x80000328) || // 1DX2 + (id == 0x80000324) || // 1DC + (id == 0x80000213) || // 5D + (id == 0x80000218) || // 5D2 + (id == 0x80000285) || // 5D3 + (id == 0x80000349) || // 5D4 + (id == 0x80000382) || // 5DS + (id == 0x80000401) || // 5DS R + (id == 0x80000302) // 6D + ) + { + imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_FF; + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Canon_EF; + } + else if ((id == 0x80000331) || // M + (id == 0x80000355) || // M2 + (id == 0x80000374) || // M3 + (id == 0x80000384) || // M10 + (id == 0x80000394) || // M5 + (id == 0x80000407) || // M6 + (id == 0x80000398) // M100 + ) + { + imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_APSC; + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Canon_EF_M; + } + else if ((id == 0x01140000) || // D30 + (id == 0x01668000) || // D60 + (id > 0x80000000)) + { + imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_APSC; + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Canon_EF; + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Unknown; + } + else + { + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; + } + + return id; +} -void CLASS processCanonCameraInfo (unsigned id, uchar *CameraInfo, unsigned maxlen) +void CLASS processCanonCameraInfo(unsigned id, uchar *CameraInfo, unsigned maxlen, unsigned type) { - ushort iCanonLensID = 0, iCanonMaxFocal = 0, iCanonMinFocal = 0, iCanonLens = 0, iCanonCurFocal = 0, iCanonFocalType = 0; - if(maxlen<16) return; // too short, so broken + ushort iCanonLensID = 0, iCanonMaxFocal = 0, iCanonMinFocal = 0, iCanonLens = 0, iCanonCurFocal = 0, + iCanonFocalType = 0; + if (maxlen < 16) + return; // too short CameraInfo[0] = 0; CameraInfo[1] = 0; - switch (id) { + if (type == 4) + { + if ((maxlen == 94) || (maxlen == 138) || (maxlen == 148) || (maxlen == 156) || (maxlen == 162) || (maxlen == 167) || + (maxlen == 171) || (maxlen == 264) || (maxlen > 400)) + imgdata.other.CameraTemperature = sget4(CameraInfo + ((maxlen - 3) << 2)); + else if (maxlen == 72) + imgdata.other.CameraTemperature = sget4(CameraInfo + ((maxlen - 1) << 2)); + else if ((maxlen == 85) || (maxlen == 93)) + imgdata.other.CameraTemperature = sget4(CameraInfo + ((maxlen - 2) << 2)); + else if ((maxlen == 96) || (maxlen == 104)) + imgdata.other.CameraTemperature = sget4(CameraInfo + ((maxlen - 4) << 2)); + } + + switch (id) + { case 0x80000001: // 1D case 0x80000167: // 1DS iCanonCurFocal = 10; iCanonLensID = 13; iCanonMinFocal = 14; iCanonMaxFocal = 16; if (!imgdata.lens.makernotes.CurFocal) imgdata.lens.makernotes.CurFocal = sget2(CameraInfo + iCanonCurFocal); if (!imgdata.lens.makernotes.MinFocal) - imgdata.lens.makernotes.MinFocal = sget2(CameraInfo + iCanonMinFocal); + imgdata.lens.makernotes.MinFocal = sget2(CameraInfo + iCanonMinFocal); if (!imgdata.lens.makernotes.MaxFocal) imgdata.lens.makernotes.MaxFocal = sget2(CameraInfo + iCanonMaxFocal); + imgdata.other.CameraTemperature = 0.0f; break; case 0x80000174: // 1DMkII case 0x80000188: // 1DsMkII iCanonCurFocal = 9; iCanonLensID = 12; iCanonMinFocal = 17; iCanonMaxFocal = 19; iCanonFocalType = 45; break; case 0x80000232: // 1DMkII N iCanonCurFocal = 9; iCanonLensID = 12; iCanonMinFocal = 17; iCanonMaxFocal = 19; break; case 0x80000169: // 1DMkIII case 0x80000215: // 1DsMkIII iCanonCurFocal = 29; iCanonLensID = 273; iCanonMinFocal = 275; iCanonMaxFocal = 277; break; case 0x80000281: // 1DMkIV iCanonCurFocal = 30; iCanonLensID = 335; iCanonMinFocal = 337; iCanonMaxFocal = 339; break; case 0x80000269: // 1D X iCanonCurFocal = 35; iCanonLensID = 423; iCanonMinFocal = 425; iCanonMaxFocal = 427; break; case 0x80000213: // 5D iCanonCurFocal = 40; - if (!sget2Rev(CameraInfo + 12)) iCanonLensID = 151; - else iCanonLensID = 12; + if (!sget2Rev(CameraInfo + 12)) + iCanonLensID = 151; + else + iCanonLensID = 12; iCanonMinFocal = 147; iCanonMaxFocal = 149; break; case 0x80000218: // 5DMkII iCanonCurFocal = 30; iCanonLensID = 230; iCanonMinFocal = 232; iCanonMaxFocal = 234; break; case 0x80000285: // 5DMkIII iCanonCurFocal = 35; iCanonLensID = 339; iCanonMinFocal = 341; iCanonMaxFocal = 343; break; case 0x80000302: // 6D iCanonCurFocal = 35; iCanonLensID = 353; iCanonMinFocal = 355; iCanonMaxFocal = 357; break; case 0x80000250: // 7D iCanonCurFocal = 30; iCanonLensID = 274; iCanonMinFocal = 276; iCanonMaxFocal = 278; break; case 0x80000190: // 40D iCanonCurFocal = 29; iCanonLensID = 214; iCanonMinFocal = 216; iCanonMaxFocal = 218; iCanonLens = 2347; break; case 0x80000261: // 50D iCanonCurFocal = 30; iCanonLensID = 234; iCanonMinFocal = 236; iCanonMaxFocal = 238; break; case 0x80000287: // 60D iCanonCurFocal = 30; iCanonLensID = 232; iCanonMinFocal = 234; iCanonMaxFocal = 236; break; case 0x80000325: // 70D iCanonCurFocal = 35; iCanonLensID = 358; iCanonMinFocal = 360; iCanonMaxFocal = 362; break; case 0x80000176: // 450D iCanonCurFocal = 29; iCanonLensID = 222; iCanonLens = 2355; break; case 0x80000252: // 500D iCanonCurFocal = 30; iCanonLensID = 246; iCanonMinFocal = 248; iCanonMaxFocal = 250; break; case 0x80000270: // 550D iCanonCurFocal = 30; iCanonLensID = 255; iCanonMinFocal = 257; iCanonMaxFocal = 259; break; case 0x80000286: // 600D case 0x80000288: // 1100D iCanonCurFocal = 30; iCanonLensID = 234; iCanonMinFocal = 236; iCanonMaxFocal = 238; break; case 0x80000301: // 650D case 0x80000326: // 700D iCanonCurFocal = 35; iCanonLensID = 295; iCanonMinFocal = 297; iCanonMaxFocal = 299; break; case 0x80000254: // 1000D iCanonCurFocal = 29; iCanonLensID = 226; iCanonMinFocal = 228; iCanonMaxFocal = 230; iCanonLens = 2359; break; } if (iCanonFocalType) - { - if(iCanonFocalType>=maxlen) return; // broken; - imgdata.lens.makernotes.FocalType = CameraInfo[iCanonFocalType]; - if (!imgdata.lens.makernotes.FocalType) // zero means 'fixed' here, replacing with standard '1' - imgdata.lens.makernotes.FocalType = 1; - } + { + if (iCanonFocalType >= maxlen) + return; // broken; + imgdata.lens.makernotes.FocalType = CameraInfo[iCanonFocalType]; + if (!imgdata.lens.makernotes.FocalType) // zero means 'fixed' here, replacing with standard '1' + imgdata.lens.makernotes.FocalType = 1; + } if (!imgdata.lens.makernotes.CurFocal) - { - if(iCanonCurFocal>=maxlen) return; // broken; - imgdata.lens.makernotes.CurFocal = sget2Rev(CameraInfo + iCanonCurFocal); - } + { + if (iCanonCurFocal >= maxlen) + return; // broken; + imgdata.lens.makernotes.CurFocal = sget2Rev(CameraInfo + iCanonCurFocal); + } if (!imgdata.lens.makernotes.LensID) - { - if(iCanonLensID>=maxlen) return; // broken; - imgdata.lens.makernotes.LensID = sget2Rev(CameraInfo + iCanonLensID); - } + { + if (iCanonLensID >= maxlen) + return; // broken; + imgdata.lens.makernotes.LensID = sget2Rev(CameraInfo + iCanonLensID); + } if (!imgdata.lens.makernotes.MinFocal) - { - if(iCanonMinFocal>=maxlen) return; // broken; - imgdata.lens.makernotes.MinFocal = sget2Rev(CameraInfo + iCanonMinFocal); - } + { + if (iCanonMinFocal >= maxlen) + return; // broken; + imgdata.lens.makernotes.MinFocal = sget2Rev(CameraInfo + iCanonMinFocal); + } if (!imgdata.lens.makernotes.MaxFocal) + { + if (iCanonMaxFocal >= maxlen) + return; // broken; + imgdata.lens.makernotes.MaxFocal = sget2Rev(CameraInfo + iCanonMaxFocal); + } + if (!imgdata.lens.makernotes.Lens[0] && iCanonLens) + { + if (iCanonLens + 64 >= maxlen) + return; // broken; + if (CameraInfo[iCanonLens] < 65) // non-Canon lens { - if(iCanonMaxFocal>=maxlen) return; // broken; - imgdata.lens.makernotes.MaxFocal = sget2Rev(CameraInfo + iCanonMaxFocal); + memcpy(imgdata.lens.makernotes.Lens, CameraInfo + iCanonLens, 64); } - if (!imgdata.lens.makernotes.Lens[0] && iCanonLens) { - if(iCanonLens+64>=maxlen) return; // broken; - if (CameraInfo[iCanonLens] < 65) // non-Canon lens - { - memcpy(imgdata.lens.makernotes.Lens, CameraInfo + iCanonLens, 64); - } else if (!strncmp((char *)CameraInfo + iCanonLens, "EF-S", 4)) - { - memcpy(imgdata.lens.makernotes.Lens, "EF-S ", 5); - memcpy(imgdata.lens.makernotes.LensFeatures_pre, "EF-E", 4); - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF_S; - memcpy(imgdata.lens.makernotes.Lens + 5, CameraInfo + iCanonLens + 4, 60); + { + memcpy(imgdata.lens.makernotes.Lens, "EF-S ", 5); + memcpy(imgdata.lens.makernotes.LensFeatures_pre, "EF-E", 4); + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF_S; + memcpy(imgdata.lens.makernotes.Lens + 5, CameraInfo + iCanonLens + 4, 60); } - else if (!strncmp((char *)CameraInfo + iCanonLens, "TS-E", 4)) { + else if (!strncmp((char *)CameraInfo + iCanonLens, "TS-E", 4)) + { memcpy(imgdata.lens.makernotes.Lens, "TS-E ", 5); memcpy(imgdata.lens.makernotes.LensFeatures_pre, "TS-E", 4); imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF; memcpy(imgdata.lens.makernotes.Lens + 5, CameraInfo + iCanonLens + 4, 60); } - else if (!strncmp((char *)CameraInfo + iCanonLens, "MP-E", 4)) { + else if (!strncmp((char *)CameraInfo + iCanonLens, "MP-E", 4)) + { memcpy(imgdata.lens.makernotes.Lens, "MP-E ", 5); memcpy(imgdata.lens.makernotes.LensFeatures_pre, "MP-E", 4); imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF; memcpy(imgdata.lens.makernotes.Lens + 5, CameraInfo + iCanonLens + 4, 60); } - else if (!strncmp((char *)CameraInfo + iCanonLens, "EF-M", 4)) { + else if (!strncmp((char *)CameraInfo + iCanonLens, "EF-M", 4)) + { memcpy(imgdata.lens.makernotes.Lens, "EF-M ", 5); memcpy(imgdata.lens.makernotes.LensFeatures_pre, "EF-M", 4); imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF_M; memcpy(imgdata.lens.makernotes.Lens + 5, CameraInfo + iCanonLens + 4, 60); } - else { + else + { memcpy(imgdata.lens.makernotes.Lens, CameraInfo + iCanonLens, 2); memcpy(imgdata.lens.makernotes.LensFeatures_pre, "EF", 2); imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF; imgdata.lens.makernotes.Lens[2] = 32; memcpy(imgdata.lens.makernotes.Lens + 3, CameraInfo + iCanonLens + 2, 62); } } return; } -void CLASS Canon_CameraSettings () +void CLASS Canon_CameraSettings() { fseek(ifp, 10, SEEK_CUR); - imgdata.shootinginfo.DriveMode = get2(); get2(); + imgdata.shootinginfo.DriveMode = get2(); + get2(); imgdata.shootinginfo.FocusMode = get2(); fseek(ifp, 18, SEEK_CUR); - imgdata.shootinginfo.MeteringMode = get2(); get2(); + imgdata.shootinginfo.MeteringMode = get2(); + get2(); imgdata.shootinginfo.AFPoint = get2(); - imgdata.shootinginfo.ExposureMode = get2(); get2(); + imgdata.shootinginfo.ExposureMode = get2(); + get2(); imgdata.lens.makernotes.LensID = get2(); imgdata.lens.makernotes.MaxFocal = get2(); imgdata.lens.makernotes.MinFocal = get2(); imgdata.lens.makernotes.CanonFocalUnits = get2(); if (imgdata.lens.makernotes.CanonFocalUnits > 1) - { - imgdata.lens.makernotes.MaxFocal /= (float)imgdata.lens.makernotes.CanonFocalUnits; - imgdata.lens.makernotes.MinFocal /= (float)imgdata.lens.makernotes.CanonFocalUnits; - } + { + imgdata.lens.makernotes.MaxFocal /= (float)imgdata.lens.makernotes.CanonFocalUnits; + imgdata.lens.makernotes.MinFocal /= (float)imgdata.lens.makernotes.CanonFocalUnits; + } imgdata.lens.makernotes.MaxAp = _CanonConvertAperture(get2()); imgdata.lens.makernotes.MinAp = _CanonConvertAperture(get2()); fseek(ifp, 12, SEEK_CUR); imgdata.shootinginfo.ImageStabilization = get2(); } -void CLASS Canon_WBpresets (int skip1, int skip2) +void CLASS Canon_WBpresets(int skip1, int skip2) { int c; FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][c ^ (c >> 1)] = get2(); - if (skip1) fseek(ifp, skip1, SEEK_CUR); + + if (skip1) + fseek(ifp, skip1, SEEK_CUR); FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][c ^ (c >> 1)] = get2(); - if (skip1) fseek(ifp, skip1, SEEK_CUR); + + if (skip1) + fseek(ifp, skip1, SEEK_CUR); FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][c ^ (c >> 1)] = get2(); - if (skip1) fseek(ifp, skip1, SEEK_CUR); + + if (skip1) + fseek(ifp, skip1, SEEK_CUR); FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][c ^ (c >> 1)] = get2(); - if (skip1) fseek(ifp, skip1, SEEK_CUR); + + if (skip1) + fseek(ifp, skip1, SEEK_CUR); FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][c ^ (c >> 1)] = get2(); - if (skip2) fseek(ifp, skip2, SEEK_CUR); + + if (skip2) + fseek(ifp, skip2, SEEK_CUR); FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][c ^ (c >> 1)] = get2(); + return; } -void CLASS Canon_WBCTpresets (short WBCTversion) +void CLASS Canon_WBCTpresets(short WBCTversion) { - if (WBCTversion == 0) - for (int i=0; i<15; i++)// tint, as shot R, as shot B, CСT - { - imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] = 1.0f; - fseek (ifp, 2, SEEK_CUR); - imgdata.color.WBCT_Coeffs[i][1] = 1024.0f /fMAX(get2(),1.f) ; - imgdata.color.WBCT_Coeffs[i][3] = 1024.0f /fMAX(get2(),1.f); - imgdata.color.WBCT_Coeffs[i][0] = get2(); - } - else if (WBCTversion == 1) - for (int i=0; i<15; i++) // as shot R, as shot B, tint, CСT - { - imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] = 1.0f; - imgdata.color.WBCT_Coeffs[i][1] = 1024.0f / fMAX(get2(),1.f); - imgdata.color.WBCT_Coeffs[i][3] = 1024.0f / fMAX(get2(),1.f); - fseek (ifp, 2, SEEK_CUR); - imgdata.color.WBCT_Coeffs[i][0] = get2(); - } - else if ((WBCTversion == 2) && - ((unique_id == 0x80000374) || // M3 - (unique_id == 0x80000384) || // M10 - (unique_id == 0x80000394) || // M5 - (unique_id == 0x03970000))) // G7 X Mark II - for (int i=0; i<15; i++) // tint, offset, as shot R, as shot B, CСT - { - fseek (ifp, 2, SEEK_CUR); - fseek (ifp, 2, SEEK_CUR); - imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] = 1.0f; - imgdata.color.WBCT_Coeffs[i][1] = 1024.0f / fMAX(1.f,get2()); - imgdata.color.WBCT_Coeffs[i][3] = 1024.0f / fMAX(1.f,get2()); - imgdata.color.WBCT_Coeffs[i][0] = get2(); - } - else if ((WBCTversion == 2) && - ((unique_id == 0x03950000) || (unique_id == 0x03930000))) // G5 X, G9 X - for (int i=0; i<15; i++) // tint, offset, as shot R, as shot B, CСT - { - fseek (ifp, 2, SEEK_CUR); - fseek (ifp, 2, SEEK_CUR); - imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] = 1.0f; - imgdata.color.WBCT_Coeffs[i][1] = (float)get2() / 512.0f; - imgdata.color.WBCT_Coeffs[i][3] = (float)get2() / 512.0f; - imgdata.color.WBCT_Coeffs[i][0] = get2(); - } - return; + if (WBCTversion == 0) + for (int i = 0; i < 15; i++) // tint, as shot R, as shot B, CСT + { + imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] = 1.0f; + fseek(ifp, 2, SEEK_CUR); + imgdata.color.WBCT_Coeffs[i][1] = 1024.0f / fMAX(get2(), 1.f); + imgdata.color.WBCT_Coeffs[i][3] = 1024.0f / fMAX(get2(), 1.f); + imgdata.color.WBCT_Coeffs[i][0] = get2(); + } + else if (WBCTversion == 1) + for (int i = 0; i < 15; i++) // as shot R, as shot B, tint, CСT + { + imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] = 1.0f; + imgdata.color.WBCT_Coeffs[i][1] = 1024.0f / fMAX(get2(), 1.f); + imgdata.color.WBCT_Coeffs[i][3] = 1024.0f / fMAX(get2(), 1.f); + fseek(ifp, 2, SEEK_CUR); + imgdata.color.WBCT_Coeffs[i][0] = get2(); + } + else if ((WBCTversion == 2) && ((unique_id == 0x80000374) || // M3 + (unique_id == 0x80000384) || // M10 + (unique_id == 0x80000394) || // M5 + (unique_id == 0x80000407) || // M6 + (unique_id == 0x80000398) || // M100 + (unique_id == 0x03970000) || // G7 X Mark II + (unique_id == 0x04100000) || // G9 X Mark II + (unique_id == 0x04180000))) // G1 X Mark III + for (int i = 0; i < 15; i++) // tint, offset, as shot R, as shot B, CСT + { + fseek(ifp, 2, SEEK_CUR); + fseek(ifp, 2, SEEK_CUR); + imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] = 1.0f; + imgdata.color.WBCT_Coeffs[i][1] = 1024.0f / fMAX(1.f, get2()); + imgdata.color.WBCT_Coeffs[i][3] = 1024.0f / fMAX(1.f, get2()); + imgdata.color.WBCT_Coeffs[i][0] = get2(); + } + else if ((WBCTversion == 2) && ((unique_id == 0x03950000) || (unique_id == 0x03930000))) // G5 X, G9 X + for (int i = 0; i < 15; i++) // tint, offset, as shot R, as shot B, CСT + { + fseek(ifp, 2, SEEK_CUR); + fseek(ifp, 2, SEEK_CUR); + imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] = 1.0f; + imgdata.color.WBCT_Coeffs[i][1] = (float)get2() / 512.0f; + imgdata.color.WBCT_Coeffs[i][3] = (float)get2() / 512.0f; + imgdata.color.WBCT_Coeffs[i][0] = get2(); + } + return; } -void CLASS processNikonLensData (uchar *LensData, unsigned len) +void CLASS processNikonLensData(uchar *LensData, unsigned len) { ushort i; if (!(imgdata.lens.nikon.NikonLensType & 0x01)) - { - imgdata.lens.makernotes.LensFeatures_pre[0] = 'A'; - imgdata.lens.makernotes.LensFeatures_pre[1] = 'F'; - } + { + imgdata.lens.makernotes.LensFeatures_pre[0] = 'A'; + imgdata.lens.makernotes.LensFeatures_pre[1] = 'F'; + } else - { - imgdata.lens.makernotes.LensFeatures_pre[0] = 'M'; - imgdata.lens.makernotes.LensFeatures_pre[1] = 'F'; - } + { + imgdata.lens.makernotes.LensFeatures_pre[0] = 'M'; + imgdata.lens.makernotes.LensFeatures_pre[1] = 'F'; + } if (imgdata.lens.nikon.NikonLensType & 0x02) - { - if (imgdata.lens.nikon.NikonLensType & 0x04) - imgdata.lens.makernotes.LensFeatures_suf[0] = 'G'; - else - imgdata.lens.makernotes.LensFeatures_suf[0] = 'D'; - imgdata.lens.makernotes.LensFeatures_suf[1] = ' '; - } + { + if (imgdata.lens.nikon.NikonLensType & 0x04) + imgdata.lens.makernotes.LensFeatures_suf[0] = 'G'; + else + imgdata.lens.makernotes.LensFeatures_suf[0] = 'D'; + imgdata.lens.makernotes.LensFeatures_suf[1] = ' '; + } if (imgdata.lens.nikon.NikonLensType & 0x08) - { - imgdata.lens.makernotes.LensFeatures_suf[2] = 'V'; - imgdata.lens.makernotes.LensFeatures_suf[3] = 'R'; - } + { + imgdata.lens.makernotes.LensFeatures_suf[2] = 'V'; + imgdata.lens.makernotes.LensFeatures_suf[3] = 'R'; + } if (imgdata.lens.nikon.NikonLensType & 0x10) { imgdata.lens.makernotes.LensMount = imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Nikon_CX; imgdata.lens.makernotes.CameraFormat = imgdata.lens.makernotes.LensFormat = LIBRAW_FORMAT_1INCH; } else imgdata.lens.makernotes.LensMount = imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Nikon_F; if (imgdata.lens.nikon.NikonLensType & 0x20) { strcpy(imgdata.lens.makernotes.Adapter, "FT-1"); imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Nikon_F; imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Nikon_CX; imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_1INCH; } imgdata.lens.nikon.NikonLensType = imgdata.lens.nikon.NikonLensType & 0xdf; - if (len < 20) { - switch (len) { + if (len < 20) + { + switch (len) + { case 9: i = 2; break; case 15: i = 7; break; case 16: i = 8; break; } imgdata.lens.nikon.NikonLensIDNumber = LensData[i]; imgdata.lens.nikon.NikonLensFStops = LensData[i + 1]; - imgdata.lens.makernotes.LensFStops = (float)imgdata.lens.nikon.NikonLensFStops /12.0f; + imgdata.lens.makernotes.LensFStops = (float)imgdata.lens.nikon.NikonLensFStops / 12.0f; if (fabsf(imgdata.lens.makernotes.MinFocal) < 1.1f) { if ((imgdata.lens.nikon.NikonLensType ^ (uchar)0x01) || LensData[i + 2]) - imgdata.lens.makernotes.MinFocal = 5.0f * libraw_powf64(2.0f, (float)LensData[i + 2] / 24.0f); + imgdata.lens.makernotes.MinFocal = 5.0f * libraw_powf64l(2.0f, (float)LensData[i + 2] / 24.0f); if ((imgdata.lens.nikon.NikonLensType ^ (uchar)0x01) || LensData[i + 3]) - imgdata.lens.makernotes.MaxFocal = 5.0f * libraw_powf64(2.0f, (float)LensData[i + 3] / 24.0f); + imgdata.lens.makernotes.MaxFocal = 5.0f * libraw_powf64l(2.0f, (float)LensData[i + 3] / 24.0f); if ((imgdata.lens.nikon.NikonLensType ^ (uchar)0x01) || LensData[i + 4]) - imgdata.lens.makernotes.MaxAp4MinFocal = libraw_powf64(2.0f, (float)LensData[i + 4] / 24.0f); + imgdata.lens.makernotes.MaxAp4MinFocal = libraw_powf64l(2.0f, (float)LensData[i + 4] / 24.0f); if ((imgdata.lens.nikon.NikonLensType ^ (uchar)0x01) || LensData[i + 5]) - imgdata.lens.makernotes.MaxAp4MaxFocal = libraw_powf64(2.0f, (float)LensData[i + 5] / 24.0f); + imgdata.lens.makernotes.MaxAp4MaxFocal = libraw_powf64l(2.0f, (float)LensData[i + 5] / 24.0f); } imgdata.lens.nikon.NikonMCUVersion = LensData[i + 6]; if (i != 2) - { - if ((LensData[i - 1]) && - (fabsf(imgdata.lens.makernotes.CurFocal) < 1.1f)) - imgdata.lens.makernotes.CurFocal = 5.0f * libraw_powf64(2.0f, (float)LensData[i - 1] / 24.0f); - if (LensData[i + 7]) imgdata.lens.nikon.NikonEffectiveMaxAp = libraw_powf64(2.0f, (float)LensData[i + 7] / 24.0f); - } + { + if ((LensData[i - 1]) && (fabsf(imgdata.lens.makernotes.CurFocal) < 1.1f)) + imgdata.lens.makernotes.CurFocal = 5.0f * libraw_powf64l(2.0f, (float)LensData[i - 1] / 24.0f); + if (LensData[i + 7]) + imgdata.lens.nikon.NikonEffectiveMaxAp = libraw_powf64l(2.0f, (float)LensData[i + 7] / 24.0f); + } imgdata.lens.makernotes.LensID = - (unsigned long long) LensData[i] << 56 | - (unsigned long long) LensData[i + 1] << 48 | - (unsigned long long) LensData[i + 2] << 40 | - (unsigned long long) LensData[i + 3] << 32 | - (unsigned long long) LensData[i + 4] << 24 | - (unsigned long long) LensData[i + 5] << 16 | - (unsigned long long) LensData[i + 6] << 8 | - (unsigned long long) imgdata.lens.nikon.NikonLensType; - + (unsigned long long)LensData[i] << 56 | (unsigned long long)LensData[i + 1] << 48 | + (unsigned long long)LensData[i + 2] << 40 | (unsigned long long)LensData[i + 3] << 32 | + (unsigned long long)LensData[i + 4] << 24 | (unsigned long long)LensData[i + 5] << 16 | + (unsigned long long)LensData[i + 6] << 8 | (unsigned long long)imgdata.lens.nikon.NikonLensType; } else if ((len == 459) || (len == 590)) - { - memcpy(imgdata.lens.makernotes.Lens, LensData + 390, 64); - } + { + memcpy(imgdata.lens.makernotes.Lens, LensData + 390, 64); + } else if (len == 509) - { - memcpy(imgdata.lens.makernotes.Lens, LensData + 391, 64); - } + { + memcpy(imgdata.lens.makernotes.Lens, LensData + 391, 64); + } else if (len == 879) - { - memcpy(imgdata.lens.makernotes.Lens, LensData + 680, 64); - } + { + memcpy(imgdata.lens.makernotes.Lens, LensData + 680, 64); + } return; } -void CLASS setOlympusBodyFeatures (unsigned long long id) +void CLASS setOlympusBodyFeatures(unsigned long long id) { imgdata.lens.makernotes.CamID = id; - if ((id == 0x4434303430ULL) || // E-1 - (id == 0x4434303431ULL) || // E-300 + if (id == 0x5330303638ULL) + { + strcpy(model, "E-M10MarkIII"); + } + if ((id == 0x4434303430ULL) || // E-1 + (id == 0x4434303431ULL) || // E-300 ((id & 0x00ffff0000ULL) == 0x0030300000ULL)) { - imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_FT; - if ((id == 0x4434303430ULL) || // E-1 - (id == 0x4434303431ULL) || // E-330 - ((id >= 0x5330303033ULL) && (id <= 0x5330303138ULL)) || // E-330 to E-520 - (id == 0x5330303233ULL) || // E-620 - (id == 0x5330303239ULL) || // E-450 - (id == 0x5330303330ULL) || // E-600 - (id == 0x5330303333ULL)) // E-5 - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FT; - } - else - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_mFT; - } + imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_FT; + if ((id == 0x4434303430ULL) || // E-1 + (id == 0x4434303431ULL) || // E-330 + ((id >= 0x5330303033ULL) && (id <= 0x5330303138ULL)) || // E-330 to E-520 + (id == 0x5330303233ULL) || // E-620 + (id == 0x5330303239ULL) || // E-450 + (id == 0x5330303330ULL) || // E-600 + (id == 0x5330303333ULL)) // E-5 + { + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FT; + } + else + { + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_mFT; + } } else { - imgdata.lens.makernotes.LensMount = - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; + imgdata.lens.makernotes.LensMount = imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; } return; } -void CLASS parseCanonMakernotes (unsigned tag, unsigned type, unsigned len) { +void CLASS parseCanonMakernotes(unsigned tag, unsigned type, unsigned len) +{ -if (tag == 0x0001) Canon_CameraSettings(); - else if (tag == 0x0002) // focal length - { - imgdata.lens.makernotes.FocalType = get2(); - imgdata.lens.makernotes.CurFocal = get2(); - if (imgdata.lens.makernotes.CanonFocalUnits > 1) - { - imgdata.lens.makernotes.CurFocal /= (float)imgdata.lens.makernotes.CanonFocalUnits; - } - } + if (tag == 0x0001) + Canon_CameraSettings(); + else if (tag == 0x0002) // focal length + { + imgdata.lens.makernotes.FocalType = get2(); + imgdata.lens.makernotes.CurFocal = get2(); + if (imgdata.lens.makernotes.CanonFocalUnits > 1) + { + imgdata.lens.makernotes.CurFocal /= (float)imgdata.lens.makernotes.CanonFocalUnits; + } + } - else if (tag == 0x0004) // shot info - { - short tempAp; - fseek(ifp, 30, SEEK_CUR); - imgdata.other.FlashEC = _CanonConvertEV((signed short)get2()); - fseek(ifp, 8-32, SEEK_CUR); - if ((tempAp = get2()) != 0x7fff) - imgdata.lens.makernotes.CurAp = _CanonConvertAperture(tempAp); - if (imgdata.lens.makernotes.CurAp < 0.7f) - { - fseek(ifp, 32, SEEK_CUR); - imgdata.lens.makernotes.CurAp = _CanonConvertAperture(get2()); - } - if (!aperture) aperture = imgdata.lens.makernotes.CurAp; - } + else if (tag == 0x0004) // shot info + { + short tempAp; + + fseek(ifp, 24, SEEK_CUR); + tempAp = get2(); + if (tempAp != 0) + imgdata.other.CameraTemperature = (float)(tempAp - 128); + tempAp = get2(); + if (tempAp != -1) + imgdata.other.FlashGN = ((float)tempAp) / 32; + get2(); - else if (tag == 0x0095 && // lens model tag - !imgdata.lens.makernotes.Lens[0]) - { - fread(imgdata.lens.makernotes.Lens, 2, 1, ifp); - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF; - if (imgdata.lens.makernotes.Lens[0] < 65) // non-Canon lens - fread(imgdata.lens.makernotes.Lens + 2, 62, 1, ifp); - else - { - char efs[2]; - imgdata.lens.makernotes.LensFeatures_pre[0] = imgdata.lens.makernotes.Lens[0]; - imgdata.lens.makernotes.LensFeatures_pre[1] = imgdata.lens.makernotes.Lens[1]; - fread(efs, 2, 1, ifp); - if (efs[0] == 45 && (efs[1] == 83 || efs[1] == 69 || efs[1] == 77)) - { // "EF-S, TS-E, MP-E, EF-M" lenses - imgdata.lens.makernotes.Lens[2] = imgdata.lens.makernotes.LensFeatures_pre[2] = efs[0]; - imgdata.lens.makernotes.Lens[3] = imgdata.lens.makernotes.LensFeatures_pre[3] = efs[1]; - imgdata.lens.makernotes.Lens[4] = 32; - if (efs[1] == 83) - { - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF_S; - imgdata.lens.makernotes.LensFormat = LIBRAW_FORMAT_APSC; - } - else if (efs[1] == 77) - { - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF_M; - } - } - else - { // "EF" lenses - imgdata.lens.makernotes.Lens[2] = 32; - imgdata.lens.makernotes.Lens[3] = efs[0]; - imgdata.lens.makernotes.Lens[4] = efs[1]; - } - fread(imgdata.lens.makernotes.Lens + 5, 58, 1, ifp); - } - } + // fseek(ifp, 30, SEEK_CUR); + imgdata.other.FlashEC = _CanonConvertEV((signed short)get2()); + fseek(ifp, 8 - 32, SEEK_CUR); + if ((tempAp = get2()) != 0x7fff) + imgdata.lens.makernotes.CurAp = _CanonConvertAperture(tempAp); + if (imgdata.lens.makernotes.CurAp < 0.7f) + { + fseek(ifp, 32, SEEK_CUR); + imgdata.lens.makernotes.CurAp = _CanonConvertAperture(get2()); + } + if (!aperture) + aperture = imgdata.lens.makernotes.CurAp; + } - else if (tag == 0x00a9) - { - long int save1 = ftell(ifp); - fseek (ifp, save1+(0x5<<1), SEEK_SET); - Canon_WBpresets(0,0); - fseek (ifp, save1, SEEK_SET); - } + else if (tag == 0x000c) + { + unsigned tS = get4(); + sprintf (imgdata.shootinginfo.BodySerial, "%d", tS); + } - else if (tag == 0x00e0) // sensor info - { - imgdata.makernotes.canon.SensorWidth = (get2(),get2()); - imgdata.makernotes.canon.SensorHeight = get2(); - imgdata.makernotes.canon.SensorLeftBorder = (get2(),get2(),get2()); - imgdata.makernotes.canon.SensorTopBorder = get2(); - imgdata.makernotes.canon.SensorRightBorder = get2(); - imgdata.makernotes.canon.SensorBottomBorder = get2(); - imgdata.makernotes.canon.BlackMaskLeftBorder = get2(); - imgdata.makernotes.canon.BlackMaskTopBorder = get2(); - imgdata.makernotes.canon.BlackMaskRightBorder = get2(); - imgdata.makernotes.canon.BlackMaskBottomBorder = get2(); - } + else if (tag == 0x0095 && // lens model tag + !imgdata.lens.makernotes.Lens[0]) + { + fread(imgdata.lens.makernotes.Lens, 2, 1, ifp); + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF; + if (imgdata.lens.makernotes.Lens[0] < 65) // non-Canon lens + fread(imgdata.lens.makernotes.Lens + 2, 62, 1, ifp); + else + { + char efs[2]; + imgdata.lens.makernotes.LensFeatures_pre[0] = imgdata.lens.makernotes.Lens[0]; + imgdata.lens.makernotes.LensFeatures_pre[1] = imgdata.lens.makernotes.Lens[1]; + fread(efs, 2, 1, ifp); + if (efs[0] == 45 && (efs[1] == 83 || efs[1] == 69 || efs[1] == 77)) + { // "EF-S, TS-E, MP-E, EF-M" lenses + imgdata.lens.makernotes.Lens[2] = imgdata.lens.makernotes.LensFeatures_pre[2] = efs[0]; + imgdata.lens.makernotes.Lens[3] = imgdata.lens.makernotes.LensFeatures_pre[3] = efs[1]; + imgdata.lens.makernotes.Lens[4] = 32; + if (efs[1] == 83) + { + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF_S; + imgdata.lens.makernotes.LensFormat = LIBRAW_FORMAT_APSC; + } + else if (efs[1] == 77) + { + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF_M; + } + } + else + { // "EF" lenses + imgdata.lens.makernotes.Lens[2] = 32; + imgdata.lens.makernotes.Lens[3] = efs[0]; + imgdata.lens.makernotes.Lens[4] = efs[1]; + } + fread(imgdata.lens.makernotes.Lens + 5, 58, 1, ifp); + } + } + + else if (tag == 0x009a) + { + get4(); + imgdata.sizes.raw_crop.cwidth = get4(); + imgdata.sizes.raw_crop.cheight = get4(); + imgdata.sizes.raw_crop.cleft = get4(); + imgdata.sizes.raw_crop.ctop = get4(); + } + + else if (tag == 0x00a9) + { + long int save1 = ftell(ifp); + int c; + fseek(ifp, (0x1 << 1), SEEK_CUR); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + Canon_WBpresets(0, 0); + fseek(ifp, save1, SEEK_SET); + } + + else if (tag == 0x00e0) // sensor info + { + imgdata.makernotes.canon.SensorWidth = (get2(), get2()); + imgdata.makernotes.canon.SensorHeight = get2(); + imgdata.makernotes.canon.SensorLeftBorder = (get2(), get2(), get2()); + imgdata.makernotes.canon.SensorTopBorder = get2(); + imgdata.makernotes.canon.SensorRightBorder = get2(); + imgdata.makernotes.canon.SensorBottomBorder = get2(); + imgdata.makernotes.canon.BlackMaskLeftBorder = get2(); + imgdata.makernotes.canon.BlackMaskTopBorder = get2(); + imgdata.makernotes.canon.BlackMaskRightBorder = get2(); + imgdata.makernotes.canon.BlackMaskBottomBorder = get2(); + } + + else if (tag == 0x4013) + { + get4(); + imgdata.makernotes.canon.AFMicroAdjMode = get4(); + imgdata.makernotes.canon.AFMicroAdjValue = ((float)get4()) / ((float)get4()); + } - else if (tag == 0x4001 && len > 500) + else if (tag == 0x4001 && len > 500) + { + int c; + long int save1 = ftell(ifp); + switch (len) + { + case 582: + imgdata.makernotes.canon.CanonColorDataVer = 1; // 20D / 350D { - int c; - long int save1 = ftell(ifp); - switch (len) - { - case 582: - imgdata.makernotes.canon.CanonColorDataVer = 1; // 20D / 350D - { - fseek (ifp, save1+(0x23<<1), SEEK_SET); - Canon_WBpresets(2,2); - fseek (ifp, save1+(0x4b<<1), SEEK_SET); - Canon_WBCTpresets (1); // ABCT - } - break; - case 653: - imgdata.makernotes.canon.CanonColorDataVer = 2; // 1Dmk2 / 1DsMK2 - { - fseek (ifp, save1+(0x27<<1), SEEK_SET); - Canon_WBpresets(2,12); - fseek (ifp, save1+(0xa4<<1), SEEK_SET); - Canon_WBCTpresets (1); // ABCT - } - break; - case 796: - imgdata.makernotes.canon.CanonColorDataVer = 3; // 1DmkIIN / 5D / 30D / 400D - imgdata.makernotes.canon.CanonColorDataSubVer = get2(); - { - fseek (ifp, save1+(0x4e<<1), SEEK_SET); - Canon_WBpresets(2,12); - fseek (ifp, save1+(0x85<<1), SEEK_SET); - Canon_WBCTpresets (0); // BCAT - fseek (ifp, save1+(0x0c4<<1), SEEK_SET); // offset 196 short - int bls=0; - FORC4 - bls+= (imgdata.makernotes.canon.ChannelBlackLevel[c]=get2()); - imgdata.makernotes.canon.AverageBlackLevel = bls/4; - } - break; - // 1DmkIII / 1DSmkIII / 1DmkIV / 5DmkII - // 7D / 40D / 50D / 60D / 450D / 500D - // 550D / 1000D / 1100D - case 674: case 692: case 702: case 1227: case 1250: - case 1251: case 1337: case 1338: case 1346: - imgdata.makernotes.canon.CanonColorDataVer = 4; - imgdata.makernotes.canon.CanonColorDataSubVer = get2(); - { - fseek (ifp, save1+(0x53<<1), SEEK_SET); - Canon_WBpresets(2,12); - fseek (ifp, save1+(0xa8<<1), SEEK_SET); - Canon_WBCTpresets (0); // BCAT - fseek (ifp, save1+(0x0e7<<1), SEEK_SET); // offset 231 short - int bls=0; - FORC4 - bls+= (imgdata.makernotes.canon.ChannelBlackLevel[c]=get2()); - imgdata.makernotes.canon.AverageBlackLevel = bls/4; - } - if ((imgdata.makernotes.canon.CanonColorDataSubVer == 4) - || (imgdata.makernotes.canon.CanonColorDataSubVer == 5)) - { - fseek (ifp, save1+(0x2b9<<1), SEEK_SET); // offset 697 shorts - imgdata.makernotes.canon.SpecularWhiteLevel = get2(); - FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.canon.SpecularWhiteLevel; - } - else if ((imgdata.makernotes.canon.CanonColorDataSubVer == 6) || - (imgdata.makernotes.canon.CanonColorDataSubVer == 7)) - { - fseek (ifp, save1+(0x2d0<<1), SEEK_SET); // offset 720 shorts - imgdata.makernotes.canon.SpecularWhiteLevel = get2(); - FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.canon.SpecularWhiteLevel; - } - else if (imgdata.makernotes.canon.CanonColorDataSubVer == 9) - { - fseek (ifp, save1+(0x2d4<<1), SEEK_SET); // offset 724 shorts - imgdata.makernotes.canon.SpecularWhiteLevel = get2(); - FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.canon.SpecularWhiteLevel; - } - break; - - case 5120: - imgdata.makernotes.canon.CanonColorDataVer = 5; // PowerSot G10, G12, G5 X, EOS M3, EOS M5 - { - fseek (ifp, save1+(0x56<<1), SEEK_SET); - if ((unique_id == 0x03970000) || // G7 X Mark II - (unique_id == 0x80000394)) // EOS M5 - { - fseek(ifp, 18, SEEK_CUR); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Other][c ^ (c >> 1)] = get2(); - fseek(ifp, 8, SEEK_CUR); - Canon_WBpresets(8,24); - fseek(ifp, 168, SEEK_CUR); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][c ^ (c >> 1)] = get2(); - fseek(ifp, 24, SEEK_CUR); - Canon_WBCTpresets (2); // BCADT - fseek(ifp, 6, SEEK_CUR); - } - else - { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Other][c ^ (c >> 1)] = get2(); - get2(); - Canon_WBpresets(2,12); - fseek (ifp, save1+(0xba<<1), SEEK_SET); - Canon_WBCTpresets (2); // BCADT - fseek (ifp, save1+(0x108<<1), SEEK_SET); // offset 264 short - } - int bls=0; - FORC4 - bls+= (imgdata.makernotes.canon.ChannelBlackLevel[c]=get2()); - imgdata.makernotes.canon.AverageBlackLevel = bls/4; - } - break; + fseek(ifp, save1 + (0x1e << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + fseek(ifp, save1 + (0x41 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom1][c ^ (c >> 1)] = get2(); + fseek(ifp, save1 + (0x46 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom2][c ^ (c >> 1)] = get2(); + + fseek(ifp, save1 + (0x23 << 1), SEEK_SET); + Canon_WBpresets(2, 2); + fseek(ifp, save1 + (0x4b << 1), SEEK_SET); + Canon_WBCTpresets(1); // ABCT + } + break; + case 653: + imgdata.makernotes.canon.CanonColorDataVer = 2; // 1Dmk2 / 1DsMK2 + { + fseek(ifp, save1 + (0x18 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + fseek(ifp, save1 + (0x90 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom1][c ^ (c >> 1)] = get2(); + fseek(ifp, save1 + (0x95 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom2][c ^ (c >> 1)] = get2(); + fseek(ifp, save1 + (0x9a << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom3][c ^ (c >> 1)] = get2(); + + fseek(ifp, save1 + (0x27 << 1), SEEK_SET); + Canon_WBpresets(2, 12); + fseek(ifp, save1 + (0xa4 << 1), SEEK_SET); + Canon_WBCTpresets(1); // ABCT + } + break; + case 796: + imgdata.makernotes.canon.CanonColorDataVer = 3; // 1DmkIIN / 5D / 30D / 400D + imgdata.makernotes.canon.CanonColorDataSubVer = get2(); + { + fseek(ifp, save1 + (0x44 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + fseek(ifp, save1 + (0x49 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Measured][c ^ (c >> 1)] = get2(); + fseek(ifp, save1 + (0x71 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom1][c ^ (c >> 1)] = get2(); + fseek(ifp, save1 + (0x76 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom2][c ^ (c >> 1)] = get2(); + fseek(ifp, save1 + (0x7b << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom3][c ^ (c >> 1)] = get2(); + fseek(ifp, save1 + (0x80 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom][c ^ (c >> 1)] = get2(); + + fseek(ifp, save1 + (0x4e << 1), SEEK_SET); + Canon_WBpresets(2, 12); + fseek(ifp, save1 + (0x85 << 1), SEEK_SET); + Canon_WBCTpresets(0); // BCAT + fseek(ifp, save1 + (0x0c4 << 1), SEEK_SET); // offset 196 short + int bls = 0; + FORC4 + bls += (imgdata.makernotes.canon.ChannelBlackLevel[c] = get2()); + imgdata.makernotes.canon.AverageBlackLevel = bls / 4; + } + break; + // 1DmkIII / 1DSmkIII / 1DmkIV / 5DmkII + // 7D / 40D / 50D / 60D / 450D / 500D + // 550D / 1000D / 1100D + case 674: + case 692: + case 702: + case 1227: + case 1250: + case 1251: + case 1337: + case 1338: + case 1346: + imgdata.makernotes.canon.CanonColorDataVer = 4; + imgdata.makernotes.canon.CanonColorDataSubVer = get2(); + { + fseek(ifp, save1 + (0x44 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + fseek(ifp, save1 + (0x49 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Measured][c ^ (c >> 1)] = get2(); + + fseek(ifp, save1 + (0x53 << 1), SEEK_SET); + Canon_WBpresets(2, 12); + fseek(ifp, save1 + (0xa8 << 1), SEEK_SET); + Canon_WBCTpresets(0); // BCAT + fseek(ifp, save1 + (0x0e7 << 1), SEEK_SET); // offset 231 short + int bls = 0; + FORC4 + bls += (imgdata.makernotes.canon.ChannelBlackLevel[c] = get2()); + imgdata.makernotes.canon.AverageBlackLevel = bls / 4; + } + if ((imgdata.makernotes.canon.CanonColorDataSubVer == 4) || (imgdata.makernotes.canon.CanonColorDataSubVer == 5)) + { + fseek(ifp, save1 + (0x2b8 << 1), SEEK_SET); // offset 696 shorts + imgdata.makernotes.canon.NormalWhiteLevel = get2(); + imgdata.makernotes.canon.SpecularWhiteLevel = get2(); + FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.canon.SpecularWhiteLevel; + } + else if ((imgdata.makernotes.canon.CanonColorDataSubVer == 6) || + (imgdata.makernotes.canon.CanonColorDataSubVer == 7)) + { + fseek(ifp, save1 + (0x2cf << 1), SEEK_SET); // offset 719 shorts + imgdata.makernotes.canon.NormalWhiteLevel = get2(); + imgdata.makernotes.canon.SpecularWhiteLevel = get2(); + FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.canon.SpecularWhiteLevel; + } + else if (imgdata.makernotes.canon.CanonColorDataSubVer == 9) + { + fseek(ifp, save1 + (0x2d3 << 1), SEEK_SET); // offset 723 shorts + imgdata.makernotes.canon.NormalWhiteLevel = get2(); + imgdata.makernotes.canon.SpecularWhiteLevel = get2(); + FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.canon.SpecularWhiteLevel; + } + break; - case 1273: case 1275: - imgdata.makernotes.canon.CanonColorDataVer = 6; // 600D / 1200D - imgdata.makernotes.canon.CanonColorDataSubVer = get2(); - { - fseek (ifp, save1+(0x67<<1), SEEK_SET); - Canon_WBpresets(2,12); - fseek (ifp, save1+(0xbc<<1), SEEK_SET); - Canon_WBCTpresets (0); // BCAT - fseek (ifp, save1+(0x0fb<<1), SEEK_SET); // offset 251 short - int bls=0; - FORC4 - bls+= (imgdata.makernotes.canon.ChannelBlackLevel[c]=get2()); - imgdata.makernotes.canon.AverageBlackLevel = bls/4; - } - fseek (ifp, save1+(0x1e4<<1), SEEK_SET); // offset 484 shorts - imgdata.makernotes.canon.SpecularWhiteLevel = get2(); - FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.canon.SpecularWhiteLevel; - break; + case 5120: + imgdata.makernotes.canon.CanonColorDataVer = 5; // PowerSot G10, G12, G5 X, G7 X, G9 X, EOS M3, EOS M5, EOS M6 + { + if ((unique_id == 0x03970000) || // G7 X Mark II + (unique_id == 0x04100000) || // G9 X Mark II + (unique_id == 0x04180000) || // G1 X Mark III + (unique_id == 0x80000394) || // EOS M5 + (unique_id == 0x80000398) || // EOS M100 + (unique_id == 0x80000407)) // EOS M6 + { + fseek(ifp, save1 + (0x4f << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + fseek(ifp, 8, SEEK_CUR); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Measured][c ^ (c >> 1)] = get2(); + fseek(ifp, 8, SEEK_CUR); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Other][c ^ (c >> 1)] = get2(); + fseek(ifp, 8, SEEK_CUR); + Canon_WBpresets(8, 24); + fseek(ifp, 168, SEEK_CUR); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][c ^ (c >> 1)] = get2(); + fseek(ifp, 24, SEEK_CUR); + Canon_WBCTpresets(2); // BCADT + fseek(ifp, 6, SEEK_CUR); + } + else + { + fseek(ifp, save1 + (0x4c << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + get2(); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Measured][c ^ (c >> 1)] = get2(); + get2(); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Other][c ^ (c >> 1)] = get2(); + get2(); + Canon_WBpresets(2, 12); + fseek(ifp, save1 + (0xba << 1), SEEK_SET); + Canon_WBCTpresets(2); // BCADT + fseek(ifp, save1 + (0x108 << 1), SEEK_SET); // offset 264 short + } + int bls = 0; + FORC4 bls += (imgdata.makernotes.canon.ChannelBlackLevel[c] = get2()); + imgdata.makernotes.canon.AverageBlackLevel = bls / 4; + } + break; - // 1DX / 5DmkIII / 6D / 100D / 650D / 700D / EOS M / 7DmkII / 750D / 760D - case 1312: case 1313: case 1316: case 1506: - imgdata.makernotes.canon.CanonColorDataVer = 7; - imgdata.makernotes.canon.CanonColorDataSubVer = get2(); - { - fseek (ifp, save1+(0x80<<1), SEEK_SET); - Canon_WBpresets(2,12); - fseek (ifp, save1+(0xd5<<1), SEEK_SET); - Canon_WBCTpresets (0); // BCAT - fseek (ifp, save1+(0x114<<1), SEEK_SET); // offset 276 shorts - int bls=0; - FORC4 - bls+= (imgdata.makernotes.canon.ChannelBlackLevel[c]=get2()); - imgdata.makernotes.canon.AverageBlackLevel = bls/4; - } - if (imgdata.makernotes.canon.CanonColorDataSubVer == 10) - { - fseek (ifp, save1+(0x1fd<<1), SEEK_SET); // offset 509 shorts - imgdata.makernotes.canon.SpecularWhiteLevel = get2(); - FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.canon.SpecularWhiteLevel; - } else if (imgdata.makernotes.canon.CanonColorDataSubVer == 11) - { - fseek (ifp, save1+(0x2dd<<1), SEEK_SET); // offset 733 shorts - imgdata.makernotes.canon.SpecularWhiteLevel = get2(); - FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.canon.SpecularWhiteLevel; - } - break; + case 1273: + case 1275: + imgdata.makernotes.canon.CanonColorDataVer = 6; // 600D / 1200D + imgdata.makernotes.canon.CanonColorDataSubVer = get2(); + { + fseek(ifp, save1 + (0x44 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + fseek(ifp, save1 + (0x49 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Measured][c ^ (c >> 1)] = get2(); + + fseek(ifp, save1 + (0x67 << 1), SEEK_SET); + Canon_WBpresets(2, 12); + fseek(ifp, save1 + (0xbc << 1), SEEK_SET); + Canon_WBCTpresets(0); // BCAT + fseek(ifp, save1 + (0x0fb << 1), SEEK_SET); // offset 251 short + int bls = 0; + FORC4 + bls += (imgdata.makernotes.canon.ChannelBlackLevel[c] = get2()); + imgdata.makernotes.canon.AverageBlackLevel = bls / 4; + } + fseek(ifp, save1 + (0x1e3 << 1), SEEK_SET); // offset 483 shorts + imgdata.makernotes.canon.NormalWhiteLevel = get2(); + imgdata.makernotes.canon.SpecularWhiteLevel = get2(); + FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.canon.SpecularWhiteLevel; + break; - // 5DS / 5DS R / 80D / 1300D / 5D4 - case 1560: case 1592: case 1353: - imgdata.makernotes.canon.CanonColorDataVer = 8; - imgdata.makernotes.canon.CanonColorDataSubVer = get2(); - { - fseek (ifp, save1+(0x85<<1), SEEK_SET); - Canon_WBpresets(2,12); - fseek (ifp, save1+(0x107<<1), SEEK_SET); - Canon_WBCTpresets (0); // BCAT - fseek (ifp, save1+(0x146<<1), SEEK_SET); // offset 326 shorts - int bls=0; - FORC4 - bls+= (imgdata.makernotes.canon.ChannelBlackLevel[c]=get2()); - imgdata.makernotes.canon.AverageBlackLevel = bls/4; - } - if (imgdata.makernotes.canon.CanonColorDataSubVer == 14) // 1300D - { - fseek (ifp, save1+(0x231<<1), SEEK_SET); - imgdata.makernotes.canon.SpecularWhiteLevel = get2(); - FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.canon.SpecularWhiteLevel; - } - else - { - fseek (ifp, save1+(0x30f<<1), SEEK_SET); // offset 783 shorts - imgdata.makernotes.canon.SpecularWhiteLevel = get2(); - FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.canon.SpecularWhiteLevel; - } - break; + // 1DX / 5DmkIII / 6D / 100D / 650D / 700D / EOS M / 7DmkII / 750D / 760D + case 1312: + case 1313: + case 1316: + case 1506: + imgdata.makernotes.canon.CanonColorDataVer = 7; + imgdata.makernotes.canon.CanonColorDataSubVer = get2(); + { + fseek(ifp, save1 + (0x44 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + fseek(ifp, save1 + (0x49 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Measured][c ^ (c >> 1)] = get2(); + + fseek(ifp, save1 + (0x80 << 1), SEEK_SET); + Canon_WBpresets(2, 12); + fseek(ifp, save1 + (0xd5 << 1), SEEK_SET); + Canon_WBCTpresets(0); // BCAT + fseek(ifp, save1 + (0x114 << 1), SEEK_SET); // offset 276 shorts + int bls = 0; + FORC4 + bls += (imgdata.makernotes.canon.ChannelBlackLevel[c] = get2()); + imgdata.makernotes.canon.AverageBlackLevel = bls / 4; + } + if (imgdata.makernotes.canon.CanonColorDataSubVer == 10) + { + fseek(ifp, save1 + (0x1fc << 1), SEEK_SET); // offset 508 shorts + imgdata.makernotes.canon.NormalWhiteLevel = get2(); + imgdata.makernotes.canon.SpecularWhiteLevel = get2(); + FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.canon.SpecularWhiteLevel; + } + else if (imgdata.makernotes.canon.CanonColorDataSubVer == 11) + { + fseek(ifp, save1 + (0x2dc << 1), SEEK_SET); // offset 732 shorts + imgdata.makernotes.canon.NormalWhiteLevel = get2(); + imgdata.makernotes.canon.SpecularWhiteLevel = get2(); + FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.canon.SpecularWhiteLevel; + } + break; - } - fseek (ifp, save1, SEEK_SET); + // 5DS / 5DS R / 80D / 1300D / 5D4 / 800D / 77D / 6D II / 200D + case 1560: + case 1592: + case 1353: + case 1602: + imgdata.makernotes.canon.CanonColorDataVer = 8; + imgdata.makernotes.canon.CanonColorDataSubVer = get2(); + { + fseek(ifp, save1 + (0x44 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + fseek(ifp, save1 + (0x49 << 1), SEEK_SET); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Measured][c ^ (c >> 1)] = get2(); + + fseek(ifp, save1 + (0x85 << 1), SEEK_SET); + Canon_WBpresets(2, 12); + fseek(ifp, save1 + (0x107 << 1), SEEK_SET); + Canon_WBCTpresets(0); // BCAT + fseek(ifp, save1 + (0x146 << 1), SEEK_SET); // offset 326 shorts + int bls = 0; + FORC4 + bls += (imgdata.makernotes.canon.ChannelBlackLevel[c] = get2()); + imgdata.makernotes.canon.AverageBlackLevel = bls / 4; + } + if (imgdata.makernotes.canon.CanonColorDataSubVer == 14) // 1300D + { + fseek(ifp, save1 + (0x230 << 1), SEEK_SET); // offset 560 shorts + imgdata.makernotes.canon.NormalWhiteLevel = get2(); + imgdata.makernotes.canon.SpecularWhiteLevel = get2(); + FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.canon.SpecularWhiteLevel; + } + else + { + fseek(ifp, save1 + (0x30e << 1), SEEK_SET); // offset 782 shorts + imgdata.makernotes.canon.NormalWhiteLevel = get2(); + imgdata.makernotes.canon.SpecularWhiteLevel = get2(); + FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.canon.SpecularWhiteLevel; } + break; + } + fseek(ifp, save1, SEEK_SET); + } } -void CLASS setPentaxBodyFeatures (unsigned id) +void CLASS setPentaxBodyFeatures(unsigned id) { imgdata.lens.makernotes.CamID = id; - switch (id) { + switch (id) + { case 0x12994: case 0x12aa2: case 0x12b1a: case 0x12b60: case 0x12b62: case 0x12b7e: case 0x12b80: case 0x12b9c: case 0x12b9d: case 0x12ba2: case 0x12c1e: case 0x12c20: case 0x12cd2: case 0x12cd4: case 0x12cfa: case 0x12d72: case 0x12d73: case 0x12db8: case 0x12dfe: case 0x12e6c: case 0x12e76: case 0x12ef8: case 0x12f52: case 0x12f70: case 0x12f71: case 0x12fb6: case 0x12fc0: case 0x12fca: case 0x1301a: case 0x13024: case 0x1309c: case 0x13222: + case 0x1322c: imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Pentax_K; imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Pentax_K; imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_APSC; break; case 0x13092: imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Pentax_K; imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Pentax_K; imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_FF; break; case 0x12e08: case 0x13010: imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Pentax_645; imgdata.lens.makernotes.LensFormat = LIBRAW_FORMAT_MF; imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Pentax_645; imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_MF; break; case 0x12ee4: case 0x12f66: case 0x12f7a: case 0x1302e: imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Pentax_Q; imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Pentax_Q; break; default: imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; } return; } -void CLASS PentaxISO (ushort c) +void CLASS PentaxISO(ushort c) { - int code [] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 50, 100, 200, 400, 800, 1600, 3200, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278}; - double value [] = {50, 64, 80, 100, 125, 160, 200, 250, 320, 400, 500, 640, 800, 1000, 1250, 1600, 2000, 2500, 3200, 4000, 5000, 6400, 8000, 10000, 12800, 16000, 20000, 25600, 32000, 40000, 51200, 64000, 80000, 102400, 128000, 160000, 204800, 50, 100, 200, 400, 800, 1600, 3200, 50, 70, 100, 140, 200, 280, 400, 560, 800, 1100, 1600, 2200, 3200, 4500, 6400, 9000, 12800, 18000, 25600, 36000, 51200}; -#define numel (sizeof(code)/sizeof(code[0])) + int code[] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 50, 100, 200, 400, 800, 1600, 3200, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278}; + double value[] = {50, 64, 80, 100, 125, 160, 200, 250, 320, 400, 500, 640, + 800, 1000, 1250, 1600, 2000, 2500, 3200, 4000, 5000, 6400, 8000, 10000, + 12800, 16000, 20000, 25600, 32000, 40000, 51200, 64000, 80000, 102400, 128000, 160000, + 204800, 258000, 325000, 409600, 516000, 650000, 819200, 50, 100, 200, 400, 800, + 1600, 3200, 50, 70, 100, 140, 200, 280, 400, 560, 800, 1100, + 1600, 2200, 3200, 4500, 6400, 9000, 12800, 18000, 25600, 36000, 51200}; +#define numel (sizeof(code) / sizeof(code[0])) int i; - for (i = 0; i < numel; i++) { - if (code[i] == c) { + for (i = 0; i < numel; i++) + { + if (code[i] == c) + { iso_speed = value[i]; return; } } - if (i == numel) iso_speed = 65535.0f; + if (i == numel) + iso_speed = 65535.0f; } #undef numel -void CLASS PentaxLensInfo (unsigned id, unsigned len) // tag 0x0207 -{ - ushort iLensData = 0; - uchar *table_buf; - table_buf = (uchar*)malloc(MAX(len,128)); - fread(table_buf, len, 1, ifp); - if ((id < 0x12b9c) || - (((id == 0x12b9c) || // K100D - (id == 0x12b9d) || // K110D - (id == 0x12ba2)) && // K100D Super - ((!table_buf[20] || - (table_buf[20] == 0xff))))) - { - iLensData = 3; - if (imgdata.lens.makernotes.LensID == -1) - imgdata.lens.makernotes.LensID = - (((unsigned)table_buf[0]) << 8) + table_buf[1]; - } - else switch (len) - { - case 90: // LensInfo3 - iLensData = 13; - if (imgdata.lens.makernotes.LensID == -1) - imgdata.lens.makernotes.LensID = - ((unsigned)((table_buf[1] & 0x0f) + table_buf[3]) <<8) + table_buf[4]; - break; - case 91: // LensInfo4 - iLensData = 12; - if (imgdata.lens.makernotes.LensID == -1) - imgdata.lens.makernotes.LensID = - ((unsigned)((table_buf[1] & 0x0f) + table_buf[3]) <<8) + table_buf[4]; - break; - case 80: // LensInfo5 - case 128: - iLensData = 15; - if (imgdata.lens.makernotes.LensID == -1) - imgdata.lens.makernotes.LensID = - ((unsigned)((table_buf[1] & 0x0f) + table_buf[4]) <<8) + table_buf[5]; - break; - default: - if (id >= 0x12b9c) // LensInfo2 - { - iLensData = 4; - if (imgdata.lens.makernotes.LensID == -1) - imgdata.lens.makernotes.LensID = - ((unsigned)((table_buf[0] & 0x0f) + table_buf[2]) <<8) + table_buf[3]; - } - } - if (iLensData) - { - if (table_buf[iLensData+9] && - (fabs(imgdata.lens.makernotes.CurFocal) < 0.1f)) - imgdata.lens.makernotes.CurFocal = - 10*(table_buf[iLensData+9]>>2) * libraw_powf64(4, (table_buf[iLensData+9] & 0x03)-2); - if (table_buf[iLensData+10] & 0xf0) - imgdata.lens.makernotes.MaxAp4CurFocal = - libraw_powf64(2.0f, (float)((table_buf[iLensData+10] & 0xf0) >>4)/4.0f); - if (table_buf[iLensData+10] & 0x0f) - imgdata.lens.makernotes.MinAp4CurFocal = - libraw_powf64(2.0f, (float)((table_buf[iLensData+10] & 0x0f) + 10)/4.0f); - - if (iLensData != 12) - { - switch (table_buf[iLensData] & 0x06) - { - case 0: imgdata.lens.makernotes.MinAp4MinFocal = 22.0f; break; - case 2: imgdata.lens.makernotes.MinAp4MinFocal = 32.0f; break; - case 4: imgdata.lens.makernotes.MinAp4MinFocal = 45.0f; break; - case 6: imgdata.lens.makernotes.MinAp4MinFocal = 16.0f; break; - } - if (table_buf[iLensData] & 0x70) - imgdata.lens.makernotes.LensFStops = - ((float)(((table_buf[iLensData] & 0x70) >> 4) ^ 0x07)) / 2.0f + 5.0f; +void CLASS PentaxLensInfo(unsigned id, unsigned len) // tag 0x0207 +{ + ushort iLensData = 0; + uchar *table_buf; + table_buf = (uchar *)malloc(MAX(len, 128)); + fread(table_buf, len, 1, ifp); + if ((id < 0x12b9c) || (((id == 0x12b9c) || // K100D + (id == 0x12b9d) || // K110D + (id == 0x12ba2)) && // K100D Super + ((!table_buf[20] || (table_buf[20] == 0xff))))) + { + iLensData = 3; + if (imgdata.lens.makernotes.LensID == -1) + imgdata.lens.makernotes.LensID = (((unsigned)table_buf[0]) << 8) + table_buf[1]; + } + else + switch (len) + { + case 90: // LensInfo3 + iLensData = 13; + if (imgdata.lens.makernotes.LensID == -1) + imgdata.lens.makernotes.LensID = ((unsigned)((table_buf[1] & 0x0f) + table_buf[3]) << 8) + table_buf[4]; + break; + case 91: // LensInfo4 + iLensData = 12; + if (imgdata.lens.makernotes.LensID == -1) + imgdata.lens.makernotes.LensID = ((unsigned)((table_buf[1] & 0x0f) + table_buf[3]) << 8) + table_buf[4]; + break; + case 80: // LensInfo5 + case 128: + iLensData = 15; + if (imgdata.lens.makernotes.LensID == -1) + imgdata.lens.makernotes.LensID = ((unsigned)((table_buf[1] & 0x0f) + table_buf[4]) << 8) + table_buf[5]; + break; + default: + if (id >= 0x12b9c) // LensInfo2 + { + iLensData = 4; + if (imgdata.lens.makernotes.LensID == -1) + imgdata.lens.makernotes.LensID = ((unsigned)((table_buf[0] & 0x0f) + table_buf[2]) << 8) + table_buf[3]; + } + } + if (iLensData) + { + if (table_buf[iLensData + 9] && (fabs(imgdata.lens.makernotes.CurFocal) < 0.1f)) + imgdata.lens.makernotes.CurFocal = + 10 * (table_buf[iLensData + 9] >> 2) * libraw_powf64l(4, (table_buf[iLensData + 9] & 0x03) - 2); + if (table_buf[iLensData + 10] & 0xf0) + imgdata.lens.makernotes.MaxAp4CurFocal = + libraw_powf64l(2.0f, (float)((table_buf[iLensData + 10] & 0xf0) >> 4) / 4.0f); + if (table_buf[iLensData + 10] & 0x0f) + imgdata.lens.makernotes.MinAp4CurFocal = + libraw_powf64l(2.0f, (float)((table_buf[iLensData + 10] & 0x0f) + 10) / 4.0f); + + if (iLensData != 12) + { + switch (table_buf[iLensData] & 0x06) + { + case 0: + imgdata.lens.makernotes.MinAp4MinFocal = 22.0f; + break; + case 2: + imgdata.lens.makernotes.MinAp4MinFocal = 32.0f; + break; + case 4: + imgdata.lens.makernotes.MinAp4MinFocal = 45.0f; + break; + case 6: + imgdata.lens.makernotes.MinAp4MinFocal = 16.0f; + break; + } + if (table_buf[iLensData] & 0x70) + imgdata.lens.makernotes.LensFStops = ((float)(((table_buf[iLensData] & 0x70) >> 4) ^ 0x07)) / 2.0f + 5.0f; - imgdata.lens.makernotes.MinFocusDistance = (float)(table_buf[iLensData+3] & 0xf8); - imgdata.lens.makernotes.FocusRangeIndex = (float)(table_buf[iLensData+3] & 0x07); + imgdata.lens.makernotes.MinFocusDistance = (float)(table_buf[iLensData + 3] & 0xf8); + imgdata.lens.makernotes.FocusRangeIndex = (float)(table_buf[iLensData + 3] & 0x07); - if ((table_buf[iLensData+14] > 1) && - (fabs(imgdata.lens.makernotes.MaxAp4CurFocal) < 0.7f)) - imgdata.lens.makernotes.MaxAp4CurFocal = - libraw_powf64(2.0f, (float)((table_buf[iLensData+14] & 0x7f) -1)/32.0f); - } - else if ((id != 0x12e76) && // K-5 - (table_buf[iLensData+15] > 1) && - (fabs(imgdata.lens.makernotes.MaxAp4CurFocal) < 0.7f)) - { - imgdata.lens.makernotes.MaxAp4CurFocal = - libraw_powf64(2.0f, (float)((table_buf[iLensData+15] & 0x7f) -1)/32.0f); - } - } - free(table_buf); - return; + if ((table_buf[iLensData + 14] > 1) && (fabs(imgdata.lens.makernotes.MaxAp4CurFocal) < 0.7f)) + imgdata.lens.makernotes.MaxAp4CurFocal = + libraw_powf64l(2.0f, (float)((table_buf[iLensData + 14] & 0x7f) - 1) / 32.0f); + } + else if ((id != 0x12e76) && // K-5 + (table_buf[iLensData + 15] > 1) && (fabs(imgdata.lens.makernotes.MaxAp4CurFocal) < 0.7f)) + { + imgdata.lens.makernotes.MaxAp4CurFocal = + libraw_powf64l(2.0f, (float)((table_buf[iLensData + 15] & 0x7f) - 1) / 32.0f); + } + } + free(table_buf); + return; } -void CLASS setPhaseOneFeatures (unsigned id) { +void CLASS setPhaseOneFeatures(unsigned id) +{ ushort i; - static const struct { + static const struct + { ushort id; char t_model[32]; } p1_unique[] = { - // Phase One section: - {1, "Hasselblad V"}, - {10, "PhaseOne/Mamiya"}, - {12, "Contax 645"}, - {16, "Hasselblad V"}, - {17, "Hasselblad V"}, - {18, "Contax 645"}, - {19, "PhaseOne/Mamiya"}, - {20, "Hasselblad V"}, - {21, "Contax 645"}, - {22, "PhaseOne/Mamiya"}, - {23, "Hasselblad V"}, - {24, "Hasselblad H"}, - {25, "PhaseOne/Mamiya"}, - {32, "Contax 645"}, - {34, "Hasselblad V"}, - {35, "Hasselblad V"}, - {36, "Hasselblad H"}, - {37, "Contax 645"}, - {38, "PhaseOne/Mamiya"}, - {39, "Hasselblad V"}, - {40, "Hasselblad H"}, - {41, "Contax 645"}, - {42, "PhaseOne/Mamiya"}, - {44, "Hasselblad V"}, - {45, "Hasselblad H"}, - {46, "Contax 645"}, - {47, "PhaseOne/Mamiya"}, - {48, "Hasselblad V"}, - {49, "Hasselblad H"}, - {50, "Contax 645"}, - {51, "PhaseOne/Mamiya"}, - {52, "Hasselblad V"}, - {53, "Hasselblad H"}, - {54, "Contax 645"}, - {55, "PhaseOne/Mamiya"}, - {67, "Hasselblad V"}, - {68, "Hasselblad H"}, - {69, "Contax 645"}, - {70, "PhaseOne/Mamiya"}, - {71, "Hasselblad V"}, - {72, "Hasselblad H"}, - {73, "Contax 645"}, - {74, "PhaseOne/Mamiya"}, - {76, "Hasselblad V"}, - {77, "Hasselblad H"}, - {78, "Contax 645"}, - {79, "PhaseOne/Mamiya"}, - {80, "Hasselblad V"}, - {81, "Hasselblad H"}, - {82, "Contax 645"}, - {83, "PhaseOne/Mamiya"}, - {84, "Hasselblad V"}, - {85, "Hasselblad H"}, - {86, "Contax 645"}, - {87, "PhaseOne/Mamiya"}, - {99, "Hasselblad V"}, - {100, "Hasselblad H"}, - {101, "Contax 645"}, - {102, "PhaseOne/Mamiya"}, - {103, "Hasselblad V"}, - {104, "Hasselblad H"}, - {105, "PhaseOne/Mamiya"}, - {106, "Contax 645"}, - {112, "Hasselblad V"}, - {113, "Hasselblad H"}, - {114, "Contax 645"}, - {115, "PhaseOne/Mamiya"}, - {131, "Hasselblad V"}, - {132, "Hasselblad H"}, - {133, "Contax 645"}, - {134, "PhaseOne/Mamiya"}, - {135, "Hasselblad V"}, - {136, "Hasselblad H"}, - {137, "Contax 645"}, - {138, "PhaseOne/Mamiya"}, - {140, "Hasselblad V"}, - {141, "Hasselblad H"}, - {142, "Contax 645"}, - {143, "PhaseOne/Mamiya"}, - {148, "Hasselblad V"}, - {149, "Hasselblad H"}, - {150, "Contax 645"}, - {151, "PhaseOne/Mamiya"}, - {160, "A-250"}, - {161, "A-260"}, - {162, "A-280"}, - {167, "Hasselblad V"}, - {168, "Hasselblad H"}, - {169, "Contax 645"}, - {170, "PhaseOne/Mamiya"}, - {172, "Hasselblad V"}, - {173, "Hasselblad H"}, - {174, "Contax 645"}, - {175, "PhaseOne/Mamiya"}, - {176, "Hasselblad V"}, - {177, "Hasselblad H"}, - {178, "Contax 645"}, - {179, "PhaseOne/Mamiya"}, - {180, "Hasselblad V"}, - {181, "Hasselblad H"}, - {182, "Contax 645"}, - {183, "PhaseOne/Mamiya"}, - {208, "Hasselblad V"}, - {211, "PhaseOne/Mamiya"}, - {448, "Phase One 645AF"}, - {457, "Phase One 645DF"}, - {471, "Phase One 645DF+"}, - {704, "Phase One iXA"}, - {705, "Phase One iXA - R"}, - {706, "Phase One iXU 150"}, - {707, "Phase One iXU 150 - NIR"}, - {708, "Phase One iXU 180"}, - {721, "Phase One iXR"}, - // Leaf section: - {333,"Mamiya"}, - {329,"Universal"}, - {330,"Hasselblad H1/H2"}, - {332,"Contax"}, - {336,"AFi"}, - {327,"Mamiya"}, - {324,"Universal"}, - {325,"Hasselblad H1/H2"}, - {326,"Contax"}, - {335,"AFi"}, - {340,"Mamiya"}, - {337,"Universal"}, - {338,"Hasselblad H1/H2"}, - {339,"Contax"}, - {323,"Mamiya"}, - {320,"Universal"}, - {322,"Hasselblad H1/H2"}, - {321,"Contax"}, - {334,"AFi"}, - {369,"Universal"}, - {370,"Mamiya"}, - {371,"Hasselblad H1/H2"}, - {372,"Contax"}, - {373,"Afi"}, + // Phase One section: + {1, "Hasselblad V"}, + {10, "PhaseOne/Mamiya"}, + {12, "Contax 645"}, + {16, "Hasselblad V"}, + {17, "Hasselblad V"}, + {18, "Contax 645"}, + {19, "PhaseOne/Mamiya"}, + {20, "Hasselblad V"}, + {21, "Contax 645"}, + {22, "PhaseOne/Mamiya"}, + {23, "Hasselblad V"}, + {24, "Hasselblad H"}, + {25, "PhaseOne/Mamiya"}, + {32, "Contax 645"}, + {34, "Hasselblad V"}, + {35, "Hasselblad V"}, + {36, "Hasselblad H"}, + {37, "Contax 645"}, + {38, "PhaseOne/Mamiya"}, + {39, "Hasselblad V"}, + {40, "Hasselblad H"}, + {41, "Contax 645"}, + {42, "PhaseOne/Mamiya"}, + {44, "Hasselblad V"}, + {45, "Hasselblad H"}, + {46, "Contax 645"}, + {47, "PhaseOne/Mamiya"}, + {48, "Hasselblad V"}, + {49, "Hasselblad H"}, + {50, "Contax 645"}, + {51, "PhaseOne/Mamiya"}, + {52, "Hasselblad V"}, + {53, "Hasselblad H"}, + {54, "Contax 645"}, + {55, "PhaseOne/Mamiya"}, + {67, "Hasselblad V"}, + {68, "Hasselblad H"}, + {69, "Contax 645"}, + {70, "PhaseOne/Mamiya"}, + {71, "Hasselblad V"}, + {72, "Hasselblad H"}, + {73, "Contax 645"}, + {74, "PhaseOne/Mamiya"}, + {76, "Hasselblad V"}, + {77, "Hasselblad H"}, + {78, "Contax 645"}, + {79, "PhaseOne/Mamiya"}, + {80, "Hasselblad V"}, + {81, "Hasselblad H"}, + {82, "Contax 645"}, + {83, "PhaseOne/Mamiya"}, + {84, "Hasselblad V"}, + {85, "Hasselblad H"}, + {86, "Contax 645"}, + {87, "PhaseOne/Mamiya"}, + {99, "Hasselblad V"}, + {100, "Hasselblad H"}, + {101, "Contax 645"}, + {102, "PhaseOne/Mamiya"}, + {103, "Hasselblad V"}, + {104, "Hasselblad H"}, + {105, "PhaseOne/Mamiya"}, + {106, "Contax 645"}, + {112, "Hasselblad V"}, + {113, "Hasselblad H"}, + {114, "Contax 645"}, + {115, "PhaseOne/Mamiya"}, + {131, "Hasselblad V"}, + {132, "Hasselblad H"}, + {133, "Contax 645"}, + {134, "PhaseOne/Mamiya"}, + {135, "Hasselblad V"}, + {136, "Hasselblad H"}, + {137, "Contax 645"}, + {138, "PhaseOne/Mamiya"}, + {140, "Hasselblad V"}, + {141, "Hasselblad H"}, + {142, "Contax 645"}, + {143, "PhaseOne/Mamiya"}, + {148, "Hasselblad V"}, + {149, "Hasselblad H"}, + {150, "Contax 645"}, + {151, "PhaseOne/Mamiya"}, + {160, "A-250"}, + {161, "A-260"}, + {162, "A-280"}, + {167, "Hasselblad V"}, + {168, "Hasselblad H"}, + {169, "Contax 645"}, + {170, "PhaseOne/Mamiya"}, + {172, "Hasselblad V"}, + {173, "Hasselblad H"}, + {174, "Contax 645"}, + {175, "PhaseOne/Mamiya"}, + {176, "Hasselblad V"}, + {177, "Hasselblad H"}, + {178, "Contax 645"}, + {179, "PhaseOne/Mamiya"}, + {180, "Hasselblad V"}, + {181, "Hasselblad H"}, + {182, "Contax 645"}, + {183, "PhaseOne/Mamiya"}, + {208, "Hasselblad V"}, + {211, "PhaseOne/Mamiya"}, + {448, "Phase One 645AF"}, + {457, "Phase One 645DF"}, + {471, "Phase One 645DF+"}, + {704, "Phase One iXA"}, + {705, "Phase One iXA - R"}, + {706, "Phase One iXU 150"}, + {707, "Phase One iXU 150 - NIR"}, + {708, "Phase One iXU 180"}, + {721, "Phase One iXR"}, + // Leaf section: + {333, "Mamiya"}, + {329, "Universal"}, + {330, "Hasselblad H1/H2"}, + {332, "Contax"}, + {336, "AFi"}, + {327, "Mamiya"}, + {324, "Universal"}, + {325, "Hasselblad H1/H2"}, + {326, "Contax"}, + {335, "AFi"}, + {340, "Mamiya"}, + {337, "Universal"}, + {338, "Hasselblad H1/H2"}, + {339, "Contax"}, + {323, "Mamiya"}, + {320, "Universal"}, + {322, "Hasselblad H1/H2"}, + {321, "Contax"}, + {334, "AFi"}, + {369, "Universal"}, + {370, "Mamiya"}, + {371, "Hasselblad H1/H2"}, + {372, "Contax"}, + {373, "Afi"}, }; imgdata.lens.makernotes.CamID = id; - if (id && !imgdata.lens.makernotes.body[0]) { - for (i=0; i < sizeof p1_unique / sizeof *p1_unique; i++) - if (id == p1_unique[i].id) { - strcpy(imgdata.lens.makernotes.body,p1_unique[i].t_model); + if (id && !imgdata.lens.makernotes.body[0]) + { + for (i = 0; i < sizeof p1_unique / sizeof *p1_unique; i++) + if (id == p1_unique[i].id) + { + strcpy(imgdata.lens.makernotes.body, p1_unique[i].t_model); } } return; } -void CLASS parseFujiMakernotes (unsigned tag, unsigned type) { - switch (tag) { - case 0x1002: imgdata.makernotes.fuji.WB_Preset = get2(); break; - case 0x1011: imgdata.other.FlashEC = getreal(type); break; - case 0x1020: imgdata.makernotes.fuji.Macro = get2(); break; - case 0x1021: imgdata.makernotes.fuji.FocusMode = get2(); break; - case 0x1022: imgdata.makernotes.fuji.AFMode = get2(); break; - case 0x1023: imgdata.makernotes.fuji.FocusPixel[0] = get2(); - imgdata.makernotes.fuji.FocusPixel[1] = get2(); - break; - case 0x1034: imgdata.makernotes.fuji.ExrMode = get2(); break; - case 0x1050: imgdata.makernotes.fuji.ShutterType = get2(); break; - case 0x1400: imgdata.makernotes.fuji.FujiDynamicRange = get2(); break; - case 0x1401: imgdata.makernotes.fuji.FujiFilmMode = get2(); break; - case 0x1402: imgdata.makernotes.fuji.FujiDynamicRangeSetting = get2(); break; - case 0x1403: imgdata.makernotes.fuji.FujiDevelopmentDynamicRange = get2(); break; - case 0x140b: imgdata.makernotes.fuji.FujiAutoDynamicRange = get2(); break; - case 0x1404: imgdata.lens.makernotes.MinFocal = getreal(type); break; - case 0x1405: imgdata.lens.makernotes.MaxFocal = getreal(type); break; - case 0x1406: imgdata.lens.makernotes.MaxAp4MinFocal = getreal(type); break; - case 0x1407: imgdata.lens.makernotes.MaxAp4MaxFocal = getreal(type); break; - case 0x1422: imgdata.makernotes.fuji.ImageStabilization[0] = get2(); - imgdata.makernotes.fuji.ImageStabilization[1] = get2(); - imgdata.makernotes.fuji.ImageStabilization[2] = get2(); - imgdata.shootinginfo.ImageStabilization = (imgdata.makernotes.fuji.ImageStabilization[0]<<9) + imgdata.makernotes.fuji.ImageStabilization[1]; - break; - case 0x1431: imgdata.makernotes.fuji.Rating = get4(); break; - case 0x3820: imgdata.makernotes.fuji.FrameRate = get2(); break; - case 0x3821: imgdata.makernotes.fuji.FrameWidth = get2(); break; - case 0x3822: imgdata.makernotes.fuji.FrameHeight = get2(); break; - } -return; -} - -void CLASS setSonyBodyFeatures (unsigned id) { +void CLASS parseFujiMakernotes(unsigned tag, unsigned type) +{ + switch (tag) + { + case 0x1002: + imgdata.makernotes.fuji.WB_Preset = get2(); + break; + case 0x1011: + imgdata.other.FlashEC = getreal(type); + break; + case 0x1020: + imgdata.makernotes.fuji.Macro = get2(); + break; + case 0x1021: + imgdata.makernotes.fuji.FocusMode = get2(); + break; + case 0x1022: + imgdata.makernotes.fuji.AFMode = get2(); + break; + case 0x1023: + imgdata.makernotes.fuji.FocusPixel[0] = get2(); + imgdata.makernotes.fuji.FocusPixel[1] = get2(); + break; + case 0x1034: + imgdata.makernotes.fuji.ExrMode = get2(); + break; + case 0x1050: + imgdata.makernotes.fuji.ShutterType = get2(); + break; + case 0x1400: + imgdata.makernotes.fuji.FujiDynamicRange = get2(); + break; + case 0x1401: + imgdata.makernotes.fuji.FujiFilmMode = get2(); + break; + case 0x1402: + imgdata.makernotes.fuji.FujiDynamicRangeSetting = get2(); + break; + case 0x1403: + imgdata.makernotes.fuji.FujiDevelopmentDynamicRange = get2(); + break; + case 0x140b: + imgdata.makernotes.fuji.FujiAutoDynamicRange = get2(); + break; + case 0x1404: + imgdata.lens.makernotes.MinFocal = getreal(type); + break; + case 0x1405: + imgdata.lens.makernotes.MaxFocal = getreal(type); + break; + case 0x1406: + imgdata.lens.makernotes.MaxAp4MinFocal = getreal(type); + break; + case 0x1407: + imgdata.lens.makernotes.MaxAp4MaxFocal = getreal(type); + break; + case 0x1422: + imgdata.makernotes.fuji.ImageStabilization[0] = get2(); + imgdata.makernotes.fuji.ImageStabilization[1] = get2(); + imgdata.makernotes.fuji.ImageStabilization[2] = get2(); + imgdata.shootinginfo.ImageStabilization = + (imgdata.makernotes.fuji.ImageStabilization[0] << 9) + imgdata.makernotes.fuji.ImageStabilization[1]; + break; + case 0x1431: + imgdata.makernotes.fuji.Rating = get4(); + break; + case 0x3820: + imgdata.makernotes.fuji.FrameRate = get2(); + break; + case 0x3821: + imgdata.makernotes.fuji.FrameWidth = get2(); + break; + case 0x3822: + imgdata.makernotes.fuji.FrameHeight = get2(); + break; + } + return; +} +void CLASS setSonyBodyFeatures(unsigned id) +{ + ushort idx; + static const struct + { + ushort scf[8]; + /* + scf[0] camera id + scf[1] camera format + scf[2] camera mount: Minolta A, Sony E, fixed, + scf[3] camera type: DSLR, NEX, SLT, ILCE, ILCA, DSC + scf[4] lens mount + scf[5] tag 0x2010 group (0 if not used) + scf[6] offset of Sony ISO in 0x2010 table, 0xffff if not valid + scf[7] offset of ImageCount3 in 0x9050 table, 0xffff if not valid + */ + } SonyCamFeatures[] = { + {256, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {257, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {258, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {259, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {260, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {261, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {262, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {263, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {264, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {265, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {266, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {267, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {268, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {269, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {270, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {271, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {272, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {273, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {274, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {275, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {276, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {277, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {278, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, 0, 0, 0xffff, 0xffff}, + {279, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, 0, 0, 0xffff, 0xffff}, + {280, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, 0, 0, 0xffff, 0xffff}, + {281, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, 0, 0, 0xffff, 0xffff}, + {282, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {283, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_DSLR, 0, 0, 0xffff, 0xffff}, + {284, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, 0, 0, 0xffff, 0xffff}, + {285, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, 0, 0, 0xffff, 0xffff}, + {286, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, 0, 2, 0x1218, 0x01bd}, + {287, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, 0, 2, 0x1218, 0x01bd}, + {288, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, 0, 1, 0x113e, 0x01bd}, + {289, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, 0, 2, 0x1218, 0x01bd}, + {290, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, 0, 2, 0x1218, 0x01bd}, + {291, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, 0, 3, 0x11f4, 0x01bd}, + {292, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, 0, 3, 0x11f4, 0x01bd}, + {293, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, 0, 3, 0x11f4, 0x01bd}, + {294, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, 0, 5, 0x1254, 0x01aa}, + {295, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, 0, 5, 0x1254, 0x01aa}, + {296, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, 0, 5, 0x1254, 0x01aa}, + {297, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens, 5, 0x1254, 0xffff}, + {298, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens, 5, 0x1258, 0xffff}, + {299, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, 0, 5, 0x1254, 0x01aa}, + {300, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, 0, 5, 0x1254, 0x01aa}, + {301, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {302, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, 0, 5, 0x1280, 0x01aa}, + {303, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_SLT, 0, 5, 0x1280, 0x01aa}, + {304, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {305, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, 0, 5, 0x1280, 0x01aa}, + {306, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, 0, 7, 0x0344, 0xffff}, + {307, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_NEX, 0, 5, 0x1254, 0x01aa}, + {308, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens, 6, 0x113c, 0xffff}, + {309, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens, 7, 0x0344, 0xffff}, + {310, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens, 5, 0x1258, 0xffff}, + {311, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, 0, 7, 0x0344, 0xffff}, + {312, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, 0, 7, 0x0344, 0xffff}, + {313, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, 0, 7, 0x0344, 0x01aa}, + {314, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {315, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {316, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {317, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens, 7, 0x0344, 0xffff}, + {318, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, 0, 7, 0x0344, 0xffff}, + {319, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_ILCA, 0, 7, 0x0344, 0x01a0}, + {320, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {321, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {322, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {323, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {324, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {325, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {326, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {327, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {328, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {329, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {330, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {331, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {332, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {333, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {334, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {335, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {336, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {337, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {338, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {339, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, 0, 7, 0x0344, 0x01a0}, + {340, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, 0, 7, 0x0344, 0xffff}, + {341, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens, 8, 0x0346, 0xffff}, + {342, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens, 8, 0x0346, 0xffff}, + {343, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {344, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens, 8, 0x0346, 0xffff}, + {345, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {346, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, 0, 7, 0x0344, 0x01a0}, + {347, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, 0, 8, 0x0346, 0x01cb}, + {348, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {349, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {350, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, 0, 8, 0x0346, 0x01cb}, + {351, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {352, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {353, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_ILCA, 0, 7, 0x0344, 0x01a0}, + {354, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Minolta_A, LIBRAW_SONY_ILCA, 0, 8, 0x0346, 0x01cd}, + {355, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens, 8, 0x0346, 0xffff}, + {356, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens, 8, 0x0346, 0xffff}, + {357, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, 0, 8, 0x0346, 0x01cd}, + {358, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, 0, 9, 0x0320, 0x019f}, + {359, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {360, LIBRAW_FORMAT_APSC, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, 0, 8, 0x0346, 0x01cd}, + {361, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {362, LIBRAW_FORMAT_FF, LIBRAW_MOUNT_Sony_E, LIBRAW_SONY_ILCE, 0, 9, 0x0320, 0x019f}, + {363, 0, 0, 0, 0, 0, 0xffff, 0xffff}, + {364, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens, 8, 0x0346, 0xffff}, + {365, LIBRAW_FORMAT_1INCH, LIBRAW_MOUNT_FixedLens, LIBRAW_SONY_DSC, LIBRAW_MOUNT_FixedLens, 9, 0x0320, 0xffff}, + }; imgdata.lens.makernotes.CamID = id; - if ( // FF cameras - (id == 257) || // a900 - (id == 269) || // a850 - (id == 340) || // ILCE-7M2 - (id == 318) || // ILCE-7S - (id == 350) || // ILCE-7SM2 - (id == 311) || // ILCE-7R - (id == 347) || // ILCE-7RM2 - (id == 306) || // ILCE-7 - (id == 298) || // DSC-RX1 - (id == 299) || // NEX-VG900 - (id == 310) || // DSC-RX1R - (id == 344) || // DSC-RX1RM2 - (id == 354) || // ILCA-99M2 - (id == 294) // SLT-99, Hasselblad HV - ) + + if (id == 2) + { + imgdata.lens.makernotes.CameraMount = imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; + imgdata.makernotes.sony.SonyCameraType = LIBRAW_SONY_DSC; + imgdata.makernotes.sony.group2010 = 0; + imgdata.makernotes.sony.real_iso_offset = 0xffff; + imgdata.makernotes.sony.ImageCount3_offset = 0xffff; + return; + } + else + idx = id - 256; + + if ((idx >= 0) && (idx < sizeof SonyCamFeatures / sizeof *SonyCamFeatures)) + { + if (!SonyCamFeatures[idx].scf[2]) + return; + imgdata.lens.makernotes.CameraFormat = SonyCamFeatures[idx].scf[1]; + imgdata.lens.makernotes.CameraMount = SonyCamFeatures[idx].scf[2]; + imgdata.makernotes.sony.SonyCameraType = SonyCamFeatures[idx].scf[3]; + if (SonyCamFeatures[idx].scf[4]) + imgdata.lens.makernotes.LensMount = SonyCamFeatures[idx].scf[4]; + imgdata.makernotes.sony.group2010 = SonyCamFeatures[idx].scf[5]; + imgdata.makernotes.sony.real_iso_offset = SonyCamFeatures[idx].scf[6]; + imgdata.makernotes.sony.ImageCount3_offset = SonyCamFeatures[idx].scf[7]; + } + + char *sbstr = strstr(software, " v"); + if (sbstr != NULL) + { + sbstr += 2; + imgdata.makernotes.sony.firmware = atof(sbstr); + + if ((id == 306) || (id == 311)) { - imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_FF; + if (imgdata.makernotes.sony.firmware < 1.2f) + imgdata.makernotes.sony.ImageCount3_offset = 0x01aa; + else + imgdata.makernotes.sony.ImageCount3_offset = 0x01c0; } - else if ((id == 297) || // DSC-RX100 - (id == 308) || // DSC-RX100M2 - (id == 309) || // DSC-RX10 - (id == 317) || // DSC-RX100M3 - (id == 341) || // DSC-RX100M4 - (id == 342) || // DSC-RX10M2 - (id == 355) || // DSC-RX10M3 - (id == 356) // DSC-RX100M5 - ) - { - imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_1INCH; - } - - else if (id != 002) // DSC-R1 - { - imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_APSC; - } - - if ( // E-mount cameras, ILCE series - (id == 302) || - (id == 306) || - (id == 311) || - (id == 312) || - (id == 313) || - (id == 318) || - (id == 339) || - (id == 340) || - (id == 346) || - (id == 347) || - (id == 350) || - (id == 360) - ) - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Sony_E; - imgdata.makernotes.sony.SonyCameraType = LIBRAW_SONY_ILCE; - } - else if ( // E-mount cameras, NEX series - (id == 278) || - (id == 279) || - (id == 284) || - (id == 288) || - (id == 289) || - (id == 290) || - (id == 293) || - (id == 295) || - (id == 296) || - (id == 299) || - (id == 300) || - (id == 305) || - (id == 307) - ) - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Sony_E; - imgdata.makernotes.sony.SonyCameraType = LIBRAW_SONY_NEX; - } - - else if ( // A-mount cameras, DSLR series - (id == 256) || - (id == 257) || - (id == 258) || - (id == 259) || - (id == 260) || - (id == 261) || - (id == 262) || - (id == 263) || - (id == 264) || - (id == 265) || - (id == 266) || - (id == 269) || - (id == 270) || - (id == 273) || - (id == 274) || - (id == 275) || - (id == 282) || - (id == 283) - ) - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Minolta_A; - imgdata.makernotes.sony.SonyCameraType = LIBRAW_SONY_DSLR; - } - else if ( // A-mount cameras, SLT series - (id == 280) || - (id == 281) || - (id == 285) || - (id == 286) || - (id == 287) || - (id == 291) || - (id == 292) || - (id == 294) || - (id == 303) - ) + else if (id == 312) { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Minolta_A; - imgdata.makernotes.sony.SonyCameraType = LIBRAW_SONY_SLT; + if (imgdata.makernotes.sony.firmware < 2.0f) + imgdata.makernotes.sony.ImageCount3_offset = 0x01aa; + else + imgdata.makernotes.sony.ImageCount3_offset = 0x01c0; } - else if ( // A-mount cameras, ILCA series - (id == 319) || - (id == 353) || - (id == 354) - ) - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Minolta_A; - imgdata.makernotes.sony.SonyCameraType = LIBRAW_SONY_ILCA; - } - - else if ( // DSC - (id == 002) || // DSC-R1 - (id == 297) || // DSC-RX100 - (id == 298) || // DSC-RX1 - (id == 308) || // DSC-RX100M2 - (id == 309) || // DSC-RX10 - (id == 310) || // DSC-RX1R - (id == 344) || // DSC-RX1RM2 - (id == 317) || // DSC-RX100M3 - (id == 341) || // DSC-RX100M4 - (id == 342) || // DSC-RX10M2 - (id == 355) || // DSC-RX10M3 - (id == 356) // DSC-RX100M5 - ) + else if ((id == 318) || (id == 340)) { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; - imgdata.makernotes.sony.SonyCameraType = LIBRAW_SONY_DSC; + if (imgdata.makernotes.sony.firmware < 1.2f) + imgdata.makernotes.sony.ImageCount3_offset = 0x01a0; + else + imgdata.makernotes.sony.ImageCount3_offset = 0x01b6; } - return; + } } -void CLASS parseSonyLensType2 (uchar a, uchar b) { +void CLASS parseSonyLensType2(uchar a, uchar b) +{ ushort lid2; - lid2 = (((ushort)a)<<8) | ((ushort)b); - if (!lid2) return; + lid2 = (((ushort)a) << 8) | ((ushort)b); + if (!lid2) + return; if (lid2 < 0x100) + { + if ((imgdata.lens.makernotes.AdapterID != 0x4900) && (imgdata.lens.makernotes.AdapterID != 0xEF00)) { - if ((imgdata.lens.makernotes.AdapterID != 0x4900) && - (imgdata.lens.makernotes.AdapterID != 0xEF00)) + imgdata.lens.makernotes.AdapterID = lid2; + switch (lid2) { - imgdata.lens.makernotes.AdapterID = lid2; - switch (lid2) { - case 1: - case 2: - case 3: - case 6: - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Minolta_A; + case 1: + case 2: + case 3: + case 6: + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Minolta_A; break; - case 44: - case 78: - case 239: - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF; + case 44: + case 78: + case 239: + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF; break; - } } } + } else imgdata.lens.makernotes.LensID = lid2; if ((lid2 >= 50481) && (lid2 < 50500)) - { - strcpy(imgdata.lens.makernotes.Adapter, "MC-11"); - imgdata.lens.makernotes.AdapterID = 0x4900; - } + { + strcpy(imgdata.lens.makernotes.Adapter, "MC-11"); + imgdata.lens.makernotes.AdapterID = 0x4900; + } return; } -#define strnXcat(buf,string) strncat(buf,string,LIM(sizeof(buf)-strbuflen(buf)-1,0,sizeof(buf))) +#define strnXcat(buf, string) strncat(buf, string, LIM(sizeof(buf) - strbuflen(buf) - 1, 0, sizeof(buf))) -void CLASS parseSonyLensFeatures (uchar a, uchar b) { +void CLASS parseSonyLensFeatures(uchar a, uchar b) +{ ushort features; - features = (((ushort)a)<<8) | ((ushort)b); + features = (((ushort)a) << 8) | ((ushort)b); if ((imgdata.lens.makernotes.LensMount == LIBRAW_MOUNT_Canon_EF) || - (imgdata.lens.makernotes.LensMount != LIBRAW_MOUNT_Sigma_X3F) || - !features) + (imgdata.lens.makernotes.LensMount != LIBRAW_MOUNT_Sigma_X3F) || !features) return; imgdata.lens.makernotes.LensFeatures_pre[0] = 0; imgdata.lens.makernotes.LensFeatures_suf[0] = 0; - if ((features & 0x0200) && (features & 0x0100)) strcpy(imgdata.lens.makernotes.LensFeatures_pre, "E"); - else if (features & 0x0200) strcpy(imgdata.lens.makernotes.LensFeatures_pre, "FE"); - else if (features & 0x0100) strcpy(imgdata.lens.makernotes.LensFeatures_pre, "DT"); + if ((features & 0x0200) && (features & 0x0100)) + strcpy(imgdata.lens.makernotes.LensFeatures_pre, "E"); + else if (features & 0x0200) + strcpy(imgdata.lens.makernotes.LensFeatures_pre, "FE"); + else if (features & 0x0100) + strcpy(imgdata.lens.makernotes.LensFeatures_pre, "DT"); if (!imgdata.lens.makernotes.LensFormat && !imgdata.lens.makernotes.LensMount) - { - imgdata.lens.makernotes.LensFormat = LIBRAW_FORMAT_FF; - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Minolta_A; + { + imgdata.lens.makernotes.LensFormat = LIBRAW_FORMAT_FF; + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Minolta_A; - if ((features & 0x0200) && (features & 0x0100)) { - imgdata.lens.makernotes.LensFormat = LIBRAW_FORMAT_APSC; - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sony_E; - } else if (features & 0x0200) { - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sony_E; - } else if (features & 0x0100) { - imgdata.lens.makernotes.LensFormat = LIBRAW_FORMAT_APSC; - } + if ((features & 0x0200) && (features & 0x0100)) + { + imgdata.lens.makernotes.LensFormat = LIBRAW_FORMAT_APSC; + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sony_E; + } + else if (features & 0x0200) + { + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sony_E; + } + else if (features & 0x0100) + { + imgdata.lens.makernotes.LensFormat = LIBRAW_FORMAT_APSC; } + } if (features & 0x4000) strnXcat(imgdata.lens.makernotes.LensFeatures_pre, " PZ"); if (features & 0x0008) strnXcat(imgdata.lens.makernotes.LensFeatures_suf, " G"); else if (features & 0x0004) - strnXcat(imgdata.lens.makernotes.LensFeatures_suf, " ZA" ); + strnXcat(imgdata.lens.makernotes.LensFeatures_suf, " ZA"); if ((features & 0x0020) && (features & 0x0040)) strnXcat(imgdata.lens.makernotes.LensFeatures_suf, " Macro"); else if (features & 0x0020) strnXcat(imgdata.lens.makernotes.LensFeatures_suf, " STF"); else if (features & 0x0040) strnXcat(imgdata.lens.makernotes.LensFeatures_suf, " Reflex"); else if (features & 0x0080) strnXcat(imgdata.lens.makernotes.LensFeatures_suf, " Fisheye"); if (features & 0x0001) strnXcat(imgdata.lens.makernotes.LensFeatures_suf, " SSM"); else if (features & 0x0002) strnXcat(imgdata.lens.makernotes.LensFeatures_suf, " SAM"); if (features & 0x8000) strnXcat(imgdata.lens.makernotes.LensFeatures_suf, " OSS"); if (features & 0x2000) strnXcat(imgdata.lens.makernotes.LensFeatures_suf, " LE"); if (features & 0x0800) strnXcat(imgdata.lens.makernotes.LensFeatures_suf, " II"); if (imgdata.lens.makernotes.LensFeatures_suf[0] == ' ') - memmove(imgdata.lens.makernotes.LensFeatures_suf, imgdata.lens.makernotes.LensFeatures_suf+1, - strbuflen(imgdata.lens.makernotes.LensFeatures_suf)-1); + memmove(imgdata.lens.makernotes.LensFeatures_suf, imgdata.lens.makernotes.LensFeatures_suf + 1, + strbuflen(imgdata.lens.makernotes.LensFeatures_suf) - 1); return; } #undef strnXcat -void CLASS process_Sony_0x940c (uchar * buf) +void CLASS process_Sony_0x0116(uchar *buf, ushort len, unsigned id) { - ushort lid2; - if ((imgdata.lens.makernotes.LensMount != LIBRAW_MOUNT_Canon_EF) && - (imgdata.lens.makernotes.LensMount != LIBRAW_MOUNT_Sigma_X3F)) - { - switch (SonySubstitution[buf[0x0008]]) { - case 1: - case 5: - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Minolta_A; - break; - case 4: - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sony_E; - break; - } - } - lid2 = (((ushort)SonySubstitution[buf[0x000a]])<<8) | - ((ushort)SonySubstitution[buf[0x0009]]); - if ((lid2 > 0) && (lid2 < 32784)) - parseSonyLensType2 (SonySubstitution[buf[0x000a]], // LensType2 - Sony lens ids - SonySubstitution[buf[0x0009]]); - return; + short bufx; + + if (((id == 257) || (id == 262) || (id == 269) || (id == 270)) && (len >= 2)) + bufx = buf[1]; + else if ((id >= 273) && (len >= 3)) + bufx = buf[2]; + else + return; + + imgdata.other.BatteryTemperature = (float)(bufx - 32) / 1.8f; } +void CLASS process_Sony_0x2010(uchar *buf, ushort len) +{ + if ((!imgdata.makernotes.sony.group2010) || (imgdata.makernotes.sony.real_iso_offset == 0xffff) || + (len < (imgdata.makernotes.sony.real_iso_offset + 2))) + return; + + if (imgdata.other.real_ISO < 0.1f) + { + uchar s[2]; + s[0] = SonySubstitution[buf[imgdata.makernotes.sony.real_iso_offset]]; + s[1] = SonySubstitution[buf[imgdata.makernotes.sony.real_iso_offset + 1]]; + imgdata.other.real_ISO = 100.0f * libraw_powf64l(2.0f, (16 - ((float)sget2(s)) / 256.0f)); + } +} -void CLASS process_Sony_0x9050 (uchar * buf, unsigned id) +void CLASS process_Sony_0x9050(uchar *buf, ushort len, unsigned id) { ushort lid; + uchar s[4]; + int c; if ((imgdata.lens.makernotes.CameraMount != LIBRAW_MOUNT_Sony_E) && (imgdata.lens.makernotes.CameraMount != LIBRAW_MOUNT_FixedLens)) - { - if (buf[0]) - imgdata.lens.makernotes.MaxAp4CurFocal = - my_roundf(libraw_powf64(2.0f, ((float)SonySubstitution[buf[0]] / 8.0 - 1.06f) / 2.0f)*10.0f) / 10.0f; + { + if (len < 2) + return; + if (buf[0]) + imgdata.lens.makernotes.MaxAp4CurFocal = + my_roundf(libraw_powf64l(2.0f, ((float)SonySubstitution[buf[0]] / 8.0 - 1.06f) / 2.0f) * 10.0f) / 10.0f; - if (buf[1]) - imgdata.lens.makernotes.MinAp4CurFocal = - my_roundf(libraw_powf64(2.0f, ((float)SonySubstitution[buf[1]] / 8.0 - 1.06f) / 2.0f)*10.0f) / 10.0f; - } + if (buf[1]) + imgdata.lens.makernotes.MinAp4CurFocal = + my_roundf(libraw_powf64l(2.0f, ((float)SonySubstitution[buf[1]] / 8.0 - 1.06f) / 2.0f) * 10.0f) / 10.0f; + } if (imgdata.lens.makernotes.CameraMount != LIBRAW_MOUNT_FixedLens) + { + if (len <= 0x106) + return; + if (buf[0x3d] | buf[0x3c]) { - if (buf[0x3d] | buf[0x3c]) - { - lid = SonySubstitution[buf[0x3d]] << 8 | - SonySubstitution[buf[0x3c]]; - imgdata.lens.makernotes.CurAp = - libraw_powf64(2.0f, ((float)lid/256.0f - 16.0f) / 2.0f); - } - if (buf[0x105] && - (imgdata.lens.makernotes.LensMount != LIBRAW_MOUNT_Canon_EF) && - (imgdata.lens.makernotes.LensMount != LIBRAW_MOUNT_Sigma_X3F)) - imgdata.lens.makernotes.LensMount = - SonySubstitution[buf[0x105]]; - if (buf[0x106]) - imgdata.lens.makernotes.LensFormat = - SonySubstitution[buf[0x106]]; - } + lid = SonySubstitution[buf[0x3d]] << 8 | SonySubstitution[buf[0x3c]]; + imgdata.lens.makernotes.CurAp = libraw_powf64l(2.0f, ((float)lid / 256.0f - 16.0f) / 2.0f); + } + if (buf[0x105] && (imgdata.lens.makernotes.LensMount != LIBRAW_MOUNT_Canon_EF) && + (imgdata.lens.makernotes.LensMount != LIBRAW_MOUNT_Sigma_X3F)) + imgdata.lens.makernotes.LensMount = SonySubstitution[buf[0x105]]; + if (buf[0x106]) + imgdata.lens.makernotes.LensFormat = SonySubstitution[buf[0x106]]; + } if (imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Sony_E) - { - parseSonyLensType2 (SonySubstitution[buf[0x0108]], // LensType2 - Sony lens ids - SonySubstitution[buf[0x0107]]); - } - if ((imgdata.lens.makernotes.LensID == -1) && - (imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Minolta_A) && + { + if (len <= 0x108) + return; + parseSonyLensType2(SonySubstitution[buf[0x0108]], // LensType2 - Sony lens ids + SonySubstitution[buf[0x0107]]); + } + + if (len <= 0x10a) + return; + if ((imgdata.lens.makernotes.LensID == -1) && (imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Minolta_A) && (buf[0x010a] | buf[0x0109])) - { - imgdata.lens.makernotes.LensID = // LensType - Minolta/Sony lens ids - SonySubstitution[buf[0x010a]] << 8 | - SonySubstitution[buf[0x0109]]; + { + imgdata.lens.makernotes.LensID = // LensType - Minolta/Sony lens ids + SonySubstitution[buf[0x010a]] << 8 | SonySubstitution[buf[0x0109]]; - if ((imgdata.lens.makernotes.LensID > 0x4900) && - (imgdata.lens.makernotes.LensID <= 0x5900)) - { - imgdata.lens.makernotes.AdapterID = 0x4900; - imgdata.lens.makernotes.LensID -= imgdata.lens.makernotes.AdapterID; - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sigma_X3F; - strcpy(imgdata.lens.makernotes.Adapter, "MC-11"); - } + if ((imgdata.lens.makernotes.LensID > 0x4900) && (imgdata.lens.makernotes.LensID <= 0x5900)) + { + imgdata.lens.makernotes.AdapterID = 0x4900; + imgdata.lens.makernotes.LensID -= imgdata.lens.makernotes.AdapterID; + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sigma_X3F; + strcpy(imgdata.lens.makernotes.Adapter, "MC-11"); + } - else if ((imgdata.lens.makernotes.LensID > 0xEF00) && - (imgdata.lens.makernotes.LensID < 0xFFFF) && - (imgdata.lens.makernotes.LensID != 0xFF00)) - { - imgdata.lens.makernotes.AdapterID = 0xEF00; - imgdata.lens.makernotes.LensID -= imgdata.lens.makernotes.AdapterID; - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF; - } + else if ((imgdata.lens.makernotes.LensID > 0xEF00) && (imgdata.lens.makernotes.LensID < 0xFFFF) && + (imgdata.lens.makernotes.LensID != 0xFF00)) + { + imgdata.lens.makernotes.AdapterID = 0xEF00; + imgdata.lens.makernotes.LensID -= imgdata.lens.makernotes.AdapterID; + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF; } + } if ((id >= 286) && (id <= 293)) + { + if (len <= 0x116) + return; // "SLT-A65", "SLT-A77", "NEX-7", "NEX-VG20E", // "SLT-A37", "SLT-A57", "NEX-F3", "Lunar" - parseSonyLensFeatures (SonySubstitution[buf[0x115]], - SonySubstitution[buf[0x116]]); + parseSonyLensFeatures(SonySubstitution[buf[0x115]], SonySubstitution[buf[0x116]]); + } else if (imgdata.lens.makernotes.CameraMount != LIBRAW_MOUNT_FixedLens) + { + if (len <= 0x117) + return; parseSonyLensFeatures(SonySubstitution[buf[0x116]], SonySubstitution[buf[0x117]]); + } - if ((id == 347) || (id == 350) || (id == 357)) + if ((id == 347) || (id == 350) || (id == 354) || (id == 357) || (id == 358) || (id == 360) || (id == 362)) { + if (len <= 0x8d) + return; unsigned long long b88 = SonySubstitution[buf[0x88]]; unsigned long long b89 = SonySubstitution[buf[0x89]]; unsigned long long b8a = SonySubstitution[buf[0x8a]]; unsigned long long b8b = SonySubstitution[buf[0x8b]]; unsigned long long b8c = SonySubstitution[buf[0x8c]]; unsigned long long b8d = SonySubstitution[buf[0x8d]]; sprintf(imgdata.shootinginfo.InternalBodySerial, "%06llx", (b88 << 40) + (b89 << 32) + (b8a << 24) + (b8b << 16) + (b8c << 8) + b8d); } - else if ((imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Minolta_A) && (id > 279) && (id != 282) && (id != 283)) + else if (imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Minolta_A) { + if (len <= 0xf4) + return; unsigned long long bf0 = SonySubstitution[buf[0xf0]]; unsigned long long bf1 = SonySubstitution[buf[0xf1]]; unsigned long long bf2 = SonySubstitution[buf[0xf2]]; unsigned long long bf3 = SonySubstitution[buf[0xf3]]; unsigned long long bf4 = SonySubstitution[buf[0xf4]]; sprintf(imgdata.shootinginfo.InternalBodySerial, "%05llx", (bf0 << 32) + (bf1 << 24) + (bf2 << 16) + (bf3 << 8) + bf4); } else if ((imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Sony_E) && (id != 288) && (id != 289) && (id != 290)) { + if (len <= 0x7f) + return; unsigned b7c = SonySubstitution[buf[0x7c]]; unsigned b7d = SonySubstitution[buf[0x7d]]; unsigned b7e = SonySubstitution[buf[0x7e]]; unsigned b7f = SonySubstitution[buf[0x7f]]; sprintf(imgdata.shootinginfo.InternalBodySerial, "%04x", (b7c << 24) + (b7d << 16) + (b7e << 8) + b7f); } + if ((imgdata.makernotes.sony.ImageCount3_offset != 0xffff) && + (len >= (imgdata.makernotes.sony.ImageCount3_offset + 4))) + { + FORC4 s[c] = SonySubstitution[buf[imgdata.makernotes.sony.ImageCount3_offset + c]]; + imgdata.makernotes.sony.ImageCount3 = sget4(s); + } + + if (id == 362) + { + for (c = 0; c < 6; c++) + { + imgdata.makernotes.sony.TimeStamp[c] = SonySubstitution[buf[0x0066 + c]]; + } + } + return; } -void CLASS parse_makernote_0xc634(int base, int uptag, unsigned dng_writer) +void CLASS process_Sony_0x9400(uchar *buf, ushort len, unsigned id) { - unsigned ver97 = 0, offset = 0, entries, tag, type, len, save, c; - unsigned i; - uchar NikonKey, ci, cj, ck; - unsigned serial = 0; - unsigned custom_serial = 0; - unsigned NikonLensDataVersion = 0; - unsigned lenNikonLensData = 0; - unsigned NikonFlashInfoVersion = 0; + uchar s[4]; + int c; + short bufx = buf[0]; - uchar *CanonCameraInfo; - unsigned lenCanonCameraInfo = 0; + if (((bufx == 0x23) || (bufx == 0x24) || (bufx == 0x26)) && (len >= 0x1f)) + { // 0x9400 'c' version - uchar *table_buf; - uchar *table_buf_0x9050; - ushort table_buf_0x9050_present = 0; - uchar *table_buf_0x940c; - ushort table_buf_0x940c_present = 0; + if ((id == 358) || (id == 362) || (id == 365)) + { + imgdata.makernotes.sony.ShotNumberSincePowerUp = SonySubstitution[buf[0x0a]]; + } + else + { + FORC4 s[c] = SonySubstitution[buf[0x0a + c]]; + imgdata.makernotes.sony.ShotNumberSincePowerUp = sget4(s); + } - short morder, sorder = order; - char buf[10]; - INT64 fsize = ifp->size(); + imgdata.makernotes.sony.Sony0x9400_version = 0xc; - fread(buf, 1, 10, ifp); - if (!strcmp(buf, "Nikon")) { - base = ftell(ifp); - order = get2(); - if (get2() != 42) goto quit; - offset = get4(); - fseek(ifp, offset - 8, SEEK_CUR); + imgdata.makernotes.sony.Sony0x9400_ReleaseMode2 = SonySubstitution[buf[0x09]]; + + FORC4 s[c] = SonySubstitution[buf[0x12 + c]]; + imgdata.makernotes.sony.Sony0x9400_SequenceImageNumber = sget4(s); + + imgdata.makernotes.sony.Sony0x9400_SequenceLength1 = SonySubstitution[buf[0x16]]; // shots + + FORC4 s[c] = SonySubstitution[buf[0x1a + c]]; + imgdata.makernotes.sony.Sony0x9400_SequenceFileNumber = sget4(s); + + imgdata.makernotes.sony.Sony0x9400_SequenceLength2 = SonySubstitution[buf[0x1e]]; // files } - else if (!strcmp(buf, "OLYMPUS") || - !strcmp(buf, "PENTAX ") || - (!strncmp(make, "SAMSUNG", 7) && (dng_writer == CameraDNG))) { - base = ftell(ifp) - 10; - fseek(ifp, -2, SEEK_CUR); - order = get2(); - if (buf[0] == 'O') get2(); + + else if ((bufx == 0x0c) && (len >= 0x1f)) + { // 0x9400 'b' version + imgdata.makernotes.sony.Sony0x9400_version = 0xb; + + FORC4 s[c] = SonySubstitution[buf[0x08 + c]]; + imgdata.makernotes.sony.Sony0x9400_SequenceImageNumber = sget4(s); + + FORC4 s[c] = SonySubstitution[buf[0x0c + c]]; + imgdata.makernotes.sony.Sony0x9400_SequenceFileNumber = sget4(s); + + imgdata.makernotes.sony.Sony0x9400_ReleaseMode2 = SonySubstitution[buf[0x10]]; + + imgdata.makernotes.sony.Sony0x9400_SequenceLength1 = SonySubstitution[buf[0x1e]]; } - else if (!strncmp(buf, "SONY", 4) || - !strcmp(buf, "Panasonic")) { - goto nf; + + else if ((bufx == 0x0a) && (len >= 0x23)) + { // 0x9400 'a' version + imgdata.makernotes.sony.Sony0x9400_version = 0xa; + + FORC4 s[c] = SonySubstitution[buf[0x08 + c]]; + imgdata.makernotes.sony.Sony0x9400_SequenceImageNumber = sget4(s); + + FORC4 s[c] = SonySubstitution[buf[0x0c + c]]; + imgdata.makernotes.sony.Sony0x9400_SequenceFileNumber = sget4(s); + + imgdata.makernotes.sony.Sony0x9400_ReleaseMode2 = SonySubstitution[buf[0x10]]; + + imgdata.makernotes.sony.Sony0x9400_SequenceLength1 = SonySubstitution[buf[0x22]]; } - else if (!strncmp(buf, "FUJIFILM", 8)) { - base = ftell(ifp) - 10; - nf: order = 0x4949; - fseek(ifp, 2, SEEK_CUR); + + else + return; +} + +void CLASS process_Sony_0x9402(uchar *buf, ushort len) +{ + + if ((imgdata.makernotes.sony.SonyCameraType == LIBRAW_SONY_SLT) || + (imgdata.makernotes.sony.SonyCameraType == LIBRAW_SONY_ILCA)) + return; + + if (len < 5) + return; + + short bufx = buf[0x00]; + if ((bufx == 0x05) || (bufx == 0xff) || (buf[0x02] != 0xff)) + return; + + imgdata.other.AmbientTemperature = (float)((short)SonySubstitution[buf[0x04]]); + + return; +} + +void CLASS process_Sony_0x9403(uchar *buf, ushort len) +{ + if (len < 6) + return; + short bufx = SonySubstitution[buf[4]]; + if ((bufx == 0x00) || (bufx == 0x94)) + return; + + imgdata.other.SensorTemperature = (float)((short)SonySubstitution[buf[5]]); + + return; +} + +void CLASS process_Sony_0x9406(uchar *buf, ushort len) +{ + if (len < 6) + return; + short bufx = buf[0]; + if ((bufx != 0x01) && (bufx != 0x08) && (bufx != 0x1b)) + return; + bufx = buf[2]; + if ((bufx != 0x08) && (bufx != 0x1b)) + return; + + imgdata.other.BatteryTemperature = (float)(SonySubstitution[buf[5]] - 32) / 1.8f; + + return; +} + +void CLASS process_Sony_0x940c(uchar *buf, ushort len) +{ + if ((imgdata.makernotes.sony.SonyCameraType != LIBRAW_SONY_ILCE) && + (imgdata.makernotes.sony.SonyCameraType != LIBRAW_SONY_NEX)) + return; + if (len <= 0x000a) + return; + + ushort lid2; + if ((imgdata.lens.makernotes.LensMount != LIBRAW_MOUNT_Canon_EF) && + (imgdata.lens.makernotes.LensMount != LIBRAW_MOUNT_Sigma_X3F)) + { + switch (SonySubstitution[buf[0x0008]]) + { + case 1: + case 5: + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Minolta_A; + break; + case 4: + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sony_E; + break; + } } - 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) && - (dng_writer == AdobeDNG))) - base = ftell(ifp); + lid2 = (((ushort)SonySubstitution[buf[0x000a]]) << 8) | ((ushort)SonySubstitution[buf[0x0009]]); + if ((lid2 > 0) && (lid2 < 32784)) + parseSonyLensType2(SonySubstitution[buf[0x000a]], // LensType2 - Sony lens ids + SonySubstitution[buf[0x0009]]); + return; +} + +void CLASS process_Sony_0x940e(uchar *buf, ushort len, unsigned id) +{ + if (((id == 286) || (id == 287) || (id == 294)) && (len >= 0x017e)) + { + imgdata.makernotes.sony.AFMicroAdjValue = SonySubstitution[buf[0x017d]]; + } + else if ((imgdata.makernotes.sony.SonyCameraType == LIBRAW_SONY_ILCA) && (len >= 0x0051)) + { + imgdata.makernotes.sony.AFMicroAdjValue = SonySubstitution[buf[0x0050]]; } + else + return; - entries = get2(); - if (entries > 1000) return; - morder = order; + if (imgdata.makernotes.sony.AFMicroAdjValue != 0) + imgdata.makernotes.sony.AFMicroAdjOn = 1; +} - while (entries--) { - order = morder; - tiff_get(base, &tag, &type, &len, &save); - INT64 pos = ifp->tell(); - if(len > 8 && pos+len > 2* fsize) continue; - tag |= uptag << 16; - if(len > 100*1024*1024) goto next; // 100Mb tag? No! +void CLASS parseSonyMakernotes(unsigned tag, unsigned type, unsigned len, unsigned dng_writer, uchar *&table_buf_0x0116, + ushort &table_buf_0x0116_len, uchar *&table_buf_0x2010, ushort &table_buf_0x2010_len, + uchar *&table_buf_0x9050, ushort &table_buf_0x9050_len, uchar *&table_buf_0x9400, + ushort &table_buf_0x9400_len, uchar *&table_buf_0x9402, ushort &table_buf_0x9402_len, + uchar *&table_buf_0x9403, ushort &table_buf_0x9403_len, uchar *&table_buf_0x9406, + ushort &table_buf_0x9406_len, uchar *&table_buf_0x940c, ushort &table_buf_0x940c_len, + uchar *&table_buf_0x940e, ushort &table_buf_0x940e_len) +{ + + ushort lid; + uchar *table_buf; + + if (tag == 0xb001) // Sony ModelID + { + unique_id = get2(); + setSonyBodyFeatures(unique_id); + + if (table_buf_0x0116_len) + { + process_Sony_0x0116(table_buf_0x0116, table_buf_0x0116_len, unique_id); + free(table_buf_0x0116); + table_buf_0x0116_len = 0; + } + + if (table_buf_0x2010_len) + { + process_Sony_0x2010(table_buf_0x2010, table_buf_0x2010_len); + free(table_buf_0x2010); + table_buf_0x2010_len = 0; + } + + if (table_buf_0x9050_len) + { + process_Sony_0x9050(table_buf_0x9050, table_buf_0x9050_len, unique_id); + free(table_buf_0x9050); + table_buf_0x9050_len = 0; + } + + if (table_buf_0x9400_len) + { + process_Sony_0x9400(table_buf_0x9400, table_buf_0x9400_len, unique_id); + free(table_buf_0x9400); + table_buf_0x9400_len = 0; + } + + if (table_buf_0x9402_len) + { + process_Sony_0x9402(table_buf_0x9402, table_buf_0x9402_len); + free(table_buf_0x9402); + table_buf_0x9402_len = 0; + } + + if (table_buf_0x9403_len) + { + process_Sony_0x9403(table_buf_0x9403, table_buf_0x9403_len); + free(table_buf_0x9403); + table_buf_0x9403_len = 0; + } + + if (table_buf_0x9406_len) + { + process_Sony_0x9406(table_buf_0x9406, table_buf_0x9406_len); + free(table_buf_0x9406); + table_buf_0x9406_len = 0; + } + + if (table_buf_0x940c_len) + { + process_Sony_0x940c(table_buf_0x940c, table_buf_0x940c_len); + free(table_buf_0x940c); + table_buf_0x940c_len = 0; + } + + if (table_buf_0x940e_len) + { + process_Sony_0x940e(table_buf_0x940e, table_buf_0x940e_len, unique_id); + free(table_buf_0x940e); + table_buf_0x940e_len = 0; + } + } - if (!strncmp(make, "Canon",5)) + else if ((tag == 0x0010) && // CameraInfo + strncasecmp(model, "DSLR-A100", 9) && strncasecmp(model, "NEX-5C", 6) && !strncasecmp(make, "SONY", 4) && + ((len == 368) || // a700 + (len == 5478) || // a850, a900 + (len == 5506) || // a200, a300, a350 + (len == 6118) || // a230, a290, a330, a380, a390 + // a450, a500, a550, a560, a580 + // a33, a35, a55 + // NEX3, NEX5, NEX5C, NEXC3, VG10E + (len == 15360))) + { + table_buf = (uchar *)malloc(len); + fread(table_buf, len, 1, ifp); + if (memcmp(table_buf, "\xff\xff\xff\xff\xff\xff\xff\xff", 8) && + memcmp(table_buf, "\x00\x00\x00\x00\x00\x00\x00\x00", 8)) + { + switch (len) { - if (tag == 0x000d && len < 256000) // camera info + case 368: + case 5478: + // a700, a850, a900: CameraInfo + if ((!dng_writer) || + (saneSonyCameraInfo(table_buf[0], table_buf[3], table_buf[2], table_buf[5], table_buf[4], table_buf[7]))) + { + if (table_buf[0] | table_buf[3]) + imgdata.lens.makernotes.MinFocal = bcd2dec(table_buf[0]) * 100 + bcd2dec(table_buf[3]); + if (table_buf[2] | table_buf[5]) + imgdata.lens.makernotes.MaxFocal = bcd2dec(table_buf[2]) * 100 + bcd2dec(table_buf[5]); + if (table_buf[4]) + imgdata.lens.makernotes.MaxAp4MinFocal = bcd2dec(table_buf[4]) / 10.0f; + if (table_buf[4]) + imgdata.lens.makernotes.MaxAp4MaxFocal = bcd2dec(table_buf[7]) / 10.0f; + parseSonyLensFeatures(table_buf[1], table_buf[6]); + + if (len == 5478) { - CanonCameraInfo = (uchar*)malloc(MAX(16,len)); - fread(CanonCameraInfo, len, 1, ifp); - lenCanonCameraInfo = len; + imgdata.makernotes.sony.AFMicroAdjValue = table_buf[304] - 20; + imgdata.makernotes.sony.AFMicroAdjOn = (((table_buf[305] & 0x80) == 0x80) ? 1 : 0); + imgdata.makernotes.sony.AFMicroAdjRegisteredLenses = table_buf[305] & 0x7f; } + } + break; + default: + // CameraInfo2 & 3 + if ((!dng_writer) || + (saneSonyCameraInfo(table_buf[1], table_buf[2], table_buf[3], table_buf[4], table_buf[5], table_buf[6]))) + { + if (table_buf[1] | table_buf[2]) + imgdata.lens.makernotes.MinFocal = bcd2dec(table_buf[1]) * 100 + bcd2dec(table_buf[2]); + if (table_buf[3] | table_buf[4]) + imgdata.lens.makernotes.MaxFocal = bcd2dec(table_buf[3]) * 100 + bcd2dec(table_buf[4]); + if (table_buf[5]) + imgdata.lens.makernotes.MaxAp4MinFocal = bcd2dec(table_buf[5]) / 10.0f; + if (table_buf[6]) + imgdata.lens.makernotes.MaxAp4MaxFocal = bcd2dec(table_buf[6]) / 10.0f; + parseSonyLensFeatures(table_buf[0], table_buf[7]); + } + } + } + free(table_buf); + } - else if (tag == 0x10) // Canon ModelID - { - unique_id = get4(); - if (unique_id == 0x03740000) unique_id = 0x80000374; // M3 - if (unique_id == 0x03840000) unique_id = 0x80000384; // M10 - if (unique_id == 0x03940000) unique_id = 0x80000394; // M5 - setCanonBodyFeatures(unique_id); - if (lenCanonCameraInfo) - { - processCanonCameraInfo(unique_id, CanonCameraInfo,lenCanonCameraInfo); - free(CanonCameraInfo); - CanonCameraInfo = 0; - lenCanonCameraInfo = 0; - } - } + else if ((!dng_writer) && (tag == 0x0020) && // WBInfoA100, needs 0xb028 processing + !strncasecmp(model, "DSLR-A100", 9)) + { + fseek(ifp, 0x49dc, SEEK_CUR); + stmread(imgdata.shootinginfo.InternalBodySerial, 12, ifp); + } - else parseCanonMakernotes (tag, type, len); - } + else if (tag == 0x0104) + { + imgdata.other.FlashEC = getreal(type); + } - else if (!strncmp(make, "FUJI", 4)) - parseFujiMakernotes (tag, type); + else if (tag == 0x0105) // Teleconverter + { + imgdata.lens.makernotes.TeleconverterID = get2(); + } - else if (!strncasecmp(make, "LEICA", 5)) + else if (tag == 0x0114 && len < 256000) // CameraSettings + { + table_buf = (uchar *)malloc(len); + fread(table_buf, len, 1, ifp); + switch (len) + { + case 280: + case 364: + case 332: + // CameraSettings and CameraSettings2 are big endian + if (table_buf[2] | table_buf[3]) + { + lid = (((ushort)table_buf[2]) << 8) | ((ushort)table_buf[3]); + imgdata.lens.makernotes.CurAp = libraw_powf64l(2.0f, ((float)lid / 8.0f - 1.0f) / 2.0f); + } + break; + case 1536: + case 2048: + // CameraSettings3 are little endian + parseSonyLensType2(table_buf[1016], table_buf[1015]); + if (imgdata.lens.makernotes.LensMount != LIBRAW_MOUNT_Canon_EF) { - if (((tag == 0x035e) || (tag == 0x035f)) && (type == 10) && (len == 9)) + switch (table_buf[153]) { - int ind = tag == 0x035e?0:1; - for (int j=0; j < 3; j++) - FORCC imgdata.color.dng_color[ind].forwardmatrix[j][c]= getreal(type); + case 16: + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Minolta_A; + break; + case 17: + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sony_E; + break; } - if ((tag == 0x0303) && (type != 4)) - { - stmread(imgdata.lens.makernotes.Lens, len,ifp); - } + } + break; + } + free(table_buf); + } - if ((tag == 0x3405) || - (tag == 0x0310) || - (tag == 0x34003405)) - { - imgdata.lens.makernotes.LensID = get4(); - imgdata.lens.makernotes.LensID = - ((imgdata.lens.makernotes.LensID>>2)<<8) | - (imgdata.lens.makernotes.LensID & 0x3); - if (imgdata.lens.makernotes.LensID != -1) - { - if ((model[0] == 'M') || - !strncasecmp (model, "LEICA M", 7)) - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_M; - if (imgdata.lens.makernotes.LensID) - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Leica_M; - } - else if ((model[0] == 'S') || - !strncasecmp (model, "LEICA S", 7)) - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_S; - if (imgdata.lens.makernotes.Lens[0]) - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Leica_S; - } - } - } + else if ((tag == 0x3000) && (len < 256000)) + { + uchar *table_buf_0x3000; + table_buf_0x3000 = (uchar *)malloc(len); + fread(table_buf_0x3000, len, 1, ifp); + for (int i = 0; i < 20; i++) + imgdata.makernotes.sony.SonyDateTime[i] = table_buf_0x3000[6 + i]; + } - else if ( - ((tag == 0x0313) || (tag == 0x34003406)) && - (fabs(imgdata.lens.makernotes.CurAp) < 0.17f) && - ((type == 10) || (type == 5)) - ) - { - imgdata.lens.makernotes.CurAp = getreal(type); - if (imgdata.lens.makernotes.CurAp > 126.3) - imgdata.lens.makernotes.CurAp = 0.0f; - } + else if (tag == 0x0116 && len < 256000) + { + table_buf_0x0116 = (uchar *)malloc(len); + table_buf_0x0116_len = len; + fread(table_buf_0x0116, len, 1, ifp); + if (imgdata.lens.makernotes.CamID) + { + process_Sony_0x0116(table_buf_0x0116, table_buf_0x0116_len, imgdata.lens.makernotes.CamID); + free(table_buf_0x0116); + table_buf_0x0116_len = 0; + } + } - else if (tag == 0x3400) - { - parse_makernote (base, 0x3400); - } - } + else if (tag == 0x2010 && len < 256000) + { + table_buf_0x2010 = (uchar *)malloc(len); + table_buf_0x2010_len = len; + fread(table_buf_0x2010, len, 1, ifp); + if (imgdata.lens.makernotes.CamID) + { + process_Sony_0x2010(table_buf_0x2010, table_buf_0x2010_len); + free(table_buf_0x2010); + table_buf_0x2010_len = 0; + } + } - else if (!strncmp(make, "NIKON", 5)) - { - if (tag == 0x1d) // serial number - while ((c = fgetc(ifp)) && c != EOF) - { - if ((!custom_serial) && (!isdigit(c))) - { - if ((strbuflen(model) == 3) && (!strcmp(model,"D50"))) - { - custom_serial = 34; - } - else - { - custom_serial = 96; - } - } - serial = serial*10 + (isdigit(c) ? c - '0' : c % 10); - } - else if (tag == 0x000a) + else if (tag == 0x201a) + { + imgdata.makernotes.sony.ElectronicFrontCurtainShutter = get4(); + } + + else if (tag == 0x201b) + { + uchar uc; + fread(&uc, 1, 1, ifp); + imgdata.shootinginfo.FocusMode = (short)uc; + } + + else if (tag == 0x202c) + { + imgdata.makernotes.sony.MeteringMode2 = get2(); + } + + else if (tag == 0x9050 && len < 256000) // little endian + { + table_buf_0x9050 = (uchar *)malloc(len); + table_buf_0x9050_len = len; + fread(table_buf_0x9050, len, 1, ifp); + + if (imgdata.lens.makernotes.CamID) + { + process_Sony_0x9050(table_buf_0x9050, table_buf_0x9050_len, imgdata.lens.makernotes.CamID); + free(table_buf_0x9050); + table_buf_0x9050_len = 0; + } + } + + else if (tag == 0x9400 && len < 256000) + { + table_buf_0x9400 = (uchar *)malloc(len); + table_buf_0x9400_len = len; + fread(table_buf_0x9400, len, 1, ifp); + if (imgdata.lens.makernotes.CamID) + { + process_Sony_0x9400(table_buf_0x9400, table_buf_0x9400_len, unique_id); + free(table_buf_0x9400); + table_buf_0x9400_len = 0; + } + } + + else if (tag == 0x9402 && len < 256000) + { + table_buf_0x9402 = (uchar *)malloc(len); + table_buf_0x9402_len = len; + fread(table_buf_0x9402, len, 1, ifp); + if (imgdata.lens.makernotes.CamID) + { + process_Sony_0x9402(table_buf_0x9402, table_buf_0x9402_len); + free(table_buf_0x9402); + table_buf_0x9402_len = 0; + } + } + + else if (tag == 0x9403 && len < 256000) + { + table_buf_0x9403 = (uchar *)malloc(len); + table_buf_0x9403_len = len; + fread(table_buf_0x9403, len, 1, ifp); + if (imgdata.lens.makernotes.CamID) + { + process_Sony_0x9403(table_buf_0x9403, table_buf_0x9403_len); + free(table_buf_0x9403); + table_buf_0x9403_len = 0; + } + } + + else if ((tag == 0x9405) && (len < 256000) && (len > 0x64)) + { + uchar *table_buf_0x9405; + table_buf_0x9405 = (uchar *)malloc(len); + fread(table_buf_0x9405, len, 1, ifp); + uchar bufx = table_buf_0x9405[0x0]; + if (imgdata.other.real_ISO < 0.1f) + { + if ((bufx == 0x25) || (bufx == 0x3a) || (bufx == 0x76) || (bufx == 0x7e) || (bufx == 0x8b) || (bufx == 0x9a) || + (bufx == 0xb3) || (bufx == 0xe1)) + { + uchar s[2]; + s[0] = SonySubstitution[table_buf_0x9405[0x04]]; + s[1] = SonySubstitution[table_buf_0x9405[0x05]]; + imgdata.other.real_ISO = 100.0f * libraw_powf64l(2.0f, (16 - ((float)sget2(s)) / 256.0f)); + } + } + free(table_buf_0x9405); + } + + else if (tag == 0x9406 && len < 256000) + { + table_buf_0x9406 = (uchar *)malloc(len); + table_buf_0x9406_len = len; + fread(table_buf_0x9406, len, 1, ifp); + if (imgdata.lens.makernotes.CamID) + { + process_Sony_0x9406(table_buf_0x9406, table_buf_0x9406_len); + free(table_buf_0x9406); + table_buf_0x9406_len = 0; + } + } + + else if (tag == 0x940c && len < 256000) + { + table_buf_0x940c = (uchar *)malloc(len); + table_buf_0x940c_len = len; + fread(table_buf_0x940c, len, 1, ifp); + if (imgdata.lens.makernotes.CamID) + { + process_Sony_0x940c(table_buf_0x940c, table_buf_0x940c_len); + free(table_buf_0x940c); + table_buf_0x940c_len = 0; + } + } + + else if (tag == 0x940e && len < 256000) + { + table_buf_0x940e = (uchar *)malloc(len); + table_buf_0x940e_len = len; + fread(table_buf_0x940e, len, 1, ifp); + if (imgdata.lens.makernotes.CamID) + { + process_Sony_0x940e(table_buf_0x940e, table_buf_0x940e_len, imgdata.lens.makernotes.CamID); + free(table_buf_0x940e); + table_buf_0x940e_len = 0; + } + } + + else if (((tag == 0xb027) || (tag == 0x010c)) && (imgdata.lens.makernotes.LensID == -1)) + { + imgdata.lens.makernotes.LensID = get4(); + if ((imgdata.lens.makernotes.LensID > 0x4900) && (imgdata.lens.makernotes.LensID <= 0x5900)) + { + imgdata.lens.makernotes.AdapterID = 0x4900; + imgdata.lens.makernotes.LensID -= imgdata.lens.makernotes.AdapterID; + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sigma_X3F; + strcpy(imgdata.lens.makernotes.Adapter, "MC-11"); + } + + else if ((imgdata.lens.makernotes.LensID > 0xEF00) && (imgdata.lens.makernotes.LensID < 0xFFFF) && + (imgdata.lens.makernotes.LensID != 0xFF00)) + { + imgdata.lens.makernotes.AdapterID = 0xEF00; + imgdata.lens.makernotes.LensID -= imgdata.lens.makernotes.AdapterID; + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF; + } + if (tag == 0x010c) + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Minolta_A; + } + + else if (tag == 0xb02a && len < 256000) // Sony LensSpec + { + table_buf = (uchar *)malloc(len); + fread(table_buf, len, 1, ifp); + if ((!dng_writer) || + (saneSonyCameraInfo(table_buf[1], table_buf[2], table_buf[3], table_buf[4], table_buf[5], table_buf[6]))) + { + if (table_buf[1] | table_buf[2]) + imgdata.lens.makernotes.MinFocal = bcd2dec(table_buf[1]) * 100 + bcd2dec(table_buf[2]); + if (table_buf[3] | table_buf[4]) + imgdata.lens.makernotes.MaxFocal = bcd2dec(table_buf[3]) * 100 + bcd2dec(table_buf[4]); + if (table_buf[5]) + imgdata.lens.makernotes.MaxAp4MinFocal = bcd2dec(table_buf[5]) / 10.0f; + if (table_buf[6]) + imgdata.lens.makernotes.MaxAp4MaxFocal = bcd2dec(table_buf[6]) / 10.0f; + parseSonyLensFeatures(table_buf[0], table_buf[7]); + } + free(table_buf); + } + + else if ((tag == 0xb02b) && !imgdata.sizes.raw_crop.cwidth && (len == 2)) + { + imgdata.sizes.raw_crop.cheight = get4(); + imgdata.sizes.raw_crop.cwidth = get4(); + } +} + +void CLASS parse_makernote_0xc634(int base, int uptag, unsigned dng_writer) +{ + unsigned ver97 = 0, offset = 0, entries, tag, type, len, save, c; + unsigned i; + + uchar NikonKey, ci, cj, ck; + unsigned serial = 0; + unsigned custom_serial = 0; + unsigned NikonLensDataVersion = 0; + unsigned lenNikonLensData = 0; + unsigned NikonFlashInfoVersion = 0; + + uchar *CanonCameraInfo; + unsigned lenCanonCameraInfo = 0; + unsigned typeCanonCameraInfo = 0; + + uchar *table_buf; + uchar *table_buf_0x0116; + ushort table_buf_0x0116_len = 0; + uchar *table_buf_0x2010; + ushort table_buf_0x2010_len = 0; + uchar *table_buf_0x9050; + ushort table_buf_0x9050_len = 0; + uchar *table_buf_0x9400; + ushort table_buf_0x9400_len = 0; + uchar *table_buf_0x9402; + ushort table_buf_0x9402_len = 0; + uchar *table_buf_0x9403; + ushort table_buf_0x9403_len = 0; + uchar *table_buf_0x9406; + ushort table_buf_0x9406_len = 0; + uchar *table_buf_0x940c; + ushort table_buf_0x940c_len = 0; + uchar *table_buf_0x940e; + ushort table_buf_0x940e_len = 0; + + short morder, sorder = order; + char buf[10]; + INT64 fsize = ifp->size(); + + fread(buf, 1, 10, ifp); + + /* + printf("===>>buf: 0x"); + for (int i = 0; i < sizeof buf; i ++) { + printf("%02x", buf[i]); + } + putchar('\n'); + */ + + 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 ") || + (!strncmp(make, "SAMSUNG", 7) && (dng_writer == CameraDNG))) + { + 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) && (dng_writer == AdobeDNG))) + base = ftell(ifp); + } + + entries = get2(); + if (entries > 1000) + return; + morder = order; + + while (entries--) + { + order = morder; + tiff_get(base, &tag, &type, &len, &save); + INT64 pos = ifp->tell(); + if (len > 8 && pos + len > 2 * fsize) + { + fseek(ifp, save, SEEK_SET); // Recover tiff-read position!! + continue; + } + tag |= uptag << 16; + if (len > 100 * 1024 * 1024) + goto next; // 100Mb tag? No! + + if (!strncmp(make, "Canon", 5)) + { + if (tag == 0x000d && len < 256000) // camera info + { + if (type != 4) + { + CanonCameraInfo = (uchar *)malloc(MAX(16, len)); + fread(CanonCameraInfo, len, 1, ifp); + } + else + { + CanonCameraInfo = (uchar *)malloc(MAX(16, len * 4)); + fread(CanonCameraInfo, len, 4, ifp); + } + lenCanonCameraInfo = len; + typeCanonCameraInfo = type; + } + + else if (tag == 0x10) // Canon ModelID + { + unique_id = get4(); + unique_id = setCanonBodyFeatures(unique_id); + if (lenCanonCameraInfo) + { + processCanonCameraInfo(unique_id, CanonCameraInfo, lenCanonCameraInfo, typeCanonCameraInfo); + free(CanonCameraInfo); + CanonCameraInfo = 0; + lenCanonCameraInfo = 0; + } + } + + else + parseCanonMakernotes(tag, type, len); + } + + else if (!strncmp(make, "FUJI", 4)) + parseFujiMakernotes(tag, type); + + else if (!strncasecmp(make, "LEICA", 5)) + { + + if ((tag == 0x0320) && (type == 9) && (len == 1) && !strncasecmp(make, "Leica Camera AG", 15) && + !strncmp(buf, "LEICA", 5) && (buf[5] == 0) && (buf[6] == 0) && (buf[7] == 0)) + imgdata.other.CameraTemperature = getreal(type); + + if (tag == 0x34003402) + imgdata.other.CameraTemperature = getreal(type); + + if (((tag == 0x035e) || (tag == 0x035f)) && (type == 10) && (len == 9)) + { + int ind = tag == 0x035e ? 0 : 1; + for (int j = 0; j < 3; j++) + FORCC imgdata.color.dng_color[ind].forwardmatrix[j][c] = getreal(type); + imgdata.color.dng_color[ind].parsedfields |= LIBRAW_DNGFM_FORWARDMATRIX; + } + if ((tag == 0x0303) && (type != 4)) + { + stmread(imgdata.lens.makernotes.Lens, len, ifp); + } + + if ((tag == 0x3405) || (tag == 0x0310) || (tag == 0x34003405)) + { + imgdata.lens.makernotes.LensID = get4(); + imgdata.lens.makernotes.LensID = + ((imgdata.lens.makernotes.LensID >> 2) << 8) | (imgdata.lens.makernotes.LensID & 0x3); + if (imgdata.lens.makernotes.LensID != -1) + { + if ((model[0] == 'M') || !strncasecmp(model, "LEICA M", 7)) { - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_M; + if (imgdata.lens.makernotes.LensID) + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Leica_M; } - else if (tag == 0x0082) // lens attachment + else if ((model[0] == 'S') || !strncasecmp(model, "LEICA S", 7)) { - stmread(imgdata.lens.makernotes.Attachment, len, ifp); + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_S; + if (imgdata.lens.makernotes.Lens[0]) + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Leica_S; } - else if (tag == 0x0083) // lens type + } + } + + else if (((tag == 0x0313) || (tag == 0x34003406)) && (fabs(imgdata.lens.makernotes.CurAp) < 0.17f) && + ((type == 10) || (type == 5))) + { + imgdata.lens.makernotes.CurAp = getreal(type); + if (imgdata.lens.makernotes.CurAp > 126.3) + imgdata.lens.makernotes.CurAp = 0.0f; + } + + else if (tag == 0x3400) + { + parse_makernote(base, 0x3400); + } + } + + else if (!strncmp(make, "NIKON", 5)) + { + if (tag == 0x1d) // serial number + while ((c = fgetc(ifp)) && c != EOF) + { + if ((!custom_serial) && (!isdigit(c))) { - imgdata.lens.nikon.NikonLensType = fgetc(ifp); + if ((strbuflen(model) == 3) && (!strcmp(model, "D50"))) + { + custom_serial = 34; + } + else + { + custom_serial = 96; + } } - else if (tag == 0x0084) // lens + serial = serial * 10 + (isdigit(c) ? c - '0' : c % 10); + } + else if (tag == 0x000a) + { + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; + } + else if (tag == 0x0082) // lens attachment + { + stmread(imgdata.lens.makernotes.Attachment, len, ifp); + } + else if (tag == 0x0083) // lens type + { + imgdata.lens.nikon.NikonLensType = fgetc(ifp); + } + else if (tag == 0x0084) // lens + { + imgdata.lens.makernotes.MinFocal = getreal(type); + imgdata.lens.makernotes.MaxFocal = getreal(type); + imgdata.lens.makernotes.MaxAp4MinFocal = getreal(type); + imgdata.lens.makernotes.MaxAp4MaxFocal = getreal(type); + } + else if (tag == 0x008b) // lens f-stops + { + uchar a, b, c; + a = fgetc(ifp); + b = fgetc(ifp); + c = fgetc(ifp); + if (c) + { + imgdata.lens.nikon.NikonLensFStops = a * b * (12 / c); + imgdata.lens.makernotes.LensFStops = (float)imgdata.lens.nikon.NikonLensFStops / 12.0f; + } + } + else if (tag == 0x0093) + { + imgdata.makernotes.nikon.NEFCompression = i = get2(); + if ((i == 7) || (i == 9)) + { + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; + } + } + else if (tag == 0x0097) + { + for (i = 0; i < 4; i++) + ver97 = ver97 * 10 + fgetc(ifp) - '0'; + if (ver97 == 601) // Coolpix A + { + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; + } + } + else if (tag == 0x0098) // contains lens data + { + for (i = 0; i < 4; i++) + { + NikonLensDataVersion = NikonLensDataVersion * 10 + fgetc(ifp) - '0'; + } + switch (NikonLensDataVersion) + { + case 100: + lenNikonLensData = 9; + break; + case 101: + case 201: // encrypted, starting from v.201 + case 202: + case 203: + lenNikonLensData = 15; + break; + case 204: + lenNikonLensData = 16; + break; + case 400: + lenNikonLensData = 459; + break; + case 401: + lenNikonLensData = 590; + break; + case 402: + lenNikonLensData = 509; + break; + case 403: + lenNikonLensData = 879; + break; + } + if (lenNikonLensData) + { + table_buf = (uchar *)malloc(lenNikonLensData); + fread(table_buf, lenNikonLensData, 1, ifp); + if ((NikonLensDataVersion < 201) && lenNikonLensData) { - imgdata.lens.makernotes.MinFocal = getreal(type); - imgdata.lens.makernotes.MaxFocal = getreal(type); - imgdata.lens.makernotes.MaxAp4MinFocal = getreal(type); - imgdata.lens.makernotes.MaxAp4MaxFocal = getreal(type); + processNikonLensData(table_buf, lenNikonLensData); + free(table_buf); + lenNikonLensData = 0; } - else if (tag == 0x008b) // lens f-stops + } + } + + else if (tag == 0xa7) // shutter count + { + NikonKey = fgetc(ifp) ^ fgetc(ifp) ^ fgetc(ifp) ^ fgetc(ifp); + if ((NikonLensDataVersion > 200) && lenNikonLensData) + { + if (custom_serial) { - uchar a, b, c; - a = fgetc(ifp); - b = fgetc(ifp); - c = fgetc(ifp); - if (c) - { - imgdata.lens.nikon.NikonLensFStops = a*b*(12/c); - imgdata.lens.makernotes.LensFStops = - (float)imgdata.lens.nikon.NikonLensFStops /12.0f; - } + ci = xlat[0][custom_serial]; } - else if (tag == 0x0093) + else { - i = get2(); - if ((i == 7) || (i == 9)) - { - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; - } + ci = xlat[0][serial & 0xff]; } - else if (tag == 0x0097) - { - for (i=0; i < 4; i++) - ver97 = ver97 * 10 + fgetc(ifp)-'0'; - if (ver97 == 601) // Coolpix A - { - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; - } - } - else if (tag == 0x0098) // contains lens data + cj = xlat[1][NikonKey]; + ck = 0x60; + for (i = 0; i < lenNikonLensData; i++) + table_buf[i] ^= (cj += ci * ck++); + processNikonLensData(table_buf, lenNikonLensData); + lenNikonLensData = 0; + free(table_buf); + } + } + else if (tag == 0x00a8) // contains flash data + { + for (i = 0; i < 4; i++) + { + NikonFlashInfoVersion = NikonFlashInfoVersion * 10 + fgetc(ifp) - '0'; + } + } + + else if (tag == 0x00b0) + { + get4(); // ME tag version, 4 symbols + imgdata.makernotes.nikon.ExposureMode = get4(); + imgdata.makernotes.nikon.nMEshots = get4(); + imgdata.makernotes.nikon.MEgainOn = get4(); + } + + else if (tag == 0x00b9) + { + uchar uc; + int8_t sc; + fread(&uc, 1, 1, ifp); + imgdata.makernotes.nikon.AFFineTune = uc; + fread(&uc, 1, 1, ifp); + imgdata.makernotes.nikon.AFFineTuneIndex = uc; + fread(&sc, 1, 1, ifp); + imgdata.makernotes.nikon.AFFineTuneAdj = sc; + } + + else if (tag == 37 && (!iso_speed || iso_speed == 65535)) + { + unsigned char cc; + fread(&cc, 1, 1, ifp); + iso_speed = (int)(100.0 * libraw_powf64l(2.0, (double)(cc) / 12.0 - 5.0)); + break; + } + } + + else if (!strncmp(make, "OLYMPUS", 7)) + { + short nWB, tWB; + int SubDirOffsetValid = strncmp(model, "E-300", 5) && strncmp(model, "E-330", 5) && strncmp(model, "E-400", 5) && + strncmp(model, "E-500", 5) && strncmp(model, "E-1", 3); + + if ((tag == 0x2010) || (tag == 0x2020) || (tag == 0x2030) || (tag == 0x2031) || (tag == 0x2040) || + (tag == 0x2050) || (tag == 0x3000)) + { + fseek(ifp, save - 4, SEEK_SET); + fseek(ifp, base + get4(), SEEK_SET); + parse_makernote_0xc634(base, tag, dng_writer); + } + if (!SubDirOffsetValid && ((len > 4) || (((type == 3) || (type == 8)) && (len > 2)) || + (((type == 4) || (type == 9)) && (len > 1)) || (type == 5) || (type > 9))) + goto skip_Oly_broken_tags; + + if ((tag >= 0x20400101) && (tag <= 0x20400111)) + { + if ((tag == 0x20400101) && (len == 2) && (!strncasecmp(model, "E-410", 5) || !strncasecmp(model, "E-510", 5))) + { + int i; + for (i = 0; i < 64; i++) { - for (i = 0; i < 4; i++) - { - NikonLensDataVersion = NikonLensDataVersion * 10 + fgetc(ifp) - '0'; - } - switch (NikonLensDataVersion) - { - case 100: lenNikonLensData = 9; break; - case 101: - case 201: // encrypted, starting from v.201 - case 202: - case 203: lenNikonLensData = 15; break; - case 204: lenNikonLensData = 16; break; - case 400: lenNikonLensData = 459; break; - case 401: lenNikonLensData = 590; break; - case 402: lenNikonLensData = 509; break; - case 403: lenNikonLensData = 879; break; - } - if(lenNikonLensData) - { - table_buf = (uchar*)malloc(lenNikonLensData); - fread(table_buf, lenNikonLensData, 1, ifp); - if ((NikonLensDataVersion < 201) && lenNikonLensData) - { - processNikonLensData(table_buf, lenNikonLensData); - free(table_buf); - lenNikonLensData = 0; - } - } + imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] = imgdata.color.WB_Coeffs[i][1] = + imgdata.color.WB_Coeffs[i][3] = 0x100; } - - else if (tag == 0xa7) // shutter count + for (i = 64; i < 256; i++) { - NikonKey = fgetc(ifp) ^ fgetc(ifp) ^ fgetc(ifp) ^ fgetc(ifp); - if ((NikonLensDataVersion > 200) && lenNikonLensData) - { - if (custom_serial) - { - ci = xlat[0][custom_serial]; - } - else - { - ci = xlat[0][serial & 0xff]; - } - cj = xlat[1][NikonKey]; - ck = 0x60; - for (i = 0; i < lenNikonLensData; i++) - table_buf[i] ^= (cj += ci * ck++); - processNikonLensData(table_buf, lenNikonLensData); - lenNikonLensData = 0; - free(table_buf); - } + imgdata.color.WB_Coeffs[i][1] = imgdata.color.WB_Coeffs[i][3] = 0x100; } - else if (tag == 0x00a8) // contains flash data + } + nWB = tag - 0x20400101; + tWB = Oly_wb_list2[nWB << 1]; + ushort CT = Oly_wb_list2[(nWB << 1) | 1]; + int wb[4]; + wb[0] = get2(); + wb[2] = get2(); + if (tWB != 0x100) + { + imgdata.color.WB_Coeffs[tWB][0] = wb[0]; + imgdata.color.WB_Coeffs[tWB][2] = wb[2]; + } + if (CT) + { + imgdata.color.WBCT_Coeffs[nWB - 1][0] = CT; + imgdata.color.WBCT_Coeffs[nWB - 1][1] = wb[0]; + imgdata.color.WBCT_Coeffs[nWB - 1][3] = wb[2]; + } + if (len == 4) + { + wb[1] = get2(); + wb[3] = get2(); + if (tWB != 0x100) { - for (i = 0; i < 4; i++) - { - NikonFlashInfoVersion = NikonFlashInfoVersion * 10 + fgetc(ifp) - '0'; - } + imgdata.color.WB_Coeffs[tWB][1] = wb[1]; + imgdata.color.WB_Coeffs[tWB][3] = wb[3]; } - - else if (tag == 37 && (!iso_speed || iso_speed == 65535)) + if (CT) { - unsigned char cc; - fread(&cc, 1, 1, ifp); - iso_speed = (int)(100.0 * libraw_powf64(2.0, (double)(cc) / 12.0 - 5.0)); - break; + imgdata.color.WBCT_Coeffs[nWB - 1][2] = wb[1]; + imgdata.color.WBCT_Coeffs[nWB - 1][4] = wb[3]; } + } + } + else if ((tag >= 0x20400112) && (tag <= 0x2040011e)) + { + nWB = tag - 0x20400112; + int wbG = get2(); + tWB = Oly_wb_list2[nWB << 1]; + if (nWB) + imgdata.color.WBCT_Coeffs[nWB - 1][2] = imgdata.color.WBCT_Coeffs[nWB - 1][4] = wbG; + if (tWB != 0x100) + imgdata.color.WB_Coeffs[tWB][1] = imgdata.color.WB_Coeffs[tWB][3] = wbG; + } + else if (tag == 0x2040011f) + { + int wbG = get2(); + if (imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][0]) + imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][3] = wbG; + FORC4 if (imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom1 + c][0]) + imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom1 + c][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom1 + c][3] = + wbG; + } + else if (tag == 0x20400121) + { + imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][0] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][2] = get2(); + if (len == 4) + { + imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][1] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][3] = get2(); + } + } + else if ((tag == 0x30000110) && strcmp(software, "v757-71")) + { + imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][0] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][2] = get2(); + if (len == 2) + { + for (int i = 0; i < 256; i++) + imgdata.color.WB_Coeffs[i][1] = imgdata.color.WB_Coeffs[i][3] = 0x100; + } } - - else if (!strncmp(make, "OLYMPUS", 7)) + else if ((((tag >= 0x30000120) && (tag <= 0x30000124)) || ((tag >= 0x30000130) && (tag <= 0x30000133))) && + strcmp(software, "v757-71")) { - int SubDirOffsetValid = - strncmp (model, "E-300", 5) && - strncmp (model, "E-330", 5) && - strncmp (model, "E-400", 5) && - strncmp (model, "E-500", 5) && - strncmp (model, "E-1", 3); - - if ((tag == 0x2010) || (tag == 0x2020)) - { - fseek(ifp, save - 4, SEEK_SET); - fseek(ifp, base + get4(), SEEK_SET); - parse_makernote_0xc634(base, tag, dng_writer); - } - if (!SubDirOffsetValid && - ((len > 4) || - ( ((type == 3) || (type == 8)) && (len > 2)) || - ( ((type == 4) || (type == 9)) && (len > 1)) || (type == 5) || (type > 9))) - goto skip_Oly_broken_tags; - - switch (tag) { + int wb_ind; + if (tag <= 0x30000124) + wb_ind = tag - 0x30000120; + else + wb_ind = tag - 0x30000130 + 5; + imgdata.color.WB_Coeffs[Oly_wb_list1[wb_ind]][0] = get2(); + imgdata.color.WB_Coeffs[Oly_wb_list1[wb_ind]][2] = get2(); + } + else + { + switch (tag) + { case 0x0207: case 0x20100100: + { + uchar sOlyID[8]; + fread(sOlyID, MIN(len, 7), 1, ifp); + sOlyID[7] = 0; + OlyID = sOlyID[0]; + i = 1; + while (i < 7 && sOlyID[i]) { - uchar sOlyID[8]; - unsigned long long OlyID; - fread (sOlyID, MIN(len,7), 1, ifp); - sOlyID[7] = 0; - OlyID = sOlyID[0]; - i = 1; - while (i < 7 && sOlyID[i]) - { - OlyID = OlyID << 8 | sOlyID[i]; - i++; - } - setOlympusBodyFeatures(OlyID); + OlyID = OlyID << 8 | sOlyID[i]; + i++; } - break; + setOlympusBodyFeatures(OlyID); + } + break; case 0x1002: - imgdata.lens.makernotes.CurAp = libraw_powf64(2.0f, getreal(type)/2); + imgdata.lens.makernotes.CurAp = libraw_powf64l(2.0f, getreal(type) / 2); break; case 0x20100102: - stmread(imgdata.shootinginfo.InternalBodySerial, len, ifp); - break; + stmread(imgdata.shootinginfo.InternalBodySerial, len, ifp); + break; case 0x20100201: - imgdata.lens.makernotes.LensID = - (unsigned long long)fgetc(ifp)<<16 | - (unsigned long long)(fgetc(ifp), fgetc(ifp))<<8 | - (unsigned long long)fgetc(ifp); + imgdata.lens.makernotes.LensID = (unsigned long long)fgetc(ifp) << 16 | + (unsigned long long)(fgetc(ifp), fgetc(ifp)) << 8 | + (unsigned long long)fgetc(ifp); imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FT; imgdata.lens.makernotes.LensFormat = LIBRAW_FORMAT_FT; - if (((imgdata.lens.makernotes.LensID < 0x20000) || - (imgdata.lens.makernotes.LensID > 0x4ffff)) && + if (((imgdata.lens.makernotes.LensID < 0x20000) || (imgdata.lens.makernotes.LensID > 0x4ffff)) && (imgdata.lens.makernotes.LensID & 0x10)) - { - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_mFT; - } + { + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_mFT; + } break; case 0x20100202: if ((!imgdata.lens.LensSerial[0])) - stmread(imgdata.lens.LensSerial, len, ifp); + stmread(imgdata.lens.LensSerial, len, ifp); break; case 0x20100203: - stmread(imgdata.lens.makernotes.Lens,len, ifp); + stmread(imgdata.lens.makernotes.Lens, len, ifp); break; case 0x20100205: - imgdata.lens.makernotes.MaxAp4MinFocal = libraw_powf64(sqrt(2.0f), get2() / 256.0f); + imgdata.lens.makernotes.MaxAp4MinFocal = libraw_powf64l(sqrt(2.0f), get2() / 256.0f); break; case 0x20100206: - imgdata.lens.makernotes.MaxAp4MaxFocal = libraw_powf64(sqrt(2.0f), get2() / 256.0f); + imgdata.lens.makernotes.MaxAp4MaxFocal = libraw_powf64l(sqrt(2.0f), get2() / 256.0f); break; case 0x20100207: imgdata.lens.makernotes.MinFocal = (float)get2(); break; case 0x20100208: imgdata.lens.makernotes.MaxFocal = (float)get2(); if (imgdata.lens.makernotes.MaxFocal > 1000.0f) imgdata.lens.makernotes.MaxFocal = imgdata.lens.makernotes.MinFocal; break; case 0x2010020a: - imgdata.lens.makernotes.MaxAp4CurFocal = libraw_powf64(sqrt(2.0f), get2() / 256.0f); + imgdata.lens.makernotes.MaxAp4CurFocal = libraw_powf64l(sqrt(2.0f), get2() / 256.0f); break; case 0x20100301: imgdata.lens.makernotes.TeleconverterID = fgetc(ifp) << 8; fgetc(ifp); - imgdata.lens.makernotes.TeleconverterID = - imgdata.lens.makernotes.TeleconverterID | fgetc(ifp); + imgdata.lens.makernotes.TeleconverterID = imgdata.lens.makernotes.TeleconverterID | fgetc(ifp); break; case 0x20100303: stmread(imgdata.lens.makernotes.Teleconverter, len, ifp); break; case 0x20100403: - stmread(imgdata.lens.makernotes.Attachment,len, ifp); + stmread(imgdata.lens.makernotes.Attachment, len, ifp); break; - case 0x20200401: - imgdata.other.FlashEC = getreal(type); - break; + case 0x20200306: + { + uchar uc; + fread(&uc, 1, 1, ifp); + imgdata.makernotes.olympus.AFFineTune = uc; } - skip_Oly_broken_tags:; - } - - else if (!strncmp(make, "PENTAX", 6) || - !strncmp(model, "PENTAX", 6) || - (!strncmp(make, "SAMSUNG", 7) && (dng_writer == CameraDNG))) - { - if (tag == 0x0005) - { - unique_id = get4(); - setPentaxBodyFeatures(unique_id); - } - else if (tag == 0x0013) - { - imgdata.lens.makernotes.CurAp = (float)get2()/10.0f; - } - else if (tag == 0x0014) - { - PentaxISO(get2()); - } - else if (tag == 0x001d) - { - imgdata.lens.makernotes.CurFocal = (float)get4()/100.0f; - } - else if (tag == 0x003f) - { - imgdata.lens.makernotes.LensID = fgetc(ifp) << 8 | fgetc(ifp); - } - else if (tag == 0x004d) + break; + case 0x20200307: + FORC3 imgdata.makernotes.olympus.AFFineTuneAdj[c] = get2(); + break; + case 0x20200401: + imgdata.other.FlashEC = getreal(type); + break; + case 0x1007: + imgdata.other.SensorTemperature = (float)get2(); + break; + case 0x1008: + imgdata.other.LensTemperature = (float)get2(); + break; + case 0x20401306: + { + int temp = get2(); + if ((temp != 0) && (temp != 100)) { - if (type == 9) imgdata.other.FlashEC = getreal(type) / 256.0f; - else imgdata.other.FlashEC = (float) ((signed short) fgetc(ifp)) / 6.0f; + if (temp < 61) + imgdata.other.CameraTemperature = (float)temp; + else + imgdata.other.CameraTemperature = (float)(temp - 32) / 1.8f; + if ((OlyID == 0x4434353933ULL) && // TG-5 + (imgdata.other.exifAmbientTemperature > -273.15f)) + imgdata.other.CameraTemperature += imgdata.other.exifAmbientTemperature; } - else if (tag == 0x007e) - { - imgdata.color.linear_max[0] = - imgdata.color.linear_max[1] = - imgdata.color.linear_max[2] = - imgdata.color.linear_max[3] = (long)(-1) * get4(); - } - else if (tag == 0x0207) + } + break; + case 0x20501500: + if (OlyID != 0x0ULL) { - if(len < 65535) // Safety belt - PentaxLensInfo(imgdata.lens.makernotes.CamID, len); + short temp = get2(); + if ((OlyID == 0x4434303430ULL) || // E-1 + (OlyID == 0x5330303336ULL) || // E-M5 + (len != 1)) + imgdata.other.SensorTemperature = (float)temp; + else if ((temp != -32768) && (temp != 0)) + { + if (temp > 199) + imgdata.other.SensorTemperature = 86.474958f - 0.120228f * (float)temp; + else + imgdata.other.SensorTemperature = (float)temp; + } } - else if (tag == 0x020d) - { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][c ^ (c >> 1)] = get2(); - } - else if (tag == 0x020e) - { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][c ^ (c >> 1)] = get2(); - } - else if (tag == 0x020f) - { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][c ^ (c >> 1)] = get2(); - } - else if (tag == 0x0210) - { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][c ^ (c >> 1)] = get2(); - } - else if (tag == 0x0211) - { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][c ^ (c >> 1)] = get2(); + break; } - else if (tag == 0x0212) + } + skip_Oly_broken_tags:; + } + + else if (!strncmp(make, "PENTAX", 6) || !strncmp(model, "PENTAX", 6) || + (!strncmp(make, "SAMSUNG", 7) && (dng_writer == CameraDNG))) + { + if (tag == 0x0005) + { + unique_id = get4(); + setPentaxBodyFeatures(unique_id); + } + else if (tag == 0x000d) + { + imgdata.makernotes.pentax.FocusMode = get2(); + } + else if (tag == 0x000e) + { + imgdata.makernotes.pentax.AFPointSelected = get2(); + } + else if (tag == 0x000f) + { + imgdata.makernotes.pentax.AFPointsInFocus = getint(type); + } + else if (tag == 0x0010) + { + imgdata.makernotes.pentax.FocusPosition = get2(); + } + else if (tag == 0x0013) + { + imgdata.lens.makernotes.CurAp = (float)get2() / 10.0f; + } + else if (tag == 0x0014) + { + PentaxISO(get2()); + } + else if (tag == 0x001d) + { + imgdata.lens.makernotes.CurFocal = (float)get4() / 100.0f; + } + else if (tag == 0x0034) + { + uchar uc; + FORC4 { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][c ^ (c >> 1)] = get2(); + fread(&uc, 1, 1, ifp); + imgdata.makernotes.pentax.DriveMode[c] = uc; } - else if (tag == 0x0213) + } + else if (tag == 0x0038) + { + imgdata.sizes.raw_crop.cleft = get2(); + imgdata.sizes.raw_crop.ctop = get2(); + } + else if (tag == 0x0039) + { + imgdata.sizes.raw_crop.cwidth = get2(); + imgdata.sizes.raw_crop.cheight = get2(); + } + else if (tag == 0x003f) + { + imgdata.lens.makernotes.LensID = fgetc(ifp) << 8 | fgetc(ifp); + } + else if (tag == 0x0047) + { + imgdata.other.CameraTemperature = (float)fgetc(ifp); + } + else if (tag == 0x004d) + { + if (type == 9) + imgdata.other.FlashEC = getreal(type) / 256.0f; + else + imgdata.other.FlashEC = (float)((signed short)fgetc(ifp)) / 6.0f; + } + else if (tag == 0x0072) + { + imgdata.makernotes.pentax.AFAdjustment = get2(); + } + else if (tag == 0x007e) + { + imgdata.color.linear_max[0] = imgdata.color.linear_max[1] = imgdata.color.linear_max[2] = + imgdata.color.linear_max[3] = (long)(-1) * get4(); + } + else if (tag == 0x0207) + { + if (len < 65535) // Safety belt + PentaxLensInfo(imgdata.lens.makernotes.CamID, len); + } + else if ((tag >= 0x020d) && (tag <= 0x0214)) + { + FORC4 imgdata.color.WB_Coeffs[Pentax_wb_list1[tag - 0x020d]][c ^ (c >> 1)] = get2(); + } + else if (tag == 0x0221) + { + int nWB = get2(); + if (nWB <= sizeof(imgdata.color.WBCT_Coeffs) / sizeof(imgdata.color.WBCT_Coeffs[0])) + for (int i = 0; i < nWB; i++) + { + imgdata.color.WBCT_Coeffs[i][0] = (unsigned)0xcfc6 - get2(); + fseek(ifp, 2, SEEK_CUR); + imgdata.color.WBCT_Coeffs[i][1] = get2(); + imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] = 0x2000; + imgdata.color.WBCT_Coeffs[i][3] = get2(); + } + } + else if (tag == 0x0215) + { + fseek(ifp, 16, SEEK_CUR); + sprintf(imgdata.shootinginfo.InternalBodySerial, "%d", get4()); + } + else if (tag == 0x0229) + { + stmread(imgdata.shootinginfo.BodySerial, len, ifp); + } + else if (tag == 0x022d) + { + int wb_ind; + getc(ifp); + for (int wb_cnt = 0; wb_cnt < nPentax_wb_list2; wb_cnt++) { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][c ^ (c >> 1)] = get2(); + wb_ind = getc(ifp); + if (wb_ind < nPentax_wb_list2) + FORC4 imgdata.color.WB_Coeffs[Pentax_wb_list2[wb_ind]][c ^ (c >> 1)] = get2(); } - else if (tag == 0x0214) + } + else if (tag == 0x0239) // Q-series lens info (LensInfoQ) + { + char LensInfo[20]; + fseek(ifp, 12, SEEK_CUR); + stread(imgdata.lens.makernotes.Lens, 30, ifp); + strcat(imgdata.lens.makernotes.Lens, " "); + stread(LensInfo, 20, ifp); + strcat(imgdata.lens.makernotes.Lens, LensInfo); + } + } + + else if (!strncmp(make, "SAMSUNG", 7) && (dng_writer == AdobeDNG)) + { + if (tag == 0x0002) + { + if (get4() == 0x2000) { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][c ^ (c >> 1)] = get2(); + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Samsung_NX; } - else if (tag == 0x0221) + else if (!strncmp(model, "NX mini", 7)) { - int nWB = get2(); - if(nWB<=sizeof(imgdata.color.WBCT_Coeffs)/sizeof(imgdata.color.WBCT_Coeffs[0])) - for (int i = 0; i < nWB; i++) - { - imgdata.color.WBCT_Coeffs[i][0] = (unsigned)0xcfc6 - get2(); - fseek(ifp, 2, SEEK_CUR); - imgdata.color.WBCT_Coeffs[i][1] = get2(); - imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] = 0x2000; - imgdata.color.WBCT_Coeffs[i][3] = get2(); - } + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Samsung_NX_M; } - else if (tag == 0x0215) + else { - fseek (ifp, 16, SEEK_CUR); - sprintf(imgdata.shootinginfo.InternalBodySerial, "%d", get4()); + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; } - else if (tag == 0x0229) + } + else if (tag == 0x0003) + { + imgdata.lens.makernotes.CamID = unique_id = get4(); + } + else if (tag == 0x0043) + { + int temp = get4(); + if (temp) { - stmread(imgdata.shootinginfo.BodySerial, len, ifp); + imgdata.other.CameraTemperature = (float)temp; + if (get4() == 10) + imgdata.other.CameraTemperature /= 10.0f; } - else if (tag == 0x022d) - { - fseek (ifp,2,SEEK_CUR); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][c ^ (c >> 1)] = get2(); - getc(ifp); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][c ^ (c >> 1)] = get2(); - getc(ifp); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][c ^ (c >> 1)] = get2(); - getc(ifp); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][c ^ (c >> 1)] = get2(); - getc(ifp); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][c ^ (c >> 1)] = get2(); - getc(ifp); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][c ^ (c >> 1)] = get2(); - getc(ifp); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][c ^ (c >> 1)] = get2(); - getc(ifp); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][c ^ (c >> 1)] = get2(); - getc(ifp); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][c ^ (c >> 1)] = get2(); - } - else if (tag == 0x0239) // Q-series lens info (LensInfoQ) - { - char LensInfo [20]; - fseek (ifp, 12, SEEK_CUR); - stread(imgdata.lens.makernotes.Lens, 30, ifp); - strcat(imgdata.lens.makernotes.Lens, " "); - stread(LensInfo, 20, ifp); - strcat(imgdata.lens.makernotes.Lens, LensInfo); - } } - - else if (!strncmp(make, "SAMSUNG", 7) && - (dng_writer == AdobeDNG)) + else if (tag == 0xa003) { - if (tag == 0x0002) - { - if(get4() == 0x2000) - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Samsung_NX; - } - else if (!strncmp(model, "NX mini", 7)) - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Samsung_NX_M; - } - else - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; - } - } - else if (tag == 0x0003) - { - imgdata.lens.makernotes.CamID = unique_id = get4(); - } - else if (tag == 0xa003) - { - imgdata.lens.makernotes.LensID = get2(); - if (imgdata.lens.makernotes.LensID) - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Samsung_NX; - } - else if (tag == 0xa005) - { - stmread(imgdata.lens.InternalLensSerial, len, ifp); - } - else if (tag == 0xa019) - { - imgdata.lens.makernotes.CurAp = getreal(type); - } - else if (tag == 0xa01a) - { - imgdata.lens.makernotes.FocalLengthIn35mmFormat = get4() / 10.0f; - if (imgdata.lens.makernotes.FocalLengthIn35mmFormat < 10.0f) - imgdata.lens.makernotes.FocalLengthIn35mmFormat *= 10.0f; - } + imgdata.lens.makernotes.LensID = get2(); + if (imgdata.lens.makernotes.LensID) + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Samsung_NX; } - - else if (!strncasecmp(make, "SONY", 4) || - !strncasecmp(make, "Konica", 6) || - !strncasecmp(make, "Minolta", 7) || - (!strncasecmp(make, "Hasselblad", 10) && - (!strncasecmp(model, "Stellar", 7) || - !strncasecmp(model, "Lunar", 5) || - !strncasecmp(model, "Lusso", 5) || - !strncasecmp(model, "HV",2)))) + else if (tag == 0xa005) { - ushort lid; - - if (tag == 0xb001) // Sony ModelID - { - unique_id = get2(); - setSonyBodyFeatures(unique_id); - if (table_buf_0x9050_present) - { - process_Sony_0x9050(table_buf_0x9050, unique_id); - free (table_buf_0x9050); - table_buf_0x9050_present = 0; - } - if (table_buf_0x940c_present) - { - if (imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Sony_E) - { - process_Sony_0x940c(table_buf_0x940c); - } - free (table_buf_0x940c); - table_buf_0x940c_present = 0; - } - } - else if ((tag == 0x0010) && // CameraInfo - strncasecmp(model, "DSLR-A100", 9) && - strncasecmp(model, "NEX-5C", 6) && - !strncasecmp(make, "SONY", 4) && - ((len == 368) || // a700 - (len == 5478) || // a850, a900 - (len == 5506) || // a200, a300, a350 - (len == 6118) || // a230, a290, a330, a380, a390 - - // a450, a500, a550, a560, a580 - // a33, a35, a55 - // NEX3, NEX5, NEX5C, NEXC3, VG10E - (len == 15360)) - ) - { - table_buf = (uchar*)malloc(len); - fread(table_buf, len, 1, ifp); - if (memcmp(table_buf, "\xff\xff\xff\xff\xff\xff\xff\xff", 8) && - memcmp(table_buf, "\x00\x00\x00\x00\x00\x00\x00\x00", 8)) - { - switch (len) { - case 368: - case 5478: - // a700, a850, a900: CameraInfo - if (saneSonyCameraInfo(table_buf[0], table_buf[3], table_buf[2], table_buf[5], table_buf[4], table_buf[7])) - { - if (table_buf[0] | table_buf[3]) - imgdata.lens.makernotes.MinFocal = - bcd2dec(table_buf[0]) * 100 + bcd2dec(table_buf[3]); - if (table_buf[2] | table_buf[5]) - imgdata.lens.makernotes.MaxFocal = - bcd2dec(table_buf[2]) * 100 + bcd2dec(table_buf[5]); - if (table_buf[4]) - imgdata.lens.makernotes.MaxAp4MinFocal = bcd2dec(table_buf[4]) / 10.0f; - if (table_buf[4]) - imgdata.lens.makernotes.MaxAp4MaxFocal = bcd2dec(table_buf[7]) / 10.0f; - parseSonyLensFeatures(table_buf[1], table_buf[6]); - } - break; - default: - // CameraInfo2 & 3 - if (saneSonyCameraInfo(table_buf[1], table_buf[2], table_buf[3], table_buf[4], table_buf[5], table_buf[6])) - { - if (table_buf[1] | table_buf[2]) - imgdata.lens.makernotes.MinFocal = - bcd2dec(table_buf[1]) * 100 + bcd2dec(table_buf[2]); - if (table_buf[3] | table_buf[4]) - imgdata.lens.makernotes.MaxFocal = - bcd2dec(table_buf[3]) * 100 + bcd2dec(table_buf[4]); - if (table_buf[5]) - imgdata.lens.makernotes.MaxAp4MinFocal = bcd2dec(table_buf[5]) / 10.0f; - if (table_buf[6]) - imgdata.lens.makernotes.MaxAp4MaxFocal = bcd2dec(table_buf[6]) / 10.0f; - parseSonyLensFeatures(table_buf[0], table_buf[7]); - } - } - } - free(table_buf); - } - - else if (tag == 0x0104) - { - imgdata.other.FlashEC = getreal(type); - } - - else if (tag == 0x0105) // Teleconverter - { - imgdata.lens.makernotes.TeleconverterID = get2(); - } - - else if (tag == 0x0114 && len < 65535) // CameraSettings - { - table_buf = (uchar*)malloc(len); - fread(table_buf, len, 1, ifp); - switch (len) { - case 280: - case 364: - case 332: - // CameraSettings and CameraSettings2 are big endian - if (table_buf[2] | table_buf[3]) - { - lid = (((ushort)table_buf[2])<<8) | - ((ushort)table_buf[3]); - imgdata.lens.makernotes.CurAp = - libraw_powf64(2.0f, ((float)lid/8.0f-1.0f)/2.0f); - } - break; - case 1536: - case 2048: - // CameraSettings3 are little endian - parseSonyLensType2(table_buf[1016], table_buf[1015]); - if (imgdata.lens.makernotes.LensMount != LIBRAW_MOUNT_Canon_EF) - { - switch (table_buf[153]) { - case 16: imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Minolta_A; break; - case 17: imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sony_E; break; - } - } - break; - } - free(table_buf); - } - - else if (tag == 0x9050 && len < 256000) // little endian - { - table_buf_0x9050 = (uchar*)malloc(len); - table_buf_0x9050_present = 1; - fread(table_buf_0x9050, len, 1, ifp); - - if (imgdata.lens.makernotes.CamID) - { - process_Sony_0x9050(table_buf_0x9050, imgdata.lens.makernotes.CamID); - free (table_buf_0x9050); - table_buf_0x9050_present = 0; - } - } - - else if (tag == 0x940c && len < 256000) - { - table_buf_0x940c = (uchar*)malloc(len); - table_buf_0x940c_present = 1; - fread(table_buf_0x940c, len, 1, ifp); - if ((imgdata.lens.makernotes.CamID) && - (imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Sony_E)) - { - process_Sony_0x940c(table_buf_0x940c); - free(table_buf_0x940c); - table_buf_0x940c_present = 0; - } - } - - else if (((tag == 0xb027) || (tag == 0x010c)) && (imgdata.lens.makernotes.LensID == -1)) - { - imgdata.lens.makernotes.LensID = get4(); - if ((imgdata.lens.makernotes.LensID > 0x4900) && - (imgdata.lens.makernotes.LensID <= 0x5900)) - { - imgdata.lens.makernotes.AdapterID = 0x4900; - imgdata.lens.makernotes.LensID -= imgdata.lens.makernotes.AdapterID; - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sigma_X3F; - strcpy(imgdata.lens.makernotes.Adapter, "MC-11"); - } - - else if ((imgdata.lens.makernotes.LensID > 0xEF00) && - (imgdata.lens.makernotes.LensID < 0xFFFF) && - (imgdata.lens.makernotes.LensID != 0xFF00)) - { - imgdata.lens.makernotes.AdapterID = 0xEF00; - imgdata.lens.makernotes.LensID -= imgdata.lens.makernotes.AdapterID; - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF; - } - if (tag == 0x010c) imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Minolta_A; - } - - else if (tag == 0xb02a && len < 256000) // Sony LensSpec - { - table_buf = (uchar*)malloc(len); - fread(table_buf, len, 1, ifp); - if (saneSonyCameraInfo(table_buf[1], table_buf[2], table_buf[3], table_buf[4], table_buf[5], table_buf[6])) - { - if (table_buf[1] | table_buf[2]) - imgdata.lens.makernotes.MinFocal = - bcd2dec(table_buf[1]) * 100 + bcd2dec(table_buf[2]); - if (table_buf[3] | table_buf[4]) - imgdata.lens.makernotes.MaxFocal = - bcd2dec(table_buf[3]) * 100 + bcd2dec(table_buf[4]); - if (table_buf[5]) - imgdata.lens.makernotes.MaxAp4MinFocal = bcd2dec(table_buf[5]) / 10.0f; - if (table_buf[6]) - imgdata.lens.makernotes.MaxAp4MaxFocal = bcd2dec(table_buf[6]) / 10.0f; - parseSonyLensFeatures(table_buf[0], table_buf[7]); - } - free(table_buf); - } + stmread(imgdata.lens.InternalLensSerial, len, ifp); + } + else if (tag == 0xa019) + { + imgdata.lens.makernotes.CurAp = getreal(type); + } + else if (tag == 0xa01a) + { + imgdata.lens.makernotes.FocalLengthIn35mmFormat = get4() / 10.0f; + if (imgdata.lens.makernotes.FocalLengthIn35mmFormat < 10.0f) + imgdata.lens.makernotes.FocalLengthIn35mmFormat *= 10.0f; } + } + + else if (!strncasecmp(make, "SONY", 4) || !strncasecmp(make, "Konica", 6) || !strncasecmp(make, "Minolta", 7) || + (!strncasecmp(make, "Hasselblad", 10) && + (!strncasecmp(model, "Stellar", 7) || !strncasecmp(model, "Lunar", 5) || + !strncasecmp(model, "Lusso", 5) || !strncasecmp(model, "HV", 2)))) + { + parseSonyMakernotes(tag, type, len, AdobeDNG, table_buf_0x0116, table_buf_0x0116_len, table_buf_0x2010, + table_buf_0x2010_len, table_buf_0x9050, table_buf_0x9050_len, table_buf_0x9400, + table_buf_0x9400_len, table_buf_0x9402, table_buf_0x9402_len, table_buf_0x9403, + table_buf_0x9403_len, table_buf_0x9406, table_buf_0x9406_len, table_buf_0x940c, + table_buf_0x940c_len, table_buf_0x940e, table_buf_0x940e_len); + } next: - fseek (ifp, save, SEEK_SET); + fseek(ifp, save, SEEK_SET); } - quit: +quit: order = sorder; } #else void CLASS parse_makernote_0xc634(int base, int uptag, unsigned dng_writer) -{ - /*placeholder */ +{ /*placeholder */ } #endif - -void CLASS parse_makernote (int base, int uptag) +void CLASS parse_makernote(int base, int uptag) { - unsigned offset=0, entries, tag, type, len, save, c; - unsigned ver97=0, serial=0, i, wbi=0, wb[4]={0,0,0,0}; + 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; + short morder, sorder = order; char buf[10]; unsigned SamsungKey[11]; uchar NikonKey; #ifdef LIBRAW_LIBRARY_BUILD unsigned custom_serial = 0; unsigned NikonLensDataVersion = 0; unsigned lenNikonLensData = 0; unsigned NikonFlashInfoVersion = 0; uchar *CanonCameraInfo; unsigned lenCanonCameraInfo = 0; + unsigned typeCanonCameraInfo = 0; uchar *table_buf; + uchar *table_buf_0x0116; + ushort table_buf_0x0116_len = 0; + uchar *table_buf_0x2010; + ushort table_buf_0x2010_len = 0; uchar *table_buf_0x9050; - ushort table_buf_0x9050_present = 0; + ushort table_buf_0x9050_len = 0; + uchar *table_buf_0x9400; + ushort table_buf_0x9400_len = 0; + uchar *table_buf_0x9402; + ushort table_buf_0x9402_len = 0; + uchar *table_buf_0x9403; + ushort table_buf_0x9403_len = 0; + uchar *table_buf_0x9406; + ushort table_buf_0x9406_len = 0; uchar *table_buf_0x940c; - ushort table_buf_0x940c_present = 0; + ushort table_buf_0x940c_len = 0; + uchar *table_buf_0x940e; + ushort table_buf_0x940e_len = 0; INT64 fsize = ifp->size(); #endif -/* - The MakerNote might have its own TIFF header (possibly with - its own byte-order!), or it might just be a table. - */ - if (!strncmp(make,"Nokia",5)) 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 */ + /* + The MakerNote might have its own TIFF header (possibly with + its own byte-order!), or it might just be a table. + */ + if (!strncmp(make, "Nokia", 5)) + return; + fread(buf, 1, 10, ifp); + + /* + printf("===>>buf: 0x"); + for (int i = 0; i < sizeof buf; i ++) { + printf("%02x", buf[i]); + } + putchar('\n'); + */ + + 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]; + 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]; + 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")) { + if (!strcmp(buf, "Nikon")) + { base = ftell(ifp); order = get2(); - if (get2() != 42) goto quit; + 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); + 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")) { + 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)) + } + 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); } // adjust pos & base for Leica M8/M9/M Mono tags and dir in tag 0x3400 if (!strncasecmp(make, "LEICA", 5)) + { + if (!strncmp(model, "M8", 2) || !strncasecmp(model, "Leica M8", 8) || !strncasecmp(model, "LEICA X", 7)) { - if (!strncmp(model, "M8", 2) || - !strncasecmp(model, "Leica M8", 8) || - !strncasecmp(model, "LEICA X", 7)) - { - base = ftell(ifp)-8; - } - else if (!strncasecmp(model, "LEICA M (Typ 240)", 17)) - { - base = 0; - } - else if (!strncmp(model, "M9", 2) || - !strncasecmp(model, "Leica M9", 8) || - !strncasecmp(model, "M Monochrom", 11) || - !strncasecmp(model, "Leica M Monochrom", 11)) - { - if (!uptag) - { - base = ftell(ifp) - 10; - fseek (ifp, 8, SEEK_CUR); - } - else if (uptag == 0x3400) - { - fseek (ifp, 10, SEEK_CUR); - base += 10; - } - } - else if (!strncasecmp(model, "LEICA T", 7)) - { - base = ftell(ifp)-8; + base = ftell(ifp) - 8; + } + else if (!strncasecmp(model, "LEICA M (Typ 240)", 17)) + { + base = 0; + } + else if (!strncmp(model, "M9", 2) || !strncasecmp(model, "Leica M9", 8) || !strncasecmp(model, "M Monochrom", 11) || + !strncasecmp(model, "Leica M Monochrom", 11)) + { + if (!uptag) + { + base = ftell(ifp) - 10; + fseek(ifp, 8, SEEK_CUR); + } + else if (uptag == 0x3400) + { + fseek(ifp, 10, SEEK_CUR); + base += 10; + } + } + else if (!strncasecmp(model, "LEICA T", 7)) + { + base = ftell(ifp) - 8; #ifdef LIBRAW_LIBRARY_BUILD - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_T; + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_T; #endif - } + } #ifdef LIBRAW_LIBRARY_BUILD - else if (!strncasecmp(model, "LEICA SL", 8)) - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_SL; - imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_FF; - } -#endif + else if (!strncasecmp(model, "LEICA SL", 8)) + { + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_SL; + imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_FF; } +#endif + } entries = get2(); - if (entries > 1000) return; + if (entries > 1000) + return; morder = order; - while (entries--) { + while (entries--) + { order = morder; - tiff_get (base, &tag, &type, &len, &save); + tiff_get(base, &tag, &type, &len, &save); tag |= uptag << 16; #ifdef LIBRAW_LIBRARY_BUILD INT64 _pos = ftell(ifp); - if(len > 8 && _pos+len > 2* fsize) continue; - if (!strncmp(make, "Canon",5)) + if (len > 8 && _pos + len > 2 * fsize) + { + fseek(ifp, save, SEEK_SET); // Recover tiff-read position!! + continue; + } + if (!strncasecmp(model, "KODAK P880", 10) || !strncasecmp(model, "KODAK P850", 10) || + !strncasecmp(model, "KODAK P712", 10)) + { + if (tag == 0xf90b) { - if (tag == 0x000d && len < 256000) // camera info - { - CanonCameraInfo = (uchar*)malloc(MAX(16,len)); - fread(CanonCameraInfo, len, 1, ifp); - lenCanonCameraInfo = len; - } - - else if (tag == 0x10) // Canon ModelID - { - unique_id = get4(); - if (unique_id == 0x03740000) unique_id = 0x80000374; // M3 - if (unique_id == 0x03840000) unique_id = 0x80000384; // M10 - if (unique_id == 0x03940000) unique_id = 0x80000394; // M5 - setCanonBodyFeatures(unique_id); - if (lenCanonCameraInfo) - { - processCanonCameraInfo(unique_id, CanonCameraInfo,lenCanonCameraInfo); - free(CanonCameraInfo); - CanonCameraInfo = 0; - lenCanonCameraInfo = 0; - } - } - - else parseCanonMakernotes (tag, type, len); - } - - else if (!strncmp(make, "FUJI", 4)) { - if (tag == 0x0010) { - char FujiSerial[sizeof(imgdata.shootinginfo.InternalBodySerial)]; - char *words[4]; - char yy[2], mm[3], dd[3], ystr[16], ynum[16]; - int year, nwords, ynum_len; - unsigned c; - stmread(FujiSerial, len, ifp); - nwords = getwords(FujiSerial, words, 4,sizeof(imgdata.shootinginfo.InternalBodySerial)); - for (int i = 0; i < nwords; i++) { - mm[2] = dd[2] = 0; - if (strnlen(words[i],sizeof(imgdata.shootinginfo.InternalBodySerial)-1) < 18) - if (i == 0) - strncpy (imgdata.shootinginfo.InternalBodySerial, - words[0], - sizeof(imgdata.shootinginfo.InternalBodySerial)-1); - else - { - char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)]; - snprintf (tbuf, sizeof(tbuf), "%s %s", - imgdata.shootinginfo.InternalBodySerial, words[i]); - strncpy(imgdata.shootinginfo.InternalBodySerial,tbuf, - sizeof(imgdata.shootinginfo.InternalBodySerial)-1); - } - else - { - strncpy (dd, words[i]+strnlen(words[i],sizeof(imgdata.shootinginfo.InternalBodySerial)-1)-14, 2); - strncpy (mm, words[i]+strnlen(words[i],sizeof(imgdata.shootinginfo.InternalBodySerial)-1)-16, 2); - strncpy (yy, words[i]+strnlen(words[i],sizeof(imgdata.shootinginfo.InternalBodySerial)-1)-18, 2); - year = (yy[0]-'0')*10 + (yy[1]-'0'); - if (year <70) year += 2000; else year += 1900; - - ynum_len = (int)strnlen(words[i],sizeof(imgdata.shootinginfo.InternalBodySerial)-1)-18; - strncpy(ynum, words[i], ynum_len); - ynum[ynum_len] = 0; - for ( int j = 0; ynum[j] && ynum[j+1] && sscanf(ynum+j, "%2x", &c); j += 2) ystr[j/2] = c; - ystr[ynum_len / 2 + 1] = 0; - strcpy (model2, ystr); - - if (i == 0) { - char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)]; - - if (nwords == 1) - snprintf (tbuf,sizeof(tbuf), - "%s %s %d:%s:%s", - words[0]+strnlen(words[0],sizeof(imgdata.shootinginfo.InternalBodySerial)-1)-12, - ystr, year, mm, dd); - - else - snprintf (tbuf,sizeof(tbuf), - "%s %d:%s:%s %s", - ystr, year, mm, dd, - words[0]+strnlen(words[0],sizeof(imgdata.shootinginfo.InternalBodySerial)-1)-12); - - strncpy(imgdata.shootinginfo.InternalBodySerial,tbuf, - sizeof(imgdata.shootinginfo.InternalBodySerial)-1); - } else { - char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)]; - snprintf (tbuf, sizeof(tbuf), - "%s %s %d:%s:%s %s", - imgdata.shootinginfo.InternalBodySerial, ystr, year, mm, dd, - words[i]+strnlen(words[i],sizeof(imgdata.shootinginfo.InternalBodySerial)-1)-12); - strncpy(imgdata.shootinginfo.InternalBodySerial,tbuf, - sizeof(imgdata.shootinginfo.InternalBodySerial)-1); - } - } - } + imgdata.makernotes.kodak.clipBlack = get2(); + } + else if (tag == 0xf90c) + { + imgdata.makernotes.kodak.clipWhite = get2(); } - else - parseFujiMakernotes (tag, type); } + if (!strncmp(make, "Canon", 5)) + { + if (tag == 0x000d && len < 256000) // camera info + { + if (type != 4) + { + CanonCameraInfo = (uchar *)malloc(MAX(16, len)); + fread(CanonCameraInfo, len, 1, ifp); + } + else + { + CanonCameraInfo = (uchar *)malloc(MAX(16, len * 4)); + fread(CanonCameraInfo, len, 4, ifp); + } + lenCanonCameraInfo = len; + typeCanonCameraInfo = type; + } - else if (!strncasecmp(make, "LEICA", 5)) + else if (tag == 0x10) // Canon ModelID { - if (((tag == 0x035e) || (tag == 0x035f)) && (type == 10) && (len == 9)) + unique_id = get4(); + unique_id = setCanonBodyFeatures(unique_id); + if (lenCanonCameraInfo) { - int ind = tag == 0x035e?0:1; - for (int j=0; j < 3; j++) - FORCC imgdata.color.dng_color[ind].forwardmatrix[j][c]= getreal(type); + processCanonCameraInfo(unique_id, CanonCameraInfo, lenCanonCameraInfo, typeCanonCameraInfo); + free(CanonCameraInfo); + CanonCameraInfo = 0; + lenCanonCameraInfo = 0; } + } - if ((tag == 0x0303) && (type != 4)) - { - stmread(imgdata.lens.makernotes.Lens, len, ifp); - } + else + parseCanonMakernotes(tag, type, len); + } - if ((tag == 0x3405) || - (tag == 0x0310) || - (tag == 0x34003405)) + else if (!strncmp(make, "FUJI", 4)) + { + if (tag == 0x0010) + { + char FujiSerial[sizeof(imgdata.shootinginfo.InternalBodySerial)]; + char *words[4]; + char yy[2], mm[3], dd[3], ystr[16], ynum[16]; + int year, nwords, ynum_len; + unsigned c; + stmread(FujiSerial, len, ifp); + nwords = getwords(FujiSerial, words, 4, sizeof(imgdata.shootinginfo.InternalBodySerial)); + for (int i = 0; i < nwords; i++) + { + mm[2] = dd[2] = 0; + if (strnlen(words[i], sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) < 18) + if (i == 0) + strncpy(imgdata.shootinginfo.InternalBodySerial, words[0], + sizeof(imgdata.shootinginfo.InternalBodySerial) - 1); + else + { + char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)]; + snprintf(tbuf, sizeof(tbuf), "%s %s", imgdata.shootinginfo.InternalBodySerial, words[i]); + strncpy(imgdata.shootinginfo.InternalBodySerial, tbuf, + sizeof(imgdata.shootinginfo.InternalBodySerial) - 1); + } + else { - imgdata.lens.makernotes.LensID = get4(); - imgdata.lens.makernotes.LensID = - ((imgdata.lens.makernotes.LensID>>2)<<8) | - (imgdata.lens.makernotes.LensID & 0x3); - if (imgdata.lens.makernotes.LensID != -1) - { - if ((model[0] == 'M') || - !strncasecmp (model, "LEICA M", 7)) - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_M; - if (imgdata.lens.makernotes.LensID) - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Leica_M; - } - else if ((model[0] == 'S') || - !strncasecmp (model, "LEICA S", 7)) - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_S; - if (imgdata.lens.makernotes.Lens[0]) - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Leica_S; - } - } - } + strncpy(dd, words[i] + strnlen(words[i], sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) - 14, 2); + strncpy(mm, words[i] + strnlen(words[i], sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) - 16, 2); + strncpy(yy, words[i] + strnlen(words[i], sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) - 18, 2); + year = (yy[0] - '0') * 10 + (yy[1] - '0'); + if (year < 70) + year += 2000; + else + year += 1900; - else if ( - ((tag == 0x0313) || (tag == 0x34003406)) && - (fabs(imgdata.lens.makernotes.CurAp) < 0.17f) && - ((type == 10) || (type == 5)) - ) - { - imgdata.lens.makernotes.CurAp = getreal(type); - if (imgdata.lens.makernotes.CurAp > 126.3) - imgdata.lens.makernotes.CurAp = 0.0f; - } + ynum_len = (int)strnlen(words[i], sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) - 18; + strncpy(ynum, words[i], ynum_len); + ynum[ynum_len] = 0; + for (int j = 0; ynum[j] && ynum[j + 1] && sscanf(ynum + j, "%2x", &c); j += 2) + ystr[j / 2] = c; + ystr[ynum_len / 2 + 1] = 0; + strcpy(model2, ystr); - else if (tag == 0x3400) - { - parse_makernote (base, 0x3400); - } - } + if (i == 0) + { + char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)]; - else if (!strncmp(make, "NIKON",5)) - { - if (tag == 0x000a) - { - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; - } - else if (tag == 0x0012) - { - char a, b, c; - a = fgetc(ifp); - b = fgetc(ifp); - c = fgetc(ifp); - if (c) imgdata.other.FlashEC = (float)(a*b)/(float)c; - } - else if (tag == 0x0082) // lens attachment - { - stmread(imgdata.lens.makernotes.Attachment, len, ifp); - } - else if (tag == 0x0083) // lens type - { - imgdata.lens.nikon.NikonLensType = fgetc(ifp); - } - else if (tag == 0x0084) // lens - { - imgdata.lens.makernotes.MinFocal = getreal(type); - imgdata.lens.makernotes.MaxFocal = getreal(type); - imgdata.lens.makernotes.MaxAp4MinFocal = getreal(type); - imgdata.lens.makernotes.MaxAp4MaxFocal = getreal(type); - } - else if (tag == 0x008b) // lens f-stops - { - uchar a, b, c; - a = fgetc(ifp); - b = fgetc(ifp); - c = fgetc(ifp); - if (c) - { - imgdata.lens.nikon.NikonLensFStops = a*b*(12/c); - imgdata.lens.makernotes.LensFStops = - (float)imgdata.lens.nikon.NikonLensFStops /12.0f; - } - } - else if (tag == 0x0093) - { - i = get2(); - if ((i == 7) || (i == 9)) + if (nwords == 1) + snprintf(tbuf, sizeof(tbuf), "%s %s %d:%s:%s", + words[0] + strnlen(words[0], sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) - 12, ystr, + year, mm, dd); + + else + snprintf(tbuf, sizeof(tbuf), "%s %d:%s:%s %s", ystr, year, mm, dd, + words[0] + strnlen(words[0], sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) - 12); + + strncpy(imgdata.shootinginfo.InternalBodySerial, tbuf, + sizeof(imgdata.shootinginfo.InternalBodySerial) - 1); + } + else { - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; + char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)]; + snprintf(tbuf, sizeof(tbuf), "%s %s %d:%s:%s %s", imgdata.shootinginfo.InternalBodySerial, ystr, year, mm, + dd, words[i] + strnlen(words[i], sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) - 12); + strncpy(imgdata.shootinginfo.InternalBodySerial, tbuf, + sizeof(imgdata.shootinginfo.InternalBodySerial) - 1); } } - else if (tag == 0x0098) // contains lens data - { - for (i = 0; i < 4; i++) - { - NikonLensDataVersion = NikonLensDataVersion * 10 + fgetc(ifp) - '0'; - } - switch (NikonLensDataVersion) - { - case 100: lenNikonLensData = 9; break; - case 101: - case 201: // encrypted, starting from v.201 - case 202: - case 203: lenNikonLensData = 15; break; - case 204: lenNikonLensData = 16; break; - case 400: lenNikonLensData = 459; break; - case 401: lenNikonLensData = 590; break; - case 402: lenNikonLensData = 509; break; - case 403: lenNikonLensData = 879; break; - } - if(lenNikonLensData>0) - { - table_buf = (uchar*)malloc(lenNikonLensData); - fread(table_buf, lenNikonLensData, 1, ifp); - if ((NikonLensDataVersion < 201) && lenNikonLensData) - { - processNikonLensData(table_buf, lenNikonLensData); - free(table_buf); - lenNikonLensData = 0; - } - } - } - else if (tag == 0x00a0) - { - stmread(imgdata.shootinginfo.BodySerial, len, ifp); - } - else if (tag == 0x00a8) // contains flash data - { - for (i = 0; i < 4; i++) - { - NikonFlashInfoVersion = NikonFlashInfoVersion * 10 + fgetc(ifp) - '0'; - } - } + } } + else + parseFujiMakernotes(tag, type); + } - else if (!strncmp(make, "OLYMPUS", 7)) + else if (!strncasecmp(model, "Hasselblad X1D", 14) || !strncasecmp(model, "Hasselblad H6D", 14) || + !strncasecmp(model, "Hasselblad A6D", 14)) + { + if (tag == 0x0045) { - switch (tag) { - case 0x0404: - case 0x101a: - case 0x20100101: - if (!imgdata.shootinginfo.BodySerial[0]) - stmread(imgdata.shootinginfo.BodySerial, len, ifp); - break; - case 0x20100102: - if (!imgdata.shootinginfo.InternalBodySerial[0]) - stmread(imgdata.shootinginfo.InternalBodySerial, len, ifp); - break; - case 0x0207: - case 0x20100100: - { - uchar sOlyID[8]; - unsigned long long OlyID; - fread (sOlyID, MIN(len,7), 1, ifp); - sOlyID[7] = 0; - OlyID = sOlyID[0]; - i = 1; - while (i < 7 && sOlyID[i]) - { - OlyID = OlyID << 8 | sOlyID[i]; - i++; - } - setOlympusBodyFeatures(OlyID); - } - break; - case 0x1002: - imgdata.lens.makernotes.CurAp = libraw_powf64(2.0f, getreal(type)/2); - break; - case 0x20401112: - imgdata.makernotes.olympus.OlympusCropID = get2(); - break; - case 0x20401113: - FORC4 imgdata.makernotes.olympus.OlympusFrame[c] = get2(); - break; - case 0x20100201: - { - unsigned long long oly_lensid [3]; - oly_lensid[0] = fgetc(ifp); - fgetc(ifp); - oly_lensid[1] = fgetc(ifp); - oly_lensid[2] = fgetc(ifp); - imgdata.lens.makernotes.LensID = - (oly_lensid[0] << 16) | (oly_lensid[1] << 8) | oly_lensid[2]; - } - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FT; - imgdata.lens.makernotes.LensFormat = LIBRAW_FORMAT_FT; - if (((imgdata.lens.makernotes.LensID < 0x20000) || - (imgdata.lens.makernotes.LensID > 0x4ffff)) && - (imgdata.lens.makernotes.LensID & 0x10)) - { - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_mFT; - } - break; - case 0x20100202: - stmread(imgdata.lens.LensSerial, len, ifp); - break; - case 0x20100203: - stmread(imgdata.lens.makernotes.Lens, len, ifp); - break; - case 0x20100205: - imgdata.lens.makernotes.MaxAp4MinFocal = libraw_powf64(sqrt(2.0f), get2() / 256.0f); - break; - case 0x20100206: - imgdata.lens.makernotes.MaxAp4MaxFocal = libraw_powf64(sqrt(2.0f), get2() / 256.0f); - break; - case 0x20100207: - imgdata.lens.makernotes.MinFocal = (float)get2(); - break; - case 0x20100208: - imgdata.lens.makernotes.MaxFocal = (float)get2(); - if (imgdata.lens.makernotes.MaxFocal > 1000.0f) - imgdata.lens.makernotes.MaxFocal = imgdata.lens.makernotes.MinFocal; - break; - case 0x2010020a: - imgdata.lens.makernotes.MaxAp4CurFocal = libraw_powf64(sqrt(2.0f), get2() / 256.0f); - break; - case 0x20100301: - imgdata.lens.makernotes.TeleconverterID = fgetc(ifp) << 8; - fgetc(ifp); - imgdata.lens.makernotes.TeleconverterID = - imgdata.lens.makernotes.TeleconverterID | fgetc(ifp); - break; - case 0x20100303: - stmread(imgdata.lens.makernotes.Teleconverter, len, ifp); - break; - case 0x20100403: - stmread(imgdata.lens.makernotes.Attachment, len, ifp); - break; - } + imgdata.makernotes.hasselblad.BaseISO = get4(); + } + else if (tag == 0x0046) + { + imgdata.makernotes.hasselblad.Gain = getreal(type); } + } - else if ((!strncmp(make, "PENTAX", 6) || !strncmp(make, "RICOH", 5)) && - !strncmp(model, "GR", 2)) - { - if (tag == 0x0005) - { - char buffer[17]; - int count=0; - fread(buffer, 16, 1, ifp); - buffer[16] = 0; - for (int i=0; i<16; i++) - { -// sprintf(imgdata.shootinginfo.InternalBodySerial+2*i, "%02x", buffer[i]); - if ((isspace(buffer[i])) || - (buffer[i] == 0x2D) || - (isalnum(buffer[i]))) - count++; - } - if (count == 16) - { - sprintf (imgdata.shootinginfo.BodySerial, "%8s", buffer+8); - buffer[8] = 0; - sprintf (imgdata.shootinginfo.InternalBodySerial, "%8s", buffer); - } - else - { - sprintf (imgdata.shootinginfo.BodySerial, "%02x%02x%02x%02x", buffer[4], buffer[5], buffer[6], buffer[7]); - sprintf (imgdata.shootinginfo.InternalBodySerial, "%02x%02x%02x%02x", buffer[8], buffer[9], buffer[10], buffer[11]); - } - } - else if ((tag == 0x1001) && (type == 3)) - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; - imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_APSC; - imgdata.lens.makernotes.LensID = -1; - imgdata.lens.makernotes.FocalType = 1; - } + else if (!strncasecmp(make, "LEICA", 5)) + { + if (((tag == 0x035e) || (tag == 0x035f)) && (type == 10) && (len == 9)) + { + int ind = tag == 0x035e ? 0 : 1; + for (int j = 0; j < 3; j++) + FORCC imgdata.color.dng_color[ind].forwardmatrix[j][c] = getreal(type); + imgdata.color.dng_color[ind].parsedfields |= LIBRAW_DNGFM_FORWARDMATRIX; + } - else if ((tag == 0x100b) && (type == 10)) - { - imgdata.other.FlashEC = getreal(type); - } + if (tag == 0x34003402) + imgdata.other.CameraTemperature = getreal(type); - else if ((tag == 0x1017) && (get2() == 2)) - { - strcpy(imgdata.lens.makernotes.Attachment, "Wide-Angle Adapter"); - } - else if (tag == 0x1500) - { - imgdata.lens.makernotes.CurFocal = getreal(type); - } - } + if ((tag == 0x0320) && (type == 9) && (len == 1) && !strncasecmp(make, "Leica Camera AG", 15) && + !strncmp(buf, "LEICA", 5) && (buf[5] == 0) && (buf[6] == 0) && (buf[7] == 0)) + imgdata.other.CameraTemperature = getreal(type); - else if (!strncmp(make, "RICOH", 5) && - strncmp(model, "PENTAX", 6)) + if ((tag == 0x0303) && (type != 4)) { - if ((tag == 0x0005) && !strncmp(model, "GXR", 3)) - { - char buffer[9]; - buffer[8] = 0; - fread(buffer, 8, 1, ifp); - sprintf (imgdata.shootinginfo.InternalBodySerial, "%8s", buffer); - } + stmread(imgdata.lens.makernotes.Lens, len, ifp); + } - else if ((tag == 0x100b) && (type == 10)) + if ((tag == 0x3405) || (tag == 0x0310) || (tag == 0x34003405)) + { + imgdata.lens.makernotes.LensID = get4(); + imgdata.lens.makernotes.LensID = + ((imgdata.lens.makernotes.LensID >> 2) << 8) | (imgdata.lens.makernotes.LensID & 0x3); + if (imgdata.lens.makernotes.LensID != -1) + { + if ((model[0] == 'M') || !strncasecmp(model, "LEICA M", 7)) { - imgdata.other.FlashEC = getreal(type); + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_M; + if (imgdata.lens.makernotes.LensID) + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Leica_M; } - - else if ((tag == 0x1017) && (get2() == 2)) + else if ((model[0] == 'S') || !strncasecmp(model, "LEICA S", 7)) { - strcpy(imgdata.lens.makernotes.Attachment, "Wide-Angle Adapter"); + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_S; + if (imgdata.lens.makernotes.Lens[0]) + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Leica_S; } + } + } - else if (tag == 0x1500) - { - imgdata.lens.makernotes.CurFocal = getreal(type); - } + else if (((tag == 0x0313) || (tag == 0x34003406)) && (fabs(imgdata.lens.makernotes.CurAp) < 0.17f) && + ((type == 10) || (type == 5))) + { + imgdata.lens.makernotes.CurAp = getreal(type); + if (imgdata.lens.makernotes.CurAp > 126.3) + imgdata.lens.makernotes.CurAp = 0.0f; + } - else if ((tag == 0x2001) && !strncmp(model, "GXR", 3)) - { - short ntags, cur_tag; - fseek(ifp, 20, SEEK_CUR); - ntags = get2(); - cur_tag = get2(); - while (cur_tag != 0x002c) - { - fseek(ifp, 10, SEEK_CUR); - cur_tag = get2(); - } - fseek(ifp, 6, SEEK_CUR); - fseek(ifp, get4()+20, SEEK_SET); - stread(imgdata.shootinginfo.BodySerial, 12, ifp); - get2(); - imgdata.lens.makernotes.LensID = getc(ifp) - '0'; - switch(imgdata.lens.makernotes.LensID) { - case 1: - case 2: - case 3: - case 5: - case 6: - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_RicohModule; - break; - case 8: - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_M; - imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_APSC; - imgdata.lens.makernotes.LensID = -1; - break; - default: - imgdata.lens.makernotes.LensID = -1; - } - fseek(ifp, 17, SEEK_CUR); - stread(imgdata.lens.LensSerial, 12, ifp); - } + else if (tag == 0x3400) + { + parse_makernote(base, 0x3400); } + } - else if ((!strncmp(make, "PENTAX", 6) || - !strncmp(model, "PENTAX", 6) || - (!strncmp(make, "SAMSUNG", 7) && dng_version)) && - strncmp(model, "GR", 2)) + else if (!strncmp(make, "NIKON", 5)) + { + if (tag == 0x000a) { - if (tag == 0x0005) - { - unique_id = get4(); - setPentaxBodyFeatures(unique_id); - } - else if (tag == 0x0013) - { - imgdata.lens.makernotes.CurAp = (float)get2()/10.0f; - } - else if (tag == 0x0014) - { - PentaxISO(get2()); - } - else if (tag == 0x001d) - { - imgdata.lens.makernotes.CurFocal = (float)get4()/100.0f; - } - else if (tag == 0x003f) - { - imgdata.lens.makernotes.LensID = fgetc(ifp) << 8 | fgetc(ifp); - } - else if (tag == 0x004d) - { - if (type == 9) imgdata.other.FlashEC = getreal(type) / 256.0f; - else imgdata.other.FlashEC = (float) ((signed short) fgetc(ifp)) / 6.0f; - } - else if (tag == 0x007e) - { - imgdata.color.linear_max[0] = - imgdata.color.linear_max[1] = - imgdata.color.linear_max[2] = - imgdata.color.linear_max[3] = (long)(-1) * get4(); - } - else if (tag == 0x0207) - { - if(len < 65535) // Safety belt - PentaxLensInfo(imgdata.lens.makernotes.CamID, len); - } - else if (tag == 0x020d) - { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][c ^ (c >> 1)] = get2(); - } - else if (tag == 0x020e) - { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][c ^ (c >> 1)] = get2(); - } - else if (tag == 0x020f) + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; + } + else if (tag == 0x0012) + { + char a, b, c; + a = fgetc(ifp); + b = fgetc(ifp); + c = fgetc(ifp); + if (c) + imgdata.other.FlashEC = (float)(a * b) / (float)c; + } + else if (tag == 0x003b) // all 1s for regular exposures + { + imgdata.makernotes.nikon.ME_WB[0] = getreal(type); + imgdata.makernotes.nikon.ME_WB[2] = getreal(type); + imgdata.makernotes.nikon.ME_WB[1] = getreal(type); + imgdata.makernotes.nikon.ME_WB[3] = getreal(type); + } + else if (tag == 0x0045) + { + imgdata.sizes.raw_crop.cleft = get2(); + imgdata.sizes.raw_crop.ctop = get2(); + imgdata.sizes.raw_crop.cwidth = get2(); + imgdata.sizes.raw_crop.cheight = get2(); + } + else if (tag == 0x0082) // lens attachment + { + stmread(imgdata.lens.makernotes.Attachment, len, ifp); + } + else if (tag == 0x0083) // lens type + { + imgdata.lens.nikon.NikonLensType = fgetc(ifp); + } + else if (tag == 0x0084) // lens + { + imgdata.lens.makernotes.MinFocal = getreal(type); + imgdata.lens.makernotes.MaxFocal = getreal(type); + imgdata.lens.makernotes.MaxAp4MinFocal = getreal(type); + imgdata.lens.makernotes.MaxAp4MaxFocal = getreal(type); + } + else if (tag == 0x008b) // lens f-stops + { + uchar a, b, c; + a = fgetc(ifp); + b = fgetc(ifp); + c = fgetc(ifp); + if (c) { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][c ^ (c >> 1)] = get2(); + imgdata.lens.nikon.NikonLensFStops = a * b * (12 / c); + imgdata.lens.makernotes.LensFStops = (float)imgdata.lens.nikon.NikonLensFStops / 12.0f; } - else if (tag == 0x0210) + } + else if (tag == 0x0093) // Nikon compression + { + imgdata.makernotes.nikon.NEFCompression = i = get2(); + if ((i == 7) || (i == 9)) { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][c ^ (c >> 1)] = get2(); + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; } - else if (tag == 0x0211) + } + else if (tag == 0x0098) // contains lens data + { + for (i = 0; i < 4; i++) { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][c ^ (c >> 1)] = get2(); + NikonLensDataVersion = NikonLensDataVersion * 10 + fgetc(ifp) - '0'; } - else if (tag == 0x0212) + switch (NikonLensDataVersion) { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][c ^ (c >> 1)] = get2(); + case 100: + lenNikonLensData = 9; + break; + case 101: + case 201: // encrypted, starting from v.201 + case 202: + case 203: + lenNikonLensData = 15; + break; + case 204: + lenNikonLensData = 16; + break; + case 400: + lenNikonLensData = 459; + break; + case 401: + lenNikonLensData = 590; + break; + case 402: + lenNikonLensData = 509; + break; + case 403: + lenNikonLensData = 879; + break; } - else if (tag == 0x0213) + if (lenNikonLensData > 0) { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][c ^ (c >> 1)] = get2(); + table_buf = (uchar *)malloc(lenNikonLensData); + fread(table_buf, lenNikonLensData, 1, ifp); + if ((NikonLensDataVersion < 201) && lenNikonLensData) + { + processNikonLensData(table_buf, lenNikonLensData); + free(table_buf); + lenNikonLensData = 0; + } } - else if (tag == 0x0214) + } + else if (tag == 0x00a0) + { + stmread(imgdata.shootinginfo.BodySerial, len, ifp); + } + else if (tag == 0x00a8) // contains flash data + { + for (i = 0; i < 4; i++) { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][c ^ (c >> 1)] = get2(); + NikonFlashInfoVersion = NikonFlashInfoVersion * 10 + fgetc(ifp) - '0'; } - else if (tag == 0x0221) + } + else if (tag == 0x00b0) + { + get4(); // ME tag version, 4 symbols + imgdata.makernotes.nikon.ExposureMode = get4(); + imgdata.makernotes.nikon.nMEshots = get4(); + imgdata.makernotes.nikon.MEgainOn = get4(); + } + else if (tag == 0x00b9) + { + uchar uc; + int8_t sc; + fread(&uc, 1, 1, ifp); + imgdata.makernotes.nikon.AFFineTune = uc; + fread(&uc, 1, 1, ifp); + imgdata.makernotes.nikon.AFFineTuneIndex = uc; + fread(&sc, 1, 1, ifp); + imgdata.makernotes.nikon.AFFineTuneAdj = sc; + } + } + + else if (!strncmp(make, "OLYMPUS", 7)) + { + switch (tag) + { + case 0x0404: + case 0x101a: + case 0x20100101: + if (!imgdata.shootinginfo.BodySerial[0]) + stmread(imgdata.shootinginfo.BodySerial, len, ifp); + break; + case 0x20100102: + if (!imgdata.shootinginfo.InternalBodySerial[0]) + stmread(imgdata.shootinginfo.InternalBodySerial, len, ifp); + break; + case 0x0207: + case 0x20100100: + { + uchar sOlyID[8]; + fread(sOlyID, MIN(len, 7), 1, ifp); + sOlyID[7] = 0; + OlyID = sOlyID[0]; + i = 1; + while (i < 7 && sOlyID[i]) { - int nWB = get2(); - if(nWB<=sizeof(imgdata.color.WBCT_Coeffs)/sizeof(imgdata.color.WBCT_Coeffs[0])) - for (int i = 0; i < nWB; i++) - { - imgdata.color.WBCT_Coeffs[i][0] = (unsigned)0xcfc6 - get2(); - fseek(ifp, 2, SEEK_CUR); - imgdata.color.WBCT_Coeffs[i][1] = get2(); - imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] = 0x2000; - imgdata.color.WBCT_Coeffs[i][3] = get2(); - } + OlyID = OlyID << 8 | sOlyID[i]; + i++; } - else if (tag == 0x0215) + setOlympusBodyFeatures(OlyID); + } + break; + case 0x1002: + imgdata.lens.makernotes.CurAp = libraw_powf64l(2.0f, getreal(type) / 2); + break; + case 0x20400612: + case 0x30000612: + imgdata.sizes.raw_crop.cleft = get2(); + break; + case 0x20400613: + case 0x30000613: + imgdata.sizes.raw_crop.ctop = get2(); + break; + case 0x20400614: + case 0x30000614: + imgdata.sizes.raw_crop.cwidth = get2(); + break; + case 0x20400615: + case 0x30000615: + imgdata.sizes.raw_crop.cheight = get2(); + break; + case 0x20401112: + imgdata.makernotes.olympus.OlympusCropID = get2(); + break; + case 0x20401113: + FORC4 imgdata.makernotes.olympus.OlympusFrame[c] = get2(); + break; + case 0x20100201: + { + unsigned long long oly_lensid[3]; + oly_lensid[0] = fgetc(ifp); + fgetc(ifp); + oly_lensid[1] = fgetc(ifp); + oly_lensid[2] = fgetc(ifp); + imgdata.lens.makernotes.LensID = (oly_lensid[0] << 16) | (oly_lensid[1] << 8) | oly_lensid[2]; + } + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FT; + imgdata.lens.makernotes.LensFormat = LIBRAW_FORMAT_FT; + if (((imgdata.lens.makernotes.LensID < 0x20000) || (imgdata.lens.makernotes.LensID > 0x4ffff)) && + (imgdata.lens.makernotes.LensID & 0x10)) { - fseek (ifp, 16, SEEK_CUR); - sprintf(imgdata.shootinginfo.InternalBodySerial, "%d", get4()); + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_mFT; } - else if (tag == 0x0229) + break; + case 0x20100202: + stmread(imgdata.lens.LensSerial, len, ifp); + break; + case 0x20100203: + stmread(imgdata.lens.makernotes.Lens, len, ifp); + break; + case 0x20100205: + imgdata.lens.makernotes.MaxAp4MinFocal = libraw_powf64l(sqrt(2.0f), get2() / 256.0f); + break; + case 0x20100206: + imgdata.lens.makernotes.MaxAp4MaxFocal = libraw_powf64l(sqrt(2.0f), get2() / 256.0f); + break; + case 0x20100207: + imgdata.lens.makernotes.MinFocal = (float)get2(); + break; + case 0x20100208: + imgdata.lens.makernotes.MaxFocal = (float)get2(); + if (imgdata.lens.makernotes.MaxFocal > 1000.0f) + imgdata.lens.makernotes.MaxFocal = imgdata.lens.makernotes.MinFocal; + break; + case 0x2010020a: + imgdata.lens.makernotes.MaxAp4CurFocal = libraw_powf64l(sqrt(2.0f), get2() / 256.0f); + break; + case 0x20100301: + imgdata.lens.makernotes.TeleconverterID = fgetc(ifp) << 8; + fgetc(ifp); + imgdata.lens.makernotes.TeleconverterID = imgdata.lens.makernotes.TeleconverterID | fgetc(ifp); + break; + case 0x20100303: + stmread(imgdata.lens.makernotes.Teleconverter, len, ifp); + break; + case 0x20100403: + stmread(imgdata.lens.makernotes.Attachment, len, ifp); + break; + case 0x1007: + imgdata.other.SensorTemperature = (float)get2(); + break; + case 0x1008: + imgdata.other.LensTemperature = (float)get2(); + break; + case 0x20401306: + { + int temp = get2(); + if ((temp != 0) && (temp != 100)) { - stmread(imgdata.shootinginfo.BodySerial, len, ifp); + if (temp < 61) + imgdata.other.CameraTemperature = (float)temp; + else + imgdata.other.CameraTemperature = (float)(temp - 32) / 1.8f; + if ((OlyID == 0x4434353933ULL) && // TG-5 + (imgdata.other.exifAmbientTemperature > -273.15f)) + imgdata.other.CameraTemperature += imgdata.other.exifAmbientTemperature; } - else if (tag == 0x022d) - { - fseek (ifp,2,SEEK_CUR); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][c ^ (c >> 1)] = get2(); - getc(ifp); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][c ^ (c >> 1)] = get2(); - getc(ifp); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][c ^ (c >> 1)] = get2(); - getc(ifp); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][c ^ (c >> 1)] = get2(); - getc(ifp); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][c ^ (c >> 1)] = get2(); - getc(ifp); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][c ^ (c >> 1)] = get2(); - getc(ifp); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][c ^ (c >> 1)] = get2(); - getc(ifp); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][c ^ (c >> 1)] = get2(); - getc(ifp); - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][c ^ (c >> 1)] = get2(); - } - else if (tag == 0x0239) // Q-series lens info (LensInfoQ) - { - char LensInfo [20]; - fseek (ifp, 2, SEEK_CUR); - stread(imgdata.lens.makernotes.Lens, 30, ifp); - strcat(imgdata.lens.makernotes.Lens, " "); - stread(LensInfo, 20, ifp); - strcat(imgdata.lens.makernotes.Lens, LensInfo); - } } - - else if (!strncmp(make, "SAMSUNG", 7)) - { - if (tag == 0x0002) + break; + case 0x20501500: + if (OlyID != 0x0ULL) + { + short temp = get2(); + if ((OlyID == 0x4434303430ULL) || // E-1 + (OlyID == 0x5330303336ULL) || // E-M5 + (len != 1)) + imgdata.other.SensorTemperature = (float)temp; + else if ((temp != -32768) && (temp != 0)) { - if(get4() == 0x2000) - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Samsung_NX; - } - else if (!strncmp(model, "NX mini", 7)) - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Samsung_NX_M; - } + if (temp > 199) + imgdata.other.SensorTemperature = 86.474958f - 0.120228f * (float)temp; else - { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; - } - } - else if (tag == 0x0003) - { - unique_id = imgdata.lens.makernotes.CamID = get4(); - } - else if (tag == 0xa002) - { - stmread(imgdata.shootinginfo.BodySerial, len, ifp); - } - else if (tag == 0xa003) - { - imgdata.lens.makernotes.LensID = get2(); - if (imgdata.lens.makernotes.LensID) - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Samsung_NX; - } - else if (tag == 0xa005) - { - stmread(imgdata.lens.InternalLensSerial, len, ifp); - } - else if (tag == 0xa019) - { - imgdata.lens.makernotes.CurAp = getreal(type); - } - else if (tag == 0xa01a) - { - imgdata.lens.makernotes.FocalLengthIn35mmFormat = get4() / 10.0f; - if (imgdata.lens.makernotes.FocalLengthIn35mmFormat < 10.0f) - imgdata.lens.makernotes.FocalLengthIn35mmFormat *= 10.0f; + imgdata.other.SensorTemperature = (float)temp; } + } + break; } + } - else if (!strncasecmp(make, "SONY", 4) || - !strncasecmp(make, "Konica", 6) || - !strncasecmp(make, "Minolta", 7) || - (!strncasecmp(make, "Hasselblad", 10) && - (!strncasecmp(model, "Stellar", 7) || - !strncasecmp(model, "Lunar", 5) || - !strncasecmp(model, "Lusso", 5) || - !strncasecmp(model, "HV",2)))) + else if ((!strncmp(make, "PENTAX", 6) || !strncmp(make, "RICOH", 5)) && !strncmp(model, "GR", 2)) + { + if (tag == 0x0005) { - ushort lid; - if (tag == 0xb001) // Sony ModelID + char buffer[17]; + int count = 0; + fread(buffer, 16, 1, ifp); + buffer[16] = 0; + for (int i = 0; i < 16; i++) { - unique_id = get2(); - setSonyBodyFeatures(unique_id); - if (table_buf_0x9050_present) - { - process_Sony_0x9050(table_buf_0x9050, unique_id); - free (table_buf_0x9050); - table_buf_0x9050_present = 0; - } - if (table_buf_0x940c_present) - { - if (imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Sony_E) - { - process_Sony_0x940c(table_buf_0x940c); - } - free (table_buf_0x940c); - table_buf_0x940c_present = 0; - } + // sprintf(imgdata.shootinginfo.InternalBodySerial+2*i, "%02x", buffer[i]); + if ((isspace(buffer[i])) || (buffer[i] == 0x2D) || (isalnum(buffer[i]))) + count++; } + if (count == 16) + { + sprintf(imgdata.shootinginfo.BodySerial, "%8s", buffer + 8); + buffer[8] = 0; + sprintf(imgdata.shootinginfo.InternalBodySerial, "%8s", buffer); + } + else + { + sprintf(imgdata.shootinginfo.BodySerial, "%02x%02x%02x%02x", buffer[4], buffer[5], buffer[6], buffer[7]); + sprintf(imgdata.shootinginfo.InternalBodySerial, "%02x%02x%02x%02x", buffer[8], buffer[9], buffer[10], + buffer[11]); + } + } + else if ((tag == 0x1001) && (type == 3)) + { + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; + imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_APSC; + imgdata.lens.makernotes.LensID = -1; + imgdata.lens.makernotes.FocalType = 1; + } - else if ((tag == 0x0010) && // CameraInfo - strncasecmp(model, "DSLR-A100", 9) && - strncasecmp(model, "NEX-5C", 6) && - !strncasecmp(make, "SONY", 4) && - ((len == 368) || // a700 - (len == 5478) || // a850, a900 - (len == 5506) || // a200, a300, a350 - (len == 6118) || // a230, a290, a330, a380, a390 - // a450, a500, a550, a560, a580 - // a33, a35, a55 - // NEX3, NEX5, NEX5C, NEXC3, VG10E - (len == 15360)) - ) - { - table_buf = (uchar*)malloc(len); - fread(table_buf, len, 1, ifp); - if (memcmp(table_buf, "\xff\xff\xff\xff\xff\xff\xff\xff", 8) && - memcmp(table_buf, "\x00\x00\x00\x00\x00\x00\x00\x00", 8)) - { - switch (len) - { - case 368: - case 5478: - // a700, a850, a900: CameraInfo - if (table_buf[0] | table_buf[3]) - imgdata.lens.makernotes.MinFocal = - bcd2dec(table_buf[0]) * 100 + bcd2dec(table_buf[3]); - if (table_buf[2] | table_buf[5]) - imgdata.lens.makernotes.MaxFocal = - bcd2dec(table_buf[2]) * 100 + bcd2dec(table_buf[5]); - if (table_buf[4]) - imgdata.lens.makernotes.MaxAp4MinFocal = bcd2dec(table_buf[4]) / 10.0f; - if (table_buf[4]) - imgdata.lens.makernotes.MaxAp4MaxFocal = bcd2dec(table_buf[7]) / 10.0f; - parseSonyLensFeatures(table_buf[1], table_buf[6]); - break; - default: - // CameraInfo2 & 3 - if (table_buf[1] | table_buf[2]) - imgdata.lens.makernotes.MinFocal = - bcd2dec(table_buf[1]) * 100 + bcd2dec(table_buf[2]); - if (table_buf[3] | table_buf[4]) - imgdata.lens.makernotes.MaxFocal = - bcd2dec(table_buf[3]) * 100 + bcd2dec(table_buf[4]); - if (table_buf[5]) - imgdata.lens.makernotes.MaxAp4MinFocal = bcd2dec(table_buf[5]) / 10.0f; - if (table_buf[6]) - imgdata.lens.makernotes.MaxAp4MaxFocal = bcd2dec(table_buf[6]) / 10.0f; - parseSonyLensFeatures(table_buf[0], table_buf[7]); - } - } - free(table_buf); - } - - else if ((tag == 0x0020) && // WBInfoA100, needs 0xb028 processing - !strncasecmp(model, "DSLR-A100", 9)) - { - fseek(ifp,0x49dc,SEEK_CUR); - stmread(imgdata.shootinginfo.InternalBodySerial, 12, ifp); - } + else if ((tag == 0x100b) && (type == 10)) + { + imgdata.other.FlashEC = getreal(type); + } - else if (tag == 0x0104) - { - imgdata.other.FlashEC = getreal(type); - } + else if ((tag == 0x1017) && (get2() == 2)) + { + strcpy(imgdata.lens.makernotes.Attachment, "Wide-Angle Adapter"); + } + else if (tag == 0x1500) + { + imgdata.lens.makernotes.CurFocal = getreal(type); + } + } - else if (tag == 0x0105) // Teleconverter - { - imgdata.lens.makernotes.TeleconverterID = get2(); - } + else if (!strncmp(make, "RICOH", 5) && strncmp(model, "PENTAX", 6)) + { + if ((tag == 0x0005) && !strncmp(model, "GXR", 3)) + { + char buffer[9]; + buffer[8] = 0; + fread(buffer, 8, 1, ifp); + sprintf(imgdata.shootinginfo.InternalBodySerial, "%8s", buffer); + } - else if (tag == 0x0114 && len < 256000) // CameraSettings - { - table_buf = (uchar*)malloc(len); - fread(table_buf, len, 1, ifp); - switch (len) { - case 280: - case 364: - case 332: - // CameraSettings and CameraSettings2 are big endian - if (table_buf[2] | table_buf[3]) - { - lid = (((ushort)table_buf[2])<<8) | - ((ushort)table_buf[3]); - imgdata.lens.makernotes.CurAp = - libraw_powf64(2.0f, ((float)lid/8.0f-1.0f)/2.0f); - } - break; - case 1536: - case 2048: - // CameraSettings3 are little endian - parseSonyLensType2(table_buf[1016], table_buf[1015]); - if (imgdata.lens.makernotes.LensMount != LIBRAW_MOUNT_Canon_EF) - { - switch (table_buf[153]) { - case 16: imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Minolta_A; break; - case 17: imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sony_E; break; - } - } - break; - } - free(table_buf); - } + else if ((tag == 0x100b) && (type == 10)) + { + imgdata.other.FlashEC = getreal(type); + } - else if (tag == 0x9050 && len < 256000) // little endian - { - table_buf_0x9050 = (uchar*)malloc(len); - table_buf_0x9050_present = 1; - fread(table_buf_0x9050, len, 1, ifp); + else if ((tag == 0x1017) && (get2() == 2)) + { + strcpy(imgdata.lens.makernotes.Attachment, "Wide-Angle Adapter"); + } - if (imgdata.lens.makernotes.CamID) - { - process_Sony_0x9050(table_buf_0x9050, imgdata.lens.makernotes.CamID); - free (table_buf_0x9050); - table_buf_0x9050_present = 0; - } - } + else if (tag == 0x1500) + { + imgdata.lens.makernotes.CurFocal = getreal(type); + } - else if (tag == 0x940c && len <256000) - { - table_buf_0x940c = (uchar*)malloc(len); - table_buf_0x940c_present = 1; - fread(table_buf_0x940c, len, 1, ifp); - if ((imgdata.lens.makernotes.CamID) && - (imgdata.lens.makernotes.CameraMount == LIBRAW_MOUNT_Sony_E)) - { - process_Sony_0x940c(table_buf_0x940c); - free(table_buf_0x940c); - table_buf_0x940c_present = 0; - } - } + else if ((tag == 0x2001) && !strncmp(model, "GXR", 3)) + { + short ntags, cur_tag; + fseek(ifp, 20, SEEK_CUR); + ntags = get2(); + cur_tag = get2(); + while (cur_tag != 0x002c) + { + fseek(ifp, 10, SEEK_CUR); + cur_tag = get2(); + } + fseek(ifp, 6, SEEK_CUR); + fseek(ifp, get4() + 20, SEEK_SET); + stread(imgdata.shootinginfo.BodySerial, 12, ifp); + get2(); + imgdata.lens.makernotes.LensID = getc(ifp) - '0'; + switch (imgdata.lens.makernotes.LensID) + { + case 1: + case 2: + case 3: + case 5: + case 6: + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_RicohModule; + break; + case 8: + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Leica_M; + imgdata.lens.makernotes.CameraFormat = LIBRAW_FORMAT_APSC; + imgdata.lens.makernotes.LensID = -1; + break; + default: + imgdata.lens.makernotes.LensID = -1; + } + fseek(ifp, 17, SEEK_CUR); + stread(imgdata.lens.LensSerial, 12, ifp); + } + } - else if (((tag == 0xb027) || (tag == 0x010c)) && (imgdata.lens.makernotes.LensID == -1)) + else if ((!strncmp(make, "PENTAX", 6) || !strncmp(model, "PENTAX", 6) || + (!strncmp(make, "SAMSUNG", 7) && dng_version)) && + strncmp(model, "GR", 2)) + { + if (tag == 0x0005) + { + unique_id = get4(); + setPentaxBodyFeatures(unique_id); + } + else if (tag == 0x000d) + { + imgdata.makernotes.pentax.FocusMode = get2(); + } + else if (tag == 0x000e) + { + imgdata.makernotes.pentax.AFPointSelected = get2(); + } + else if (tag == 0x000f) + { + imgdata.makernotes.pentax.AFPointsInFocus = getint(type); + } + else if (tag == 0x0010) + { + imgdata.makernotes.pentax.FocusPosition = get2(); + } + else if (tag == 0x0013) + { + imgdata.lens.makernotes.CurAp = (float)get2() / 10.0f; + } + else if (tag == 0x0014) + { + PentaxISO(get2()); + } + else if (tag == 0x001d) + { + imgdata.lens.makernotes.CurFocal = (float)get4() / 100.0f; + } + else if (tag == 0x0034) + { + uchar uc; + FORC4 + { + fread(&uc, 1, 1, ifp); + imgdata.makernotes.pentax.DriveMode[c] = uc; + } + } + else if (tag == 0x0038) + { + imgdata.sizes.raw_crop.cleft = get2(); + imgdata.sizes.raw_crop.ctop = get2(); + } + else if (tag == 0x0039) + { + imgdata.sizes.raw_crop.cwidth = get2(); + imgdata.sizes.raw_crop.cheight = get2(); + } + else if (tag == 0x003f) + { + imgdata.lens.makernotes.LensID = fgetc(ifp) << 8 | fgetc(ifp); + } + else if (tag == 0x0047) + { + imgdata.other.CameraTemperature = (float)fgetc(ifp); + } + else if (tag == 0x004d) + { + if (type == 9) + imgdata.other.FlashEC = getreal(type) / 256.0f; + else + imgdata.other.FlashEC = (float)((signed short)fgetc(ifp)) / 6.0f; + } + else if (tag == 0x0072) + { + imgdata.makernotes.pentax.AFAdjustment = get2(); + } + else if (tag == 0x007e) + { + imgdata.color.linear_max[0] = imgdata.color.linear_max[1] = imgdata.color.linear_max[2] = + imgdata.color.linear_max[3] = (long)(-1) * get4(); + } + else if (tag == 0x0207) + { + if (len < 65535) // Safety belt + PentaxLensInfo(imgdata.lens.makernotes.CamID, len); + } + else if ((tag >= 0x020d) && (tag <= 0x0214)) + { + FORC4 imgdata.color.WB_Coeffs[Pentax_wb_list1[tag - 0x020d]][c ^ (c >> 1)] = get2(); + } + else if (tag == 0x0221) + { + int nWB = get2(); + if (nWB <= sizeof(imgdata.color.WBCT_Coeffs) / sizeof(imgdata.color.WBCT_Coeffs[0])) + for (int i = 0; i < nWB; i++) { - imgdata.lens.makernotes.LensID = get4(); - if ((imgdata.lens.makernotes.LensID > 0x4900) && - (imgdata.lens.makernotes.LensID <= 0x5900)) - { - imgdata.lens.makernotes.AdapterID = 0x4900; - imgdata.lens.makernotes.LensID -= imgdata.lens.makernotes.AdapterID; - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Sigma_X3F; - strcpy(imgdata.lens.makernotes.Adapter, "MC-11"); - } - - else if ((imgdata.lens.makernotes.LensID > 0xEF00) && - (imgdata.lens.makernotes.LensID < 0xFFFF) && - (imgdata.lens.makernotes.LensID != 0xFF00)) - { - imgdata.lens.makernotes.AdapterID = 0xEF00; - imgdata.lens.makernotes.LensID -= imgdata.lens.makernotes.AdapterID; - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Canon_EF; - } - if (tag == 0x010c) imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Minolta_A; + imgdata.color.WBCT_Coeffs[i][0] = (unsigned)0xcfc6 - get2(); + fseek(ifp, 2, SEEK_CUR); + imgdata.color.WBCT_Coeffs[i][1] = get2(); + imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] = 0x2000; + imgdata.color.WBCT_Coeffs[i][3] = get2(); } + } + else if (tag == 0x0215) + { + fseek(ifp, 16, SEEK_CUR); + sprintf(imgdata.shootinginfo.InternalBodySerial, "%d", get4()); + } + else if (tag == 0x0229) + { + stmread(imgdata.shootinginfo.BodySerial, len, ifp); + } + else if (tag == 0x022d) + { + int wb_ind; + getc(ifp); + for (int wb_cnt = 0; wb_cnt < nPentax_wb_list2; wb_cnt++) + { + wb_ind = getc(ifp); + if (wb_ind < nPentax_wb_list2) + FORC4 imgdata.color.WB_Coeffs[Pentax_wb_list2[wb_ind]][c ^ (c >> 1)] = get2(); + } + } + else if (tag == 0x0239) // Q-series lens info (LensInfoQ) + { + char LensInfo[20]; + fseek(ifp, 2, SEEK_CUR); + stread(imgdata.lens.makernotes.Lens, 30, ifp); + strcat(imgdata.lens.makernotes.Lens, " "); + stread(LensInfo, 20, ifp); + strcat(imgdata.lens.makernotes.Lens, LensInfo); + } + } - else if (tag == 0xb02a && len < 256000) // Sony LensSpec - { - table_buf = (uchar*)malloc(len); - fread(table_buf, len, 1, ifp); - if (table_buf[1] | table_buf[2]) - imgdata.lens.makernotes.MinFocal = - bcd2dec(table_buf[1]) * 100 + bcd2dec(table_buf[2]); - if (table_buf[3] | table_buf[4]) - imgdata.lens.makernotes.MaxFocal = - bcd2dec(table_buf[3]) * 100 + bcd2dec(table_buf[4]); - if (table_buf[5]) - imgdata.lens.makernotes.MaxAp4MinFocal = bcd2dec(table_buf[5]) / 10.0f; - if (table_buf[6]) - imgdata.lens.makernotes.MaxAp4MaxFocal = bcd2dec(table_buf[6]) / 10.0f; - parseSonyLensFeatures(table_buf[0], table_buf[7]); - free(table_buf); - } + else if (!strncmp(make, "SAMSUNG", 7)) + { + if (tag == 0x0002) + { + if (get4() == 0x2000) + { + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Samsung_NX; + } + else if (!strncmp(model, "NX mini", 7)) + { + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Samsung_NX_M; + } + else + { + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; + } + } + else if (tag == 0x0003) + { + unique_id = imgdata.lens.makernotes.CamID = get4(); + } + else if (tag == 0x0043) + { + int temp = get4(); + if (temp) + { + imgdata.other.CameraTemperature = (float)temp; + if (get4() == 10) + imgdata.other.CameraTemperature /= 10.0f; + } + } + else if (tag == 0xa002) + { + stmread(imgdata.shootinginfo.BodySerial, len, ifp); + } + else if (tag == 0xa003) + { + imgdata.lens.makernotes.LensID = get2(); + if (imgdata.lens.makernotes.LensID) + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Samsung_NX; + } + else if (tag == 0xa005) + { + stmread(imgdata.lens.InternalLensSerial, len, ifp); } + else if (tag == 0xa019) + { + imgdata.lens.makernotes.CurAp = getreal(type); + } + else if (tag == 0xa01a) + { + imgdata.lens.makernotes.FocalLengthIn35mmFormat = get4() / 10.0f; + if (imgdata.lens.makernotes.FocalLengthIn35mmFormat < 10.0f) + imgdata.lens.makernotes.FocalLengthIn35mmFormat *= 10.0f; + } + } + + else if (!strncasecmp(make, "SONY", 4) || !strncasecmp(make, "Konica", 6) || !strncasecmp(make, "Minolta", 7) || + (!strncasecmp(make, "Hasselblad", 10) && + (!strncasecmp(model, "Stellar", 7) || !strncasecmp(model, "Lunar", 5) || + !strncasecmp(model, "Lusso", 5) || !strncasecmp(model, "HV", 2)))) + { + parseSonyMakernotes(tag, type, len, nonDNG, table_buf_0x0116, table_buf_0x0116_len, table_buf_0x2010, + table_buf_0x2010_len, table_buf_0x9050, table_buf_0x9050_len, table_buf_0x9400, + table_buf_0x9400_len, table_buf_0x9402, table_buf_0x9402_len, table_buf_0x9403, + table_buf_0x9403_len, table_buf_0x9406, table_buf_0x9406_len, table_buf_0x940c, + table_buf_0x940c_len, table_buf_0x940e, table_buf_0x940e_len); + } - fseek(ifp,_pos,SEEK_SET); + fseek(ifp, _pos, SEEK_SET); #endif - if (tag == 2 && strstr(make,"NIKON") && !iso_speed) - iso_speed = (get2(),get2()); - if (tag == 37 && strstr(make,"NIKON") && (!iso_speed || iso_speed == 65535)) - { - unsigned char cc; - fread(&cc,1,1,ifp); - iso_speed = int(100.0 * libraw_powf64(2.0f,float(cc)/12.0-5.0)); - } - if (tag == 4 && len > 26 && len < 35) { - if ((i=(get4(),get2())) != 0x7fff && (!iso_speed || iso_speed == 65535)) - iso_speed = 50 * libraw_powf64(2.0, i/32.0 - 4); + if (tag == 2 && strstr(make, "NIKON") && !iso_speed) + iso_speed = (get2(), get2()); + if (tag == 37 && strstr(make, "NIKON") && (!iso_speed || iso_speed == 65535)) + { + unsigned char cc; + fread(&cc, 1, 1, ifp); + iso_speed = int(100.0 * libraw_powf64l(2.0f, float(cc) / 12.0 - 5.0)); + } + if (tag == 4 && len > 26 && len < 35) + { + if ((i = (get4(), get2())) != 0x7fff && (!iso_speed || iso_speed == 65535)) + iso_speed = 50 * libraw_powf64l(2.0, i / 32.0 - 4); #ifdef LIBRAW_LIBRARY_BUILD get4(); #else - if ((i=(get2(),get2())) != 0x7fff && !aperture) - aperture = libraw_powf64(2.0, i/64.0); + if ((i = (get2(), get2())) != 0x7fff && !aperture) + aperture = libraw_powf64l(2.0, i / 64.0); #endif - if ((i=get2()) != 0xffff && !shutter) - shutter = libraw_powf64(2.0, (short) i/-32.0); - wbi = (get2(),get2()); - shot_order = (get2(),get2()); + if ((i = get2()) != 0xffff && !shutter) + shutter = libraw_powf64l(2.0, (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 == 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); + fgets(model2, 64, ifp); if (tag == 8 && type == 4) shot_order = get4(); - if (tag == 9 && !strncmp(make,"Canon",5)) - fread (artist, 64, 1, ifp); + if (tag == 9 && !strncmp(make, "Canon", 5)) + 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 == 0xd && type == 7 && get2() == 0xaaaa) + { +#if 0 /* Canon rotation data is handled by EXIF.Orientation */ + 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'; +#endif } #ifndef LIBRAW_LIBRARY_BUILD - if (tag == 0x10 && type == 4) unique_id = get4(); + if (tag == 0x10 && type == 4) + unique_id = get4(); #endif #ifdef LIBRAW_LIBRARY_BUILD INT64 _pos2 = ftell(ifp); - if (!strncasecmp(make,"Olympus",7)) - { - short nWB, tWB; - if ((tag == 0x20300108) || (tag == 0x20310109)) - imgdata.makernotes.olympus.ColorSpace = get2(); - - if ((tag == 0x20400102) && (len == 2) && - (!strncasecmp(model, "E-410", 5) || !strncasecmp(model, "E-510", 5))) - { - int i; - for (i=0; i<64; i++) - imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] = - imgdata.color.WB_Coeffs[i][1] = imgdata.color.WB_Coeffs[i][3] = 0x100; - for (i=64; i<256; i++) - imgdata.color.WB_Coeffs[i][1] = imgdata.color.WB_Coeffs[i][3] = 0x100; - } - if ((tag >= 0x20400102) && (tag <= 0x2040010d)) - { - ushort CT; - nWB = tag-0x20400102; - switch (nWB) - { - case 0 : CT = 3000; tWB = LIBRAW_WBI_Tungsten; break; - case 1 : CT = 3300; tWB = 0x100; break; - case 2 : CT = 3600; tWB = 0x100; break; - case 3 : CT = 3900; tWB = 0x100; break; - case 4 : CT = 4000; tWB = LIBRAW_WBI_FL_W; break; - case 5 : CT = 4300; tWB = 0x100; break; - case 6 : CT = 4500; tWB = LIBRAW_WBI_FL_D; break; - case 7 : CT = 4800; tWB = 0x100; break; - case 8 : CT = 5300; tWB = LIBRAW_WBI_FineWeather; break; - case 9 : CT = 6000; tWB = LIBRAW_WBI_Cloudy; break; - case 10: CT = 6600; tWB = LIBRAW_WBI_FL_N; break; - case 11: CT = 7500; tWB = LIBRAW_WBI_Shade; break; - default: CT = 0; tWB = 0x100; - } - if (CT) - { - imgdata.color.WBCT_Coeffs[nWB][0] = CT; - imgdata.color.WBCT_Coeffs[nWB][1] = get2(); - imgdata.color.WBCT_Coeffs[nWB][3] = get2(); - if (len == 4) - { - imgdata.color.WBCT_Coeffs[nWB][2] = get2(); - imgdata.color.WBCT_Coeffs[nWB][4] = get2(); - } - } - if (tWB != 0x100) - FORC4 imgdata.color.WB_Coeffs[tWB][c] = imgdata.color.WBCT_Coeffs[nWB][c+1]; - } - if ((tag >= 0x20400113) && (tag <= 0x2040011e)) - { - nWB = tag-0x20400113; - imgdata.color.WBCT_Coeffs[nWB][2] = imgdata.color.WBCT_Coeffs[nWB][4] = get2(); - switch (nWB) - { - case 0: tWB = LIBRAW_WBI_Tungsten; break; - case 4: tWB = LIBRAW_WBI_FL_W; break; - case 6: tWB = LIBRAW_WBI_FL_D; break; - case 8: tWB = LIBRAW_WBI_FineWeather; break; - case 9: tWB = LIBRAW_WBI_Cloudy; break; - case 10: tWB = LIBRAW_WBI_FL_N; break; - case 11: tWB = LIBRAW_WBI_Shade; break; - default: tWB = 0x100; - } - if (tWB != 0x100) - imgdata.color.WB_Coeffs[tWB][1] = imgdata.color.WB_Coeffs[tWB][3] = - imgdata.color.WBCT_Coeffs[nWB][2]; - } + if (!strncasecmp(make, "Olympus", 7)) + { + short nWB, tWB; + if ((tag == 0x20300108) || (tag == 0x20310109)) + imgdata.makernotes.olympus.ColorSpace = get2(); - if (tag == 0x20400121) - { - imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][2] = get2(); - if (len == 4) - { - imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][1] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][3] = get2(); - } - } - if (tag == 0x2040011f) - { - imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][3] = get2(); - } - if (tag == 0x30000120) - { - imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][2] = get2(); - if (len == 2) - { - for (int i=0; i<256; i++) - imgdata.color.WB_Coeffs[i][1] = imgdata.color.WB_Coeffs[i][3] = 0x100; - } - } - if (tag == 0x30000121) - { - imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][2] = get2(); - } - if (tag == 0x30000122) - { - imgdata.color.WB_Coeffs[LIBRAW_WBI_FineWeather][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_FineWeather][2] = get2(); - } - if (tag == 0x30000123) - { - imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][2] = get2(); - } - if (tag == 0x30000124) - { - imgdata.color.WB_Coeffs[LIBRAW_WBI_Sunset][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Sunset][2] = get2(); - } - if (tag == 0x30000130) - { - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][2] = get2(); - } - if (tag == 0x30000131) - { - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][2] = get2(); - } - if (tag == 0x30000132) - { - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][2] = get2(); - } - if (tag == 0x30000133) - { - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][2] = get2(); - } + if ((tag == 0x20400101) && (len == 2) && (!strncasecmp(model, "E-410", 5) || !strncasecmp(model, "E-510", 5))) + { + int i; + for (i = 0; i < 64; i++) + imgdata.color.WBCT_Coeffs[i][2] = imgdata.color.WBCT_Coeffs[i][4] = imgdata.color.WB_Coeffs[i][1] = + imgdata.color.WB_Coeffs[i][3] = 0x100; + for (i = 64; i < 256; i++) + imgdata.color.WB_Coeffs[i][1] = imgdata.color.WB_Coeffs[i][3] = 0x100; + } + if ((tag >= 0x20400101) && (tag <= 0x20400111)) + { + nWB = tag - 0x20400101; + tWB = Oly_wb_list2[nWB << 1]; + ushort CT = Oly_wb_list2[(nWB << 1) | 1]; + int wb[4]; + wb[0] = get2(); + wb[2] = get2(); + if (tWB != 0x100) + { + imgdata.color.WB_Coeffs[tWB][0] = wb[0]; + imgdata.color.WB_Coeffs[tWB][2] = wb[2]; + } + if (CT) + { + imgdata.color.WBCT_Coeffs[nWB - 1][0] = CT; + imgdata.color.WBCT_Coeffs[nWB - 1][1] = wb[0]; + imgdata.color.WBCT_Coeffs[nWB - 1][3] = wb[2]; + } + if (len == 4) + { + wb[1] = get2(); + wb[3] = get2(); + if (tWB != 0x100) + { + imgdata.color.WB_Coeffs[tWB][1] = wb[1]; + imgdata.color.WB_Coeffs[tWB][3] = wb[3]; + } + if (CT) + { + imgdata.color.WBCT_Coeffs[nWB - 1][2] = wb[1]; + imgdata.color.WBCT_Coeffs[nWB - 1][4] = wb[3]; + } + } + } + if ((tag >= 0x20400112) && (tag <= 0x2040011e)) + { + nWB = tag - 0x20400112; + int wbG = get2(); + tWB = Oly_wb_list2[nWB << 1]; + if (nWB) + imgdata.color.WBCT_Coeffs[nWB - 1][2] = imgdata.color.WBCT_Coeffs[nWB - 1][4] = wbG; + if (tWB != 0x100) + imgdata.color.WB_Coeffs[tWB][1] = imgdata.color.WB_Coeffs[tWB][3] = wbG; + } - if((tag == 0x20400805) && (len == 2)) - { - imgdata.makernotes.olympus.OlympusSensorCalibration[0]=getreal(type); - imgdata.makernotes.olympus.OlympusSensorCalibration[1]=getreal(type); - FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.olympus.OlympusSensorCalibration[0]; - } - if (tag == 0x20200401) - { - imgdata.other.FlashEC = getreal(type); - } - } - fseek(ifp,_pos2,SEEK_SET); + if (tag == 0x20400121) + { + imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][0] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][2] = get2(); + if (len == 4) + { + imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][1] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][3] = get2(); + } + } + if (tag == 0x2040011f) + { + int wbG = get2(); + if (imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][0]) + imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][3] = wbG; + FORC4 if (imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom1 + c][0]) + imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom1 + c][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom1 + c][3] = + wbG; + } + if ((tag == 0x30000110) && strcmp(software, "v757-71")) + { + imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][0] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][2] = get2(); + if (len == 2) + { + for (int i = 0; i < 256; i++) + imgdata.color.WB_Coeffs[i][1] = imgdata.color.WB_Coeffs[i][3] = 0x100; + } + } + if ((((tag >= 0x30000120) && (tag <= 0x30000124)) || ((tag >= 0x30000130) && (tag <= 0x30000133))) && + strcmp(software, "v757-71")) + { + int wb_ind; + if (tag <= 0x30000124) + wb_ind = tag - 0x30000120; + else + wb_ind = tag - 0x30000130 + 5; + imgdata.color.WB_Coeffs[Oly_wb_list1[wb_ind]][0] = get2(); + imgdata.color.WB_Coeffs[Oly_wb_list1[wb_ind]][2] = get2(); + } + + if ((tag == 0x20400805) && (len == 2)) + { + imgdata.makernotes.olympus.OlympusSensorCalibration[0] = getreal(type); + imgdata.makernotes.olympus.OlympusSensorCalibration[1] = getreal(type); + FORC4 imgdata.color.linear_max[c] = imgdata.makernotes.olympus.OlympusSensorCalibration[0]; + } + if (tag == 0x20200306) + { + uchar uc; + fread(&uc, 1, 1, ifp); + imgdata.makernotes.olympus.AFFineTune = uc; + } + if (tag == 0x20200307) + { + FORC3 imgdata.makernotes.olympus.AFFineTuneAdj[c] = get2(); + } + if (tag == 0x20200401) + { + imgdata.other.FlashEC = getreal(type); + } + } + fseek(ifp, _pos2, SEEK_SET); #endif - if (tag == 0x11 && is_raw && !strncmp(make,"NIKON",5)) { - fseek (ifp, get4()+base, SEEK_SET); - parse_tiff_ifd (base); + 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; + 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; + 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; + fread(model, 64, 1, ifp); + if (strstr(make, "PENTAX")) + { + if (tag == 0x1b) + tag = 0x1018; + if (tag == 0x1c) + tag = 0x1017; } - if (tag == 0x1d) { + if (tag == 0x1d) + { while ((c = fgetc(ifp)) && c != EOF) #ifdef LIBRAW_LIBRARY_BUILD { if ((!custom_serial) && (!isdigit(c))) { - if ((strbuflen(model) == 3) && (!strcmp(model,"D50"))) + if ((strbuflen(model) == 3) && (!strcmp(model, "D50"))) { custom_serial = 34; } else { custom_serial = 96; } } #endif - serial = serial*10 + (isdigit(c) ? c - '0' : c % 10); + serial = serial * 10 + (isdigit(c) ? c - '0' : c % 10); #ifdef LIBRAW_LIBRARY_BUILD } if (!imgdata.shootinginfo.BodySerial[0]) sprintf(imgdata.shootinginfo.BodySerial, "%d", serial); #endif } - if (tag == 0x29 && type == 1) { // Canon PowerShot G9 - c = wbi < 18 ? "012347800000005896"[wbi]-'0' : 0; - fseek (ifp, 8 + c*32, SEEK_CUR); + if (tag == 0x29 && type == 1) + { // Canon PowerShot G9 + c = wbi < 18 ? "012347800000005896"[wbi] - '0' : 0; + fseek(ifp, 8 + c * 32, SEEK_CUR); FORC4 cam_mul[c ^ (c >> 1) ^ 1] = get4(); } #ifndef LIBRAW_LIBRARY_BUILD if (tag == 0x3d && type == 3 && len == 4) - FORC4 cblack[c ^ c >> 1] = get2() >> (14-tiff_bps); + FORC4 cblack[c ^ c >> 1] = get2() >> (14 - tiff_bps); #endif - if (tag == 0x81 && type == 4) { + if (tag == 0x81 && type == 4) + { data_offset = get4(); - fseek (ifp, data_offset + 41, SEEK_SET); + fseek(ifp, data_offset + 41, SEEK_SET); raw_height = get2() * 2; - raw_width = get2(); + raw_width = get2(); filters = 0x61616161; } - if ((tag == 0x81 && type == 7) || - (tag == 0x100 && type == 7) || - (tag == 0x280 && type == 1)) { + 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); - FORC4 cam_mul[c ^ (c >> 1)] = get2(); - break; - 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) { + 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); + FORC4 cam_mul[c ^ (c >> 1)] = get2(); + break; + 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) && strncasecmp(make, "Samsung", 7)) + { order = 0x4949; - fseek (ifp, 140, SEEK_CUR); + fseek(ifp, 140, SEEK_CUR); FORC3 cam_mul[c] = get4(); } - if (tag == 0xa4 && type == 3) { - fseek (ifp, wbi*48, SEEK_CUR); + if (tag == 0xa4 && type == 3) + { + fseek(ifp, wbi * 48, SEEK_CUR); FORC3 cam_mul[c] = get2(); } - if (tag == 0xa7) { // shutter count - NikonKey = fgetc(ifp)^fgetc(ifp)^fgetc(ifp)^fgetc(ifp); - if ( (unsigned) (ver97-200) < 17) { + if (tag == 0xa7) + { // shutter count + NikonKey = fgetc(ifp) ^ fgetc(ifp) ^ fgetc(ifp) ^ fgetc(ifp); + if ((unsigned)(ver97 - 200) < 17) + { ci = xlat[0][serial & 0xff]; cj = xlat[1][NikonKey]; ck = 0x60; - for (i=0; i < 324; i++) + 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); + i = "66666>666;6A;:;55"[ver97 - 200] - '0'; + FORC4 cam_mul[c ^ (c >> 1) ^ (i & 1)] = sget2(buf97 + (i & -2) + c * 2); } #ifdef LIBRAW_LIBRARY_BUILD if ((NikonLensDataVersion > 200) && lenNikonLensData) { if (custom_serial) { ci = xlat[0][custom_serial]; } else { ci = xlat[0][serial & 0xff]; } cj = xlat[1][NikonKey]; ck = 0x60; for (i = 0; i < lenNikonLensData; i++) table_buf[i] ^= (cj += ci * ck++); processNikonLensData(table_buf, lenNikonLensData); lenNikonLensData = 0; free(table_buf); } - if (ver97 == 601) // Coolpix A - { - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; - } + if (ver97 == 601) // Coolpix A + { + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; + } #endif } - if(tag == 0xb001 && type == 3) // Sony ModelID - { - unique_id = get2(); - } + if (tag == 0xb001 && type == 3) // Sony ModelID + { + unique_id = get2(); + } if (tag == 0x200 && len == 3) - shot_order = (get4(),get4()); - if (tag == 0x200 && len == 4) + shot_order = (get4(), get4()); + if (tag == 0x200 && len == 4) // Pentax black level FORC4 cblack[c ^ c >> 1] = get2(); - if (tag == 0x201 && len == 4) - FORC4 cam_mul[c ^ (c >> 1)] = get2(); + if (tag == 0x201 && len == 4) // Pentax As Shot WB + FORC4 cam_mul[c ^ (c >> 1)] = get2(); if (tag == 0x220 && type == 7) meta_offset = ftell(ifp); if (tag == 0x401 && type == 4 && len == 4) FORC4 cblack[c ^ c >> 1] = get4(); #ifdef LIBRAW_LIBRARY_BUILD // not corrected for file bitcount, to be patched in open_datastream - if (tag == 0x03d && strstr(make,"NIKON") && len == 4) - { - FORC4 cblack[c ^ c >> 1] = get2(); - i = cblack[3]; - FORC3 if(i>cblack[c]) i = cblack[c]; - FORC4 cblack[c]-=i; - black += i; - } + if (tag == 0x03d && strstr(make, "NIKON") && len == 4) + { + FORC4 cblack[c ^ c >> 1] = get2(); + i = cblack[3]; + FORC3 if (i > cblack[c]) i = cblack[c]; + FORC4 cblack[c] -= i; + black += i; + } #endif - if (tag == 0xe01) { /* Nikon Capture Note */ + if (tag == 0xe01) + { /* Nikon Capture Note */ #ifdef LIBRAW_LIBRARY_BUILD - int loopc = 0; + int loopc = 0; #endif order = 0x4949; - fseek (ifp, 22, SEEK_CUR); - for (offset=22; offset+22 < len; offset += 22+i) { + fseek(ifp, 22, SEEK_CUR); + for (offset = 22; offset + 22 < len; offset += 22 + i) + { #ifdef LIBRAW_LIBRARY_BUILD - if(loopc++>1024) - throw LIBRAW_EXCEPTION_IO_CORRUPT; + if (loopc++ > 1024) + throw LIBRAW_EXCEPTION_IO_CORRUPT; #endif - tag = get4(); - fseek (ifp, 14, SEEK_CUR); - i = get4()-4; - if (tag == 0x76a43207) flip = get2(); - else fseek (ifp, i, SEEK_CUR); + 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); + 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 (tag == 0xf00 && type == 7) + { if (len == 614) - fseek (ifp, 176, SEEK_CUR); + fseek(ifp, 176, SEEK_CUR); else if (len == 734 || len == 1502) - fseek (ifp, 148, SEEK_CUR); - else goto next; + fseek(ifp, 148, SEEK_CUR); + else + goto next; goto get2_256; } - if ((tag == 0x1011 && len == 9) || tag == 0x20400200) - for (i=0; i < 3; i++) - { + if (((tag == 0x1011 && len == 9) || tag == 0x20400200) && strcmp(software, "v757-71")) + for (i = 0; i < 3; i++) + { #ifdef LIBRAW_LIBRARY_BUILD - if (!imgdata.makernotes.olympus.ColorSpace) - { - FORC3 cmatrix[i][c] = ((short) get2()) / 256.0; - } - else - { - FORC3 imgdata.color.ccm[i][c] = ((short) get2()) / 256.0; - } + if (!imgdata.makernotes.olympus.ColorSpace) + { + FORC3 cmatrix[i][c] = ((short)get2()) / 256.0; + } + else + { + FORC3 imgdata.color.ccm[i][c] = ((short)get2()) / 256.0; + } #else - FORC3 cmatrix[i][c] = ((short) get2()) / 256.0; + FORC3 cmatrix[i][c] = ((short)get2()) / 256.0; #endif - } + } 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: + 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); + fseek(ifp, get4() + base, SEEK_SET); #ifdef LIBRAW_LIBRARY_BUILD -// IB start + // IB start if (tag == 0x2010) - { - INT64 _pos3 = ftell(ifp); - parse_makernote(base, 0x2010); - fseek(ifp,_pos3,SEEK_SET); - } + { + INT64 _pos3 = ftell(ifp); + parse_makernote(base, 0x2010); + fseek(ifp, _pos3, SEEK_SET); + } - if ( - ((tag == 0x2020) || (tag == 0x3000) || (tag == 0x2030) || (tag == 0x2031)) && - ((type == 7) || (type == 13)) && - !strncasecmp(make,"Olympus",7) - ) - { - INT64 _pos3 = ftell(ifp); - parse_makernote(base, tag); - fseek(ifp,_pos3,SEEK_SET); - } + if (((tag == 0x2020) || (tag == 0x3000) || (tag == 0x2030) || (tag == 0x2031) || (tag == 0x2050)) && + ((type == 7) || (type == 13)) && !strncasecmp(make, "Olympus", 7)) + { + INT64 _pos3 = ftell(ifp); + parse_makernote(base, tag); + fseek(ifp, _pos3, SEEK_SET); + } // IB end #endif - if ((tag == 0x2020) && ((type == 7) || (type == 13)) && !strncmp(buf,"OLYMP",5)) - parse_thumb_note (base, 257, 258); + if ((tag == 0x2020) && ((type == 7) || (type == 13)) && !strncmp(buf, "OLYMP", 5)) + 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); + parse_makernote(base, 0x2040); + if (tag == 0xb028) + { + fseek(ifp, get4() + base, SEEK_SET); + parse_thumb_note(base, 136, 137); } - if (tag == 0x4001 && len > 500 && len < 100000) { + if (tag == 0x4001 && len > 500 && len < 100000) + { i = len == 582 ? 50 : len == 653 ? 68 : len == 5120 ? 142 : 126; - fseek (ifp, i, SEEK_CUR); + fseek(ifp, i, SEEK_CUR); FORC4 cam_mul[c ^ (c >> 1)] = get2(); - for (i+=18; i <= len; i+=10) { - get2(); - FORC4 sraw_mul[c ^ (c >> 1)] = get2(); - if (sraw_mul[1] == 1170) break; + for (i += 18; i <= len; i += 10) + { + get2(); + FORC4 sraw_mul[c ^ (c >> 1)] = get2(); + if (sraw_mul[1] == 1170) + break; } } - if(!strncasecmp(make,"Samsung",7)) - { - if (tag == 0xa020) // get the full Samsung encryption key - for (i=0; i<11; i++) SamsungKey[i] = get4(); - if (tag == 0xa021) // get and decode Samsung cam_mul array - FORC4 cam_mul[c ^ (c >> 1)] = get4() - SamsungKey[c]; + if (!strncasecmp(make, "Samsung", 7)) + { + if (tag == 0xa020) // get the full Samsung encryption key + for (i = 0; i < 11; i++) + SamsungKey[i] = get4(); + if (tag == 0xa021) // get and decode Samsung cam_mul array + FORC4 cam_mul[c ^ (c >> 1)] = get4() - SamsungKey[c]; #ifdef LIBRAW_LIBRARY_BUILD - if (tag == 0xa023) - { - imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][0] = get4() - SamsungKey[8]; - imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][1] = get4() - SamsungKey[9]; - imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][3] = get4() - SamsungKey[10]; - imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][2] = get4() - SamsungKey[0]; - if (imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][0] < (imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][1]>>1)) - { - imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][1] >> 4; - imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][3] >> 4; - } - } - if (tag == 0xa024) - { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][c ^ (c >> 1)] = get4() - SamsungKey[c+1]; - if (imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][0] < (imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][1]>>1)) - { - imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][1] >> 4; - imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][3] >> 4; - } - } - if (tag == 0xa025) - imgdata.color.linear_max[0]= - imgdata.color.linear_max[1]= - imgdata.color.linear_max[2]= - imgdata.color.linear_max[3]= get4() - SamsungKey[0]; - if (tag == 0xa030 && len == 9) - for (i=0; i < 3; i++) - FORC3 imgdata.color.ccm[i][c] = (float)((short)((get4() + SamsungKey[i*3+c])))/256.0; -#endif - if (tag == 0xa031 && len == 9) // get and decode Samsung color matrix - for (i=0; i < 3; i++) - FORC3 cmatrix[i][c] = (float)((short)((get4() + SamsungKey[i*3+c])))/256.0; - - if (tag == 0xa028) - FORC4 cblack[c ^ (c >> 1)] = get4() - SamsungKey[c]; + if (tag == 0xa022) + { + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get4() - SamsungKey[c + 4]; + if (imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][0] < (imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][1] >> 1)) + { + imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][1] >> 4; + imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][3] >> 4; + } + } + + if (tag == 0xa023) + { + imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][0] = get4() - SamsungKey[8]; + imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][1] = get4() - SamsungKey[9]; + imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][3] = get4() - SamsungKey[10]; + imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][2] = get4() - SamsungKey[0]; + if (imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][0] < (imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][1] >> 1)) + { + imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][1] >> 4; + imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Ill_A][3] >> 4; + } + } + if (tag == 0xa024) + { + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][c ^ (c >> 1)] = get4() - SamsungKey[c + 1]; + if (imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][0] < (imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][1] >> 1)) + { + imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][1] >> 4; + imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_D65][3] >> 4; + } } + /* + if (tag == 0xa025) { + i = get4(); + imgdata.color.linear_max[0] = imgdata.color.linear_max[1] = imgdata.color.linear_max[2] = + imgdata.color.linear_max[3] = i - SamsungKey[0]; printf ("Samsung 0xa025 %d\n", i); } + */ + if (tag == 0xa030 && len == 9) + for (i = 0; i < 3; i++) + FORC3 imgdata.color.ccm[i][c] = (float)((short)((get4() + SamsungKey[i * 3 + c]))) / 256.0; +#endif + if (tag == 0xa031 && len == 9) // get and decode Samsung color matrix + for (i = 0; i < 3; i++) + FORC3 cmatrix[i][c] = (float)((short)((get4() + SamsungKey[i * 3 + c]))) / 256.0; + + if (tag == 0xa028) + FORC4 cblack[c ^ (c >> 1)] = get4() - SamsungKey[c]; + } else + { + // Somebody else use 0xa021 and 0xa028? + if (tag == 0xa021) + FORC4 cam_mul[c ^ (c >> 1)] = get4(); + if (tag == 0xa028) + FORC4 cam_mul[c ^ (c >> 1)] -= get4(); + } +#ifdef LIBRAW_LIBRARY_BUILD + if (tag == 0x4021 && (imgdata.makernotes.canon.multishot[0] = get4()) && + (imgdata.makernotes.canon.multishot[1] = get4())) + { + if (len >= 4) { - // Somebody else use 0xa021 and 0xa028? - if (tag == 0xa021) - FORC4 cam_mul[c ^ (c >> 1)] = get4(); - if (tag == 0xa028) - FORC4 cam_mul[c ^ (c >> 1)] -= get4(); + imgdata.makernotes.canon.multishot[2] = get4(); + imgdata.makernotes.canon.multishot[3] = get4(); } + FORC4 cam_mul[c] = 1024; + } +#else if (tag == 0x4021 && get4() && get4()) FORC4 cam_mul[c] = 1024; -next: - fseek (ifp, save, SEEK_SET); +#endif + 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) +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); + 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) + 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) +void CLASS parse_exif(int base) { unsigned kodak, entries, tag, type, len, save, c; - double expo,ape; + double expo, ape; - kodak = !strncmp(make,"EASTMAN",7) && tiff_nifds < 3; + kodak = !strncmp(make, "EASTMAN", 7) && tiff_nifds < 3; entries = get2(); - if(!strncmp(make,"Hasselblad",10) && (tiff_nifds > 3) && (entries > 512)) return; + if (!strncmp(make, "Hasselblad", 10) && (tiff_nifds > 3) && (entries > 512)) + return; #ifdef LIBRAW_LIBRARY_BUILD INT64 fsize = ifp->size(); #endif - while (entries--) { - tiff_get (base, &tag, &type, &len, &save); + while (entries--) + { + tiff_get(base, &tag, &type, &len, &save); #ifdef LIBRAW_LIBRARY_BUILD INT64 savepos = ftell(ifp); if (len > 8 && savepos + len > fsize * 2) { - fseek(ifp, save, SEEK_SET); // Recover tiff-read position!! - continue; + fseek(ifp, save, SEEK_SET); // Recover tiff-read position!! + continue; + } + if (callbacks.exif_cb) + { + callbacks.exif_cb(callbacks.exifparser_data, tag, type, len, order, ifp); + fseek(ifp, savepos, SEEK_SET); } - if(callbacks.exif_cb) - { - callbacks.exif_cb(callbacks.exifparser_data,tag,type,len,order,ifp); - fseek(ifp,savepos,SEEK_SET); - } #endif - switch (tag) { + switch (tag) + { #ifdef LIBRAW_LIBRARY_BUILD - case 0xa405: // FocalLengthIn35mmFormat + + case 0x9400: + imgdata.other.exifAmbientTemperature = getreal(type); + if ((imgdata.other.CameraTemperature > -273.15f) && (OlyID == 0x4434353933ULL)) // TG-5 + imgdata.other.CameraTemperature += imgdata.other.exifAmbientTemperature; + break; + case 0x9401: + imgdata.other.exifHumidity = getreal(type); + break; + case 0x9402: + imgdata.other.exifPressure = getreal(type); + break; + case 0x9403: + imgdata.other.exifWaterDepth = getreal(type); + break; + case 0x9404: + imgdata.other.exifAcceleration = getreal(type); + break; + case 0x9405: + imgdata.other.exifCameraElevationAngle = getreal(type); + break; + + case 0xa405: // FocalLengthIn35mmFormat imgdata.lens.FocalLengthIn35mmFormat = get2(); break; - case 0xa431: // BodySerialNumber + case 0xa431: // BodySerialNumber stmread(imgdata.shootinginfo.BodySerial, len, ifp); break; - case 0xa432: // LensInfo, 42034dec, Lens Specification per EXIF standard + case 0xa432: // LensInfo, 42034dec, Lens Specification per EXIF standard imgdata.lens.MinFocal = getreal(type); imgdata.lens.MaxFocal = getreal(type); imgdata.lens.MaxAp4MinFocal = getreal(type); imgdata.lens.MaxAp4MaxFocal = getreal(type); break; - case 0xa435: // LensSerialNumber + case 0xa435: // LensSerialNumber stmread(imgdata.lens.LensSerial, len, ifp); break; - case 0xc630: // DNG LensInfo, Lens Specification per EXIF standard + case 0xc630: // DNG LensInfo, Lens Specification per EXIF standard imgdata.lens.dng.MinFocal = getreal(type); imgdata.lens.dng.MaxFocal = getreal(type); imgdata.lens.dng.MaxAp4MinFocal = getreal(type); imgdata.lens.dng.MaxAp4MaxFocal = getreal(type); break; - case 0xa433: // LensMake + case 0xa433: // LensMake stmread(imgdata.lens.LensMake, len, ifp); break; - case 0xa434: // LensModel + case 0xa434: // LensModel stmread(imgdata.lens.Lens, len, ifp); if (!strncmp(imgdata.lens.Lens, "----", 4)) imgdata.lens.Lens[0] = 0; break; case 0x9205: - imgdata.lens.EXIF_MaxAp = libraw_powf64(2.0f, (getreal(type) / 2.0f)); + imgdata.lens.EXIF_MaxAp = libraw_powf64l(2.0f, (getreal(type) / 2.0f)); break; #endif - case 33434: tiff_ifd[tiff_nifds-1].t_shutter = - shutter = getreal(type); break; - case 33437: aperture = getreal(type); break; // 0x829d FNumber - case 34855: iso_speed = get2(); break; - case 34866: - if (iso_speed == 0xffff && (!strncasecmp(make, "SONY",4) || !strncasecmp(make, "CANON",5))) - iso_speed = getreal(type); - break; - case 36867: - case 36868: get_timestamp(0); break; - case 37377: if ((expo = -getreal(type)) < 128 && shutter == 0.) - tiff_ifd[tiff_nifds-1].t_shutter = - shutter = libraw_powf64(2.0, expo); - break; - case 37378: // 0x9202 ApertureValue - if ((fabs(ape = getreal(type))<256.0) && (!aperture)) - aperture = libraw_powf64(2.0, ape/2); - break; - case 37385: flash_used = getreal(type); break; - case 37386: focal_len = getreal(type); break; - case 37500: // tag 0x927c + case 33434: + tiff_ifd[tiff_nifds - 1].t_shutter = shutter = getreal(type); + break; + case 33437: + aperture = getreal(type); + break; // 0x829d FNumber + case 34855: + iso_speed = get2(); + break; + case 34865: + if (iso_speed == 0xffff && !strncasecmp(make, "FUJI", 4)) + iso_speed = getreal(type); + break; + case 34866: + if (iso_speed == 0xffff && (!strncasecmp(make, "SONY", 4) || !strncasecmp(make, "CANON", 5))) + iso_speed = getreal(type); + break; + case 36867: + case 36868: + get_timestamp(0); + break; + case 37377: + if ((expo = -getreal(type)) < 128 && shutter == 0.) + tiff_ifd[tiff_nifds - 1].t_shutter = shutter = libraw_powf64l(2.0, expo); + break; + case 37378: // 0x9202 ApertureValue + if ((fabs(ape = getreal(type)) < 256.0) && (!aperture)) + aperture = libraw_powf64l(2.0, ape / 2); + break; + case 37385: + flash_used = getreal(type); + break; + case 37386: + focal_len = getreal(type); + break; + case 37500: // tag 0x927c #ifdef LIBRAW_LIBRARY_BUILD - if (((make[0] == '\0') && (!strncmp(model, "ov5647",6))) || - ((!strncmp(make, "RaspberryPi",11)) && (!strncmp(model, "RP_OV5647",9))) || - ((!strncmp(make, "RaspberryPi",11)) && (!strncmp(model, "RP_imx219",9)))) { + if (((make[0] == '\0') && (!strncmp(model, "ov5647", 6))) || + ((!strncmp(make, "RaspberryPi", 11)) && (!strncmp(model, "RP_OV5647", 9))) || + ((!strncmp(make, "RaspberryPi", 11)) && (!strncmp(model, "RP_imx219", 9)))) + { char mn_text[512]; char *pos; char ccms[512]; ushort l; float num; fgets(mn_text, MIN(len,511), ifp); mn_text[511] = 0; pos = strstr(mn_text, "gain_r="); if (pos) cam_mul[0] = atof(pos + 7); pos = strstr(mn_text, "gain_b="); if (pos) cam_mul[2] = atof(pos + 7); if ((cam_mul[0] > 0.001f) && (cam_mul[2] > 0.001f)) cam_mul[1] = cam_mul[3] = 1.0f; else cam_mul[0] = cam_mul[2] = 0.0f; pos = strstr(mn_text, "ccm="); if(pos) { pos +=4; char *pos2 = strstr(pos, " "); if(pos2) { l = pos2 - pos; memcpy(ccms, pos, l); ccms[l] = '\0'; #if defined WIN32 || defined(__MINGW32__) // Win32 strtok is already thread-safe pos = strtok(ccms, ","); #else char *last=0; pos = strtok_r(ccms, ",",&last); #endif if(pos) { for (l = 0; l < 4; l++) { num = 0.0; for (c = 0; c < 3; c++) { imgdata.color.ccm[l][c] = (float)atoi(pos); num += imgdata.color.ccm[l][c]; #if defined WIN32 || defined(__MINGW32__) pos = strtok(NULL, ","); #else pos = strtok_r(NULL, ",",&last); #endif if(!pos) goto end; // broken } if (num > 0.01) FORC3 imgdata.color.ccm[l][c] = imgdata.color.ccm[l][c] / num; } } } } end:; } else + #endif - 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; + 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) * 0x01010101U << c; } - fseek (ifp, save, SEEK_SET); + fseek(ifp, save, SEEK_SET); } } #ifdef LIBRAW_LIBRARY_BUILD void CLASS parse_gps_libraw(int base) { unsigned entries, tag, type, len, save, c; entries = get2(); if (entries > 200) - return; + return; if (entries > 0) imgdata.other.parsed_gps.gpsparsed = 1; - while (entries--) { + while (entries--) + { tiff_get(base, &tag, &type, &len, &save); - if(len > 1024) continue; // no GPS tags are 1k or larger - switch (tag) { - case 1: imgdata.other.parsed_gps.latref = getc(ifp); break; - case 3: imgdata.other.parsed_gps.longref = getc(ifp); break; - case 5: imgdata.other.parsed_gps.altref = getc(ifp); break; + if (len > 1024) + { + fseek(ifp, save, SEEK_SET); // Recover tiff-read position!! + continue; // no GPS tags are 1k or larger + } + switch (tag) + { + case 1: + imgdata.other.parsed_gps.latref = getc(ifp); + break; + case 3: + imgdata.other.parsed_gps.longref = getc(ifp); + break; + case 5: + imgdata.other.parsed_gps.altref = getc(ifp); + break; case 2: if (len == 3) FORC(3) imgdata.other.parsed_gps.latitude[c] = getreal(type); break; case 4: if (len == 3) FORC(3) imgdata.other.parsed_gps.longtitude[c] = getreal(type); break; case 7: if (len == 3) FORC(3) imgdata.other.parsed_gps.gpstimestamp[c] = getreal(type); break; case 6: imgdata.other.parsed_gps.altitude = getreal(type); break; - case 9: imgdata.other.parsed_gps.gpsstatus = getc(ifp); break; + case 9: + imgdata.other.parsed_gps.gpsstatus = getc(ifp); + break; } fseek(ifp, save, SEEK_SET); } } #endif -void CLASS parse_gps (int base) +void CLASS parse_gps(int base) { unsigned entries, tag, type, len, save, c; entries = get2(); - while (entries--) { - tiff_get (base, &tag, &type, &len, &save); - if(len > 1024) continue; // no GPS tags are 1k or larger - 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); + while (entries--) + { + tiff_get(base, &tag, &type, &len, &save); + if (len > 1024) + { + fseek(ifp, save, SEEK_SET); // Recover tiff-read position!! + continue; // no GPS tags are 1k or larger + } + 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); + fseek(ifp, save, SEEK_SET); } } -void CLASS romm_coeff (float romm_cam[3][3]) +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 } }; + 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]; + 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) +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", - "AFi-II 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" }; + 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", + "AFi-II 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; + fseek(ifp, offset, SEEK_SET); + while (1) + { + if (get4() != 0x504b5453) + break; get4(); - fread (data, 1, 40, ifp); + fread(data, 1, 40, ifp); skip = get4(); from = ftell(ifp); // IB start #ifdef LIBRAW_LIBRARY_BUILD - if (!strcmp(data,"CameraObj_camera_type")) { - stmread(imgdata.lens.makernotes.body, skip, ifp); - } - if (!strcmp(data,"back_serial_number")) { - char buffer [sizeof(imgdata.shootinginfo.BodySerial)]; - char *words[4]; - int nwords; - stmread(buffer, skip, ifp); - nwords = getwords(buffer, words, 4,sizeof(imgdata.shootinginfo.BodySerial)); - strcpy (imgdata.shootinginfo.BodySerial, words[0]); + if (!strcmp(data, "CameraObj_camera_type")) + { + stmread(imgdata.lens.makernotes.body, skip, ifp); } - if (!strcmp(data,"CaptProf_serial_number")) { - char buffer [sizeof(imgdata.shootinginfo.InternalBodySerial)]; - char *words[4]; - int nwords; - stmread(buffer, skip, ifp); - nwords = getwords(buffer, words, 4,sizeof(imgdata.shootinginfo.InternalBodySerial)); - strcpy (imgdata.shootinginfo.InternalBodySerial, words[0]); + if (!strcmp(data, "back_serial_number")) + { + char buffer[sizeof(imgdata.shootinginfo.BodySerial)]; + char *words[4]; + int nwords; + stmread(buffer, skip, ifp); + nwords = getwords(buffer, words, 4, sizeof(imgdata.shootinginfo.BodySerial)); + strcpy(imgdata.shootinginfo.BodySerial, words[0]); + } + if (!strcmp(data, "CaptProf_serial_number")) + { + char buffer[sizeof(imgdata.shootinginfo.InternalBodySerial)]; + char *words[4]; + int nwords; + stmread(buffer, skip, ifp); + nwords = getwords(buffer, words, 4, sizeof(imgdata.shootinginfo.InternalBodySerial)); + strcpy(imgdata.shootinginfo.InternalBodySerial, words[0]); } #endif -// IB end - if (!strcmp(data,"JPEG_preview_data")) { + // IB end + if (!strcmp(data, "JPEG_preview_data")) + { thumb_offset = from; thumb_length = skip; } - if (!strcmp(data,"icc_camera_profile")) { + if (!strcmp(data, "icc_camera_profile")) + { profile_offset = from; profile_length = skip; } - if (!strcmp(data,"ShootObj_back_type")) { - fscanf (ifp, "%d", &i); - if ((unsigned) i < sizeof mod / sizeof (*mod)) - strcpy (model, mod[i]); - } - if (!strcmp(data,"icc_camera_to_tone_matrix")) { - for (i=0; i < 9; i++) - ((float *)romm_cam)[i] = int_to_float(get4()); - romm_coeff (romm_cam); - } - if (!strcmp(data,"CaptProf_color_matrix")) { - for (i=0; i < 9; i++) - fscanf (ifp, "%f", (float *)romm_cam + 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); + if (!strcmp(data, "ShootObj_back_type")) + { + fscanf(ifp, "%d", &i); + if ((unsigned)i < sizeof mod / sizeof(*mod)) + strcpy(model, mod[i]); + } + if (!strcmp(data, "icc_camera_to_tone_matrix")) + { + for (i = 0; i < 9; i++) + ((float *)romm_cam)[i] = int_to_float(get4()); + romm_coeff(romm_cam); + } + if (!strcmp(data, "CaptProf_color_matrix")) + { + for (i = 0; i < 9; i++) + fscanf(ifp, "%f", (float *)romm_cam + 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, "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")) + if (!strcmp(data, "Rows_data")) load_flags = get4(); - parse_mos (from); - fseek (ifp, skip+from, SEEK_SET); + parse_mos(from); + fseek(ifp, skip + from, SEEK_SET); } if (planes) - filters = (planes == 1) * 0x01010101 * - (uchar) "\x94\x61\x16\x49"[(flip/90 + frot) & 3]; + filters = (planes == 1) * 0x01010101U * (uchar) "\x94\x61\x16\x49"[(flip / 90 + frot) & 3]; } -void CLASS linear_table (unsigned len) +void CLASS linear_table(unsigned len) { int i; - if (len > 0x10000) len = 0x10000; - read_shorts (curve, len); - for (i=len; i < 0x10000; i++) - curve[i] = curve[i-1]; - maximum = curve[len<0x1000?0xfff:len-1]; + if (len > 0x10000) + len = 0x10000; + else if(len < 1) + return; + read_shorts(curve, len); + for (i = len; i < 0x10000; i++) + curve[i] = curve[i - 1]; + maximum = curve[len < 0x1000 ? 0xfff : len - 1]; } #ifdef LIBRAW_LIBRARY_BUILD -void CLASS Kodak_WB_0x08tags (int wb, unsigned type) +void CLASS Kodak_WB_0x08tags(int wb, unsigned type) { - float mul[3]={1,1,1}, num, mul2; - int c; - FORC3 mul[c] = (num=getreal(type))==0 ? 1 : num; - imgdata.color.WB_Coeffs[wb][1] = imgdata.color.WB_Coeffs[wb][3] = mul[1]; - mul2 = mul[1] * mul[1]; - imgdata.color.WB_Coeffs[wb][0] = mul2 / mul[0]; - imgdata.color.WB_Coeffs[wb][2] = mul2 / mul[2]; - return; + float mul[3] = {1, 1, 1}, num, mul2; + int c; + FORC3 mul[c] = (num = getreal(type)) == 0 ? 1 : num; + imgdata.color.WB_Coeffs[wb][1] = imgdata.color.WB_Coeffs[wb][3] = mul[1]; + mul2 = mul[1] * mul[1]; + imgdata.color.WB_Coeffs[wb][0] = mul2 / mul[0]; + imgdata.color.WB_Coeffs[wb][2] = mul2 / mul[2]; + return; } /* Thanks to Alexey Danilchenko for wb as-shot parsing code */ -void CLASS parse_kodak_ifd (int base) +void CLASS parse_kodak_ifd(int base) { unsigned entries, tag, type, len, save; - int i, c, wbi=-2; - float mul[3]={1,1,1}, num; - static const int wbtag[] = { 64037,64040,64039,64041,-1,-1,64042 }; + int j, c, wbi = -2, romm_camTemp[9], romm_camScale[3]; + float mul[3] = {1, 1, 1}, num; + static const int wbtag[] = {64037, 64040, 64039, 64041, -1, -1, 64042}; + // int a_blck = 0; entries = get2(); - if (entries > 1024) return; + if (entries > 1024) + return; INT64 fsize = ifp->size(); - while (entries--) { - tiff_get (base, &tag, &type, &len, &save); + while (entries--) + { + tiff_get(base, &tag, &type, &len, &save); INT64 savepos = ftell(ifp); - if (len > 8 && savepos + len > fsize * 2) + if (len > 8 && len + savepos > 2 * fsize) { - fseek(ifp, save, SEEK_SET); // Recover tiff-read position!! - continue; + fseek(ifp, save, SEEK_SET); // Recover tiff-read position!! + continue; } - if(callbacks.exif_cb) - { - callbacks.exif_cb(callbacks.exifparser_data,tag | 0x20000,type,len,order,ifp); - fseek(ifp,savepos,SEEK_SET); - } - if (tag == 1011) imgdata.other.FlashEC = getreal(type); - 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 / fMAX(1.0f,get2()); + if (callbacks.exif_cb) + { + callbacks.exif_cb(callbacks.exifparser_data, tag | 0x20000, type, len, order, ifp); + fseek(ifp, savepos, SEEK_SET); + } + if (tag == 1003) + imgdata.sizes.raw_crop.cleft = get2(); + if (tag == 1004) + imgdata.sizes.raw_crop.ctop = get2(); + if (tag == 1005) + imgdata.sizes.raw_crop.cwidth = get2(); + if (tag == 1006) + imgdata.sizes.raw_crop.cheight = get2(); + if (tag == 1007) + imgdata.makernotes.kodak.BlackLevelTop = get2(); + if (tag == 1008) + imgdata.makernotes.kodak.BlackLevelBottom = get2(); + if (tag == 1011) + imgdata.other.FlashEC = getreal(type); + 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 / fMAX(1.0f, get2()); wbi = -2; } - if (tag == 0x0848) Kodak_WB_0x08tags(LIBRAW_WBI_Daylight, type); - if (tag == 0x0849) Kodak_WB_0x08tags(LIBRAW_WBI_Tungsten, type); - if (tag == 0x084a) Kodak_WB_0x08tags(LIBRAW_WBI_Fluorescent, type); - if (tag == 0x084b) Kodak_WB_0x08tags(LIBRAW_WBI_Flash, type); - if (tag == 0x0e93) imgdata.color.linear_max[0] = - imgdata.color.linear_max[1] = - imgdata.color.linear_max[2] = - imgdata.color.linear_max[3] = get2(); - if (tag == 0x09ce) - stmread(imgdata.shootinginfo.InternalBodySerial,len, ifp); - if (tag == 0xfa00) - stmread(imgdata.shootinginfo.BodySerial, len, ifp); - if (tag == 0xfa27) - { - FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][c] = get4(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][1]; - } - if (tag == 0xfa28) - { - FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][c] = get4(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][1]; - } - if (tag == 0xfa29) - { - FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][c] = get4(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][1]; - } - if (tag == 0xfa2a) - { - FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][c] = get4(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][1]; - } + if ((tag == 1030) && (len == 1)) + imgdata.other.CameraTemperature = getreal(type); + if ((tag == 1043) && (len == 1)) + imgdata.other.SensorTemperature = getreal(type); + + if ((tag == 0x03ef) && (!strcmp(model, "EOS D2000C"))) + black = get2(); + if ((tag == 0x03f0) && (!strcmp(model, "EOS D2000C"))) + { + if (black) // already set by tag 0x03ef + black = (black + get2()) / 2; + else + black = get2(); + } + INT64 _pos2 = ftell(ifp); + if (tag == 0x0848) + Kodak_WB_0x08tags(LIBRAW_WBI_Daylight, type); + if (tag == 0x0849) + Kodak_WB_0x08tags(LIBRAW_WBI_Tungsten, type); + if (tag == 0x084a) + Kodak_WB_0x08tags(LIBRAW_WBI_Fluorescent, type); + if (tag == 0x084b) + Kodak_WB_0x08tags(LIBRAW_WBI_Flash, type); + if (tag == 0x084c) + Kodak_WB_0x08tags(LIBRAW_WBI_Custom, type); + if (tag == 0x084d) + Kodak_WB_0x08tags(LIBRAW_WBI_Auto, type); + if (tag == 0x0e93) + imgdata.color.linear_max[0] = imgdata.color.linear_max[1] = imgdata.color.linear_max[2] = + imgdata.color.linear_max[3] = get2(); + if (tag == 0x09ce) + stmread(imgdata.shootinginfo.InternalBodySerial, len, ifp); + if (tag == 0xfa00) + stmread(imgdata.shootinginfo.BodySerial, len, ifp); + if (tag == 0xfa27) + { + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][c] = get4(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][1]; + } + if (tag == 0xfa28) + { + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][c] = get4(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][1]; + } + if (tag == 0xfa29) + { + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][c] = get4(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][1]; + } + if (tag == 0xfa2a) + { + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][c] = get4(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][1]; + } - if (tag == 2120 + wbi || - (wbi<0 && tag == 2125)) /* use Auto WB if illuminant index is not set */ + fseek(ifp, _pos2, SEEK_SET); + + if (((tag == 0x07e4) || (tag == 0xfb01)) && (len == 9)) + { + short validM = 0; + if (type == 10) + { + for (j = 0; j < 9; j++) + { + ((float *)imgdata.makernotes.kodak.romm_camDaylight)[j] = getreal(type); + } + validM = 1; + } + else if (type == 9) + { + FORC3 + { + romm_camScale[c] = 0; + for (j = 0; j < 3; j++) + { + romm_camTemp[c * 3 + j] = get4(); + romm_camScale[c] += romm_camTemp[c * 3 + j]; + } + } + if ((romm_camScale[0] > 0x1fff) && (romm_camScale[1] > 0x1fff) && (romm_camScale[2] > 0x1fff)) + { + FORC3 for (j = 0; j < 3; j++) + { + ((float *)imgdata.makernotes.kodak.romm_camDaylight)[c * 3 + j] = + ((float)romm_camTemp[c * 3 + j]) / ((float)romm_camScale[c]); + } + validM = 1; + } + } + if (validM) + { + romm_coeff(imgdata.makernotes.kodak.romm_camDaylight); + } + } + if (((tag == 0x07e5) || (tag == 0xfb02)) && (len == 9)) + { + if (type == 10) + { + for (j = 0; j < 9; j++) + { + ((float *)imgdata.makernotes.kodak.romm_camTungsten)[j] = getreal(type); + } + } + else if (type == 9) + { + FORC3 + { + romm_camScale[c] = 0; + for (j = 0; j < 3; j++) + { + romm_camTemp[c * 3 + j] = get4(); + romm_camScale[c] += romm_camTemp[c * 3 + j]; + } + } + if ((romm_camScale[0] > 0x1fff) && (romm_camScale[1] > 0x1fff) && (romm_camScale[2] > 0x1fff)) + { + FORC3 for (j = 0; j < 3; j++) + { + ((float *)imgdata.makernotes.kodak.romm_camTungsten)[c * 3 + j] = + ((float)romm_camTemp[c * 3 + j]) / ((float)romm_camScale[c]); + } + } + } + } + if (((tag == 0x07e6) || (tag == 0xfb03)) && (len == 9)) + { + if (type == 10) + { + for (j = 0; j < 9; j++) + { + ((float *)imgdata.makernotes.kodak.romm_camFluorescent)[j] = getreal(type); + } + } + else if (type == 9) + { + FORC3 + { + romm_camScale[c] = 0; + for (j = 0; j < 3; j++) + { + romm_camTemp[c * 3 + j] = get4(); + romm_camScale[c] += romm_camTemp[c * 3 + j]; + } + } + if ((romm_camScale[0] > 0x1fff) && (romm_camScale[1] > 0x1fff) && (romm_camScale[2] > 0x1fff)) + { + FORC3 for (j = 0; j < 3; j++) + { + ((float *)imgdata.makernotes.kodak.romm_camFluorescent)[c * 3 + j] = + ((float)romm_camTemp[c * 3 + j]) / ((float)romm_camScale[c]); + } + } + } + } + if (((tag == 0x07e7) || (tag == 0xfb04)) && (len == 9)) + { + if (type == 10) + { + for (j = 0; j < 9; j++) + { + ((float *)imgdata.makernotes.kodak.romm_camFlash)[j] = getreal(type); + } + } + else if (type == 9) + { + FORC3 + { + romm_camScale[c] = 0; + for (j = 0; j < 3; j++) + { + romm_camTemp[c * 3 + j] = get4(); + romm_camScale[c] += romm_camTemp[c * 3 + j]; + } + } + if ((romm_camScale[0] > 0x1fff) && (romm_camScale[1] > 0x1fff) && (romm_camScale[2] > 0x1fff)) + { + FORC3 for (j = 0; j < 3; j++) + { + ((float *)imgdata.makernotes.kodak.romm_camFlash)[c * 3 + j] = + ((float)romm_camTemp[c * 3 + j]) / ((float)romm_camScale[c]); + } + } + } + } + if (((tag == 0x07e8) || (tag == 0xfb05)) && (len == 9)) + { + if (type == 10) + { + for (j = 0; j < 9; j++) + { + ((float *)imgdata.makernotes.kodak.romm_camCustom)[j] = getreal(type); + } + } + else if (type == 9) { - FORC3 mul[c] = (num=getreal(type))==0 ? 1 : num; - FORC3 cam_mul[c] = mul[1] / mul[c]; /* normalise against green */ + FORC3 + { + romm_camScale[c] = 0; + for (j = 0; j < 3; j++) + { + romm_camTemp[c * 3 + j] = get4(); + romm_camScale[c] += romm_camTemp[c * 3 + j]; + } + } + if ((romm_camScale[0] > 0x1fff) && (romm_camScale[1] > 0x1fff) && (romm_camScale[2] > 0x1fff)) + { + FORC3 for (j = 0; j < 3; j++) + { + ((float *)imgdata.makernotes.kodak.romm_camCustom)[c * 3 + j] = + ((float)romm_camTemp[c * 3 + j]) / ((float)romm_camScale[c]); + } + } + } + } + if (((tag == 0x07e9) || (tag == 0xfb06)) && (len == 9)) + { + if (type == 10) + { + for (j = 0; j < 9; j++) + { + ((float *)imgdata.makernotes.kodak.romm_camAuto)[j] = getreal(type); + } + } + else if (type == 9) + { + FORC3 + { + romm_camScale[c] = 0; + for (j = 0; j < 3; j++) + { + romm_camTemp[c * 3 + j] = get4(); + romm_camScale[c] += romm_camTemp[c * 3 + j]; + } + } + if ((romm_camScale[0] > 0x1fff) && (romm_camScale[1] > 0x1fff) && (romm_camScale[2] > 0x1fff)) + { + FORC3 for (j = 0; j < 3; j++) + { + ((float *)imgdata.makernotes.kodak.romm_camAuto)[c * 3 + j] = + ((float)romm_camTemp[c * 3 + j]) / ((float)romm_camScale[c]); + } + } } - if (tag == 2317) linear_table (len); - if (tag == 0x903) iso_speed = getreal(type); - //if (tag == 6020) iso_speed = getint(type); - if (tag == 64013) wbi = fgetc(ifp); - if ((unsigned) wbi < 7 && tag == wbtag[wbi]) + } + + if (tag == 2120 + wbi || (wbi < 0 && tag == 2125)) /* use Auto WB if illuminant index is not set */ + { + FORC3 mul[c] = (num = getreal(type)) == 0 ? 1 : num; + FORC3 cam_mul[c] = mul[1] / mul[c]; /* normalise against green */ + } + if (tag == 2317) + linear_table(len); + if (tag == 0x903) + iso_speed = getreal(type); + // 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); + if (tag == 0xfa13) + width = getint(type); + if (tag == 0xfa14) + height = (getint(type) + 1) & -2; + + /* + height = getint(type); + + if (tag == 0xfa16) + raw_width = get2(); + if (tag == 0xfa17) + raw_height = get2(); + */ + if (tag == 0xfa18) + { + imgdata.makernotes.kodak.offset_left = getint(8); + if (type != 8) + imgdata.makernotes.kodak.offset_left += 1; + } + if (tag == 0xfa19) + { + imgdata.makernotes.kodak.offset_top = getint(8); + if (type != 8) + imgdata.makernotes.kodak.offset_top += 1; + } + + if (tag == 0xfa31) + imgdata.sizes.raw_crop.cwidth = get2(); + if (tag == 0xfa32) + imgdata.sizes.raw_crop.cheight = get2(); + if (tag == 0xfa3e) + imgdata.sizes.raw_crop.cleft = get2(); + if (tag == 0xfa3f) + imgdata.sizes.raw_crop.ctop = get2(); + + fseek(ifp, save, SEEK_SET); } } #else -void CLASS parse_kodak_ifd (int base) +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 }; + 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 / fMAX(1.0,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 / fMAX(1.0, get2()); wbi = -2; } - if (tag == 2118) wbtemp = getint(type); + if (tag == 2118) + wbtemp = getint(type); if (tag == 2120 + wbi && wbi >= 0) - FORC3 cam_mul[c] = 2048.0 / fMAX(1.0,getreal(type)); + FORC3 cam_mul[c] = 2048.0 / fMAX(1.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 / fMAX(1.0,(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 + { + for (num = i = 0; i < 4; i++) + num += getreal(type) * pow(wbtemp / 100.0, i); + cam_mul[c] = 2048 / fMAX(1.0, (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); + if (tag == 64019) + width = getint(type); + if (tag == 64020) + height = (getint(type) + 1) & -2; + fseek(ifp, save, SEEK_SET); } } #endif -int CLASS parse_tiff_ifd (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; + unsigned entries, tag, type, len, plen = 16, save; + int ifd, use_cm = 0, cfa, i, j, c, ima_len = 0; char *cbuf, *cp; - uchar cfa_pat[16], cfa_pc[] = { 0,1,2,3 }, tab[256]; + uchar cfa_pat[16], cfa_pc[] = {0, 1, 2, 3}, tab[256]; double fm[3][4], 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; + 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; int pana_raw = 0; #ifndef LIBRAW_LIBRARY_BUILD FILE *sfp; #endif 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++) + for (j = 0; j < 4; j++) + for (i = 0; i < 4; i++) cc[j][i] = i == j; entries = get2(); - if (entries > 512) return 1; + if (entries > 512) + return 1; #ifdef LIBRAW_LIBRARY_BUILD INT64 fsize = ifp->size(); #endif - while (entries--) { - tiff_get (base, &tag, &type, &len, &save); + while (entries--) + { + tiff_get(base, &tag, &type, &len, &save); #ifdef LIBRAW_LIBRARY_BUILD INT64 savepos = ftell(ifp); - if (len > 8 && savepos + len > fsize * 2) + if (len > 8 && savepos + len > 2 * fsize) { - fseek(ifp, save, SEEK_SET); // Recover tiff-read position!! - continue; + fseek(ifp, save, SEEK_SET); // Recover tiff-read position!! + continue; + } + if (callbacks.exif_cb) + { + callbacks.exif_cb(callbacks.exifparser_data, tag | (pana_raw ? 0x30000 : ((ifd + 1) << 20)), type, len, order, + ifp); + fseek(ifp, savepos, SEEK_SET); + } +#endif + +#ifdef LIBRAW_LIBRARY_BUILD + if (!strncasecmp(make, "SONY", 4) || + (!strncasecmp(make, "Hasselblad", 10) && + (!strncasecmp(model, "Stellar", 7) || !strncasecmp(model, "Lunar", 5) || !strncasecmp(model, "HV", 2)))) + { + switch (tag) + { + case 0x7300: // SR2 black level + for (int i = 0; i < 4 && i < len; i++) + cblack[i] = get2(); + break; + case 0x7302: + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c < 2)] = get2(); + break; + case 0x7312: + { + int i, lc[4]; + FORC4 lc[c] = get2(); + i = (lc[1] == 1024 && lc[2] == 1024) << 1; + SWAP(lc[i], lc[i + 1]); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c] = lc[c]; + } + break; + case 0x7480: + case 0x7820: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][c] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][1]; + break; + case 0x7481: + case 0x7821: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][c] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][1]; + break; + case 0x7482: + case 0x7822: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][c] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][1]; + break; + case 0x7483: + case 0x7823: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][c] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][1]; + break; + case 0x7484: + case 0x7824: + imgdata.color.WBCT_Coeffs[0][0] = 4500; + FORC3 imgdata.color.WBCT_Coeffs[0][c + 1] = get2(); + imgdata.color.WBCT_Coeffs[0][4] = imgdata.color.WBCT_Coeffs[0][2]; + break; + case 0x7486: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][c] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][1]; + break; + case 0x7825: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][c] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][1]; + break; + case 0x7826: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][c] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][1]; + break; + case 0x7827: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][c] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][1]; + break; + case 0x7828: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][c] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][1]; + break; + case 0x7829: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][c] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][1]; + break; + case 0x782a: + imgdata.color.WBCT_Coeffs[1][0] = 8500; + FORC3 imgdata.color.WBCT_Coeffs[1][c + 1] = get2(); + imgdata.color.WBCT_Coeffs[1][4] = imgdata.color.WBCT_Coeffs[1][2]; + break; + case 0x782b: + imgdata.color.WBCT_Coeffs[2][0] = 6000; + FORC3 imgdata.color.WBCT_Coeffs[2][c + 1] = get2(); + imgdata.color.WBCT_Coeffs[2][4] = imgdata.color.WBCT_Coeffs[2][2]; + break; + case 0x782c: + imgdata.color.WBCT_Coeffs[3][0] = 3200; + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_StudioTungsten][c] = imgdata.color.WBCT_Coeffs[3][c + 1] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_StudioTungsten][3] = imgdata.color.WBCT_Coeffs[3][4] = + imgdata.color.WB_Coeffs[LIBRAW_WBI_StudioTungsten][1]; + break; + case 0x782d: + imgdata.color.WBCT_Coeffs[4][0] = 2500; + FORC3 imgdata.color.WBCT_Coeffs[4][c + 1] = get2(); + imgdata.color.WBCT_Coeffs[4][4] = imgdata.color.WBCT_Coeffs[4][2]; + break; + case 0x787f: + if (len == 3) + { + FORC3 imgdata.color.linear_max[c] = get2(); + imgdata.color.linear_max[3] = imgdata.color.linear_max[1]; + } + else if (len == 1) + { + imgdata.color.linear_max[0] = imgdata.color.linear_max[1] = imgdata.color.linear_max[2] = + imgdata.color.linear_max[3] = getreal(type); // Is non-short possible here?? + } + break; + } } - if(callbacks.exif_cb) - { - callbacks.exif_cb(callbacks.exifparser_data,tag|(pana_raw?0x30000:0),type,len,order,ifp); - fseek(ifp,savepos,SEEK_SET); - } -#endif - -#ifdef LIBRAW_LIBRARY_BUILD - if (!strncasecmp(make, "SONY", 4) || - (!strncasecmp(make, "Hasselblad", 10) && - (!strncasecmp(model, "Stellar", 7) || - !strncasecmp(model, "Lunar", 5) || - !strncasecmp(model, "HV",2)))) - { - switch (tag) { - case 0x7300: // SR2 black level - for (int i = 0; i < 4 && i < len; i++) - cblack[i] = get2(); - break; - case 0x7480: - case 0x7820: - FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][c] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][1]; - break; - case 0x7481: - case 0x7821: - FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][c] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][1]; - break; - case 0x7482: - case 0x7822: - FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][c] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][1]; - break; - case 0x7483: - case 0x7823: - FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][c] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][1]; - break; - case 0x7484: - case 0x7824: - imgdata.color.WBCT_Coeffs[0][0] = 4500; - FORC3 imgdata.color.WBCT_Coeffs[0][c+1] = get2(); - imgdata.color.WBCT_Coeffs[0][4] = imgdata.color.WBCT_Coeffs[0][2]; - break; - case 0x7486: - FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][c] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][1]; - break; - case 0x7825: - FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][c] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][1]; - break; - case 0x7826: - FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][c] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][1]; - break; - case 0x7827: - FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][c] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][1]; - break; - case 0x7828: - FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][c] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][1]; - break; - case 0x7829: - FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][c] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][1]; - break; - case 0x782a: - imgdata.color.WBCT_Coeffs[1][0] = 8500; - FORC3 imgdata.color.WBCT_Coeffs[1][c+1] = get2(); - imgdata.color.WBCT_Coeffs[1][4] = imgdata.color.WBCT_Coeffs[1][2]; - break; - case 0x782b: - imgdata.color.WBCT_Coeffs[2][0] = 6000; - FORC3 imgdata.color.WBCT_Coeffs[2][c+1] = get2(); - imgdata.color.WBCT_Coeffs[2][4] = imgdata.color.WBCT_Coeffs[2][2]; - break; - case 0x782c: - imgdata.color.WBCT_Coeffs[3][0] = 3200; - FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_StudioTungsten][c] = imgdata.color.WBCT_Coeffs[3][c+1] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_StudioTungsten][3] = imgdata.color.WBCT_Coeffs[3][4] = imgdata.color.WB_Coeffs[LIBRAW_WBI_StudioTungsten][1]; - break; - case 0x782d: - imgdata.color.WBCT_Coeffs[4][0] = 2500; - FORC3 imgdata.color.WBCT_Coeffs[4][c+1] = get2(); - imgdata.color.WBCT_Coeffs[4][4] = imgdata.color.WBCT_Coeffs[4][2]; - break; - case 0x787f: - FORC3 imgdata.color.linear_max[c] = get2(); - imgdata.color.linear_max[3] = imgdata.color.linear_max[1]; - break; - } - } -#endif - - - switch (tag) { - case 1: if(len==4) pana_raw = get4(); break; - case 5: width = get2(); break; - case 6: height = get2(); break; - case 7: width += get2(); break; - case 9: if ((i = get2())) filters = i; -#ifdef LIBRAW_LIBRARY_BUILD - if(pana_raw && len == 1 && type ==3) - pana_black[3]+=i; #endif + + switch (tag) + { + case 1: + if (len == 4) + pana_raw = get4(); + break; + case 5: + width = get2(); + break; + case 6: + height = get2(); + break; + case 7: + width += get2(); + break; + case 9: + if ((i = get2())) + filters = i; + break; +#ifdef LIBRAW_LIBRARY_BUILD + case 10: + if (pana_raw && len == 1 && type == 3) + { + pana_bpp = get2(); + } + break; +#endif + case 14: + case 15: + case 16: +#ifdef LIBRAW_LIBRARY_BUILD + if (pana_raw) + { + imgdata.color.linear_max[tag - 14] = get2(); + if (tag == 15) + imgdata.color.linear_max[3] = imgdata.color.linear_max[1]; + } +#endif + break; + case 17: + case 18: + if (type == 3 && len == 1) + cam_mul[(tag - 17) * 2] = get2() / 256.0; + break; +#ifdef LIBRAW_LIBRARY_BUILD + case 19: + if (pana_raw) + { + ushort nWB, cnt, tWB; + nWB = get2(); + if (nWB > 0x100) + break; + for (cnt = 0; cnt < nWB; cnt++) + { + tWB = get2(); + if (tWB < 0x100) + { + imgdata.color.WB_Coeffs[tWB][0] = get2(); + imgdata.color.WB_Coeffs[tWB][2] = get2(); + imgdata.color.WB_Coeffs[tWB][1] = imgdata.color.WB_Coeffs[tWB][3] = 0x100; + } + else + get4(); + } + } + break; + + case 0x0120: + if (pana_raw) + { + unsigned sorder = order; + unsigned long sbase = base; + base = ftell(ifp); + order = get2(); + fseek(ifp, 2, SEEK_CUR); + fseek(ifp, get4()-8, SEEK_CUR); + parse_tiff_ifd (base); + base = sbase; + order = sorder; + } + break; + + case 0x2009: + if ((pana_encoding == 4) || (pana_encoding == 5)) + { + int n = MIN (8, len); + int permut[8] = {3, 2, 1, 0, 3+4, 2+4, 1+4, 0+4}; + + imgdata.makernotes.panasonic.BlackLevelDim = len; + + for (int i=0; i < n; i++) + { + imgdata.makernotes.panasonic.BlackLevel[permut[i]] = + (float) (get2()) / (float) (powf(2.f, 14.f-pana_bpp)); + } + } + break; +#endif + + case 23: + if (type == 3) + iso_speed = get2(); break; - case 8: - case 10: + case 28: + case 29: + case 30: #ifdef LIBRAW_LIBRARY_BUILD - if(pana_raw && len == 1 && type ==3) - pana_black[3]+=get2(); + if (pana_raw && len == 1 && type == 3) + { + pana_black[tag - 28] = get2(); + } + else #endif + { + cblack[tag - 28] = get2(); + cblack[3] = cblack[1]; + } + break; + case 36: + case 37: + case 38: + cam_mul[tag - 36] = get2(); break; - case 14: case 15: case 16: + case 39: #ifdef LIBRAW_LIBRARY_BUILD - if(pana_raw) { - imgdata.color.linear_max[tag-14] = get2(); - if (tag == 15 ) imgdata.color.linear_max[3] = imgdata.color.linear_max[1]; + if (pana_raw) + { + ushort nWB, cnt, tWB; + nWB = get2(); + if (nWB > 0x100) + break; + for (cnt = 0; cnt < nWB; cnt++) + { + tWB = get2(); + if (tWB < 0x100) + { + imgdata.color.WB_Coeffs[tWB][0] = get2(); + imgdata.color.WB_Coeffs[tWB][1] = imgdata.color.WB_Coeffs[tWB][3] = get2(); + imgdata.color.WB_Coeffs[tWB][2] = get2(); + } + else + fseek(ifp, 6, SEEK_CUR); } + } + break; #endif + if (len < 50 || cam_mul[0]) + break; + fseek(ifp, 12, SEEK_CUR); + FORC3 cam_mul[c] = get2(); break; - case 17: case 18: - if (type == 3 && len == 1) - cam_mul[(tag-17)*2] = get2() / 256.0; - break; #ifdef LIBRAW_LIBRARY_BUILD - case 19: - if(pana_raw) { - ushort nWB, cnt, tWB; - nWB = get2(); - if (nWB > 0x100) break; - for (cnt=0; cnt 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 28: case 29: case 30: #ifdef LIBRAW_LIBRARY_BUILD - if(pana_raw && len == 1 && type ==3) - { - pana_black[tag-28] = get2(); - } - else + case 278: + tiff_ifd[ifd].rows_per_strip = getint(type); + break; #endif + case 280: /* Panasonic RW2 offset */ + if (type != 4) + break; + load_raw = &CLASS panasonic_load_raw; + load_flags = 0x2008; + case 273: /* StripOffset */ +#ifdef LIBRAW_LIBRARY_BUILD + if (len > 1 && len < 16384) + { + off_t sav = ftell(ifp); + tiff_ifd[ifd].strip_offsets = (int *)calloc(len, sizeof(int)); + tiff_ifd[ifd].strip_offsets_count = len; + for (int i = 0; i < len; i++) + tiff_ifd[ifd].strip_offsets[i] = get4() + base; + fseek(ifp, sav, SEEK_SET); // restore position + } +/* fallback */ +#endif + 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].t_width = jh.wide; + tiff_ifd[ifd].t_height = jh.high; + tiff_ifd[ifd].bps = jh.bits; + tiff_ifd[ifd].samples = jh.clrs; + if (!(jh.sraw || (jh.clrs & 1))) + tiff_ifd[ifd].t_width *= jh.clrs; + if ((tiff_ifd[ifd].t_width > 4 * tiff_ifd[ifd].t_height) & ~jh.clrs) { - cblack[tag-28] = get2(); - cblack[3] = cblack[1]; - } - break; - case 36: case 37: case 38: - cam_mul[tag-36] = get2(); - break; - case 39: -#ifdef LIBRAW_LIBRARY_BUILD - if(pana_raw) { - ushort nWB, cnt, tWB; - nWB = get2(); - if (nWB > 0x100) break; - for (cnt=0; cnt 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; -#ifdef LIBRAW_LIBRARY_BUILD - case 278: - tiff_ifd[ifd].rows_per_strip = getint(type); - break; -#endif - case 280: /* Panasonic RW2 offset */ - if (type != 4) break; - load_raw = &CLASS panasonic_load_raw; - load_flags = 0x2008; - case 273: /* StripOffset */ -#ifdef LIBRAW_LIBRARY_BUILD - if(len > 1 && len < 16384) - { - off_t sav = ftell(ifp); - tiff_ifd[ifd].strip_offsets = (int*)calloc(len,sizeof(int)); - tiff_ifd[ifd].strip_offsets_count = len; - for(int i=0; i< len; i++) - tiff_ifd[ifd].strip_offsets[i]=get4()+base; - fseek(ifp,sav,SEEK_SET); // restore position - } - /* fallback */ -#endif - 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].t_width = jh.wide; - tiff_ifd[ifd].t_height = jh.high; - tiff_ifd[ifd].bps = jh.bits; - tiff_ifd[ifd].samples = jh.clrs; - if (!(jh.sraw || (jh.clrs & 1))) - tiff_ifd[ifd].t_width *= jh.clrs; - if ((tiff_ifd[ifd].t_width > 4*tiff_ifd[ifd].t_height) & ~jh.clrs) { - tiff_ifd[ifd].t_width /= 2; - tiff_ifd[ifd].t_height *= 2; - } - i = order; - parse_tiff (tiff_ifd[ifd].offset + 12); - order = i; - } - } - break; - case 274: /* Orientation */ - tiff_ifd[ifd].t_flip = "50132467"[get2() & 7]-'0'; - break; - case 277: /* SamplesPerPixel */ - tiff_ifd[ifd].samples = getint(type) & 7; - break; - case 279: /* StripByteCounts */ -#ifdef LIBRAW_LIBRARY_BUILD - if(len > 1 && len < 16384) - { - off_t sav = ftell(ifp); - tiff_ifd[ifd].strip_byte_counts = (int*)calloc(len,sizeof(int)); - tiff_ifd[ifd].strip_byte_counts_count = len; - for(int i=0; i< len; i++) - tiff_ifd[ifd].strip_byte_counts[i]=get4(); - fseek(ifp,sav,SEEK_SET); // restore position - } - /* fallback */ -#endif - 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) || - !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 317: - tiff_ifd[ifd].predictor = getint(type); - break; - case 322: /* TileWidth */ - tiff_ifd[ifd].t_tile_width = getint(type); - break; - case 323: /* TileLength */ - tiff_ifd[ifd].t_tile_length = getint(type); - break; - case 324: /* TileOffsets */ - tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4(); - if (len == 1) - tiff_ifd[ifd].t_tile_width = tiff_ifd[ifd].t_tile_length = 0; - if (len == 4) { - load_raw = &CLASS sinar_4shot_load_raw; - is_raw = 5; - } - break; - case 325: - tiff_ifd[ifd].bytes = len > 1 ? ftell(ifp): get4(); - break; - case 330: /* SubIFDs */ - if (!strcmp(model,"DSLR-A100") && tiff_ifd[ifd].t_width == 3872) { - load_raw = &CLASS sony_arw_load_raw; - data_offset = get4()+base; - ifd++; -#ifdef LIBRAW_LIBRARY_BUILD - if (ifd >= sizeof tiff_ifd / sizeof tiff_ifd[0]) - throw LIBRAW_EXCEPTION_IO_CORRUPT; -#endif - break; - } -#ifdef LIBRAW_LIBRARY_BUILD - if (!strncmp(make,"Hasselblad",10) && libraw_internal_data.unpacker_data.hasselblad_parser_flag) { - fseek (ifp, ftell(ifp)+4, SEEK_SET); - fseek (ifp, get4()+base, SEEK_SET); - parse_tiff_ifd (base); - break; - } -#endif - 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 339: - tiff_ifd[ifd].sample_format = getint(type); - break; - case 400: - strcpy (make, "Sarnoff"); - maximum = 0xfff; - break; -#ifdef LIBRAW_LIBRARY_BUILD - case 700: - if((type == 1 || type == 2 || type == 6 || type == 7) && len > 1 && len < 5100000) - { - xmpdata = (char*)malloc(xmplen = len+1); - fread(xmpdata,len,1,ifp); - xmpdata[len]=0; + tiff_ifd[ifd].t_width /= 2; + tiff_ifd[ifd].t_height *= 2; } + i = order; + parse_tiff(tiff_ifd[ifd].offset + 12); + order = i; + } + } + break; + case 274: /* Orientation */ + tiff_ifd[ifd].t_flip = "50132467"[get2() & 7] - '0'; + break; + case 277: /* SamplesPerPixel */ + tiff_ifd[ifd].samples = getint(type) & 7; + break; + case 279: /* StripByteCounts */ +#ifdef LIBRAW_LIBRARY_BUILD + if (len > 1 && len < 16384) + { + off_t sav = ftell(ifp); + tiff_ifd[ifd].strip_byte_counts = (int *)calloc(len, sizeof(int)); + tiff_ifd[ifd].strip_byte_counts_count = len; + for (int i = 0; i < len; i++) + tiff_ifd[ifd].strip_byte_counts[i] = get4(); + fseek(ifp, sav, SEEK_SET); // restore position + } +/* fallback */ +#endif + case 514: + case 61448: + tiff_ifd[ifd].bytes = get4(); + break; + case 61454: // FujiFilm "As Shot" + FORC3 cam_mul[(4 - c) % 3] = getint(type); + break; + case 305: + case 11: /* Software */ + if ((pana_raw) && (tag == 11) && (type == 3)) + { +#ifdef LIBRAW_LIBRARY_BUILD + imgdata.makernotes.panasonic.Compression = get2(); +#endif + break; + } + fgets(software, 64, ifp); + if (!strncmp(software, "Adobe", 5) || !strncmp(software, "dcraw", 5) || !strncmp(software, "UFRaw", 5) || + !strncmp(software, "Bibble", 6) || !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 317: + tiff_ifd[ifd].predictor = getint(type); + break; + case 322: /* TileWidth */ + tiff_ifd[ifd].t_tile_width = getint(type); + break; + case 323: /* TileLength */ + tiff_ifd[ifd].t_tile_length = getint(type); + break; + case 324: /* TileOffsets */ + tiff_ifd[ifd].offset = len > 1 ? ftell(ifp) : get4(); + if (len == 1) + tiff_ifd[ifd].t_tile_width = tiff_ifd[ifd].t_tile_length = 0; + if (len == 4) + { + load_raw = &CLASS sinar_4shot_load_raw; + is_raw = 5; + } + break; + case 325: + tiff_ifd[ifd].bytes = len > 1 ? ftell(ifp) : get4(); + break; + case 330: /* SubIFDs */ + if (!strcmp(model, "DSLR-A100") && tiff_ifd[ifd].t_width == 3872) + { + load_raw = &CLASS sony_arw_load_raw; + data_offset = get4() + base; + ifd++; +#ifdef LIBRAW_LIBRARY_BUILD + if (ifd >= sizeof tiff_ifd / sizeof tiff_ifd[0]) + throw LIBRAW_EXCEPTION_IO_CORRUPT; +#endif + break; + } +#ifdef LIBRAW_LIBRARY_BUILD + if (!strncmp(make, "Hasselblad", 10) && libraw_internal_data.unpacker_data.hasselblad_parser_flag) + { + fseek(ifp, ftell(ifp) + 4, SEEK_SET); + fseek(ifp, get4() + base, SEEK_SET); + parse_tiff_ifd(base); break; + } +#endif + 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 339: + tiff_ifd[ifd].sample_format = getint(type); + break; + case 400: + strcpy(make, "Sarnoff"); + maximum = 0xfff; + break; +#ifdef LIBRAW_LIBRARY_BUILD + case 700: + if ((type == 1 || type == 2 || type == 6 || type == 7) && len > 1 && len < 5100000) + { + xmpdata = (char *)malloc(xmplen = len + 1); + fread(xmpdata, len, 1, ifp); + xmpdata[len] = 0; + } + break; #endif - 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 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; #ifdef LIBRAW_LIBRARY_BUILD case 30720: // Sony matrix, Sony_SR2SubIFD_0x7800 - for (i=0; i < 3; i++) { + for (i = 0; i < 3; i++) + { float num = 0.0; - for (c=0; c<3; c++) { - imgdata.color.ccm[i][c] = (float) ((short)get2()); + for (c = 0; c < 3; c++) + { + imgdata.color.ccm[i][c] = (float)((short)get2()); num += imgdata.color.ccm[i][c]; } - if (num > 0.01) FORC3 imgdata.color.ccm[i][c] = imgdata.color.ccm[i][c] / num; + if (num > 0.01) + FORC3 imgdata.color.ccm[i][c] = imgdata.color.ccm[i][c] / num; } break; #endif case 29456: // Sony black level, Sony_SR2SubIFD_0x7310, no more needs to be divided by 4 - FORC4 cblack[c ^ c >> 1] = get2(); - i = cblack[3]; - FORC3 if(i>cblack[c]) i = cblack[c]; - FORC4 cblack[c]-=i; - black = i; + FORC4 cblack[c ^ c >> 1] = get2(); + i = cblack[3]; + FORC3 if (i > cblack[c]) i = cblack[c]; + FORC4 cblack[c] -= i; + black = i; #ifdef DCRAW_VERBOSE - if (verbose) fprintf (stderr, _("...Sony black: %u cblack: %u %u %u %u\n"),black, cblack[0],cblack[1],cblack[2], cblack[3]); -#endif - 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) ((char *)xtrans)[c] = fgetc(ifp) & 3; - break; - } - case 64777: /* Kodak P-series */ - if(len == 36) - { - filters = 9; - colors = 3; - FORC(36) xtrans[0][c] = fgetc(ifp) & 3; - } - else if(len > 0) - { - 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; - } + if (verbose) + fprintf(stderr, _("...Sony black: %u cblack: %u %u %u %u\n"), black, cblack[0], cblack[1], cblack[2], + cblack[3]); +#endif + 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)((char *)xtrans)[c] = fgetc(ifp) & 3; break; - case 33424: - case 65024: - fseek (ifp, get4()+base, SEEK_SET); - parse_kodak_ifd (base); - break; - case 33434: /* ExposureTime */ - tiff_ifd[ifd].t_shutter = shutter = getreal(type); - break; - case 33437: /* FNumber */ - aperture = getreal(type); - break; + } + case 64777: /* Kodak P-series */ + if (len == 36) + { + filters = 9; + colors = 3; + FORC(36) xtrans[0][c] = fgetc(ifp) & 3; + } + else if (len > 0) + { + if ((plen = len) > 16) + plen = 16; + fread(cfa_pat, 1, plen, ifp); + for (colors = cfa = i = 0; i < plen && colors < 4; i++) + { + if(cfa_pat[i] > 31) continue; // Skip wrong data + 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; + } + break; + case 33424: + case 65024: + fseek(ifp, get4() + base, SEEK_SET); + parse_kodak_ifd(base); + break; + case 33434: /* ExposureTime */ + tiff_ifd[ifd].t_shutter = shutter = getreal(type); + break; + case 33437: /* FNumber */ + aperture = getreal(type); + break; #ifdef LIBRAW_LIBRARY_BUILD -// IB start - case 0xa405: // FocalLengthIn35mmFormat + // IB start + case 0x9400: + imgdata.other.exifAmbientTemperature = getreal(type); + if ((imgdata.other.CameraTemperature > -273.15f) && (OlyID == 0x4434353933ULL)) // TG-5 + imgdata.other.CameraTemperature += imgdata.other.exifAmbientTemperature; + break; + case 0x9401: + imgdata.other.exifHumidity = getreal(type); + break; + case 0x9402: + imgdata.other.exifPressure = getreal(type); + break; + case 0x9403: + imgdata.other.exifWaterDepth = getreal(type); + break; + case 0x9404: + imgdata.other.exifAcceleration = getreal(type); + break; + case 0x9405: + imgdata.other.exifCameraElevationAngle = getreal(type); + break; + case 0xa405: // FocalLengthIn35mmFormat imgdata.lens.FocalLengthIn35mmFormat = get2(); break; - case 0xa431: // BodySerialNumber + case 0xa431: // BodySerialNumber case 0xc62f: stmread(imgdata.shootinginfo.BodySerial, len, ifp); break; - case 0xa432: // LensInfo, 42034dec, Lens Specification per EXIF standard + case 0xa432: // LensInfo, 42034dec, Lens Specification per EXIF standard imgdata.lens.MinFocal = getreal(type); imgdata.lens.MaxFocal = getreal(type); imgdata.lens.MaxAp4MinFocal = getreal(type); imgdata.lens.MaxAp4MaxFocal = getreal(type); break; - case 0xa435: // LensSerialNumber + case 0xa435: // LensSerialNumber stmread(imgdata.lens.LensSerial, len, ifp); break; - case 0xc630: // DNG LensInfo, Lens Specification per EXIF standard + case 0xc630: // DNG LensInfo, Lens Specification per EXIF standard imgdata.lens.MinFocal = getreal(type); imgdata.lens.MaxFocal = getreal(type); imgdata.lens.MaxAp4MinFocal = getreal(type); imgdata.lens.MaxAp4MaxFocal = getreal(type); break; - case 0xa433: // LensMake + case 0xa433: // LensMake stmread(imgdata.lens.LensMake, len, ifp); break; - case 0xa434: // LensModel + case 0xa434: // LensModel stmread(imgdata.lens.Lens, len, ifp); if (!strncmp(imgdata.lens.Lens, "----", 4)) imgdata.lens.Lens[0] = 0; break; case 0x9205: - imgdata.lens.EXIF_MaxAp = libraw_powf64(2.0f, (getreal(type) / 2.0f)); + imgdata.lens.EXIF_MaxAp = libraw_powf64l(2.0f, (getreal(type) / 2.0f)); break; // IB end #endif - 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] /= MAX(1,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 */ - { - unsigned pos; - fseek(ifp, pos = (get4() + base), SEEK_SET); - parse_gps(base); -#ifdef LIBRAW_LIBRARY_BUILD - fseek(ifp, pos, SEEK_SET); - parse_gps_libraw(base); -#endif - } - 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 && ima_len == 234317952 ) { - height = 5412; - width = 7216; - left_margin = 7; - filters=0; - } else 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 (len < 1 || len > 2560000 || !(cbuf = (char *) malloc(len))) break; + case 34306: /* Leaf white balance */ + FORC4 + { + int q = get2(); + if(q > 0) cam_mul[c ^ 1] = 4096.0 / q; + } + 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] /= MAX(1, 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 */ + { + unsigned pos; + fseek(ifp, pos = (get4() + base), SEEK_SET); + parse_gps(base); +#ifdef LIBRAW_LIBRARY_BUILD + fseek(ifp, pos, SEEK_SET); + parse_gps_libraw(base); +#endif + } + 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 && ima_len == 234317952) + { + height = 5412; + width = 7216; + left_margin = 7; + filters = 0; + } + else 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 (len < 1 || len > 2560000 || !(cbuf = (char *)malloc(len))) + break; #ifndef LIBRAW_LIBRARY_BUILD - fread (cbuf, 1, len, ifp); + fread(cbuf, 1, len, ifp); #else - if(fread (cbuf, 1, len, ifp) != len) - throw LIBRAW_EXCEPTION_IO_CORRUPT; // cbuf to be free'ed in recycle -#endif - cbuf[len-1] = 0; - 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 */ -#ifdef LIBRAW_LIBRARY_BUILD - libraw_internal_data.unpacker_data.hasselblad_parser_flag=1; -#endif - 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 50708: /* UniqueCameraModel */ -#ifdef LIBRAW_LIBRARY_BUILD - stmread(imgdata.color.UniqueCameraModel, len, ifp); - imgdata.color.UniqueCameraModel[sizeof(imgdata.color.UniqueCameraModel)-1] = 0; -#endif - if (model[0]) break; + if (fread(cbuf, 1, len, ifp) != len) + throw LIBRAW_EXCEPTION_IO_CORRUPT; // cbuf to be free'ed in recycle +#endif + cbuf[len - 1] = 0; + 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 */ +#ifdef LIBRAW_LIBRARY_BUILD + libraw_internal_data.unpacker_data.hasselblad_parser_flag = 1; +#endif + 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 50708: /* UniqueCameraModel */ +#ifdef LIBRAW_LIBRARY_BUILD + stmread(imgdata.color.UniqueCameraModel, len, ifp); + imgdata.color.UniqueCameraModel[sizeof(imgdata.color.UniqueCameraModel) - 1] = 0; +#endif + if (model[0]) + break; #ifndef LIBRAW_LIBRARY_BUILD - fgets (make, 64, ifp); + fgets(make, 64, ifp); #else - strncpy (make, imgdata.color.UniqueCameraModel, MIN(len, sizeof(imgdata.color.UniqueCameraModel))); -#endif - if ((cp = strchr(make,' '))) { - strcpy(model,cp+1); - *cp = 0; - } - 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; - break; - case 291: - case 50712: /* LinearizationTable */ - linear_table (len); - break; - case 50713: /* BlackLevelRepeatDim */ -#ifdef LIBRAW_LIBRARY_BUILD - imgdata.color.dng_levels.dng_cblack[4] = -#endif - cblack[4] = get2(); -#ifdef LIBRAW_LIBRARY_BUILD - imgdata.color.dng_levels.dng_cblack[5] = -#endif - cblack[5] = get2(); - if (cblack[4] * cblack[5] > (sizeof(cblack) / sizeof (cblack[0]) - 6)) -#ifdef LIBRAW_LIBRARY_BUILD - imgdata.color.dng_levels.dng_cblack[4]= - imgdata.color.dng_levels.dng_cblack[5]= -#endif - cblack[4] = cblack[5] = 1; - break; - -#ifdef LIBRAW_LIBRARY_BUILD - case 0xf00c: { - unsigned fwb[4]; - FORC4 fwb[c] = get4(); - if (fwb[3] < 0x100) - { - imgdata.color.WB_Coeffs[fwb[3]][0] = fwb[1]; - imgdata.color.WB_Coeffs[fwb[3]][1] = imgdata.color.WB_Coeffs[fwb[3]][3] = fwb[0]; - imgdata.color.WB_Coeffs[fwb[3]][2] = fwb[2]; - if ((fwb[3] == 17) && libraw_internal_data.unpacker_data.lenRAFData>3 && libraw_internal_data.unpacker_data.lenRAFData < 10240000) - { - long long f_save = ftell(ifp); - int fj, found = 0; - ushort *rafdata = (ushort*) malloc (sizeof(ushort)*libraw_internal_data.unpacker_data.lenRAFData); - fseek (ifp, libraw_internal_data.unpacker_data.posRAFData, SEEK_SET); - fread (rafdata, sizeof(ushort), libraw_internal_data.unpacker_data.lenRAFData, ifp); - fseek(ifp, f_save, SEEK_SET); - for (int fi=0; fi<(libraw_internal_data.unpacker_data.lenRAFData-3); fi++) - { - if ((fwb[0]==rafdata[fi]) && (fwb[1]==rafdata[fi+1]) && (fwb[2]==rafdata[fi+2])) - { - if (rafdata[fi-15] != fwb[0]) continue; - fi = fi - 15; - imgdata.color.WB_Coeffs[LIBRAW_WBI_FineWeather][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FineWeather][3] = rafdata[fi]; - imgdata.color.WB_Coeffs[LIBRAW_WBI_FineWeather][0] = rafdata[fi+1]; - imgdata.color.WB_Coeffs[LIBRAW_WBI_FineWeather][2] = rafdata[fi+2]; - - imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][3] = rafdata[fi+3]; - imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][0] = rafdata[fi+4]; - imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][2] = rafdata[fi+5]; - - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][3] = rafdata[fi+6]; - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][0] = rafdata[fi+7]; - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][2] = rafdata[fi+8]; - - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][3] = rafdata[fi+9]; - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][0] = rafdata[fi+10]; - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][2] = rafdata[fi+11]; - - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][3] = rafdata[fi+12]; - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][0] = rafdata[fi+13]; - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][2] = rafdata[fi+14]; - - imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][3] = rafdata[fi+15]; - imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][0] = rafdata[fi+16]; - imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][2] = rafdata[fi+17]; - - fi += 111; - for (fj = fi; fj<(fi+15); fj+=3) + strncpy(make, imgdata.color.UniqueCameraModel, MIN(len, sizeof(imgdata.color.UniqueCameraModel))); +#endif + if ((cp = strchr(make, ' '))) + { + strcpy(model, cp + 1); + *cp = 0; + } + 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; + break; + case 291: + case 50712: /* LinearizationTable */ +#ifdef LIBRAW_LIBRARY_BUILD + tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_LINTABLE; + tiff_ifd[ifd].lineartable_offset = ftell(ifp); + tiff_ifd[ifd].lineartable_len = len; +#endif + linear_table(len); + break; + case 50713: /* BlackLevelRepeatDim */ +#ifdef LIBRAW_LIBRARY_BUILD + tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BLACK; + tiff_ifd[ifd].dng_levels.dng_cblack[4] = +#endif + cblack[4] = get2(); +#ifdef LIBRAW_LIBRARY_BUILD + tiff_ifd[ifd].dng_levels.dng_cblack[5] = +#endif + cblack[5] = get2(); + if (cblack[4] * cblack[5] > (sizeof(cblack) / sizeof(cblack[0]) - 6)) +#ifdef LIBRAW_LIBRARY_BUILD + tiff_ifd[ifd].dng_levels.dng_cblack[4] = tiff_ifd[ifd].dng_levels.dng_cblack[5] = +#endif + cblack[4] = cblack[5] = 1; + break; + +#ifdef LIBRAW_LIBRARY_BUILD + case 0xf00d: + if (strcmp(model, "X-A3") && + strcmp(model, "X-A10") && + strcmp(model, "X-A5") && + strcmp(model, "X-A20")) + { + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][(4 - c) % 3] = getint(type); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][1]; + } + break; + case 0xf00c: + if (strcmp(model, "X-A3") && + strcmp(model, "X-A10") && + strcmp(model, "X-A5") && + strcmp(model, "X-A20")) + { + unsigned fwb[4]; + FORC4 fwb[c] = get4(); + if (fwb[3] < 0x100) + { + imgdata.color.WB_Coeffs[fwb[3]][0] = fwb[1]; + imgdata.color.WB_Coeffs[fwb[3]][1] = imgdata.color.WB_Coeffs[fwb[3]][3] = fwb[0]; + imgdata.color.WB_Coeffs[fwb[3]][2] = fwb[2]; + if ((fwb[3] == 17) && (libraw_internal_data.unpacker_data.lenRAFData > 3) && + (libraw_internal_data.unpacker_data.lenRAFData < 10240000)) + { + INT64 f_save = ftell(ifp); + ushort *rafdata = (ushort *)malloc(sizeof(ushort) * libraw_internal_data.unpacker_data.lenRAFData); + fseek(ifp, libraw_internal_data.unpacker_data.posRAFData, SEEK_SET); + fread(rafdata, sizeof(ushort), libraw_internal_data.unpacker_data.lenRAFData, ifp); + fseek(ifp, f_save, SEEK_SET); + int fj, found = 0; + for (int fi = 0; fi < (libraw_internal_data.unpacker_data.lenRAFData - 3); fi++) + { + if ((fwb[0] == rafdata[fi]) && (fwb[1] == rafdata[fi + 1]) && (fwb[2] == rafdata[fi + 2])) + { + if (rafdata[fi - 15] != fwb[0]) + continue; + + for (int wb_ind = 0, ofst = fi - 15; wb_ind < nFuji_wb_list1; wb_ind++, ofst += 3) + { + imgdata.color.WB_Coeffs[Fuji_wb_list1[wb_ind]][1] = + imgdata.color.WB_Coeffs[Fuji_wb_list1[wb_ind]][3] = rafdata[ofst]; + imgdata.color.WB_Coeffs[Fuji_wb_list1[wb_ind]][0] = rafdata[ofst + 1]; + imgdata.color.WB_Coeffs[Fuji_wb_list1[wb_ind]][2] = rafdata[ofst + 2]; + } + fi += 0x60; + for (fj = fi; fj < (fi + 15); fj += 3) if (rafdata[fj] != rafdata[fi]) { found = 1; break; } if (found) { - int FujiCCT_K [31] = {2500,2550,2650,2700,2800,2850,2950,3000,3100,3200,3300,3400,3600,3700,3800,4000,4200,4300,4500,4800,5000,5300,5600,5900,6300,6700,7100,7700,8300,9100,10000}; fj = fj - 93; - for (int iCCT=0; iCCT < 31; iCCT++) + for (int iCCT = 0; iCCT < 31; iCCT++) { imgdata.color.WBCT_Coeffs[iCCT][0] = FujiCCT_K[iCCT]; - imgdata.color.WBCT_Coeffs[iCCT][1] = rafdata[iCCT*3+1+fj]; - imgdata.color.WBCT_Coeffs[iCCT][2] = imgdata.color.WBCT_Coeffs[iCCT][4] = rafdata[iCCT*3+fj]; - imgdata.color.WBCT_Coeffs[iCCT][3] = rafdata[iCCT*3+2+fj]; - } - } - free (rafdata); - break; - } - } - } - } - FORC4 fwb[c] = get4(); - if (fwb[3] < 0x100) - { - imgdata.color.WB_Coeffs[fwb[3]][0] = fwb[1]; - imgdata.color.WB_Coeffs[fwb[3]][1] = imgdata.color.WB_Coeffs[fwb[3]][3] = fwb[0]; - imgdata.color.WB_Coeffs[fwb[3]][2] = fwb[2]; - } - } - break; + imgdata.color.WBCT_Coeffs[iCCT][1] = rafdata[iCCT * 3 + 1 + fj]; + imgdata.color.WBCT_Coeffs[iCCT][2] = imgdata.color.WBCT_Coeffs[iCCT][4] = rafdata[iCCT * 3 + fj]; + imgdata.color.WBCT_Coeffs[iCCT][3] = rafdata[iCCT * 3 + 2 + fj]; + } + } + free(rafdata); + break; + } + } + } + } + FORC4 fwb[c] = get4(); + if (fwb[3] < 0x100) + { + imgdata.color.WB_Coeffs[fwb[3]][0] = fwb[1]; + imgdata.color.WB_Coeffs[fwb[3]][1] = imgdata.color.WB_Coeffs[fwb[3]][3] = fwb[0]; + imgdata.color.WB_Coeffs[fwb[3]][2] = fwb[2]; + } + } + break; #endif #ifdef LIBRAW_LIBRARY_BUILD - case 50709: - stmread(imgdata.color.LocalizedCameraModel,len, ifp); + case 50709: + stmread(imgdata.color.LocalizedCameraModel, len, ifp); break; #endif - case 61450: - cblack[4] = cblack[5] = MIN(sqrt((double)len),64); - case 50714: /* BlackLevel */ + case 61450: + cblack[4] = cblack[5] = MIN(sqrt((double)len), 64); + case 50714: /* BlackLevel */ +#ifdef LIBRAW_LIBRARY_BUILD + if (tiff_ifd[ifd].samples > 1 && tiff_ifd[ifd].samples == len) // LinearDNG, per-channel black + { + tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BLACK; + for (i = 0; i < colors && i < 4 && i < len; i++) + tiff_ifd[ifd].dng_levels.dng_cblack[i] = cblack[i] = getreal(type) + 0.5; + + tiff_ifd[ifd].dng_levels.dng_black = black = 0; + } + else +#endif + if ((cblack[4] * cblack[5] < 2) && len == 1) + { +#ifdef LIBRAW_LIBRARY_BUILD + tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BLACK; + tiff_ifd[ifd].dng_levels.dng_black = +#endif + black = getreal(type); + } + else if (cblack[4] * cblack[5] <= len) + { + FORC(cblack[4] * cblack[5]) + cblack[6 + c] = getreal(type); + black = 0; + FORC4 + cblack[c] = 0; + #ifdef LIBRAW_LIBRARY_BUILD - if(tiff_ifd[ifd].samples > 1 && tiff_ifd[ifd].samples == len) // LinearDNG, per-channel black - { - for(i=0; i < colors && i < 4 && i < len; i++) - imgdata.color.dng_levels.dng_cblack[i]= - cblack[i]= - getreal(type)+0.5; - - imgdata.color.dng_levels.dng_black= black = 0; - } - else + if (tag == 50714) + { + tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BLACK; + FORC(cblack[4] * cblack[5]) + tiff_ifd[ifd].dng_levels.dng_cblack[6 + c] = cblack[6 + c]; + tiff_ifd[ifd].dng_levels.dng_black = 0; + FORC4 + tiff_ifd[ifd].dng_levels.dng_cblack[c] = 0; + } #endif - if((cblack[4] * cblack[5] < 2) && len == 1) - { + } + break; + case 50715: /* BlackLevelDeltaH */ + case 50716: /* BlackLevelDeltaV */ + for (num = i = 0; i < len && i < 65536; i++) + num += getreal(type); + if(len>0) + { + black += num / len + 0.5; #ifdef LIBRAW_LIBRARY_BUILD - imgdata.color.dng_levels.dng_black= -#endif - black = - getreal(type); - } - else if(cblack[4] * cblack[5] <= len) - { - FORC (cblack[4] * cblack[5]) - cblack[6+c] = getreal(type); - black = 0; - FORC4 - cblack[c] = 0; - -#ifdef LIBRAW_LIBRARY_BUILD - if(tag == 50714) - { - FORC (cblack[4] * cblack[5]) - imgdata.color.dng_levels.dng_cblack[6+c]= cblack[6+c]; - imgdata.color.dng_levels.dng_black=0; - FORC4 - imgdata.color.dng_levels.dng_cblack[c]= 0; - } + tiff_ifd[ifd].dng_levels.dng_black += num / len + 0.5; + tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_BLACK; #endif - } + } break; - case 50715: /* BlackLevelDeltaH */ - case 50716: /* BlackLevelDeltaV */ - for (num=i=0; i < len && i < 65536; i++) - num += getreal(type); - black += num/len + 0.5; + case 50717: /* WhiteLevel */ #ifdef LIBRAW_LIBRARY_BUILD - imgdata.color.dng_levels.dng_black += num/len + 0.5; + tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_WHITE; + tiff_ifd[ifd].dng_levels.dng_whitelevel[0] = #endif - break; - case 50717: /* WhiteLevel */ + maximum = getint(type); #ifdef LIBRAW_LIBRARY_BUILD - imgdata.color.dng_levels.dng_whitelevel[0]= + if (tiff_ifd[ifd].samples > 1) // Linear DNG case + for (i = 1; i < colors && i < 4 && i < len; i++) + tiff_ifd[ifd].dng_levels.dng_whitelevel[i] = getint(type); #endif - maximum = getint(type); + break; + case 50718: /* DefaultScale */ + { + float q1 = getreal(type); + float q2 = getreal(type); + if(q1 > 0.00001f && q2 > 0.00001f) + { + pixel_aspect = q1/q2; + if (pixel_aspect > 0.995 && pixel_aspect < 1.005) + pixel_aspect = 1.0; + } + } + break; #ifdef LIBRAW_LIBRARY_BUILD - if(tiff_ifd[ifd].samples > 1 ) // Linear DNG case - for(i=1; i < colors && i < 4 && i < len; i++) - imgdata.color.dng_levels.dng_whitelevel[i]=getint(type); + case 50719: /* DefaultCropOrigin */ + if (len == 2) + { + tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_CROPORIGIN; + tiff_ifd[ifd].dng_levels.default_crop[0] = getreal(type); + tiff_ifd[ifd].dng_levels.default_crop[1] = getreal(type); + if (!strncasecmp(make, "SONY", 4)) + { + imgdata.sizes.raw_crop.cleft = tiff_ifd[ifd].dng_levels.default_crop[0]; + imgdata.sizes.raw_crop.ctop = tiff_ifd[ifd].dng_levels.default_crop[1]; + } + } + break; + case 50720: /* DefaultCropSize */ + if (len == 2) + { + tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_CROPSIZE; + tiff_ifd[ifd].dng_levels.default_crop[2] = getreal(type); + tiff_ifd[ifd].dng_levels.default_crop[3] = getreal(type); + if (!strncasecmp(make, "SONY", 4)) + { + imgdata.sizes.raw_crop.cwidth = tiff_ifd[ifd].dng_levels.default_crop[2]; + imgdata.sizes.raw_crop.cheight = tiff_ifd[ifd].dng_levels.default_crop[3]; + } + } + break; + case 0x74c7: + if ((len == 2) && !strncasecmp(make, "SONY", 4)) + { + imgdata.makernotes.sony.raw_crop.cleft = get4(); + imgdata.makernotes.sony.raw_crop.ctop = get4(); + } + break; + case 0x74c8: + if ((len == 2) && !strncasecmp(make, "SONY", 4)) + { + imgdata.makernotes.sony.raw_crop.cwidth = get4(); + imgdata.makernotes.sony.raw_crop.cheight = get4(); + } + break; + #endif - break; - case 50718: /* DefaultScale */ - pixel_aspect = getreal(type); - pixel_aspect /= getreal(type); - if(pixel_aspect > 0.995 && pixel_aspect < 1.005) - pixel_aspect = 1.0; - break; #ifdef LIBRAW_LIBRARY_BUILD - case 50778: - imgdata.color.dng_color[0].illuminant = get2(); - break; - case 50779: - imgdata.color.dng_color[1].illuminant = get2(); - break; + case 50778: + tiff_ifd[ifd].dng_color[0].illuminant = get2(); + tiff_ifd[ifd].dng_color[0].parsedfields |= LIBRAW_DNGFM_ILLUMINANT; + break; + case 50779: + tiff_ifd[ifd].dng_color[1].illuminant = get2(); + tiff_ifd[ifd].dng_color[1].parsedfields |= LIBRAW_DNGFM_ILLUMINANT; + break; + #endif - case 50721: /* ColorMatrix1 */ - case 50722: /* ColorMatrix2 */ + case 50721: /* ColorMatrix1 */ + case 50722: /* ColorMatrix2 */ #ifdef LIBRAW_LIBRARY_BUILD - i = tag == 50721?0:1; + i = tag == 50721 ? 0 : 1; + tiff_ifd[ifd].dng_color[i].parsedfields |= LIBRAW_DNGFM_COLORMATRIX; #endif - FORCC for (j=0; j < 3; j++) - { + FORCC for (j = 0; j < 3; j++) + { #ifdef LIBRAW_LIBRARY_BUILD - imgdata.color.dng_color[i].colormatrix[c][j]= + tiff_ifd[ifd].dng_color[i].colormatrix[c][j] = #endif - cm[c][j] = getreal(type); - } - use_cm = 1; - break; + cm[c][j] = getreal(type); + } + use_cm = 1; + break; - case 0xc714: /* ForwardMatrix1 */ - case 0xc715: /* ForwardMatrix2 */ + case 0xc714: /* ForwardMatrix1 */ + case 0xc715: /* ForwardMatrix2 */ #ifdef LIBRAW_LIBRARY_BUILD - i = tag == 0xc714?0:1; + i = tag == 0xc714 ? 0 : 1; + tiff_ifd[ifd].dng_color[i].parsedfields |= LIBRAW_DNGFM_FORWARDMATRIX; #endif - for (j=0; j < 3; j++) - FORCC - { + for (j = 0; j < 3; j++) + FORCC + { #ifdef LIBRAW_LIBRARY_BUILD - imgdata.color.dng_color[i].forwardmatrix[j][c]= + tiff_ifd[ifd].dng_color[i].forwardmatrix[j][c] = #endif fm[j][c] = getreal(type); - } - break; + } + break; - case 50723: /* CameraCalibration1 */ - case 50724: /* CameraCalibration2 */ + case 50723: /* CameraCalibration1 */ + case 50724: /* CameraCalibration2 */ #ifdef LIBRAW_LIBRARY_BUILD - j = tag == 50723?0:1; + j = tag == 50723 ? 0 : 1; + tiff_ifd[ifd].dng_color[j].parsedfields |= LIBRAW_DNGFM_CALIBRATION; #endif - for (i=0; i < colors; i++) - FORCC - { + for (i = 0; i < colors; i++) + FORCC + { #ifdef LIBRAW_LIBRARY_BUILD - imgdata.color.dng_color[j].calibration[i][c]= + tiff_ifd[ifd].dng_color[j].calibration[i][c] = #endif cc[i][c] = getreal(type); - } - break; - case 50727: /* AnalogBalance */ - FORCC{ -#ifdef LIBRAW_LIBRARY_BUILD - imgdata.color.dng_levels.analogbalance[c]= -#endif - 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; -#ifdef LIBRAW_LIBRARY_BUILD - case 50730: /* DNG: Baseline Exposure */ - baseline_exposure = getreal(type); - break; + } + break; + case 50727: /* AnalogBalance */ +#ifdef LIBRAW_LIBRARY_BUILD + tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_ANALOGBALANCE; +#endif + FORCC + { +#ifdef LIBRAW_LIBRARY_BUILD + tiff_ifd[ifd].dng_levels.analogbalance[c] = #endif - // IB start - case 50740: /* tag 0xc634 : DNG Adobe, DNG Pentax, Sony SR2, DNG Private */ + 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; #ifdef LIBRAW_LIBRARY_BUILD + case 50730: /* DNG: Baseline Exposure */ + baseline_exposure = getreal(type); + break; +#endif + // IB start + case 50740: /* tag 0xc634 : DNG Adobe, DNG Pentax, Sony SR2, DNG Private */ +#ifdef LIBRAW_LIBRARY_BUILD + { + char mbuf[64]; + unsigned short makernote_found = 0; + INT64 curr_pos, start_pos = ftell(ifp); + unsigned MakN_order, m_sorder = order; + unsigned MakN_length; + unsigned pos_in_original_raw; + fread(mbuf, 1, 6, ifp); + + if (!strcmp(mbuf, "Adobe")) { - char mbuf[64]; - unsigned short makernote_found = 0; - INT64 curr_pos, start_pos = ftell(ifp); - unsigned MakN_order, m_sorder = order; - unsigned MakN_length; - unsigned pos_in_original_raw; - fread(mbuf, 1, 6, ifp); - - if (!strcmp(mbuf, "Adobe")) + order = 0x4d4d; // Adobe header is always in "MM" / big endian + curr_pos = start_pos + 6; + while (curr_pos + 8 - start_pos <= len) + { + fread(mbuf, 1, 4, ifp); + curr_pos += 8; + if (!strncmp(mbuf, "MakN", 4)) { - order = 0x4d4d; // Adobe header is always in "MM" / big endian - curr_pos = start_pos + 6; - while (curr_pos + 8 - start_pos <= len) + makernote_found = 1; + MakN_length = get4(); + MakN_order = get2(); + pos_in_original_raw = get4(); + order = MakN_order; + + INT64 save_pos = ifp->tell(); + parse_makernote_0xc634(curr_pos + 6 - pos_in_original_raw, 0, AdobeDNG); + + curr_pos = save_pos + MakN_length - 6; + fseek(ifp, curr_pos, SEEK_SET); + + fread(mbuf, 1, 4, ifp); + curr_pos += 8; + if (!strncmp(mbuf, "SR2 ", 4)) + { + order = 0x4d4d; + MakN_length = get4(); + MakN_order = get2(); + pos_in_original_raw = get4(); + order = MakN_order; + + unsigned *buf_SR2; + uchar *cbuf_SR2; + unsigned icbuf_SR2; + unsigned entries, tag, type, len, save; + int ival; + unsigned SR2SubIFDOffset = 0; + unsigned SR2SubIFDLength = 0; + unsigned SR2SubIFDKey = 0; + int base = curr_pos + 6 - pos_in_original_raw; + entries = get2(); + while (entries--) { - fread(mbuf, 1, 4, ifp); - curr_pos += 8; - if (!strncmp(mbuf, "MakN", 4)) { - makernote_found = 1; - MakN_length = get4(); - MakN_order = get2(); - pos_in_original_raw = get4(); - order = MakN_order; - parse_makernote_0xc634(curr_pos + 6 - pos_in_original_raw, 0, AdobeDNG); - break; + tiff_get(base, &tag, &type, &len, &save); + + if (tag == 0x7200) + { + SR2SubIFDOffset = get4(); + } + else if (tag == 0x7201) + { + SR2SubIFDLength = get4(); + } + else if (tag == 0x7221) + { + SR2SubIFDKey = get4(); } + fseek(ifp, save, SEEK_SET); } - } - else - { - fread(mbuf + 6, 1, 2, ifp); - if (!strcmp(mbuf, "PENTAX ") || - !strcmp(mbuf, "SAMSUNG")) + + if (SR2SubIFDLength && (SR2SubIFDLength < 10240000) && (buf_SR2 = (unsigned *)malloc(SR2SubIFDLength+1024))) // 1024b for safety { - makernote_found = 1; - fseek(ifp, start_pos, SEEK_SET); - parse_makernote_0xc634(base, 0, CameraDNG); + fseek(ifp, SR2SubIFDOffset + base, SEEK_SET); + fread(buf_SR2, SR2SubIFDLength, 1, ifp); + sony_decrypt(buf_SR2, SR2SubIFDLength / 4, 1, SR2SubIFDKey); + cbuf_SR2 = (uchar *)buf_SR2; + entries = sget2(cbuf_SR2); + icbuf_SR2 = 2; + while (entries--) + { + tag = sget2(cbuf_SR2 + icbuf_SR2); + icbuf_SR2 += 2; + type = sget2(cbuf_SR2 + icbuf_SR2); + icbuf_SR2 += 2; + len = sget4(cbuf_SR2 + icbuf_SR2); + icbuf_SR2 += 4; + + if (len * ("11124811248484"[type < 14 ? type : 0] - '0') > 4) + { + ival = sget4(cbuf_SR2 + icbuf_SR2) - SR2SubIFDOffset; + } + else + { + ival = icbuf_SR2; + } + if(ival > SR2SubIFDLength) // points out of orig. buffer size + break; // END processing. Generally we should check against SR2SubIFDLength minus 6 of 8, depending on tag, but we allocated extra 1024b for buffer, so this does not matter + + icbuf_SR2 += 4; + + switch (tag) + { + case 0x7302: + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c < 2)] = sget2(cbuf_SR2 + ival + 2 * c); + break; + case 0x7312: + { + int i, lc[4]; + FORC4 lc[c] = sget2(cbuf_SR2 + ival + 2 * c); + i = (lc[1] == 1024 && lc[2] == 1024) << 1; + SWAP(lc[i], lc[i + 1]); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c] = lc[c]; + } + break; + case 0x7480: + case 0x7820: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][c] = sget2(cbuf_SR2 + ival + 2 * c); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][1]; + break; + case 0x7481: + case 0x7821: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][c] = sget2(cbuf_SR2 + ival + 2 * c); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][1]; + break; + case 0x7482: + case 0x7822: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][c] = sget2(cbuf_SR2 + ival + 2 * c); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][1]; + break; + case 0x7483: + case 0x7823: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][c] = sget2(cbuf_SR2 + ival + 2 * c); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][1]; + break; + case 0x7484: + case 0x7824: + imgdata.color.WBCT_Coeffs[0][0] = 4500; + FORC3 imgdata.color.WBCT_Coeffs[0][c + 1] = sget2(cbuf_SR2 + ival + 2 * c); + imgdata.color.WBCT_Coeffs[0][4] = imgdata.color.WBCT_Coeffs[0][2]; + break; + case 0x7486: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][c] = sget2(cbuf_SR2 + ival + 2 * c); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][3] = + imgdata.color.WB_Coeffs[LIBRAW_WBI_Fluorescent][1]; + break; + case 0x7825: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][c] = sget2(cbuf_SR2 + ival + 2 * c); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][1]; + break; + case 0x7826: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][c] = sget2(cbuf_SR2 + ival + 2 * c); + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][1]; + break; + case 0x7827: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][c] = sget2(cbuf_SR2 + ival + 2 * c); + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][1]; + break; + case 0x7828: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][c] = sget2(cbuf_SR2 + ival + 2 * c); + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][1]; + break; + case 0x7829: + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][c] = sget2(cbuf_SR2 + ival + 2 * c); + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][3] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][1]; + break; + case 0x782a: + imgdata.color.WBCT_Coeffs[1][0] = 8500; + FORC3 imgdata.color.WBCT_Coeffs[1][c + 1] = sget2(cbuf_SR2 + ival + 2 * c); + imgdata.color.WBCT_Coeffs[1][4] = imgdata.color.WBCT_Coeffs[1][2]; + break; + case 0x782b: + imgdata.color.WBCT_Coeffs[2][0] = 6000; + FORC3 imgdata.color.WBCT_Coeffs[2][c + 1] = sget2(cbuf_SR2 + ival + 2 * c); + imgdata.color.WBCT_Coeffs[2][4] = imgdata.color.WBCT_Coeffs[2][2]; + break; + case 0x782c: + imgdata.color.WBCT_Coeffs[3][0] = 3200; + FORC3 imgdata.color.WB_Coeffs[LIBRAW_WBI_StudioTungsten][c] = imgdata.color.WBCT_Coeffs[3][c + 1] = + sget2(cbuf_SR2 + ival + 2 * c); + imgdata.color.WB_Coeffs[LIBRAW_WBI_StudioTungsten][3] = imgdata.color.WBCT_Coeffs[3][4] = + imgdata.color.WB_Coeffs[LIBRAW_WBI_StudioTungsten][1]; + break; + case 0x782d: + imgdata.color.WBCT_Coeffs[4][0] = 2500; + FORC3 imgdata.color.WBCT_Coeffs[4][c + 1] = sget2(cbuf_SR2 + ival + 2 * c); + imgdata.color.WBCT_Coeffs[4][4] = imgdata.color.WBCT_Coeffs[4][2]; + break; + } + } + + free(buf_SR2); } - } - fseek(ifp, start_pos, SEEK_SET); - order = m_sorder; + } /* SR2 processed */ + break; + } + } } - // IB end + else + { + fread(mbuf + 6, 1, 2, ifp); + if (!strcmp(mbuf, "PENTAX ") || !strcmp(mbuf, "SAMSUNG")) + { + makernote_found = 1; + fseek(ifp, start_pos, SEEK_SET); + parse_makernote_0xc634(base, 0, CameraDNG); + } + } + + fseek(ifp, start_pos, SEEK_SET); + order = m_sorder; + } +// IB end #endif - if (dng_version) break; - parse_minolta (j = get4()+base); - fseek (ifp, j, SEEK_SET); - parse_tiff_ifd (base); + 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); + read_shorts(cr2_slice, 3); break; - case 50829: /* ActiveArea */ + 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++) - ((int*)mask)[i] = getint(type); + case 50830: /* MaskedAreas */ + for (i = 0; i < len && i < 32; i++) + ((int *)mask)[i] = getint(type); black = 0; break; - case 51009: /* OpcodeList2 */ - meta_offset = ftell(ifp); +#ifdef LIBRAW_LIBRARY_BUILD + case 50970: /* PreviewColorSpace */ + tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_PREVIEWCS; + tiff_ifd[ifd].dng_levels.preview_colorspace = getint(type); + break; +#endif + case 51009: /* OpcodeList2 */ +#ifdef LIBRAW_LIBRARY_BUILD + tiff_ifd[ifd].dng_levels.parsedfields |= LIBRAW_DNGFM_OPCODE2; + tiff_ifd[ifd].opcode2_offset = +#endif + meta_offset = ftell(ifp); break; - case 64772: /* Kodak P-series */ - if (len < 13) break; - fseek (ifp, 16, SEEK_CUR); + case 64772: /* Kodak P-series */ + if (len < 13) + break; + fseek(ifp, 16, SEEK_CUR); data_offset = get4(); - fseek (ifp, 28, SEEK_CUR); + fseek(ifp, 28, SEEK_CUR); data_offset += get4(); load_raw = &CLASS packed_load_raw; break; case 65026: - if (type == 2) fgets (model2, 64, ifp); + if (type == 2) + fgets(model2, 64, ifp); } - fseek (ifp, save, SEEK_SET); + fseek(ifp, save, SEEK_SET); } - if (sony_length && sony_length < 10240000 && (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); + if (sony_length && sony_length < 10240000 && (buf = (unsigned *)malloc(sony_length))) + { + fseek(ifp, sony_offset, SEEK_SET); + fread(buf, sony_length, 1, ifp); + sony_decrypt(buf, sony_length / 4, 1, sony_key); #ifndef LIBRAW_LIBRARY_BUILD sfp = ifp; - if ((ifp = tmpfile())) { - fwrite (buf, sony_length, 1, ifp); - fseek (ifp, 0, SEEK_SET); - parse_tiff_ifd (-sony_offset); - fclose (ifp); + if ((ifp = tmpfile())) + { + fwrite(buf, sony_length, 1, ifp); + fseek(ifp, 0, SEEK_SET); + parse_tiff_ifd(-sony_offset); + fclose(ifp); } ifp = sfp; #else - if( !ifp->tempbuffer_open(buf,sony_length)) - { - parse_tiff_ifd(-sony_offset); - ifp->tempbuffer_close(); - } + if (!ifp->tempbuffer_open(buf, sony_length)) + { + parse_tiff_ifd(-sony_offset); + ifp->tempbuffer_close(); + } +#endif + free(buf); + } + for (i = 0; i < colors; i++) + FORCC cc[i][c] *= ab[i]; + if (use_cm) + { + FORCC for (i = 0; i < 3; i++) for (cam_xyz[c][i] = j = 0; j < colors; j++) cam_xyz[c][i] += + cc[c][j] * cm[j][i] * xyz[i]; + cam_xyz_coeff(cmatrix, cam_xyz); + } + if (asn[0]) + { + cam_mul[3] = 0; + FORCC + if(fabs(asn[c])>0.0001) + cam_mul[c] = 1 / asn[c]; + } + if (!use_cm) + FORCC if(fabs(cc[c][c])>0.0001) 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, ties = 0, raw = -1, thm = -1, i; + unsigned long long ns, os; + 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 = tiff_nifds; i--;) + { + if (tiff_ifd[i].t_shutter) + shutter = tiff_ifd[i].t_shutter; + tiff_ifd[i].t_shutter = shutter; + } + for (i = 0; i < tiff_nifds; i++) + { + if( tiff_ifd[i].t_width < 1 || tiff_ifd[i].t_width > 65535 + || tiff_ifd[i].t_height < 1 || tiff_ifd[i].t_height > 65535) + continue; /* wrong image dimensions */ + if (max_samp < tiff_ifd[i].samples) + max_samp = tiff_ifd[i].samples; + if (max_samp > 3) + max_samp = 3; + os = raw_width * raw_height; + ns = tiff_ifd[i].t_width * tiff_ifd[i].t_height; + if (tiff_bps) + { + os *= tiff_bps; + ns *= tiff_ifd[i].bps; + } + if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3) && + unsigned(tiff_ifd[i].t_width | tiff_ifd[i].t_height) < 0x10000 && (unsigned)tiff_ifd[i].bps < 33 && + (unsigned)tiff_ifd[i].samples < 13 && ns && ((ns > os && (ties = 1)) || (ns == os && shot_select == ties++))) + { + raw_width = tiff_ifd[i].t_width; + raw_height = tiff_ifd[i].t_height; + tiff_bps = tiff_ifd[i].bps; + tiff_compress = tiff_ifd[i].comp; + data_offset = tiff_ifd[i].offset; +#ifdef LIBRAW_LIBRARY_BUILD + data_size = tiff_ifd[i].bytes; +#endif + tiff_flip = tiff_ifd[i].t_flip; + tiff_samples = tiff_ifd[i].samples; + tile_width = tiff_ifd[i].t_tile_width; + tile_length = tiff_ifd[i].t_tile_length; + shutter = tiff_ifd[i].t_shutter; + raw = i; + } + } + if (is_raw == 1 && ties) + is_raw = ties; + if (!tile_width) + tile_width = INT_MAX; + if (!tile_length) + tile_length = INT_MAX; + for (i = tiff_nifds; i--;) + if (tiff_ifd[i].t_flip) + tiff_flip = tiff_ifd[i].t_flip; + if (raw >= 0 && !load_raw) + switch (tiff_compress) + { + case 32767: +#ifdef LIBRAW_LIBRARY_BUILD + if (!dng_version && INT64(tiff_ifd[raw].bytes) == INT64(raw_width) * INT64(raw_height)) +#else + if (tiff_ifd[raw].bytes == raw_width * raw_height) +#endif + { + tiff_bps = 14; + load_raw = &CLASS sony_arw2_load_raw; + break; + } +#ifdef LIBRAW_LIBRARY_BUILD + if (!dng_version && !strncasecmp(make, "Sony", 4) && INT64(tiff_ifd[raw].bytes) == INT64(raw_width) * INT64(raw_height) * 2ULL) +#else + if (!strncasecmp(make, "Sony", 4) && tiff_ifd[raw].bytes == raw_width * raw_height * 2) +#endif + { + tiff_bps = 14; + load_raw = &CLASS unpacked_load_raw; + break; + } +#ifdef LIBRAW_LIBRARY_BUILD + if (INT64(tiff_ifd[raw].bytes) * 8ULL != INT64(raw_width) * INT64(raw_height) * INT64(tiff_bps)) +#else + if (tiff_ifd[raw].bytes * 8 != raw_width * raw_height * tiff_bps) +#endif + { + 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: +#ifdef LIBRAW_LIBRARY_BUILD + // Sony 14-bit uncompressed + if (!dng_version && !strncasecmp(make, "Sony", 4) && INT64(tiff_ifd[raw].bytes) == INT64(raw_width) * INT64(raw_height) * 2ULL) + { + tiff_bps = 14; + load_raw = &CLASS unpacked_load_raw; + break; + } + if (!dng_version && !strncasecmp(make, "Sony", 4) && tiff_ifd[raw].samples == 4 && + INT64(tiff_ifd[raw].bytes) == INT64(raw_width) * INT64(raw_height) * 8ULL) // Sony ARQ + { + tiff_bps = 14; + tiff_samples = 4; + load_raw = &CLASS sony_arq_load_raw; + filters = 0; + strcpy(cdesc, "RGBG"); + break; + } + if (!strncasecmp(make, "Nikon", 5) && !strncmp(software, "Nikon Scan", 10)) + { + load_raw = &CLASS nikon_coolscan_load_raw; + raw_color = 1; + filters = 0; + break; + } + if (!strncmp(make, "OLYMPUS", 7) && INT64(tiff_ifd[raw].bytes) * 2ULL == INT64(raw_width) * INT64(raw_height) * 3ULL) +#else + if (!strncmp(make, "OLYMPUS", 7) && tiff_ifd[raw].bytes * 2 == raw_width * raw_height * 3) +#endif + load_flags = 24; +#ifdef LIBRAW_LIBRARY_BUILD + if (!dng_version && INT64(tiff_ifd[raw].bytes) * 5ULL == INT64(raw_width) * INT64(raw_height) * 8ULL) +#else + if (tiff_ifd[raw].bytes * 5 == raw_width * raw_height * 8) +#endif + { + 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; +#ifdef LIBRAW_LIBRARY_BUILD + if (!strncmp(make, "OLYMPUS", 7) && INT64(tiff_ifd[raw].bytes) * 7ULL > INT64(raw_width) * INT64(raw_height)) +#else + if (!strncmp(make, "OLYMPUS", 7) && tiff_ifd[raw].bytes * 7 > raw_width * raw_height) +#endif + 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: +#ifdef LIBRAW_LIBRARY_BUILD + if ((INT64(raw_width) + 9ULL) / 10ULL * 16ULL * INT64(raw_height) == INT64(tiff_ifd[raw].bytes)) +#else + if ((raw_width + 9) / 10 * 16 * raw_height == tiff_ifd[raw].bytes) +#endif + { + load_raw = &CLASS packed_load_raw; + load_flags = 1; + } +#ifdef LIBRAW_LIBRARY_BUILD + else if (INT64(raw_width) * INT64(raw_height) * 3ULL == INT64(tiff_ifd[raw].bytes) * 2ULL) +#else + else if (raw_width * raw_height * 3 == tiff_ifd[raw].bytes * 2) +#endif + { + load_raw = &CLASS packed_load_raw; + if (model[0] == 'N') + load_flags = 80; + } +#ifdef LIBRAW_LIBRARY_BUILD + else if (INT64(raw_width) * INT64(raw_height) * 3ULL == INT64(tiff_ifd[raw].bytes)) +#else + else if (raw_width * raw_height * 3 == tiff_ifd[raw].bytes) #endif - free (buf); - } - for (i=0; i < colors; i++) - FORCC cc[i][c] *= ab[i]; - if (use_cm) { - FORCC for (i=0; i < 3; i++) - for (cam_xyz[c][i]=j=0; j < colors; j++) - cam_xyz[c][i] += cc[c][j] * cm[j][i] * xyz[i]; - cam_xyz_coeff (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, ties=0, os, ns, 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=tiff_nifds; i--; ) { - if (tiff_ifd[i].t_shutter) - shutter = tiff_ifd[i].t_shutter; - tiff_ifd[i].t_shutter = shutter; - } - 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; - os = raw_width*raw_height; - ns = tiff_ifd[i].t_width*tiff_ifd[i].t_height; - if (tiff_bps) { - os *= tiff_bps; - ns *= tiff_ifd[i].bps; - } - if ((tiff_ifd[i].comp != 6 || tiff_ifd[i].samples != 3) && - unsigned(tiff_ifd[i].t_width | tiff_ifd[i].t_height) < 0x10000 && - (unsigned)tiff_ifd[i].bps < 33 && (unsigned)tiff_ifd[i].samples < 13 && - ns && ((ns > os && (ties = 1)) || - (ns == os && shot_select == ties++))) { - raw_width = tiff_ifd[i].t_width; - raw_height = tiff_ifd[i].t_height; - tiff_bps = tiff_ifd[i].bps; - tiff_compress = tiff_ifd[i].comp; - data_offset = tiff_ifd[i].offset; + { + load_raw = &CLASS nikon_yuv_load_raw; + gamma_curve(1 / 2.4, 12.92, 1, 4095); + memset(cblack, 0, sizeof cblack); + filters = 0; + } #ifdef LIBRAW_LIBRARY_BUILD - data_size = tiff_ifd[i].bytes; + else if (INT64(raw_width) * INT64(raw_height) * 2ULL == INT64(tiff_ifd[raw].bytes)) +#else + else if (raw_width * raw_height * 2 == tiff_ifd[raw].bytes) #endif - tiff_flip = tiff_ifd[i].t_flip; - tiff_samples = tiff_ifd[i].samples; - tile_width = tiff_ifd[i].t_tile_width; - tile_length = tiff_ifd[i].t_tile_length; - shutter = tiff_ifd[i].t_shutter; - raw = i; - } - } - if (is_raw == 1 && ties) is_raw = ties; - if (!tile_width ) tile_width = INT_MAX; - if (!tile_length) tile_length = INT_MAX; - for (i=tiff_nifds; i--; ) - if (tiff_ifd[i].t_flip) tiff_flip = tiff_ifd[i].t_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 (!strncasecmp(make,"Sony",4) && - tiff_ifd[raw].bytes == raw_width*raw_height*2) { - tiff_bps = 14; - load_raw = &CLASS unpacked_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: + { + load_raw = &CLASS unpacked_load_raw; + load_flags = 4; + order = 0x4d4d; + } + else #ifdef LIBRAW_LIBRARY_BUILD - // Sony 14-bit uncompressed - if(!strncasecmp(make,"Sony",4) && - tiff_ifd[raw].bytes == raw_width*raw_height*2) - { - tiff_bps = 14; - load_raw = &CLASS unpacked_load_raw; - break; - } - if(!strncasecmp(make,"Nikon",5) && !strncmp(software,"Nikon Scan",10)) + if (INT64(raw_width) * INT64(raw_height) * 3ULL == INT64(tiff_ifd[raw].bytes) * 2ULL) + { + load_raw = &CLASS packed_load_raw; + load_flags = 80; + } + else if (tiff_ifd[raw].rows_per_strip && tiff_ifd[raw].strip_offsets_count && + tiff_ifd[raw].strip_offsets_count == tiff_ifd[raw].strip_byte_counts_count) + { + int fit = 1; + for (int i = 0; i < tiff_ifd[raw].strip_byte_counts_count - 1; i++) // all but last + if (INT64(tiff_ifd[raw].strip_byte_counts[i]) * 2ULL != INT64(tiff_ifd[raw].rows_per_strip) * INT64(raw_width) * 3ULL) { - load_raw = &CLASS nikon_coolscan_load_raw; - raw_color = 1; - filters = 0; + fit = 0; break; } + if (fit) + load_raw = &CLASS nikon_load_striped_packed_raw; + else + load_raw = &CLASS nikon_load_raw; // fallback + } + else #endif - 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 -#ifdef LIBRAW_LIBRARY_BUILD - if(raw_width*raw_height*3 == tiff_ifd[raw].bytes*2) - { - load_raw = &CLASS packed_load_raw; - load_flags=80; - } - else if(tiff_ifd[raw].rows_per_strip && tiff_ifd[raw].strip_offsets_count && - tiff_ifd[raw].strip_offsets_count == tiff_ifd[raw].strip_byte_counts_count) - { - int fit = 1; - for(int i = 0; i < tiff_ifd[raw].strip_byte_counts_count-1; i++) // all but last - if(tiff_ifd[raw].strip_byte_counts[i]*2 != tiff_ifd[raw].rows_per_strip*raw_width*3) - { - fit = 0; - break; - } - if(fit) - load_raw = &CLASS nikon_load_striped_packed_raw; - else - load_raw = &CLASS nikon_load_raw; // fallback - } - else -#endif - 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; + 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; #ifdef LIBRAW_LIBRARY_BUILD - case 8: break; + case 8: + break; #endif - default: is_raw = 0; + 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 && strncmp(make,"Phase",5) && - !strcasestr(make,"Kodak") && - !strstr(model2,"DEBUG RAW"))) - && strncmp(software,"Nikon Scan",10)) + if (((tiff_samples == 3 && tiff_ifd[raw].bytes && tiff_bps != 14 && (tiff_compress & -16) != 32768) || + (tiff_bps == 8 && strncmp(make, "Phase", 5) && strncmp(make, "Leaf", 4) && !strcasestr(make, "Kodak") && + !strstr(model2, "DEBUG RAW"))) && + strncmp(software, "Nikon Scan", 10)) is_raw = 0; - for (i=0; i < tiff_nifds; i++) - if (i != raw - && (tiff_ifd[i].samples == max_samp || (tiff_ifd[i].comp == 7 && tiff_ifd[i].samples == 1)) /* Allow 1-bps JPEGs */ - && tiff_ifd[i].bps>0 && tiff_ifd[i].bps < 33 - && tiff_ifd[i].phint != 32803 - && tiff_ifd[i].phint != 34892 - && unsigned(tiff_ifd[i].t_width | tiff_ifd[i].t_height) < 0x10000 && - tiff_ifd[i].t_width * tiff_ifd[i].t_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].t_width; + for (i = 0; i < tiff_nifds; i++) + if (i != raw && + (tiff_ifd[i].samples == max_samp || (tiff_ifd[i].comp == 7 && tiff_ifd[i].samples == 1)) /* Allow 1-bps JPEGs */ + && tiff_ifd[i].bps > 0 && tiff_ifd[i].bps < 33 && tiff_ifd[i].phint != 32803 && tiff_ifd[i].phint != 34892 && + unsigned(tiff_ifd[i].t_width | tiff_ifd[i].t_height) < 0x10000 && + tiff_ifd[i].t_width * tiff_ifd[i].t_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].t_width; thumb_height = tiff_ifd[i].t_height; thumb_offset = tiff_ifd[i].offset; thumb_length = tiff_ifd[i].bytes; - thumb_misc = tiff_ifd[i].bps; + thumb_misc = tiff_ifd[i].bps; thm = i; } - if (thm >= 0) { + 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 (!strncmp(make,"Imacon",6)) - 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; + 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 (!strncmp(make, "Imacon", 6)) + 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) +void CLASS parse_minolta(int base) { - int save, tag, len, offset, high=0, wide=0, i, c; - short sorder=order; + 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; + fseek(ifp, base, SEEK_SET); + if (fgetc(ifp) || fgetc(ifp) - 'M' || fgetc(ifp) - 'R') + return; order = fgetc(ifp) * 0x101; offset = base + get4() + 8; #ifdef LIBRAW_LIBRARY_BUILD if(offset>ifp->size()-8) // At least 8 bytes for tag/len offset = ifp->size()-8; #endif - while ((save=ftell(ifp)) < offset) { - for (tag=i=0; i < 4; i++) + + while ((save = ftell(ifp)) < offset) + { + for (tag = i = 0; i < 4; i++) tag = tag << 8 | fgetc(ifp); len = get4(); if(len < 0) return; // just ignore wrong len?? or raise bad file exception? - switch (tag) { - case 0x505244: /* PRD */ - fseek (ifp, 8, SEEK_CUR); - high = get2(); - wide = get2(); - break; -#ifdef LIBRAW_LIBRARY_BUILD - case 0x524946: /* RIF */ - if (!strncasecmp(model,"DSLR-A100", 9)) + switch (tag) { + case 0x505244: /* PRD */ fseek(ifp, 8, SEEK_CUR); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][2] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][2] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][2] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][2] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][2] = get2(); + high = get2(); + wide = get2(); + break; +#ifdef LIBRAW_LIBRARY_BUILD + case 0x524946: /* RIF */ + if (!strncasecmp(model, "DSLR-A100", 9)) + { + fseek(ifp, 8, SEEK_CUR); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][0] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][2] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][0] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][2] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][0] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][2] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][0] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][2] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][0] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][2] = get2(); + get4(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][0] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][2] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][0] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][2] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][0] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][2] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][0] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][2] = get2(); + imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][3] = + imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][3] = + imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][3] = + imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][3] = + imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][3] = + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][3] = + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][1] = + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][3] = + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][1] = + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][3] = + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][1] = + imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][3] = 0x100; + } + break; +#endif + case 0x574247: /* WBG */ get4(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][2] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][2] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][2] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][0] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][2] = get2(); - imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][3] = - imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][3] = - imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][3] = - imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][3] = - imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][3] = - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][3] = - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][3] = - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_W][3] = - imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][1] = imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][3] = 0x100; - } - break; -#endif - 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); + 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; + raw_width = wide; order = sorder; } /* Many cameras have a "debug mode" that writes JPEG and raw at the same time. The raw file has no header, so try to to open the matching JPEG file and read its metadata. */ void CLASS parse_external_jpeg() { const char *file, *ext; char *jname, *jfile, *jext; #ifndef LIBRAW_LIBRARY_BUILD - FILE *save=ifp; + FILE *save = ifp; #else #if defined(_WIN32) && !defined(__MINGW32__) && defined(_MSC_VER) && (_MSC_VER > 1310) - if(ifp->wfname()) + if (ifp->wfname()) { - std::wstring rawfile(ifp->wfname()); - rawfile.replace(rawfile.length()-3,3,L"JPG"); - if(!ifp->subfile_open(rawfile.c_str())) - { - parse_tiff (12); - thumb_offset = 0; - is_raw = 1; - ifp->subfile_close(); - } - else - imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA ; - return; + std::wstring rawfile(ifp->wfname()); + rawfile.replace(rawfile.length() - 3, 3, L"JPG"); + if (!ifp->subfile_open(rawfile.c_str())) + { + parse_tiff(12); + thumb_offset = 0; + is_raw = 1; + ifp->subfile_close(); + } + else + imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA; + return; } #endif - if(!ifp->fname()) - { - imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA ; - return; - } + if (!ifp->fname()) + { + imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA; + return; + } #endif - ext = strrchr (ifname, '.'); - file = strrchr (ifname, '/'); - if (!file) file = strrchr (ifname, '\\'); + ext = strrchr(ifname, '.'); + file = strrchr(ifname, '/'); + if (!file) + file = strrchr(ifname, '\\'); #ifndef LIBRAW_LIBRARY_BUILD - if (!file) file = ifname-1; + if (!file) + file = ifname - 1; #else - if (!file) file = (char*)ifname-1; + if (!file) + file = (char *)ifname - 1; #endif file++; - if (!ext || strlen(ext) != 4 || ext-file != 8) return; - jname = (char *) malloc (strlen(ifname) + 1); - merror (jname, "parse_external_jpeg()"); - strcpy (jname, ifname); + 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 = ext - ifname + jname; + if (strcasecmp(ext, ".jpg")) + { + strcpy(jext, isupper(ext[1]) ? ".JPG" : ".jpg"); + if (isdigit(*file)) + { + memcpy(jfile, file + 4, 4); + memcpy(jfile + 4, file, 4); + } + } + else + while (isdigit(*--jext)) + { + if (*jext != '9') + { + (*jext)++; + break; } *jext = '0'; } #ifndef LIBRAW_LIBRARY_BUILD - if (strcmp (jname, ifname)) { - if ((ifp = fopen (jname, "rb"))) { + if (strcmp(jname, ifname)) + { + if ((ifp = fopen(jname, "rb"))) + { #ifdef DCRAW_VERBOSE if (verbose) - fprintf (stderr,_("Reading metadata from %s ...\n"), jname); + fprintf(stderr, _("Reading metadata from %s ...\n"), jname); #endif - parse_tiff (12); + parse_tiff(12); thumb_offset = 0; is_raw = 1; - fclose (ifp); + fclose(ifp); } } #else - if (strcmp (jname, ifname)) - { - if(!ifp->subfile_open(jname)) - { - parse_tiff (12); - thumb_offset = 0; - is_raw = 1; - ifp->subfile_close(); - } - else - imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA ; - } + if (strcmp(jname, ifname)) + { + if (!ifp->subfile_open(jname)) + { + parse_tiff(12); + thumb_offset = 0; + is_raw = 1; + ifp->subfile_close(); + } + else + imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA; + } #endif if (!timestamp) - { + { #ifdef LIBRAW_LIBRARY_BUILD - imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA ; + imgdata.process_warnings |= LIBRAW_WARN_NO_METADATA; #endif #ifdef DCRAW_VERBOSE - fprintf (stderr,_("Failed to read metadata from %s\n"), jname); + fprintf(stderr, _("Failed to read metadata from %s\n"), jname); #endif - } - free (jname); + } + free(jname); #ifndef LIBRAW_LIBRARY_BUILD ifp = save; #endif } /* CIFF block 0x1030 contains an 8x8 white sample. Load this into white[][] for use in scale_colors(). */ void CLASS ciff_block_1030() { - static const ushort key[] = { 0x410, 0x45f3 }; - int i, bpp, row, col, vbits=0; - unsigned long bitbuf=0; + static const ushort key[] = {0x410, 0x45f3}; + int i, bpp, row, col, vbits = 0; + unsigned long bitbuf = 0; - if ((get2(),get4()) != 0x80008 || !get4()) return; + 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; + 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 >> (vbits -= bpp) & ~(-1 << bpp); } } /* Parse a CIFF file, better known as Canon CRW format. */ -void CLASS parse_ciff (int offset, int length, int depth) +void CLASS parse_ciff(int offset, int length, int depth) { - int tboff, nrecs, c, type, len, save, wbi=-1; - ushort key[] = { 0x410, 0x45f3 }; + int tboff, nrecs, c, type, len, save, wbi = -1; + ushort key[] = {0x410, 0x45f3}; - fseek (ifp, offset+length-4, SEEK_SET); + fseek(ifp, offset + length - 4, SEEK_SET); tboff = get4() + offset; - fseek (ifp, tboff, SEEK_SET); + fseek(ifp, tboff, SEEK_SET); nrecs = get2(); - if ((nrecs | depth) > 127) return; - while (nrecs--) { + if ((nrecs | depth) > 127) + return; + while (nrecs--) + { type = get2(); - len = get4(); + 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 */ + fseek(ifp, offset + get4(), SEEK_SET); + if ((((type >> 8) + 8) | 8) == 0x38) + { + parse_ciff(ftell(ifp), len, depth + 1); /* Parse a sub-table */ } #ifdef LIBRAW_LIBRARY_BUILD - if (type == 0x3004) parse_ciff (ftell(ifp), len, depth+1); + if (type == 0x3004) + parse_ciff(ftell(ifp), len, depth + 1); #endif if (type == 0x0810) - fread (artist, 64, 1, ifp); - if (type == 0x080a) { - fread (make, 64, 1, ifp); - fseek (ifp, strbuflen(make) - 63, SEEK_CUR); - fread (model, 64, 1, ifp); + fread(artist, 64, 1, ifp); + if (type == 0x080a) + { + fread(make, 64, 1, ifp); + fseek(ifp, strbuflen(make) - 63, SEEK_CUR); + fread(model, 64, 1, ifp); } - if (type == 0x1810) { + if (type == 0x1810) + { width = get4(); height = get4(); pixel_aspect = int_to_float(get4()); flip = get4(); } - if (type == 0x1835) /* Get the decoder table */ + if (type == 0x1835) /* Get the decoder table */ tiff_compress = get4(); - if (type == 0x2007) { + if (type == 0x2007) + { thumb_offset = ftell(ifp); thumb_length = len; } - if (type == 0x1818) { - shutter = libraw_powf64(2.0f, -int_to_float((get4(),get4()))); - aperture = libraw_powf64(2.0f, int_to_float(get4())/2); + if (type == 0x1818) + { + shutter = libraw_powf64l(2.0f, -int_to_float((get4(), get4()))); + aperture = libraw_powf64l(2.0f, int_to_float(get4()) / 2); #ifdef LIBRAW_LIBRARY_BUILD imgdata.lens.makernotes.CurAp = aperture; #endif } - if (type == 0x102a) { -// iso_speed = pow (2.0, (get4(),get2())/32.0 - 4) * 50; - iso_speed = libraw_powf64(2.0f, ((get2(),get2()) + get2())/32.0f - 5.0f) * 100.0f; + if (type == 0x102a) + { + // iso_speed = pow (2.0, (get4(),get2())/32.0 - 4) * 50; + iso_speed = libraw_powf64l(2.0f, ((get2(), get2()) + get2()) / 32.0f - 5.0f) * 100.0f; #ifdef LIBRAW_LIBRARY_BUILD - aperture = _CanonConvertAperture((get2(),get2())); + aperture = _CanonConvertAperture((get2(), get2())); imgdata.lens.makernotes.CurAp = aperture; #else - aperture = libraw_powf64(2.0, (get2(),(short)get2())/64.0); + aperture = libraw_powf64l(2.0, (get2(), (short)get2()) / 64.0); #endif - shutter = libraw_powf64(2.0,-((short)get2())/32.0); - wbi = (get2(),get2()); - if (wbi > 17) wbi = 0; - fseek (ifp, 32, SEEK_CUR); - if (shutter > 1e6) shutter = get2()/10.0; + shutter = libraw_powf64l(2.0, -((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 == 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(); } } #ifdef LIBRAW_LIBRARY_BUILD if (type == 0x10a9) - { - INT64 o = ftell(ifp); - fseek (ifp, (0x5<<1), SEEK_CUR); - Canon_WBpresets(0,0); - fseek(ifp,o,SEEK_SET); - } + { + INT64 o = ftell(ifp); + fseek(ifp, (0x1 << 1), SEEK_CUR); + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ (c >> 1)] = get2(); + Canon_WBpresets(0, 0); + fseek(ifp, o, SEEK_SET); + } if (type == 0x102d) - { - INT64 o = ftell(ifp); - Canon_CameraSettings(); - fseek(ifp,o,SEEK_SET); - } + { + INT64 o = ftell(ifp); + Canon_CameraSettings(); + fseek(ifp, o, SEEK_SET); + } if (type == 0x580b) - { - if (strcmp(model,"Canon EOS D30")) sprintf(imgdata.shootinginfo.BodySerial, "%d", len); - else sprintf(imgdata.shootinginfo.BodySerial, "%0x-%05d", len>>16, len&0xffff); - } + { + if (strcmp(model, "Canon EOS D30")) + sprintf(imgdata.shootinginfo.BodySerial, "%d", len); + else + sprintf(imgdata.shootinginfo.BodySerial, "%0x-%05d", len >> 16, len & 0xffff); + } #endif - if (type == 0x0032) { - if (len == 768) { /* EOS D30 */ - fseek (ifp, 72, SEEK_CUR); + if (type == 0x0032) + { + if (len == 768) + { /* EOS D30 */ + fseek(ifp, 72, SEEK_CUR); FORC4 { ushort q = get2(); cam_mul[c ^ (c >> 1)] = 1024.0/ MAX(1,q); } - 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")[LIM(0,wbi,17)]-'0'+ 2; - else { /* G3, G5, S45, S50 */ - c = "023457000000006000"[LIM(0,wbi,17)]-'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"[LIM(0,wbi,9)]-'0'; - fseek (ifp, 2 + wbi*8, SEEK_CUR); + 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")[LIM(0, wbi, 17)] - '0' + 2; + else + { /* G3, G5, S45, S50 */ + c = "023457000000006000"[LIM(0, wbi, 17)] - '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"[LIM(0, wbi, 9)] - '0'; + fseek(ifp, 2 + wbi * 8, SEEK_CUR); FORC4 cam_mul[c ^ (c >> 1)] = get2(); } - if (type == 0x1030 && wbi>=0 && (0x18040 >> wbi & 1)) - ciff_block_1030(); /* all that don't have 0x10a9 */ - if (type == 0x1031) { - raw_width = (get2(),get2()); + if (type == 0x1030 && wbi >= 0 && (0x18040 >> wbi & 1)) + ciff_block_1030(); /* all that don't have 0x10a9 */ + if (type == 0x1031) + { + raw_width = (get2(), get2()); raw_height = get2(); } - if (type == 0x501c) { + if (type == 0x501c) + { iso_speed = len & 0xffff; } - if (type == 0x5029) { + if (type == 0x5029) + { #ifdef LIBRAW_LIBRARY_BUILD - imgdata.lens.makernotes.CurFocal = len >> 16; + imgdata.lens.makernotes.CurFocal = len >> 16; imgdata.lens.makernotes.FocalType = len & 0xffff; - if (imgdata.lens.makernotes.FocalType == 2) { + if (imgdata.lens.makernotes.FocalType == 2) + { imgdata.lens.makernotes.CanonFocalUnits = 32; - if(imgdata.lens.makernotes.CanonFocalUnits>1) - imgdata.lens.makernotes.CurFocal /= (float)imgdata.lens.makernotes.CanonFocalUnits; + if (imgdata.lens.makernotes.CanonFocalUnits > 1) + imgdata.lens.makernotes.CurFocal /= (float)imgdata.lens.makernotes.CanonFocalUnits; } focal_len = imgdata.lens.makernotes.CurFocal; #else focal_len = len >> 16; - if ((len & 0xffff) == 2) focal_len /= 32; + if ((len & 0xffff) == 2) + focal_len /= 32; #endif } - 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 == 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; + { + unique_id = len; #ifdef LIBRAW_LIBRARY_BUILD - setCanonBodyFeatures(unique_id); + unique_id = setCanonBodyFeatures(unique_id); #endif - } - if (type == 0x580e) timestamp = len; - if (type == 0x180e) timestamp = get4(); + } + if (type == 0x580e) + timestamp = len; + if (type == 0x180e) + timestamp = get4(); #ifdef LOCALTIME if ((type | 0x4000) == 0x580e) - timestamp = mktime (gmtime (×tamp)); + timestamp = mktime(gmtime(×tamp)); #endif - fseek (ifp, save, SEEK_SET); + 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,'='))) + fseek(ifp, 0, SEEK_SET); + memset(&t, 0, sizeof t); + do + { + fgets(line, 128, ifp); + if ((val = strchr(line, '='))) *val++ = 0; else val = line + strbuflen(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")) + 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 ")) + if (!strcmp(line, "X ")) raw_width = atoi(val); - if (!strcmp(line,"Y ")) + if (!strcmp(line, "Y ")) raw_height = atoi(val); - if (!strcmp(line,"TX ")) + if (!strcmp(line, "TX ")) thumb_width = atoi(val); - if (!strcmp(line,"TY ")) + if (!strcmp(line, "TY ")) thumb_height = atoi(val); - } while (strncmp(line,"EOHD",4)); + } 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"); + 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); + 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); + 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); + if ((cp = strchr(make, ' '))) + { + strcpy(model, cp + 1); *cp = 0; } - raw_width = get2(); + raw_width = get2(); raw_height = get2(); load_raw = &CLASS unpacked_load_raw; - thumb_width = (get4(),get2()); + thumb_width = (get4(), get2()); thumb_height = get2(); write_thumb = &CLASS ppm_thumb; maximum = 0x3fff; } -void CLASS parse_phase_one (int base) +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); + 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); + if (get4() >> 8 != 0x526177) + return; /* "Raw" */ + fseek(ifp, get4() + base, SEEK_SET); entries = get4(); get4(); - while (entries--) { - tag = get4(); + while (entries--) + { + tag = get4(); type = get4(); - len = get4(); + len = get4(); data = get4(); save = ftell(ifp); - fseek (ifp, base+data, SEEK_SET); - switch (tag) { + fseek(ifp, base + data, SEEK_SET); + switch (tag) + { #ifdef LIBRAW_LIBRARY_BUILD case 0x0102: stmread(imgdata.shootinginfo.BodySerial, len, ifp); - if ((imgdata.shootinginfo.BodySerial[0] == 0x4c) && (imgdata.shootinginfo.BodySerial[1] == 0x49)) { - unique_id = (((imgdata.shootinginfo.BodySerial[0] & 0x3f) << 5) | (imgdata.shootinginfo.BodySerial[2] & 0x3f)) - 0x41; - } else { - unique_id = (((imgdata.shootinginfo.BodySerial[0] & 0x3f) << 5) | (imgdata.shootinginfo.BodySerial[1] & 0x3f)) - 0x41; + if ((imgdata.shootinginfo.BodySerial[0] == 0x4c) && (imgdata.shootinginfo.BodySerial[1] == 0x49)) + { + unique_id = + (((imgdata.shootinginfo.BodySerial[0] & 0x3f) << 5) | (imgdata.shootinginfo.BodySerial[2] & 0x3f)) - 0x41; + } + else + { + unique_id = + (((imgdata.shootinginfo.BodySerial[0] & 0x3f) << 5) | (imgdata.shootinginfo.BodySerial[1] & 0x3f)) - 0x41; } setPhaseOneFeatures(unique_id); break; + case 0x0211: + imgdata.other.SensorTemperature2 = int_to_float(data); + break; case 0x0401: - if (type == 4) imgdata.lens.makernotes.CurAp = libraw_powf64(2.0f, (int_to_float(data)/2.0f)); - else imgdata.lens.makernotes.CurAp = libraw_powf64(2.0f, (getreal(type)/2.0f)); + if (type == 4) + imgdata.lens.makernotes.CurAp = libraw_powf64l(2.0f, (int_to_float(data) / 2.0f)); + else + imgdata.lens.makernotes.CurAp = libraw_powf64l(2.0f, (getreal(type) / 2.0f)); break; case 0x0403: - if (type == 4) imgdata.lens.makernotes.CurFocal = int_to_float(data); - else imgdata.lens.makernotes.CurFocal = getreal(type); + if (type == 4) + imgdata.lens.makernotes.CurFocal = int_to_float(data); + else + imgdata.lens.makernotes.CurFocal = getreal(type); break; case 0x0410: stmread(imgdata.lens.makernotes.body, len, ifp); break; case 0x0412: stmread(imgdata.lens.makernotes.Lens, len, ifp); break; case 0x0414: - if (type == 4) { - imgdata.lens.makernotes.MaxAp4CurFocal = libraw_powf64(2.0f, (int_to_float(data)/2.0f)); - } else { - imgdata.lens.makernotes.MaxAp4CurFocal = libraw_powf64(2.0f, (getreal(type) / 2.0f)); + if (type == 4) + { + imgdata.lens.makernotes.MaxAp4CurFocal = libraw_powf64l(2.0f, (int_to_float(data) / 2.0f)); + } + else + { + imgdata.lens.makernotes.MaxAp4CurFocal = libraw_powf64l(2.0f, (getreal(type) / 2.0f)); } break; case 0x0415: - if (type == 4) { - imgdata.lens.makernotes.MinAp4CurFocal = libraw_powf64(2.0f, (int_to_float(data)/2.0f)); - } else { - imgdata.lens.makernotes.MinAp4CurFocal = libraw_powf64(2.0f, (getreal(type) / 2.0f)); + if (type == 4) + { + imgdata.lens.makernotes.MinAp4CurFocal = libraw_powf64l(2.0f, (int_to_float(data) / 2.0f)); + } + else + { + imgdata.lens.makernotes.MinAp4CurFocal = libraw_powf64l(2.0f, (getreal(type) / 2.0f)); } break; case 0x0416: - if (type == 4) { - imgdata.lens.makernotes.MinFocal = int_to_float(data); - } else { + if (type == 4) + { + imgdata.lens.makernotes.MinFocal = int_to_float(data); + } + else + { imgdata.lens.makernotes.MinFocal = getreal(type); } if (imgdata.lens.makernotes.MinFocal > 1000.0f) - { - imgdata.lens.makernotes.MinFocal = 0.0f; - } + { + imgdata.lens.makernotes.MinFocal = 0.0f; + } break; case 0x0417: - if (type == 4) { - imgdata.lens.makernotes.MaxFocal = int_to_float(data); - } else { + if (type == 4) + { + imgdata.lens.makernotes.MaxFocal = int_to_float(data); + } + else + { imgdata.lens.makernotes.MaxFocal = getreal(type); } break; #endif - case 0x100: flip = "0653"[data & 3]-'0'; break; - case 0x106: - for (i=0; i < 9; i++) -#ifdef LIBRAW_LIBRARY_BUILD - imgdata.color.P1_color[0].romm_cam[i]= -#endif - ((float *)romm_cam)[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.t_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; -#ifdef LIBRAW_LIBRARY_BUILD - case 0x226: - for (i=0; i < 9; i++) - imgdata.color.P1_color[1].romm_cam[i] = getreal(11); - break; -#endif - case 0x301: - model[63] = 0; - fread (model, 1, 63, ifp); - if ((cp = strstr(model," camera"))) *cp = 0; - } - fseek (ifp, save, SEEK_SET); - } - -#ifdef LIBRAW_LIBRARY_BUILD - if (!imgdata.lens.makernotes.body[0] && !imgdata.shootinginfo.BodySerial[0]) { - fseek (ifp, meta_offset, SEEK_SET); + case 0x100: + flip = "0653"[data & 3] - '0'; + break; + case 0x106: + for (i = 0; i < 9; i++) +#ifdef LIBRAW_LIBRARY_BUILD + imgdata.color.P1_color[0].romm_cam[i] = +#endif + ((float *)romm_cam)[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); +#ifdef LIBRAW_LIBRARY_BUILD + imgdata.other.SensorTemperature = ph1.tag_210; +#endif + break; + case 0x21a: + ph1.tag_21a = data; + break; + case 0x21c: + strip_offset = data + base; + break; + case 0x21d: + ph1.t_black = data; + break; + case 0x222: + ph1.split_col = data; + break; + case 0x223: + ph1.black_col = data + base; + break; + case 0x224: + ph1.split_row = data; + break; + case 0x225: + ph1.black_row = data + base; + break; +#ifdef LIBRAW_LIBRARY_BUILD + case 0x226: + for (i = 0; i < 9; i++) + imgdata.color.P1_color[1].romm_cam[i] = getreal(11); + break; +#endif + case 0x301: + model[63] = 0; + fread(model, 1, 63, ifp); + if ((cp = strstr(model, " camera"))) + *cp = 0; + } + fseek(ifp, save, SEEK_SET); + } + +#ifdef LIBRAW_LIBRARY_BUILD + if (!imgdata.lens.makernotes.body[0] && !imgdata.shootinginfo.BodySerial[0]) + { + 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(); + 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 == 0x0407) { + fseek(ifp, meta_offset + data, SEEK_SET); + if (tag == 0x0407) + { stmread(imgdata.shootinginfo.BodySerial, len, ifp); - if ((imgdata.shootinginfo.BodySerial[0] == 0x4c) && (imgdata.shootinginfo.BodySerial[1] == 0x49)) { - unique_id = (((imgdata.shootinginfo.BodySerial[0] & 0x3f) << 5) | (imgdata.shootinginfo.BodySerial[2] & 0x3f)) - 0x41; - } else { - unique_id = (((imgdata.shootinginfo.BodySerial[0] & 0x3f) << 5) | (imgdata.shootinginfo.BodySerial[1] & 0x3f)) - 0x41; + if ((imgdata.shootinginfo.BodySerial[0] == 0x4c) && (imgdata.shootinginfo.BodySerial[1] == 0x49)) + { + unique_id = + (((imgdata.shootinginfo.BodySerial[0] & 0x3f) << 5) | (imgdata.shootinginfo.BodySerial[2] & 0x3f)) - 0x41; + } + else + { + unique_id = + (((imgdata.shootinginfo.BodySerial[0] & 0x3f) << 5) | (imgdata.shootinginfo.BodySerial[1] & 0x3f)) - 0x41; } setPhaseOneFeatures(unique_id); } - fseek (ifp, save, SEEK_SET); + fseek(ifp, save, SEEK_SET); } } #endif - load_raw = ph1.format < 3 ? - &CLASS phase_one_load_raw : &CLASS phase_one_load_raw_c; + 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; + 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) +void CLASS parse_fuji(int offset) { unsigned entries, tag, len, save, c; - fseek (ifp, offset, SEEK_SET); + fseek(ifp, offset, SEEK_SET); entries = get4(); if (entries > 255) return; #ifdef LIBRAW_LIBRARY_BUILD - imgdata.process_warnings |= LIBRAW_WARN_PARSEFUJI_PROCESSED; + imgdata.process_warnings |= LIBRAW_WARN_PARSEFUJI_PROCESSED; #endif while (entries--) { tag = get2(); len = get2(); save = ftell(ifp); - if (tag == 0x100) { + if (tag == 0x100) + { raw_height = get2(); - raw_width = get2(); - } else if (tag == 0x121) { + raw_width = get2(); + } + else if (tag == 0x121) + { height = get2(); - if ((width = get2()) == 4284) width += 3; - } else if (tag == 0x130) { + if ((width = get2()) == 4284) + width += 3; + } + else if (tag == 0x130) + { fuji_layout = fgetc(ifp) >> 7; fuji_width = !(fgetc(ifp) & 8); - } else if (tag == 0x131) { + } + else if (tag == 0x131) + { filters = 9; FORC(36) - { - int q = fgetc(ifp); - xtrans_abs[0][35 - c] = MAX(0,MIN(q,2)); /* & 3;*/ - } - } else if (tag == 0x2ff0) { - FORC4 cam_mul[c ^ 1] = get2(); + { + int q = fgetc(ifp); + xtrans_abs[0][35 - c] = MAX(0, MIN(q, 2)); /* & 3;*/ + } } + else if (tag == 0x2ff0) + { + FORC4 cam_mul[c ^ 1] = get2(); + // IB start #ifdef LIBRAW_LIBRARY_BUILD + } + + else if (tag == 0x110) + { + imgdata.sizes.raw_crop.ctop = get2(); + imgdata.sizes.raw_crop.cleft = get2(); + } + + else if (tag == 0x111) + { + imgdata.sizes.raw_crop.cheight = get2(); + imgdata.sizes.raw_crop.cwidth = get2(); + } + + else if ((tag == 0x122) && !strcmp(model, "DBP for GX680")) + { + int k = get2(); + int l = get2(); /* margins? */ + int m = get2(); /* margins? */ + int n = get2(); + // printf ("==>>0x122: height= %d l= %d m= %d width= %d\n", k, l, m, n); + } + else if (tag == 0x9650) { short a = (short)get2(); - float b =fMAX(1.0f, get2()); + float b = fMAX(1.0f, get2()); imgdata.makernotes.fuji.FujiExpoMidPointShift = a / b; - } else if (tag == 0x2100) { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Daylight][c ^ 1] = get2(); - } else if (tag == 0x2200) { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Cloudy][c ^ 1] = get2(); - } else if (tag == 0x2300) { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][c ^ 1] = get2(); - } else if (tag == 0x2301) { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][c ^ 1] = get2(); - } else if (tag == 0x2302) { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][c ^ 1] = get2(); - } else if (tag == 0x2310) { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][c ^ 1] = get2(); - } else if (tag == 0x2400) { - FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][c ^ 1] = get2(); } + + else if (tag == 0x2f00) + { + int nWBs = get4(); + nWBs = MIN(nWBs, 6); + for (int wb_ind = 0; wb_ind < nWBs; wb_ind++) + { + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Custom1 + wb_ind][c ^ 1] = get2(); + fseek(ifp, 8, SEEK_CUR); + } + } + + else if (tag == 0x2000) + { + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Auto][c ^ 1] = get2(); + } + else if (tag == 0x2100) + { + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FineWeather][c ^ 1] = get2(); + } + else if (tag == 0x2200) + { + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Shade][c ^ 1] = get2(); + } + else if (tag == 0x2300) + { + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_D][c ^ 1] = get2(); + } + else if (tag == 0x2301) + { + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_N][c ^ 1] = get2(); + } + else if (tag == 0x2302) + { + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_WW][c ^ 1] = get2(); + } + else if (tag == 0x2310) + { + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_FL_L][c ^ 1] = get2(); + } + else if (tag == 0x2400) + { + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Tungsten][c ^ 1] = get2(); + } + else if (tag == 0x2410) + { + FORC4 imgdata.color.WB_Coeffs[LIBRAW_WBI_Flash][c ^ 1] = get2(); #endif -// IB end - else if (tag == 0xc000) { + // IB end + } + else if (tag == 0xc000) + /* 0xc000 tag versions, second ushort; valid if the first ushort is 0 + X100F 0x0259 + X100T 0x0153 + X-E2 0x014f 0x024f depends on firmware + X-A1 0x014e + XQ2 0x0150 + XQ1 0x0150 + X100S 0x0149 0x0249 depends on firmware + X30 0x0152 + X20 0x0146 + X-T10 0x0154 + X-T2 0x0258 + X-M1 0x014d + X-E2s 0x0355 + X-A2 0x014e + X-T20 0x025b + GFX 50S 0x025a + X-T1 0x0151 0x0251 0x0351 depends on firmware + X70 0x0155 + X-Pro2 0x0255 + */ + { c = order; order = 0x4949; - if ((tag = get4()) > 10000) tag = get4(); - if (tag > 10000) tag = get4(); + if ((tag = get4()) > 10000) + tag = get4(); + if (tag > 10000) + tag = get4(); width = tag; height = get4(); #ifdef LIBRAW_LIBRARY_BUILD - libraw_internal_data.unpacker_data.posRAFData = save; - libraw_internal_data.unpacker_data.lenRAFData = (len>>1); + if (!strcmp(model, "X-A3") || + !strcmp(model, "X-A10") || + !strcmp(model, "X-A5") || + !strcmp(model, "X-A20")) + { + int wb[4]; + int nWB, tWB, pWB; + int iCCT = 0; + int cnt; + fseek(ifp, save + 0x200, SEEK_SET); + for (int wb_ind = 0; wb_ind < 42; wb_ind++) + { + nWB = get4(); + tWB = get4(); + wb[0] = get4() << 1; + wb[1] = get4(); + wb[3] = get4(); + wb[2] = get4() << 1; + if (tWB && (iCCT < 255)) + { + imgdata.color.WBCT_Coeffs[iCCT][0] = tWB; + for (cnt = 0; cnt < 4; cnt++) + imgdata.color.WBCT_Coeffs[iCCT][cnt + 1] = wb[cnt]; + iCCT++; + } + if (nWB != 70) + { + for (pWB = 1; pWB < nFuji_wb_list2; pWB += 2) + { + if (Fuji_wb_list2[pWB] == nWB) + { + for (cnt = 0; cnt < 4; cnt++) + imgdata.color.WB_Coeffs[Fuji_wb_list2[pWB - 1]][cnt] = wb[cnt]; + break; + } + } + } + } + } + else + { + libraw_internal_data.unpacker_data.posRAFData = save; + libraw_internal_data.unpacker_data.lenRAFData = (len >> 1); + } #endif - order = c; + order = c; } - fseek (ifp, save+len, SEEK_SET); + fseek(ifp, save + len, SEEK_SET); } height <<= fuji_layout; - width >>= fuji_layout; + width >>= fuji_layout; } -int CLASS parse_jpeg (int offset) +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; + fseek(ifp, offset, SEEK_SET); + if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8) + return 0; - while (fgetc(ifp) == 0xff && (mark = fgetc(ifp)) != 0xda) { + while (fgetc(ifp) == 0xff && (mark = fgetc(ifp)) != 0xda) + { order = 0x4d4d; - len = get2() - 2; - save = ftell(ifp); - if (mark == 0xc0 || mark == 0xc3 || mark == 0xc9) { + len = get2() - 2; + save = ftell(ifp); + if (mark == 0xc0 || mark == 0xc3 || mark == 0xc9) + { fgetc(ifp); raw_height = get2(); - raw_width = get2(); + raw_width = get2(); } order = get2(); - hlen = get4(); + hlen = get4(); if (get4() == 0x48454150 #ifdef LIBRAW_LIBRARY_BUILD - && (save+hlen) >= 0 && (save+hlen)<=ifp->size() + && (save + hlen) >= 0 && (save + hlen) <= ifp->size() #endif - ) /* "HEAP" */ + ) /* "HEAP" */ { #ifdef LIBRAW_LIBRARY_BUILD imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; #endif - parse_ciff (save+hlen, len-hlen, 0); + parse_ciff(save + hlen, len - hlen, 0); } - if (parse_tiff (save+6)) apply_tiff(); - fseek (ifp, save+len, SEEK_SET); + 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" }; + 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); + fread(tag, 4, 1, ifp); size = get4(); end = ftell(ifp) + size; - if (!memcmp(tag,"RIFF",4) || !memcmp(tag,"LIST",4)) { + if (!memcmp(tag, "RIFF", 4) || !memcmp(tag, "LIST", 4)) + { int maxloop = 1000; get4(); - while (ftell(ifp)+7 < end && !feof(ifp) && maxloop--) + while (ftell(ifp) + 7 < end && !feof(ifp) && maxloop--) parse_riff(); - } else if (!memcmp(tag,"nctg",4)) { - while (ftell(ifp)+7 < end) { + } + 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); + 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); + } + 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++); + 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); + timestamp = mktime(&t); } - } else - fseek (ifp, size, SEEK_CUR); + } + else + fseek(ifp, size, SEEK_CUR); } -void CLASS parse_qt (int end) +void CLASS parse_qt(int end) { unsigned save, size; char tag[4]; order = 0x4d4d; - while (ftell(ifp)+7 < end) { + while (ftell(ifp) + 7 < end) + { save = ftell(ifp); - if ((size = get4()) < 8) return; + if ((size = get4()) < 8) + return; if ((int)size < 0) return; // 2+GB is too much if (save + size < save) return; // 32bit overflow - 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); + 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) +void CLASS parse_smal(int offset, int fsize) { int ver; - fseek (ifp, offset+2, SEEK_SET); + 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(); + 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; + 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); + fseek(ifp, 4, SEEK_SET); is_raw = get2() == 2; - fseek (ifp, 14, SEEK_CUR); + 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); + 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; + 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 = ~((~0u) << get4()); - fseek (ifp, 668, SEEK_CUR); - shutter = get4()/1000000000.0; - fseek (ifp, off_image, SEEK_SET); + 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; + 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(); + 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) { + fseek(ifp, 0, SEEK_END); + fseek(ifp, -(i = ftello(ifp) & 511), SEEK_CUR); + if (get4() != i || get4() != 0x52454f42) + { #ifdef DCRAW_VERBOSE - fprintf (stderr,_("%s: Tail is missing, parsing from head...\n"), ifname); + fprintf(stderr, _("%s: Tail is missing, parsing from head...\n"), ifname); #endif - fseek (ifp, 0, SEEK_SET); - while ((len = get4()) != EOF) { + 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); + if (is_raw++ == shot_select) + data_offset = ftello(ifp) - 8; + fseek(ifp, len - 8, SEEK_CUR); } - } else { + } + else + { rdvo = get4(); - fseek (ifp, 12, SEEK_CUR); + fseek(ifp, 12, SEEK_CUR); is_raw = get4(); - fseeko (ifp, rdvo+8 + shot_select*4, SEEK_SET); + fseeko(ifp, rdvo + 8 + shot_select * 4, SEEK_SET); data_offset = get4(); } } /* All matrices are from Adobe DNG Converter unless otherwise noted. */ -void CLASS adobe_coeff (const char *t_make, const char *t_model +void CLASS adobe_coeff(const char *t_make, const char *t_model #ifdef LIBRAW_LIBRARY_BUILD - ,int internal_only + , + int internal_only #endif ) { - static const struct { + // clang-format off + static const struct + { const char *prefix; int t_black, t_maximum, trans[12]; } table[] = { - { "AgfaPhoto DC-833m", 0, 0, /* DJC */ + { "AgfaPhoto DC-833m", 0, 0, /* DJC */ { 11438,-3762,-1115,-2409,9914,2497,-1227,2295,5300 } }, - { "Apple QuickTake", 0, 0, /* DJC */ + + { "Apple QuickTake", 0, 0, /* DJC */ { 21392,-5653,-3353,2406,8010,-415,7166,1427,2078 } }, + {"Broadcom RPi IMX219", 66, 0x3ff, - { 5302,1083,-728,-5320,14112,1699,-863,2371,5136 } }, /* LibRaw */ + { 5302,1083,-728,-5320,14112,1699,-863,2371,5136 } }, /* LibRaw */ { "Broadcom RPi OV5647", 16, 0x3ff, { 12782,-4059,-379,-478,9066,1413,1340,1513,5176 } }, /* DJC */ + { "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 D30", 0, 0, /* updated */ + { 9900,-2771,-1324,-7072,14229,3140,-2790,3344,8861 } }, + { "Canon EOS D60", 0, 0xfa0, /* updated */ + { 6211,-1358,-896,-8557,15766,3012,-3001,3507,8567 } }, { "Canon EOS 5DS", 0, 0x3c96, { 6250,-711,-808,-5153,12794,2636,-1249,2198,5610 } }, { "Canon EOS 5D Mark IV", 0, 0, - { 6446, -366, -864, -4436, 12204, 2513, -952, 2496, 6348 }}, + { 6446,-366,-864,-4436,12204,2513,-952,2496,6348 } }, { "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 Mark II", 0, 0x38de, + { 6875,-970,-932,-4691,12459,2501,-874,1953,5809 } }, { "Canon EOS 6D", 0, 0x3c82, - { 8621,-2197,-787,-3150,11358,912,-1161,2400,4836 } }, + {7034, -804, -1014, -4420, 12564, 2058, -851, 1994, 5758 } }, + { "Canon EOS 77D", 0, 0, + { 7377,-742,-998,-4235,11981,2549,-673,1918,5538 } }, { "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 800D", 0, 0, + { 6970,-512,-968,-4425,12161,2553,-739,1982,5601 } }, { "Canon EOS 80D", 0, 0, { 7457,-671,-937,-4849,12495,2643,-1213,2354,5492 } }, - { "Canon EOS 10D", 0, 0xfa0, - { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } }, + { "Canon EOS 10D", 0, 0xfa0, /* updated */ + { 8250,-2044,-1127,-8092,15606,2664,-2893,3453,8348 } }, + { "Canon EOS 200D", 0, 0, + { 7377,-742,-998,-4235,11981,2549,-673,1918,5538 } }, { "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 60Da", 0, 0x2ff7, /* added */ + { 17492,-7240,-2023,-1791,10323,1701,-186,1329,5406 } }, { "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 300D", 0, 0xfa0, /* updated */ + { 8250,-2044,-1127,-8092,15606,2664,-2893,3453,8348 } }, { "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 750D", 0, 0x3c00, { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } }, { "Canon EOS 760D", 0, 0x3c00, { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } }, { "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 1300D", 0, 0x37c2, - { 6939, -1016, -866, -4428, 12473, 2177, -1175, 2178, 6162 } }, + { 6939,-1016,-866,-4428,12473,2177,-1175,2178,6162 } }, + { "Canon EOS M6", 0, 0, + { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } }, + { "Canon EOS M5", 0, 0, + { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } }, { "Canon EOS M3", 0, 0, { 6362,-823,-847,-4426,12109,2616,-743,1857,5635 } }, - { "Canon EOS M5", 0, 0, /* Adobe */ - { 8532, -701, -1167, -4095, 11879, 2508, -797, 2424, 7010 }}, + { "Canon EOS M2", 0, 0, /* added */ + { 6400,-480,-888,-5294,13416,2047,-1296,2203,6137 } }, + { "Canon EOS M100", 0, 0, + { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } }, { "Canon EOS M10", 0, 0, { 6400,-480,-888,-5294,13416,2047,-1296,2203,6137 } }, { "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-1DS", 0, 0xe20, /* updated */ + { 3925,4060,-1739,-8973,16552,2545,-3287,3945,8243 } }, { "Canon EOS-1D C", 0, 0x3c4e, { 6847,-614,-1014,-4669,12737,2139,-1197,2488,6846 } }, - { "Canon EOS-1D X Mark II", 0, 0x3c4e, - { 7596,-978,967,-4808,12571,2503,-1398,2567,5752 } }, + { "Canon EOS-1D X Mark II", 0, 0x3c4e, /* updated */ + { 7596,-978,-967,-4808,12571,2503,-1398,2567,5752 } }, { "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 */ + { "Canon EOS C500", 853, 0, /* DJC */ { 17851,-10604,922,-7425,16662,763,-3660,3636,22278 } }, + {"Canon PowerShot 600", 0, 0, /* added */ + { -3822,10019,1311,4085,-157,3386,-5341,10829,4812,-1969,10969,1126 } }, { "Canon PowerShot A530", 0, 0, - { 0 } }, /* don't want the A5 matrix */ + { 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, - { 14130,-8071,127,2199,6528,1551,3402,-1721,4960 } }, + { "Canon PowerShot G16", 0, 0, /* updated */ + { 8020,-2687,-682,-3704,11879,2052,-965,1921,5556 } }, + { "Canon PowerShot G1 X Mark III", 0, 0, + { 8532,-701,-1167,-4095,11879,2508,-797,2424,7010 } }, { "Canon PowerShot G1 X Mark II", 0, 0, { 7378,-1255,-1043,-4088,12251,2048,-876,1946,5805 } }, { "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 G1", 0, 0, /* updated */ + { -5686,10300,2223,4725,-1157,4383,-6128,10783,6163,-2688,12093,604 } }, + { "Canon PowerShot G2", 0, 0, /* updated */ + { 9194,-2787,-1059,-8098,15657,2608,-2610,3064,7867 } }, { "Canon PowerShot G3 X", 0, 0, { 9701,-3857,-921,-3149,11537,1817,-786,1817,5147 } }, - { "Canon PowerShot G3", 0, 0, - { 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } }, + { "Canon PowerShot G3", 0, 0, /* updated */ + { 9326,-2882,-1084,-7940,15447,2677,-2620,3090,7740 } }, { "Canon PowerShot G5 X",0, 0, { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } }, - { "Canon PowerShot G5", 0, 0, - { 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } }, + { "Canon PowerShot G5", 0, 0, /* updated */ + { 9869,-2972,-942,-7314,15098,2369,-1898,2536,7282 } }, { "Canon PowerShot G6", 0, 0, { 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } }, { "Canon PowerShot G7 X Mark II", 0, 0, { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } }, { "Canon PowerShot G7 X", 0, 0, { 9602,-3823,-937,-2984,11495,1675,-407,1415,5049 } }, + { "Canon PowerShot G9 X Mark II", 0, 0, + { 10056,-4131,-944,-2576,11143,1625,-238,1294,5179 } }, { "Canon PowerShot G9 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 Pro70", 34, 0, /* updated */ + { -5106,10695,1576,3820,53,4566,-6497,10736,6701,-3336,11887,1394 } }, + { "Canon PowerShot Pro90", 0, 0, /* updated */ + { -5912,10768,2288,4612,-989,4333,-6153,10897,5944,-2907,12288,624 } }, + { "Canon PowerShot S30", 0, 0, /* updated */ + { 10744,-3813,-1142,-7962,15966,2075,-2492,2805,7744 } }, + { "Canon PowerShot S40", 0, 0, /* updated */ + { 8606,-2573,-949,-8237,15489,2974,-2649,3076,9100 } }, + { "Canon PowerShot S45", 0, 0, /* updated */ + { 8251,-2410,-964,-8047,15430,2823,-2380,2824,8119 } }, + { "Canon PowerShot S50", 0, 0, /* updated */ + { 8979,-2658,-871,-7721,15500,2357,-1773,2366,6634 } }, { "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 S120", 0, 0, { 6961,-1685,-695,-4625,12945,1836,-1114,2152,5518 } }, { "Canon PowerShot S110", 0, 0, { 8039,-2643,-654,-3783,11230,2930,-206,690,4194 } }, { "Canon PowerShot S100", 0, 0, { 7968,-2565,-636,-2873,10697,2513,180,667,4211 } }, { "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 */ + { "Canon PowerShot A3300", 0, 0, /* DJC */ { 10826,-3654,-1023,-3215,11310,1906,0,999,4960 } }, - { "Canon PowerShot A470", 0, 0, /* DJC */ + { "Canon PowerShot A470", 0, 0, /* DJC */ { 12513,-4407,-1242,-2680,10276,2405,-878,2215,4734 } }, - { "Canon PowerShot A610", 0, 0, /* DJC */ + { "Canon PowerShot A610", 0, 0, /* DJC */ { 15591,-6402,-1592,-5365,13198,2168,-1300,1824,5075 } }, - { "Canon PowerShot A620", 0, 0, /* DJC */ + { "Canon PowerShot A620", 0, 0, /* DJC */ { 15265,-6193,-1558,-4125,12116,2010,-888,1639,5220 } }, - { "Canon PowerShot A630", 0, 0, /* DJC */ + { "Canon PowerShot A630", 0, 0, /* DJC */ { 14201,-5308,-1757,-6087,14472,1617,-2191,3105,5348 } }, - { "Canon PowerShot A640", 0, 0, /* DJC */ + { "Canon PowerShot A640", 0, 0, /* DJC */ { 13124,-5329,-1390,-3602,11658,1944,-1612,2863,4885 } }, - { "Canon PowerShot A650", 0, 0, /* DJC */ + { "Canon PowerShot A650", 0, 0, /* DJC */ { 9427,-3036,-959,-2581,10671,1911,-1039,1982,4430 } }, - { "Canon PowerShot A720", 0, 0, /* DJC */ + { "Canon PowerShot A720", 0, 0, /* DJC */ { 14573,-5482,-1546,-1266,9799,1468,-1040,1912,3810 } }, - { "Canon PowerShot S3 IS", 0, 0, /* DJC */ + { "Canon PowerShot D10", 127, 0, /* DJC */ + { 14052,-5229,-1156,-1325,9420,2252,-498,1957,4116 } }, + { "Canon PowerShot S3 IS", 0, 0, /* DJC */ { 14062,-5199,-1446,-4712,12470,2243,-1286,2028,4836 } }, - { "Canon PowerShot SX110 IS", 0, 0, /* DJC */ + { "Canon PowerShot SX110 IS", 0, 0, /* DJC */ { 14134,-5576,-1527,-1991,10719,1273,-1158,1929,3581 } }, - { "Canon PowerShot SX220", 0, 0, /* DJC */ + { "Canon PowerShot SX220", 0, 0, /* DJC */ { 13898,-5076,-1447,-1405,10109,1297,-244,1860,3687 } }, - { "Canon IXUS 160", 0, 0, /* DJC */ + { "Canon IXUS 160", 0, 0, /* DJC */ { 11657,-3781,-1136,-3544,11262,2283,-160,1219,4700 } }, - { "Casio EX-S20", 0, 0, /* DJC */ + + { "Casio EX-F1", 0, 0, /* added */ + { 9084,-2016,-848,-6711,14351,2570,-1059,1725,6135 } }, + { "Casio EX-FH100", 0, 0, /* added */ + { 12771,-4179,-1558,-2149,10938,1375,-453,1751,4494 } }, + { "Casio EX-S20", 0, 0, /* DJC */ { 11634,-3924,-1128,-4968,12954,2015,-1588,2648,7206 } }, - { "Casio EX-Z750", 0, 0, /* DJC */ + { "Casio EX-Z750", 0, 0, /* DJC */ { 10819,-3873,-1099,-4903,13730,1175,-1755,3751,4632 } }, - { "Casio EX-Z10", 128, 0xfff, /* DJC */ + { "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 } }, + { "DXO ONE", 0, 0, { 6596,-2079,-562,-4782,13016,1933,-970,1581,5181 } }, + { "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 E550", 0, 0, /* updated */ + { 11044,-3888,-1120,-7248,15167,2208,-1531,2276,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 F810", 0, 0, /* added */ + { 11044,-3888,-1120,-7248,15167,2208,-1531,2276,8069 } }, { "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 S2Pro", 128, 0, /* updated */ + { 12741,-4916,-1420,-8510,16791,1715,-1767,2302,7771 } }, { "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 X100F", 0, 0, + { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, { "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 X70", 0, 0, { 10450,-4329,-878,-3217,11105,2421,-752,1758,6519 } }, { "Fujifilm X-Pro1", 0, 0, { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } }, { "Fujifilm X-Pro2", 0, 0, { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, + { "Fujifilm X-A10", 0, 0, + { 11540,-4999,-991,-2949,10963,2278,-382,1049,5605} }, + + { "Fujifilm X-A20", 0, 0, /* temp */ + { 11540,-4999,-991,-2949,10963,2278,-382,1049,5605} }, + { "Fujifilm X-A1", 0, 0, { 11086,-4555,-839,-3512,11310,2517,-815,1341,5940 } }, { "Fujifilm X-A2", 0, 0, { 10763,-4560,-917,-3346,11311,2322,-475,1135,5843 } }, + { "Fujifilm X-A3", 0, 0, + { 12407,-5222,-1086,-2971,11116,2120,-294,1029,5284 } }, + + { "Fujifilm X-A5", 0, 0, /* temp */ + { 12407,-5222,-1086,-2971,11116,2120,-294,1029,5284 } }, + { "Fujifilm X-E1", 0, 0, { 10413,-3996,-993,-3721,11640,2361,-733,1540,6011 } }, { "Fujifilm X-E2S", 0, 0, { 11562,-5118,-961,-3022,11007,2311,-525,1569,6097 } }, { "Fujifilm X-E2", 0, 0, - { 12066,-5927,-367,-1969,9878,1503,-721,2034,5453 } }, + { 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 } }, + { "Fujifilm X-E3", 0, 0, + { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, { "Fujifilm XF1", 0, 0, { 13509,-6199,-1254,-4430,12733,1865,-331,1441,5022 } }, { "Fujifilm X-M1", 0, 0, - { 13193,-6685,-425,-2229,10458,1534,-878,1763,5217 } }, + { 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-T10", 0, 0, - { 10763,-4560,-917,-3346,11311,2322,-475,1135,5843 } }, + { "Fujifilm X-T20", 0, 0, + { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, + { "Fujifilm X-T2", 0, 0, + { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, + { "Fujifilm X-T10", 0, 0, /* updated */ + { 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 } }, { "Fujifilm X-T1", 0, 0, { 8458,-2451,-855,-4597,12447,2407,-1475,2482,6526 } }, - { "Fujifilm X-T2", 0, 0, + { "Fujifilm X-H1", 0, 0, { 11434,-4948,-1210,-3746,12042,1903,-666,1479,5235 } }, { "Fujifilm XQ1", 0, 0, { 9252,-2704,-1064,-5893,14265,1717,-1101,2341,4349 } }, { "Fujifilm XQ2", 0, 0, { 9252,-2704,-1064,-5893,14265,1717,-1101,2341,4349 } }, + { "Fujifilm GFX 50S", 0, 0, + { 11756,-4754,-874,-3056,11045,2305,-381,1457,6006 } }, + + { "GITUP GIT2P", 4160, 0, + { 8489, -2583,-1036,-8051,15583,2643,-1307,1407,7354 } }, { "GITUP GIT2", 3200, 0, - {8489, -2583,-1036,-8051,15583,2643,-1307,1407,7354}}, + { 8489, -2583,-1036,-8051,15583,2643,-1307,1407,7354 } }, + + { "Hasselblad HV", 0, 0, /* added */ + { 6344,-1612,-461,-4862,12476,2680,-864,1785,6898 } }, { "Hasselblad Lunar", 0, 0, { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, + { "Hasselblad Lusso", 0, 0, /* added */ + { 4912,-540,-201,-6129,13513,2906,-1563,2151,7182 } }, { "Hasselblad Stellar", -800, 0, { 8651,-2754,-1057,-3464,12207,1373,-568,1398,4434 } }, - { "Hasselblad CFV", 0, 0, /* Adobe */ - { 8519, -3260, -280, -5081, 13459, 1738, -1449, 2960, 7809, } }, + { "Hasselblad 500 mech.", 0, 0, /* added */ + { 8519,-3260,-280,-5081,13459,1738,-1449,2960,7809 } }, + { "Hasselblad CFV", 0, 0, + { 8519,-3260,-280,-5081,13459,1738,-1449,2960,7809 } }, { "Hasselblad H-16MP", 0, 0, /* LibRaw */ { 17765,-5322,-1734,-6168,13354,2135,-264,2524,7440 } }, { "Hasselblad H-22MP", 0, 0, /* LibRaw */ { 17765,-5322,-1734,-6168,13354,2135,-264,2524,7440 } }, { "Hasselblad H-31MP",0, 0, /* LibRaw */ { 14480,-5448,-1686,-3534,13123,2260,384,2952,7232 } }, - { "Hasselblad H-39MP",0, 0, /* Adobe */ - { 3857,452, -46, -6008, 14477, 1596, -2627, 4481, 5718 } }, - { "Hasselblad H3D-50", 0, 0, /* Adobe */ - { 3857,452, -46, -6008, 14477, 1596, -2627, 4481, 5718 } }, + { "Hasselblad 39-Coated", 0, 0, /* added */ + { 3857,452,-46,-6008,14477,1596,-2627,4481,5718 } }, + { "Hasselblad H-39MP",0, 0, + { 3857,452,-46,-6008,14477,1596,-2627,4481,5718 } }, + { "Hasselblad H2D-39", 0, 0, /* added */ + { 3894,-110,287,-4672,12610,2295,-2092,4100,6196 } }, + { "Hasselblad H3D-50", 0, 0, + { 3857,452,-46,-6008,14477,1596,-2627,4481,5718 } }, + { "Hasselblad H3D", 0, 0, /* added */ + { 3857,452,-46,-6008,14477,1596,-2627,4481,5718 } }, { "Hasselblad H4D-40",0, 0, /* LibRaw */ { 6325,-860,-957,-6559,15945,266,167,770,5936 } }, { "Hasselblad H4D-50",0, 0, /* LibRaw */ { 15283,-6272,-465,-2030,16031,478,-2379,390,7965 } }, - { "Hasselblad H4D-60",0, 0, /* Adobe */ - { 9662, -684, -279, -4903, 12293, 2950, -344, 1669, 6024 } }, - { "Hasselblad H5D-50c",0, 0, /* Adobe */ - { 4932, -835, 141, -4878, 11868, 3437, -1138, 1961, 7067 } }, - { "Hasselblad H5D-50",0, 0, /* Adobe */ - { 5656, -659, -346, -3923, 12306, 1791, -1602, 3509, 5442 } }, - { "Hasselblad X1D",0, 0, /* Adobe */ - {4932, -835, 141, -4878, 11868, 3437, -1138, 1961, 7067 }}, + { "Hasselblad H4D-60",0, 0, + { 9662,-684,-279,-4903,12293,2950,-344,1669,6024 } }, + { "Hasselblad H5D-50c",0, 0, + { 4932,-835,141,-4878,11868,3437,-1138,1961,7067 } }, + { "Hasselblad H5D-50",0, 0, + { 5656,-659,-346,-3923,12306,1791,-1602,3509,5442 } }, + { "Hasselblad H6D-100c",0, 0, + { 5110,-1357,-308,-5573,12835,3077,-1279,2025,7010 } }, + { "Hasselblad X1D",0, 0, + { 4932,-835,141,-4878,11868,3437,-1138,1961,7067 } }, + { "HTC One A9", 64, 1023, /* this is CM1 transposed */ { 101, -20, -2, -11, 145, 41, -24, 1, 56 } }, - { "Imacon Ixpress", 0, 0, /* DJC */ + + { "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 } }, + { "Photo Control Camerz ZDS 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, + + { "Leaf C-Most", 0, 0, /* updated */ { 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-II 8", 0, 0, /* added */ + { 7361,1257,-163,-6929,14061,3176,-1839,3454,5603 } }, + { "Leaf AFi-II 7", 0, 0, /* added */ + { 7691,-108,-339,-6185,13627,2833,-2046,3899,5952 } }, + { "Leaf Aptus-II 5", 0, 0, /* added */ + { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } }, { "Leaf Aptus 65", 0, 0, { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } }, + { "Leaf AFi 65S", 0, 0, /* added */ + { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } }, { "Leaf Aptus 75", 0, 0, { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } }, + { "Leaf AFi 75S", 0, 0, /* added */ + { 7914,1414,-1190,-8777,16582,2280,-2811,4605,5562 } }, { "Leaf Credo 40", 0, 0, - { 8035, 435, -962, -6001, 13872, 2320, -1159, 3065, 5434 } }, + { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, { "Leaf Credo 50", 0, 0, - { 3984, 0, 0, 0, 10000, 0, 0, 0, 7666 } }, + { 3984,0,0,0,10000,0,0,0,7666 } }, { "Leaf Credo 60", 0, 0, - { 8035, 435, -962, -6001, 13872,2320,-1159,3065,5434 } }, + { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, { "Leaf Credo 80", 0, 0, - { 6294, 686, -712, -5435, 13417, 2211, -1006, 2435, 5042 } }, + { 6294,686,-712,-5435, 13417,2211,-1006,2435,5042 } }, { "Leaf", 0, 0, { 8236,1746,-1314,-8251,15953,2428,-3673,5786,5771 } }, + + { "Leica M10", 0, 0, /* added */ + { 9090,-3342,-740,-4006,13456,493,-569,2266,6871 } }, + { "Leica M9", 0, 0, /* added */ + { 6687,-1751,-291,-3556,11373,2492,-548,2204,7146 } }, + { "Leica M8", 0, 0, /* added */ + { 7675,-2196,-305,-5860,14119,1856,-2425,4006,6578 } }, + { "Leica M (Typ 240)", 0, 0, /* added */ + { 7199,-2140,-712,-4005,13327,649,-810,2521,6673 } }, + { "Leica M (Typ 262)", 0, 0, + { 7199,-2140,-712,-4005,13327,649,-810,2521,6673 } }, + { "Leica SL (Typ 601)", 0, 0, + { 11865,-4523,-1441,-5423,14458,935,-1587,2687,4830} }, + { "Leica S2", 0, 0, /* added */ + { 5627,-721,-447,-4423,12456,2192,-1048,2948,7379 } }, + {"Leica S-E (Typ 006)", 0, 0, /* added */ + { 5749,-1072,-382,-4274,12432,2048,-1166,3104,7105 } }, + {"Leica S (Typ 006)", 0, 0, /* added */ + { 5749,-1072,-382,-4274,12432,2048,-1166,3104,7105 } }, + { "Leica S (Typ 007)", 0, 0, + { 6063,-2234,-231,-5210,13787,1500,-1043,2866,6997 } }, + { "Leica Q (Typ 116)", 0, 0, /* updated */ + { 10068,-4043,-1068,-5319,14268,1044,-765,1701,6522 } }, + { "Leica T (Typ 701)", 0, 0, /* added */ + { 6295 ,-1679 ,-475 ,-5586 ,13046 ,2837 ,-1410 ,1889 ,7075 } }, + { "Leica X2", 0, 0, /* added */ + { 8336,-2853,-699,-4425,11989,2760,-954,1625,6396 } }, + { "Leica X1", 0, 0, /* added */ + { 9055,-2611,-666,-4906,12652,2519,-555,1384,7417 } }, + { "Leica X", 0, 0, /* X(113), X-U(113), XV, X Vario(107) */ /* updated */ + { 9062,-3198,-828,-4065,11772,2603,-761,1468,6458 } }, + + { "Mamiya M31", 0, 0, /* added */ + { 4516 ,-244 ,-36 ,-7020 ,14976 ,2174 ,-3206 ,4670 ,7087 } }, + { "Mamiya M22", 0, 0, /* added */ + { 2905 ,732 ,-237 ,-8135 ,16626 ,1476 ,-3038 ,4253 ,7517 } }, + { "Mamiya M18", 0, 0, /* added */ + { 6516 ,-2050 ,-507 ,-8217 ,16703 ,1479 ,-3492 ,4741 ,8489 } }, { "Mamiya ZD", 0, 0, { 7645,2579,-1363,-8689,16717,2015,-3712,5941,5961 } }, - { "Micron 2010", 110, 0, /* DJC */ + + { "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 5", 0, 0xf7d, /* updated */ + { 9117,-3063,-973,-7949,15763,2306,-2752,3136,8093 } }, + { "Minolta DiMAGE 7Hi", 0, 0xf7d, /* updated */ + { 11555,-4064,-1256,-7903,15633,2409,-2811,3320,7358 } }, + { "Minolta DiMAGE 7i", 0, 0xf7d, /* added */ + { 11050,-3791,-1199,-7875,15585,2434,-2797,3359,7560 } }, + { "Minolta DiMAGE 7", 0, 0xf7d, /* updated */ + { 9258,-2879,-1008,-8076,15847,2351,-2806,3280,7821 } }, + { "Minolta DiMAGE A1", 0, 0xf8b, /* updated */ + { 9274,-2548,-1167,-8220,16324,1943,-2273,2721,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 */ + { "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 Maxxum 5D", 0, 0xffb, /* added */ + { 10284,-3283,-1086,-7957,15762,2316,-829,882,6644 } }, + { "Minolta ALPHA-5 DIGITAL", 0, 0xffb, /* added */ + { 10284,-3283,-1086,-7957,15762,2316,-829,882,6644 } }, + { "Minolta ALPHA SWEET DIGITAL", 0, 0xffb, /* added */ + { 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 */ + { "Minolta Maxxum 7D", 0, 0xffb, /* added */ + { 10239,-3104,-1099,-8037,15727,2451,-927,925,6871 } }, + { "Minolta ALPHA-7 DIGITAL", 0, 0xffb, /* added */ + { 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 D1H", 0, 0, /* updated */ + { 7659,-2238,-935,-8942,16969,2004,-2701,3051,8690 } }, { "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 } }, + { 5733,-911,-629,-7967,15987,2055,-3050,4013,7048 } }, + { "Nikon D2X", 0, 0, /* updated */ + { 10231,-2768,-1254,-8302,15900,2551,-797,681,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 D3400", 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, { 8821,-2938,-785,-4178,12142,2287,-824,1651,6860 } }, + { "Nikon D5600", 0, 0, + { 8821,-2938,-785,-4178,12142,2287,-824,1651,6860 } }, { "Nikon D500", 0, 0, { 8813,-3210,-1036,-4703,12868,2021,-1054,1940,6129 } }, { "Nikon D50", 0, 0, { 7732,-2422,-789,-8238,15884,2498,-859,783,7330 } }, { "Nikon D5", 0, 0, { 9200,-3522,-992,-5755,13803,2117,-753,1486,6338 } }, { "Nikon D600", 0, 0x3e07, { 8178,-2245,-609,-4857,12394,2776,-1207,2086,7298 } }, - { "Nikon D610",0, 0, - { 10426,-4005,-444,-3565,11764,1403,-1206,2266,6549 } }, + { "Nikon D610",0, 0, /* updated */ + { 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 D7200", 0, 0, { 8322,-3112,-1047,-6367,14342,2179,-988,1638,6394 } }, + { "Nikon D7500", 0, 0, + { 8813,-3210,-1036,-4703,12868,2021,-1054,1940,6129 } }, { "Nikon D750", -600, 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 D850", 0, 0, + { 10405,-3755,-1270,-5461,13787,1793,-1040,2015,6785 } }, { "Nikon D810A", 0, 0, - { 11973, -5685, -888, -1965, 10326, 1901, -115, 1123, 7169 } }, + { 11973,-5685,-888,-1965,10326,1901,-115,1123,7169 } }, { "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 */ + { "Nikon E700", 0, 0x3dd, /* DJC */ { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } }, - { "Nikon E800", 0, 0x3dd, /* DJC */ + { "Nikon E800", 0, 0x3dd, /* DJC */ { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } }, - { "Nikon E950", 0, 0x3dd, /* DJC */ + { "Nikon E950", 0, 0x3dd, /* DJC */ { -3746,10611,1665,9621,-1734,2114,-2389,7082,3064,3406,6116,-244 } }, - { "Nikon E995", 0, 0, /* copied from E5000 */ + { "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 */ + { "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 */ + { "Nikon E3200", 0, 0, /* DJC */ { 9846,-2085,-1019,-3278,11109,2170,-774,2134,5745 } }, - { "Nikon E4300", 0, 0, /* copied from Minolta DiMAGE Z2 */ + { "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 E5000", 0, 0, /* updated */ + { -6678,12805,2248,5725,-499,3375,-5903,10713,6034,-270,9976,134 } }, + { "Nikon E5400", 0, 0, /* updated */ + { 9349,-2988,-1001,-7918,15766,2266,-2097,2680,6839 } }, + { "Nikon E5700", 0, 0, /* updated */ + { -6475,12496,2428,5409,-16,3180,-5965,10912,5866,-177,9918,248 } }, { "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 B700", 0, 0, { 14387,-6014,-1299,-1357,9975,1616,467,1047,4744 } }, { "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 Kalon", 0, 0, /* added */ + { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } }, + { "Nikon COOLPIX Deneb", 0, 0, /* added */ + { 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", -3200, 0, { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } }, { "Nikon COOLPIX P7800", -3200, 0, { 10321,-3920,-931,-2750,11146,1824,-442,1545,5539 } }, { "Nikon 1 V3", -200, 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 J5", 0, 0, - { 7520,-2518,-645,-3844,12102,1945,-913,2249,6835} }, + { 7520,-2518,-645,-3844,12102,1945,-913,2249,6835 } }, { "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, - { 8144,-2671,-473,-1740,9834,1601,-58,1971,4296 } }, + { "Nikon 1 J3", 0, 0, /* updated */ + { 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 */ + { "Nikon 1 ", 0, 0, /* J1, J2, S1, V1 */ { 8994,-2667,-865,-4594,12324,2552,-699,1786,6260 } }, + { "Olympus AIR-A01", 0, 0xfe1, { 8992,-3093,-639,-2563,10721,2122,-437,1270,5473 } }, - { "Olympus C5050", 0, 0, - { 10508,-3124,-1273,-6079,14294,1901,-1653,2306,6237 } }, + { "Olympus C5050", 0, 0, /* updated */ + { 10633,-3234,-1285,-7460,15570,1967,-1917,2510,6299 } }, { "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-10", 0, 0xffc, /* updated */ + { 12970,-4703,-1433,-7466,15843,1644,-2191,2451,6668 } }, { "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-20", 0, 0xffc, /* updated */ + { 13414,-4950,-1517,-7166,15293,1960,-2325,2664,7212 } }, { "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-PL8", 0, 0, { 9197,-3190,-659,-2606,10830,2039,-458,1250,5458 } }, + { "Olympus E-PL9", 0, 0, + { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, { "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, /* Same for E-M10MarkII */ + { "Olympus E-M10", 0, 0, /* Same for E-M10MarkII, E-M10MarkIII */ { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, - { "Olympus E-M1MarkII", 0, 0, /* Adobe */ - { 8380, -2630, -639, -2887, 10725, 2496, -627, 1427, 5438 }}, + { "Olympus E-M1MarkII", 0, 0, + { 9383,-3170,-763,-2457,10702,2020,-384,1236,5552 } }, { "Olympus E-M1", 0, 0, { 7687,-1984,-606,-4327,11928,2721,-1381,2339,6452 } }, { "Olympus E-M5MarkII", 0, 0, { 9422,-3258,-711,-2655,10898,2015,-512,1354,5512 } }, { "Olympus E-M5", 0, 0xfe1, { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } }, { "Olympus PEN-F",0, 0, { 9476,-3182,-765,-2613,10958,1893,-449,1315,5268 } }, { "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 SP565UZ", 0, 0, /* added */ + { 11856,-4469,-1159,-4814,12368,2756,-993,1779,5589 } }, { "Olympus SP570UZ", 0, 0, { 11522,-4044,-1146,-4736,12172,2904,-988,1829,6039 } }, { "Olympus SH-2", 0, 0, { 10156,-3425,-1077,-2611,11177,1624,-385,1592,5080 } }, { "Olympus SH-3", 0, 0, /* Alias of SH-2 */ { 10156,-3425,-1077,-2611,11177,1624,-385,1592,5080 } }, - { "Olympus STYLUS1",0, 0, - { 11976,-5518,-545,-1419,10472,846,-475,1766,4524 } }, + { "Olympus STYLUS1",0, 0, /* updated */ + { 8360,-2420,-880,-3928,12353,1739,-1381,2416,5173 } }, { "Olympus TG-4", 0, 0, { 11426,-4159,-1126,-2066,10678,1593,-120,1327,4998 } }, + { "Olympus TG-5", 0, 0, + { 10899,-3833,-1082,-2112,10736,1575,-267,1452,5269 } }, { "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", 16, 0x3ff, { 12782,-4059,-379,-478,9066,1413,1340,1513,5176 } }, /* DJC */ + { "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 GR", 0, 0, /* added */ + { 5329,-1459,-390,-5407,12930,2768,-1119,1772,6046 } }, + { "Pentax K-01", 0, 0, /* added */ + { 8134,-2728,-645,-4365,11987,2694,-838,1509,6498 } }, + { "Pentax K10D", 0, 0, /* updated */ + { 9679,-2965,-811,-8622,16514,2182,-975,883,9793 } }, { "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 K2000", 0, 0, /* updated */ + { 9730,-2989,-970,-8527,16258,2381,-1060,970,8362 } }, + { "Pentax K-m", 0, 0, /* updated */ + { 9730,-2989,-970,-8527,16258,2381,-1060,970,8362 } }, + { "Pentax KP", 0, 0, + { 7825,-2160,-1403,-4841,13555,1349,-1559,2449,5814 } }, { "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-1", 0, 0, - { 8566,-2746,-1201,-3612,12204,1550,-893,1680,6264 } }, - { "Pentax K-30", 0, 0, - { 8710,-2632,-1167,-3995,12301,1881,-981,1719,6535 } }, - { "Pentax K-3 II", 0, 0, - { 8626,-2607,-1155,-3995,12301,1881,-1039,1822,6925 } }, + { "Pentax K-1", 0, 0, /* updated */ + { 8596,-2981,-639,-4202,12046,2431,-685,1424,6122 } }, + { "Pentax K-30", 0, 0, /* updated */ + { 8134,-2728,-645,-4365,11987,2694,-838,1509,6498 } }, + { "Pentax K-3 II", 0, 0, /* updated */ + { 7415,-2052,-721,-5186,12788,2682,-1446,2157,6773 } }, { "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-500", 0, 0, /* added */ + { 8109,-2740,-608,-4593,12175,2731,-1006,1515,6545 } }, + { "Pentax K-50", 0, 0, /* added */ + { 8109,-2740,-608,-4593,12175,2731,-1006,1515,6545 } }, { "Pentax K-5", 0, 0, { 8713,-2833,-743,-4342,11900,2772,-722,1543,6247 } }, { "Pentax K-70", 0, 0, - {8766, -3149, -747, -3976, 11943, 2292, -517, 1259, 5552 }}, + { 8766,-3149,-747,-3976,11943,2292,-517,1259,5552 } }, { "Pentax K-7", 0, 0, { 9142,-2947,-678,-8648,16967,1663,-2224,2898,8615 } }, + { "Pentax KP", 0, 0, /* temp */ + { 8626,-2607,-1155,-3995,12301,1881,-1039,1822,6925 } }, { "Pentax K-S1", 0, 0, { 8512,-3211,-787,-4167,11966,2487,-638,1288,6054 } }, { "Pentax K-S2", 0, 0, { 8662,-3280,-798,-3928,11771,2444,-586,1232,6054 } }, { "Pentax Q-S1", 0, 0, { 12995,-5593,-1107,-1879,10139,2027,-64,1233,4919 } }, - { "Pentax MX-1", 0, 0, - { 8804,-2523,-1238,-2423,11627,860,-682,1774,4753 } }, - { "Pentax Q10", 0, 0, - { 12995,-5593,-1107,-1879,10139,2027,-64,1233,4919 } }, + { "Pentax Q7", 0, 0, /* added */ + { 10901,-3938,-1025,-2743,11210,1738,-823,1805,5344 } }, + { "Pentax Q10", 0, 0, /* updated */ + { 11562,-4183,-1172,-2357,10919,1641,-582,1726,5112 } }, + { "Pentax Q", 0, 0, /* added */ + { 11731,-4169,-1267,-2015,10727,1473,-217,1492,4870 } }, + { "Pentax MX-1", 0, 0, /* updated */ + { 9296,-3146,-888,-2860,11287,1783,-618,1698,5151 } }, { "Pentax 645D", 0, 0x3e00, { 10646,-3593,-1158,-3329,11699,1831,-667,2874,6287 } }, - { "Pentax 645Z", 0, 0, /* Adobe */ - { 9702, -3060, -1254, -3685, 12133, 1721, -1086, 2010, 6971}}, + { "Pentax 645Z", 0, 0, /* updated */ + { 9519,-3591,-664,-4074,11725,2671,-624,1501,6653 } }, + { "Panasonic DMC-CM10", -15, 0, - { 8770, -3194,-820,-2871,11281,1803,-513,1552,4434 } }, + { 8770,-3194,-820,-2871,11281,1803,-513,1552,4434 } }, { "Panasonic DMC-CM1", -15, 0, - { 8770, -3194,-820,-2871,11281,1803,-513,1552,4434 } }, + { 8770,-3194,-820,-2871,11281,1803,-513,1552,4434 } }, + { "Panasonic DC-FZ82", -15, 0, /* markets: FZ80 FZ82 */ + { 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 } }, + { "Panasonic DC-FZ80", -15, 0, /* markets: FZ80 FZ82 */ + { 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 } }, { "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-FZ300", -15, 0xfff, { 8378,-2798,-769,-3068,11410,1877,-538,1792,4623 } }, - { "Panasonic DMC-FZ330", -15, 0xfff, // same as FZ300 + { "Panasonic DMC-FZ330", -15, 0xfff, { 8378,-2798,-769,-3068,11410,1877,-538,1792,4623 } }, { "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, + { "Panasonic DMC-FZ4", -15, 0, /* 40,42,45 */ { 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 } }, + { "Leica V-LUX 1", 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 DIGILUX3", 0, 0xf7f, /* added */ + { 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 DIGILUX2", 0, 0, /* added */ + { 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-LX9", -15, 0, /* markets: LX9 LX10 LX15 */ - { 7790, -2736, -755, -3452, 11870, 1769, -628, 1647, 4898 }}, /* Adobe*/ - { "Panasonic DMC-LX10", -15, 0, /* markets: LX9 LX10 LX15 */ - { 7790, -2736, -755, -3452, 11870, 1769, -628, 1647, 4898 }}, /* Adobe*/ - { "Panasonic DMC-LX15", -15, 0, /* markets: LX9 LX10 LX15 */ - { 7790, -2736, -755, -3452, 11870, 1769, -628, 1647, 4898 }}, /* Adobe*/ - + { "Panasonic DMC-LX9", -15, 0, /* markets: LX9 LX10 LX15 */ + { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } }, + { "Panasonic DMC-LX10", -15, 0, /* markets: LX9 LX10 LX15 */ + { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } }, + { "Panasonic DMC-LX15", -15, 0, /* markets: LX9 LX10 LX15 */ + { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } }, { "Panasonic DMC-LX1", 0, 0xf7f, { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } }, { "Leica D-Lux (Typ 109)", 0, 0xf7f, { 8844,-3538,-768,-3709,11762,2200,-698,1792,5220 } }, { "Leica D-LUX2", 0, 0xf7f, { 10704,-4187,-1230,-8314,15952,2501,-920,945,8927 } }, + { "Leica D-LUX 2", 0, 0xf7f, /* added */ + { 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 } }, + { "Leica D-LUX 3", 0, 0, /* added */ + { 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-FZ2000", -15, 0, /* markets: DMC-FZ2000,DMC-FZ2500,FZH1 */ - { 7386, -2443, -743, -3437, 11864, 1757, -608, 1660, 4766 }}, + { "Panasonic DMC-FZ2000", -15, 0, /* markets: DMC-FZ2000, DMC-FZ2500 ,FZH1 */ + { 7386,-2443,-743,-3437,11864,1757,-608,1660,4766 } }, { "Panasonic DMC-FZ2500", -15, 0, - { 7386, -2443, -743, -3437, 11864, 1757, -608, 1660, 4766 }}, + { 7386,-2443,-743,-3437,11864,1757,-608,1660,4766 } }, { "Panasonic DMC-FZH1", -15, 0, - { 7386, -2443, -743, -3437, 11864, 1757, -608, 1660, 4766 }}, + { 7386,-2443,-743,-3437,11864,1757,-608,1660,4766 } }, { "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-FX180", -15, 0xfff, /* added */ + { 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-G7", -15, 0xfff, { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, - { "Panasonic DMC-G8", -15, 0xfff, /* markets: DMC-G8, DMC-G80, DMC-G81, DMC-G85 */ + { "Panasonic DMC-G8", -15, 0xfff, /* markets: DMC-G8, DMC-G80, DMC-G81, DMC-G85 */ { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, + { "Panasonic DC-G9", -15, 0, + { 7685,-2375,-634,-3687,11700,2249,-748,1546,5111 } }, { "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, { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, { "Panasonic DMC-GF8", -15, 0, { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, { "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 AG-GH4", -15, 0, /* added */ + { 7122,-2108,-512,-3155,11201,2231,-541,1423,5045 } }, + {"Panasonic DC-GH5s", -15, 0, + { 6929,-2355,-708,-4192,12534,1828,-1097,1989,5195 } }, + { "Panasonic DC-GH5", -15, 0, + { 7641,-2336,-605,-3218,11299,2187,-485,1338,5121 } }, { "Yuneec CGO4", -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-GX85", -15, 0, /* markets: GX85 GX80 GX7MK2 */ - { 7771,-3020,-629,4029,11950,2345,-821,1977,6119 } }, - { "Panasonic DMC-GX80", -15, 0, /* markets: GX85 GX80 GX7MK2 */ - { 7771,-3020,-629,4029,11950,2345,-821,1977,6119 } }, - { "Panasonic DMC-GX7MK2", -15, 0, /* markets: GX85 GX80 GX7MK2 */ - { 7771,-3020,-629,4029,11950,2345,-821,1977,6119 } }, + + { "Panasonic DC-GF10", -15, 0, /* temp, markets: GF10, GF90 */ + { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, + { "Panasonic DC-GF90", -15, 0, /* temp, markets: GF10, GF90 */ + { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, + + { "Panasonic DC-GX850", -15, 0, /* markets: GX850 GX800 GF9 */ + { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, + { "Panasonic DC-GX800", -15, 0, /* markets: GX850 GX800 GF9 */ + { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, + { "Panasonic DC-GF9", -15, 0, /* markets: GX850 GX800 GF9 */ + { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, + { "Panasonic DMC-GX85", -15, 0, /* markets: GX85 GX80 GX7MK2 */ + { 7771,-3020,-629,-4029,11950,2345,-821,1977,6119 } }, + { "Panasonic DMC-GX80", -15, 0, /* markets: GX85 GX80 GX7MK2 */ + { 7771,-3020,-629,-4029,11950,2345,-821,1977,6119 } }, + { "Panasonic DMC-GX7MK2", -15, 0, /* markets: GX85 GX80 GX7MK2 */ + { 7771,-3020,-629,-4029,11950,2345,-821,1977,6119 } }, { "Panasonic DMC-GX7", -15,0, { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } }, { "Panasonic DMC-GX8", -15,0, { 7564,-2263,-606,-3148,11239,2177,-540,1435,4853 } }, + + { "Panasonic DC-GX9", -15, 0, /* temp */ + { 7685,-2375,-634,-3687,11700,2249,-748,1546,5111 } }, + { "Panasonic DMC-TZ6", -15, 0, /* markets: ZS40 TZ60 TZ61 */ { 8607,-2822,-808,-3755,11930,2049,-820,2060,5224 } }, - { "Panasonic DMC-TZ8", -15, 0, /* markets: ZS60 TZ80 TZ81 TZ85 */ + { "Panasonic DMC-TZ8", -15, 0, /* markets: ZS60 TZ80 TZ81 TZ82 TZ85 */ { 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 } }, - { "Panasonic DMC-ZS4", -15, 0, /* markets: ZS40 TZ60 TZ61 */ + { "Panasonic DC-TZ90", -15, 0, /* markets: ZS70 TZ90 TZ91 TZ92 T93 */ + { 9052,-3117,-883,-3045,11346,1927,-205,1520,4730 } }, + { "Panasonic DC-TZ91", -15, 0, /* markets: ZS70 TZ90 TZ91 TZ92 T93 */ + { 9052,-3117,-883,-3045,11346,1927,-205,1520,4730 } }, + { "Panasonic DC-TZ92", -15, 0, /* markets: ZS70 TZ90 TZ91 TZ92 T93 */ + { 9052,-3117,-883,-3045,11346,1927,-205,1520,4730 } }, + { "Panasonic DC-T93", -15, 0, /* markets: ZS70 TZ90 TZ91 TZ92 T93 */ + { 9052,-3117,-883,-3045,11346,1927,-205,1520,4730 } }, + { "Panasonic DMC-ZS4", -15, 0, /* markets: ZS40 TZ60 TZ61 */ { 8607,-2822,-808,-3755,11930,2049,-820,2060,5224 } }, - { "Panasonic DMC-TZ7", -15, 0, /* markets: ZS50 TZ70 TZ71 */ + { "Panasonic DMC-TZ7", -15, 0, /* markets: ZS50 TZ70 TZ71 */ { 8802,-3135,-789,-3151,11468,1904,-550,1745,4810 } }, - { "Panasonic DMC-ZS5", -15, 0, /* markets: ZS50 TZ70 TZ71 */ + { "Panasonic DMC-ZS5", -15, 0, /* markets: ZS50 TZ70 TZ71 */ { 8802,-3135,-789,-3151,11468,1904,-550,1745,4810 } }, - { "Panasonic DMC-ZS6", -15, 0, /* markets: ZS60 TZ80 TZ81 TZ85 */ + { "Panasonic DMC-ZS6", -15, 0, /* markets: ZS60 TZ80 TZ81 TZ85 */ { 8550,-2908,-842,-3195,11529,1881,-338,1603,4631 } }, - { "Panasonic DMC-ZS100", -15, 0, /* markets: ZS100 ZS110 TZ100 TZ101 TZ110 TX1 */ + { "Panasonic DC-ZS70", -15, 0, /* markets: ZS70 TZ90 TZ91 TZ92 T93 */ + { 9052,-3117,-883,-3045,11346,1927,-205,1520,4730 } }, + { "Panasonic DMC-ZS100", -15, 0, /* markets: ZS100 ZS110 TZ100 TZ101 TZ110 TX1 */ { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } }, - { "Panasonic DMC-ZS110", -15, 0, /* markets: ZS100 ZS110 TZ100 TZ101 TZ110 TX1 */ + { "Panasonic DMC-ZS110", -15, 0, /* markets: ZS100 ZS110 TZ100 TZ101 TZ110 TX1 */ { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } }, - { "Panasonic DMC-TZ100", -15, 0, /* markets: ZS100 ZS110 TZ100 TZ101 TZ110 TX1 */ + { "Panasonic DMC-TZ100", -15, 0, /* markets: ZS100 ZS110 TZ100 TZ101 TZ110 TX1 */ { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } }, - { "Panasonic DMC-TZ101", -15, 0, /* markets: ZS100 ZS110 TZ100 TZ101 TZ110 TX1 */ + { "Panasonic DMC-TZ101", -15, 0, /* markets: ZS100 ZS110 TZ100 TZ101 TZ110 TX1 */ { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } }, - { "Panasonic DMC-TZ110", -15, 0, /* markets: ZS100 ZS110 TZ100 TZ101 TZ110 TX1 */ + { "Panasonic DMC-TZ110", -15, 0, /* markets: ZS100 ZS110 TZ100 TZ101 TZ110 TX1 */ { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } }, - { "Panasonic DMC-TX1", -15, 0, /* markets: ZS100 ZS110 TZ100 TZ101 TZ110 TX1 */ + { "Panasonic DMC-TX1", -15, 0, /* markets: ZS100 ZS110 TZ100 TZ101 TZ110 TX1 */ { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } }, - { "Leica S (Typ 007)", 0, 0, - { 6063,-2234,-231,-5210,13787,1500,-1043,2866,6997 } }, - { "Leica X", 0, 0, /* X and X-U, both (Typ 113) */ - { 7712,-2059,-653,-3882,11494,2726,-710,1332,5958 } }, - { "Leica Q (Typ 116)", 0, 0, - { 11865,-4523,-1441,-5423,14458,935,-1587,2687,4830 } }, - { "Leica M (Typ 262)", 0, 0, - { 6653,-1486,-611,-4221,13303,929,-881,2416,7226 } }, - { "Leica SL (Typ 601)", 0, 0, - { 11865,-4523,-1441,-5423,14458,935,-1587,2687,4830} }, - { "Phase One H 20", 0, 0, /* DJC */ + + { "Panasonic DC-ZS200", -15, 0, /* temp, markets: ZS200 TZ200 */ + { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } }, + { "Panasonic DC-TZ200", -15, 0, /* temp, markets: ZS200 TZ200 */ + { 7790,-2736,-755,-3452,11870,1769,-628,1647,4898 } }, + + { "Phase One H 20", 0, 0, /* DJC */ + { 1313,1855,-109,-6715,15908,808,-327,1840,6020 } }, + { "Phase One H20", 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 IQ250",0, 0, - { 4396,-153,-249,-5267,12249,2657,-1397,2323,6014 } }, - { "Phase One P 2", 0, 0, + { "Phase One H25", 0, 0, /* added */ { 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, + { "Phase One IQ280", 0, 0, /* added */ + { 6294,686,-712,-5435,13417,2211,-1006,2435,5042 } }, + { "Phase One IQ260", 0, 0, /* added */ + { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, + { "Phase One IQ250",0, 0, +// {3984,0,0,0,10000,0,0,0,7666}}, + {10325,845,-604,-4113,13385,481,-1791,4163,6924}}, /* emb */ + { "Phase One IQ180", 0, 0, /* added */ + { 6294,686,-712,-5435,13417,2211,-1006,2435,5042 } }, + { "Phase One IQ160", 0, 0, /* added */ + { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, + { "Phase One IQ150", 0, 0, /* added */ + {10325,845,-604,-4113,13385,481,-1791,4163,6924}}, /* temp */ /* emb */ +// { 3984,0,0,0,10000,0,0,0,7666 } }, + { "Phase One IQ140", 0, 0, /* added */ { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, { "Phase One P65", 0, 0, { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, - { "Photron BC2-HD", 0, 0, /* DJC */ + { "Phase One P 65", 0, 0, + { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, + { "Phase One P45", 0, 0, /* added */ + { 5053,-24,-117,-5685,14077,1703,-2619,4491,5850 } }, + { "Phase One P 45", 0, 0, /* added */ + { 5053,-24,-117,-5685,14077,1703,-2619,4491,5850 } }, + { "Phase One P40", 0, 0, + { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, + { "Phase One P 40", 0, 0, + { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, + { "Phase One P30", 0, 0, /* added */ + { 4516,-244,-36,-7020,14976,2174,-3206,4670,7087 } }, + { "Phase One P 30", 0, 0, /* added */ + { 4516,-244,-36,-7020,14976,2174,-3206,4670,7087 } }, + { "Phase One P25", 0, 0, /* added */ + { 2905,732,-237,-8135,16626,1476,-3038,4253,7517 } }, + { "Phase One P 25", 0, 0, /* added */ + { 2905,732,-237,-8135,16626,1476,-3038,4253,7517 } }, + { "Phase One P21", 0, 0, /* added */ + { 6516,-2050,-507,-8217,16703,1479,-3492,4741,8489 } }, + { "Phase One P 21", 0, 0, /* added */ + { 6516,-2050,-507,-8217,16703,1479,-3492,4741,8489 } }, + { "Phase One P20", 0, 0, /* added */ + { 2905,732,-237,-8135,16626,1476,-3038,4253,7517 } }, + { "Phase One P20", 0, 0, /* added */ + { 2905,732,-237,-8135,16626,1476,-3038,4253,7517 } }, + { "Phase One P 2", 0, 0, + { 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } }, + { "Phase One P2", 0, 0, + { 2905,732,-237,-8134,16626,1476,-3038,4253,7517 } }, + { "Phase One IQ3 100MP", 0, 0, /* added */ +// {2423,0,0,0,9901,0,0,0,7989}}, + { 10999,354,-742,-4590,13342,937,-1060,2166,8120} }, /* emb */ + { "Phase One IQ3 80MP", 0, 0, /* added */ + { 6294,686,-712,-5435,13417,2211,-1006,2435,5042 } }, + { "Phase One IQ3 60MP", 0, 0, /* added */ + { 8035,435,-962,-6001,13872,2320,-1159,3065,5434 } }, + { "Phase One IQ3 50MP", 0, 0, /* added */ +// { 3984,0,0,0,10000,0,0,0,7666 } }, + {10058,1079,-587,-4135,12903,944,-916,2726,7480}}, /* emb */ + { "Photron BC2-HD", 0, 0, /* DJC */ { 14603,-4122,-528,-1810,9794,2017,-297,2763,5936 } }, - { "Red One", 704, 0xffff, /* DJC */ + + { "Polaroid x530", 0, 0, + { 13458,-2556,-510,-5444,15081,205,0,0,12120 } }, + + { "Red One", 704, 0xffff, /* DJC */ { 21014,-7891,-2613,-3056,12201,856,-2203,5125,8042 } }, + + { "Ricoh S10 24-72mm F2.5-4.4 VC", 0, 0, /* added */ + { 10531,-4043,-878,-2038,10270,2052,-107,895,4577 } }, + { "Ricoh GR A12 50mm F2.5 MACRO", 0, 0, /* added */ + { 8849,-2560,-689,-5092,12831,2520,-507,1280,7104 } }, + { "Ricoh GR DIGITAL 3", 0, 0, /* added */ + { 8170,-2496,-655,-5147,13056,2312,-1367,1859,5265 } }, + { "Ricoh GR DIGITAL 4", 0, 0, /* added */ + { 8771,-3151,-837,-3097,11015,2389,-703,1343,4924 } }, { "Ricoh GR II", 0, 0, { 4630,-834,-423,-4977,12805,2417,-638,1467,6115 } }, { "Ricoh GR", 0, 0, - { 3708,-543,-160,-5381,12254,3556,-1471,1929,8234 } }, - { "Samsung EK-GN120", 0, 0, /* Adobe; Galaxy NX */ + { 3708,-543,-160,-5381,12254,3556,-1471,1929,8234 } }, + { "Ricoh GX200", 0, 0, /* added */ + { 8040,-2368,-626,-4659,12543,2363,-1125,1581,5660 } }, + { "Ricoh RICOH GX200", 0, 0, /* added */ + { 8040,-2368,-626,-4659,12543,2363,-1125,1581,5660 } }, + { "Ricoh GXR MOUNT A12", 0, 0, /* added */ + { 7834,-2182,-739,-5453,13409,2241,-952,2005,6620 } }, + { "Ricoh GXR A16", 0, 0, /* added */ + { 7837,-2538,-730,-4370,12184,2461,-868,1648,5830 } }, + { "Ricoh GXR A12", 0, 0, /* added */ + { 10228,-3159,-933,-5304,13158,2371,-943,1873,6685 } }, + + { "Samsung EK-GN100", 0, 0, /* added */ /* Galaxy NX */ + { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } }, + { "Samsung EK-GN110", 0, 0, /* added */ /* Galaxy NX */ + { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } }, + { "Samsung EK-GN120", 0, 0, /* Galaxy NX */ + { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } }, + { "Samsung EK-KN120", 0, 0, /* added */ /* Galaxy NX */ { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } }, { "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 Galaxy S7 Edge", 0, 0, /* added */ + { 9927,-3704,-1024,-3935,12758,1257,-389,1512,4993 } }, + { "Samsung Galaxy S7", 0, 0, /* added */ + { 9927,-3704,-1024,-3935,12758,1257,-389,1512,4993 } }, + { "Samsung Galaxy NX", 0, 0, /* added */ + { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } }, + { "Samsung NX U", 0, 0, /* added */ + { 7557,-2522,-739,-4679,12949,1894,-840,1777,5311 } }, { "Samsung NX mini", 0, 0, { 5222,-1196,-550,-6540,14649,2009,-1666,2819,5657 } }, - { "Samsung NX3300", 0, 0, /* same as NX3000 */ + { "Samsung NX3300", 0, 0, { 8060,-2933,-761,-4504,12890,1762,-630,1489,5227 } }, { "Samsung NX3000", 0, 0, { 8060,-2933,-761,-4504,12890,1762,-630,1489,5227 } }, - { "Samsung NX30", 0, 0, /* NX30, NX300, NX300M */ + { "Samsung NX30", 0, 0, /* used for 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 */ + { "Samsung NX2", 0, 0xfff, /* used for 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 */ + { "Samsung NX10", 0, 0, /* used for NX10/NX100 */ { 10332,-3234,-1168,-6111,14639,1520,-1352,2647,8331 } }, { "Samsung NX500", 0, 0, { 10686,-4042,-1052,-3595,13238,276,-464,1259,5931 } }, { "Samsung NX5", 0, 0, { 10332,-3234,-1168,-6111,14639,1520,-1352,2647,8331 } }, { "Samsung NX1", 0, 0, { 10686,-4042,-1052,-3595,13238,276,-464,1259,5931 } }, + { "Samsung NXF1", 0, 0, /* added */ + { 5222,-1196,-550,-6540,14649,2009,-1666,2819,5657 } }, { "Samsung WB2000", 0, 0xfff, { 12093,-3557,-1155,-1000,9534,1733,-22,1787,4576 } }, - { "Samsung GX-1", 0, 0, + { "Samsung GX10", 0, 0, /* added */ /* Pentax K10D */ + { 9679,-2965,-811,-8622,16514,2182,-975,883,9793 } }, + { "Samsung GX-10", 0, 0, /* added */ /* Pentax K10D */ + { 9679,-2965,-811,-8622,16514,2182,-975,883,9793 } }, + { "Samsung GX-1", 0, 0, /* used for GX-1L/GX-1S */ { 10504,-2438,-1189,-8603,16207,2531,-1022,863,12242 } }, - { "Samsung GX20", 0, 0, /* copied from Pentax K20D */ + { "Samsung GX20", 0, 0, /* copied from Pentax K20D */ { 9427,-2714,-868,-7493,16092,1373,-2199,3264,7180 } }, - { "Samsung S85", 0, 0, /* DJC */ + { "Samsung GX-20", 0, 0, /* added */ /* 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 } }, - // Foveon: LibRaw color data + +// Foveon: LibRaw color data { "Sigma dp0 Quattro", 2047, 0, { 13801,-3390,-1016,5535,3802,877,1848,4245,3730 } }, { "Sigma dp1 Quattro", 2047, 0, { 13801,-3390,-1016,5535,3802,877,1848,4245,3730 } }, { "Sigma dp2 Quattro", 2047, 0, { 13801,-3390,-1016,5535,3802,877,1848,4245,3730 } }, { "Sigma dp3 Quattro", 2047, 0, { 13801,-3390,-1016,5535,3802,877,1848,4245,3730 } }, - { "Sigma sd Quattro H", 256, 0, - {1295,108,-311, 256,828,-65,-28,750,254}}, /* temp, same as sd Quattro */ + { "Sigma sd Quattro H", 256, 0, + { 1295,108,-311, 256,828,-65,-28,750,254 } }, /* temp */ { "Sigma sd Quattro", 2047, 0, - {1295,108,-311, 256,828,-65,-28,750,254}}, /* temp */ - { "Sigma SD9", 15, 4095, /* LibRaw */ - { 14082,-2201,-1056,-5243,14788,167,-121,196,8881 } }, - { "Sigma SD10", 15, 16383, /* LibRaw */ - { 14082,-2201,-1056,-5243,14788,167,-121,196,8881 } }, - { "Sigma SD14", 15, 16383, /* LibRaw */ - { 14082,-2201,-1056,-5243,14788,167,-121,196,8881 } }, - { "Sigma SD15", 15, 4095, /* LibRaw */ - { 14082,-2201,-1056,-5243,14788,167,-121,196,8881 } }, - // Merills + SD1 - { "Sigma SD1", 31, 4095, /* LibRaw */ + { 1295,108,-311, 256,828,-65,-28,750,254 } }, /* temp */ + { "Sigma SD9", 15, 4095, /* updated */ + { 13564,-2537,-751,-5465,15154,194,-67,116,10425 } }, + { "Sigma SD10", 15, 16383, /* updated */ + { 6787,-1682,575,-3091,8357,160,217,-369,12314 } }, + { "Sigma SD14", 15, 16383, /* updated */ + { 13589,-2509,-739,-5440,15104,193,-61,105,10554 } }, + { "Sigma SD15", 15, 4095, /* updated */ + { 13556,-2537,-730,-5462,15144,195,-61,106,10577 } }, +// Merills + SD1 + { "Sigma SD1", 31, 4095, /* LibRaw */ { 5133,-1895,-353,4978,744,144,3837,3069,2777 } }, - { "Sigma DP1 Merrill", 31, 4095, /* LibRaw */ + { "Sigma DP1 Merrill", 31, 4095, /* LibRaw */ { 5133,-1895,-353,4978,744,144,3837,3069,2777 } }, - { "Sigma DP2 Merrill", 31, 4095, /* LibRaw */ + { "Sigma DP2 Merrill", 31, 4095, /* LibRaw */ { 5133,-1895,-353,4978,744,144,3837,3069,2777 } }, - { "Sigma DP3 Merrill", 31, 4095, /* LibRaw */ + { "Sigma DP3 Merrill", 31, 4095, /* LibRaw */ { 5133,-1895,-353,4978,744,144,3837,3069,2777 } }, - // Sigma DP (non-Merill Versions) - { "Sigma DP", 0, 4095, /* LibRaw */ +// Sigma DP (non-Merill Versions) + { "Sigma DP1X", 0, 4095, /* updated */ + { 13704,-2452,-857,-5413,15073,186,-89,151,9820 } }, + { "Sigma DP1", 0, 4095, /* updated */ + { 12774,-2591,-394,-5333,14676,207,15,-21,12127 } }, + { "Sigma DP", 0, 4095, /* LibRaw */ // { 7401,-1169,-567,2059,3769,1510,664,3367,5328 } }, { 13100,-3638,-847,6855,2369,580,2723,3218,3251 } }, - { "Sinar", 0, 0, /* DJC */ + + { "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", 0, 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-RX100M5", -800, 0, /* Adobe */ - {6596, -2079, -562, -4782, 13016, 1933, -970, 1581, 5181 }}, - { "Sony DSC-RX100M", -800, 0, /* M2 and M3 and M4 */ + {"Sony DSC-RX100M5", -800, 0, + { 6596,-2079,-562,-4782,13016,1933,-970,1581,5181 } }, + { "Sony DSC-RX100M", -800, 0, /* used for M2/M3/M4 */ { 6596,-2079,-562,-4782,13016,1933,-970,1581,5181 } }, { "Sony DSC-RX100", 0, 0, { 8651,-2754,-1057,-3464,12207,1373,-568,1398,4434 } }, - { "Sony DSC-RX10",0, 0, /* And M2/M3 too */ + {"Sony DSC-RX10M4", -800, 0, + { 7699,-2566,-629,-2967,11270,1928,-378,1286,4807 } }, + { "Sony DSC-RX10",0, 0, /* same for M2/M3 */ { 6679,-1825,-745,-5047,13256,1953,-1580,2422,5183 } }, { "Sony DSC-RX1RM2", 0, 0, { 6629,-1900,-483,-4618,12349,2550,-622,1381,6514 } }, - { "Sony DSC-RX1R", 0, 0, - { 8195,-2800,-422,-4261,12273,1709,-1505,2400,5624 } }, + { "Sony DSC-RX1R", 0, 0, /* updated */ + { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } }, { "Sony DSC-RX1", 0, 0, { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } }, + + {"Sony DSC-RX0", -800, 0, /* temp */ + { 9396,-3507,-843,-2497,11111,1572,-343,1355,5089 } }, + { "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", 0, 0xfeb, { 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } }, - { "Sony DSLR-A580", 0, 0xfeb, + { "Sony DSLR-A580", 0, 16596, { 5932,-1492,-411,-4813,12285,2856,-741,1524,6739 } }, - { "Sony DSLR-A500", 0, 0xfeb, + { "Sony DSLR-A500", 0, 16596, { 6046,-1127,-278,-5574,13076,2786,-691,1419,7625 } }, - { "Sony DSLR-A5", 0, 0xfeb, + { "Sony DSLR-A550", 0, 16596, + { 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } }, + { "Sony DSLR-A5", 0, 0xfeb, /* Is there any cameras not covered above? */ { 4950,-580,-103,-5228,12542,3029,-709,1435,7371 } }, { "Sony DSLR-A700", 0, 0, { 5775,-805,-359,-8574,16295,2391,-1943,2341,7249 } }, { "Sony DSLR-A850", 0, 0, { 5413,-1162,-365,-5665,13098,2866,-608,1179,8440 } }, { "Sony DSLR-A900", 0, 0, { 5209,-1072,-397,-8845,16120,2919,-1618,1803,8654 } }, { "Sony ILCA-68", 0, 0, { 6435,-1903,-536,-4722,12449,2550,-663,1363,6517 } }, { "Sony ILCA-77M2", 0, 0, { 5991,-1732,-443,-4100,11989,2381,-704,1467,5992 } }, - { "Sony ILCA-99M2", 0, 0, /* Adobe */ - { 6660, -1918, -471, -4613, 12398, 2485, -649, 1433, 6447}}, + { "Sony ILCA-99M2", 0, 0, + { 6660,-1918,-471,-4613,12398,2485,-649,1433,6447 } }, + { "Sony ILCE-9", 0, 0, + { 6389,-1703,-378,-4562,12265,2587,-670,1489,6550 } }, { "Sony ILCE-7M2", 0, 0, { 5271,-712,-347,-6153,13653,2763,-1601,2366,7242 } }, { "Sony ILCE-7SM2", 0, 0, { 5838,-1430,-246,-3497,11477,2297,-748,1885,5778 } }, { "Sony ILCE-7S", 0, 0, { 5838,-1430,-246,-3497,11477,2297,-748,1885,5778 } }, + { "Sony ILCE-7RM3", 0, 0, + { 6640,-1847,-503,-5238,13010,2474,-993,1673,6527 } }, { "Sony ILCE-7RM2", 0, 0, { 6629,-1900,-483,-4618,12349,2550,-622,1381,6514 } }, { "Sony ILCE-7R", 0, 0, { 4913,-541,-202,-6130,13513,2906,-1564,2151,7183 } }, { "Sony ILCE-7", 0, 0, { 5271,-712,-347,-6153,13653,2763,-1601,2366,7242 } }, { "Sony ILCE-6300", 0, 0, { 5973,-1695,-419,-3826,11797,2293,-639,1398,5789 } }, - { "Sony ILCE-6500", 0, 0, /* Adobe */ + { "Sony ILCE-6500", 0, 0, { 5973,-1695,-419,-3826,11797,2293,-639,1398,5789 } }, - { "Sony ILCE", 0, 0, /* 3000, 5000, 5100, 6000, and QX1 */ + { "Sony ILCE", 0, 0, /* 3000, 5000, 5100, 6000, and QX1 */ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, + { "Sony MODEL-NAME", 0, 0, /* added */ + { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, { "Sony NEX-5N", 0, 0, { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, { "Sony NEX-5R", 0, 0, { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, { "Sony NEX-5T", 0, 0, { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, { "Sony NEX-3N", 0, 0, { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, - { "Sony NEX-3", 0, 0, /* Adobe */ + { "Sony NEX-3", 0, 0, { 6549,-1550,-436,-4880,12435,2753,-854,1868,6976 } }, - { "Sony NEX-5", 0, 0, /* Adobe */ + { "Sony NEX-5", 0, 0, { 6549,-1550,-436,-4880,12435,2753,-854,1868,6976 } }, { "Sony NEX-6", 0, 0, { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, { "Sony NEX-7", 0, 0, { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, - { "Sony NEX", 0, 0, /* NEX-C3, NEX-F3 */ + { "Sony NEX-VG30", 0, 0, /* added */ + { 6129,-1545,-418,-4930,12490,2743,-977,1693,6615 } }, + { "Sony NEX-VG900", 0, 0, /* added */ + { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } }, + { "Sony NEX", 0, 0, /* NEX-C3, NEX-F3, NEX-VG20 */ { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, { "Sony SLT-A33", 0, 0, { 6069,-1221,-366,-5221,12779,2734,-1024,2066,6834 } }, { "Sony SLT-A35", 0, 0, { 5986,-1618,-415,-4557,11820,3120,-681,1404,6971 } }, { "Sony SLT-A37", 0, 0, { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, { "Sony SLT-A55", 0, 0, { 5932,-1492,-411,-4813,12285,2856,-741,1524,6739 } }, { "Sony SLT-A57", 0, 0, { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, { "Sony SLT-A58", 0, 0, { 5991,-1456,-455,-4764,12135,2980,-707,1425,6701 } }, { "Sony SLT-A65", 0, 0, { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, { "Sony SLT-A77", 0, 0, { 5491,-1192,-363,-4951,12342,2948,-911,1722,7192 } }, { "Sony SLT-A99", 0, 0, { 6344,-1612,-462,-4863,12477,2681,-865,1786,6899 } }, }; + // clang-format on + double cam_xyz[4][3]; char name[130]; int i, j; - if(colors>4 || colors < 1) return; + if (colors > 4 || colors < 1) + return; - int bl4=(cblack[0]+cblack[1]+cblack[2]+cblack[3])/4,bl64=0; - if(cblack[4]*cblack[5]>0) + int bl4 = (cblack[0] + cblack[1] + cblack[2] + cblack[3]) / 4, bl64 = 0; + if (cblack[4] * cblack[5] > 0) { - for (unsigned c = 0; c < 4096 && c < cblack[4]*cblack[5]; c++) - bl64+=cblack[c+6]; - bl64 /= cblack[4]*cblack[5]; + for (unsigned c = 0; c < 4096 && c < cblack[4] * cblack[5]; c++) + bl64 += cblack[c + 6]; + bl64 /= cblack[4] * cblack[5]; } - int rblack = black+bl4+bl64; + int rblack = black + bl4 + bl64; - sprintf (name, "%s %s", t_make, t_model); - for (i=0; i < sizeof table / sizeof *table; i++) - if (!strncasecmp(name, table[i].prefix, strlen(table[i].prefix))) { - if(!dng_version) - { - if (table[i].t_black>0) - { - black = (ushort) table[i].t_black; - memset(cblack,0,sizeof(cblack)); - } - else if(table[i].t_black <0 && rblack == 0 ) - { - black = (ushort) (-table[i].t_black); - memset(cblack,0,sizeof(cblack)); - } - if (table[i].t_maximum) - maximum = (ushort) table[i].t_maximum; - } - if (table[i].trans[0]) { - for (raw_color = j=0; j < 12; j++) + sprintf(name, "%s %s", t_make, t_model); + for (i = 0; i < sizeof table / sizeof *table; i++) + if (!strncasecmp(name, table[i].prefix, strlen(table[i].prefix))) + { + if (!dng_version) + { + if (table[i].t_black > 0) + { + black = (ushort)table[i].t_black; + memset(cblack, 0, sizeof(cblack)); + } + else if (table[i].t_black < 0 && rblack == 0) + { + black = (ushort)(-table[i].t_black); + memset(cblack, 0, sizeof(cblack)); + } + if (table[i].t_maximum) + maximum = (ushort)table[i].t_maximum; + } + if (table[i].trans[0]) + { + for (raw_color = j = 0; j < 12; j++) #ifdef LIBRAW_LIBRARY_BUILD - if(internal_only) - imgdata.color.cam_xyz[0][j] = table[i].trans[j] / 10000.0; - else - imgdata.color.cam_xyz[0][j] = + if (internal_only) + imgdata.color.cam_xyz[0][j] = table[i].trans[j] / 10000.0; + else + imgdata.color.cam_xyz[0][j] = #endif - ((double*)cam_xyz)[j] = table[i].trans[j] / 10000.0; + ((double *)cam_xyz)[j] = table[i].trans[j] / 10000.0; #ifdef LIBRAW_LIBRARY_BUILD - if(!internal_only) + if (!internal_only) #endif - cam_xyz_coeff (rgb_cam, cam_xyz); + cam_xyz_coeff(rgb_cam, cam_xyz); } break; } } -void CLASS simple_coeff (int index) +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 } - }; + 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]; + 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) +short CLASS guess_byte_order(int words) { uchar test[4][2]; - int t=2, msb; - double diff, sum[2] = {0,0}; + 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; + 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; + t = (t + 1) & 3; } return sum[0] < sum[1] ? 0x4d4d : 0x4949; } -float CLASS find_green (int bps, int bite, int off0, int off1) +float CLASS find_green(int bps, int bite, int off0, int off1) { - UINT64 bitbuf=0; + UINT64 bitbuf = 0; int vbits, col, i, c; ushort img[2][2064]; double sum[] = {0, 0}; if(width > 2064) return 0.f; // too wide - 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); + 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); + 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]); + 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]); + return 100 * log(sum[0] / sum[1]); } #ifdef LIBRAW_LIBRARY_BUILD static void remove_trailing_spaces(char *string, size_t len) { if (len < 1) return; // not needed, b/c sizeof of make/model is 64 string[len - 1] = 0; if (len < 3) return; // also not needed len = strnlen(string, len - 1); for (int i = len - 1; i >= 0; i--) { if (isspace((unsigned char)string[i])) string[i] = 0; else break; } } +void CLASS initdata() +{ + 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); + for (int i = 0; i < LIBRAW_IFD_MAXCOUNT; i++) + { + tiff_ifd[i].dng_color[0].illuminant = tiff_ifd[i].dng_color[1].illuminant = 0xffff; + for (int c = 0; c < 4; c++) + tiff_ifd[i].dng_levels.analogbalance[c] = 1.0f; + } + for (int i = 0; i < 0x10000; i++) + curve[i] = i; + 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; +} #endif /* 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 }, + {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 }, /* EOS M */ - { 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 }, - { 6096, 4056, 72, 34, 0, 0 }, /* EOS M3 */ - { 6288, 4056, 266, 36, 0, 0 }, /* EOS 80D */ - { 6880, 4544, 136, 42, 0, 0 }, /* EOS 5D4 */ - { 8896, 5920, 160, 64, 0, 0 }, + {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}, /* EOS M */ + {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}, + {6096, 4056, 72, 34, 0, 0}, /* EOS M3 */ + {6288, 4056, 266, 36, 0, 0}, /* EOS 80D */ + {6384, 4224, 120, 44, 0, 0}, /* 6D II */ + {6880, 4544, 136, 42, 0, 0}, /* EOS 5D4 */ + {8896, 5920, 160, 64, 0, 0}, }; - static const struct { + static const struct + { ushort id; char t_model[20]; - } unique[] = { - { 0x001, "EOS-1D" }, - { 0x167, "EOS-1DS" }, - { 0x168, "EOS 10D" }, - { 0x169, "EOS-1D Mark III" }, - { 0x170, "EOS 300D" }, - { 0x174, "EOS-1D Mark II" }, - { 0x175, "EOS 20D" }, - { 0x176, "EOS 450D" }, - { 0x188, "EOS-1Ds Mark II" }, - { 0x189, "EOS 350D" }, - { 0x190, "EOS 40D" }, - { 0x213, "EOS 5D" }, - { 0x215, "EOS-1Ds Mark III" }, - { 0x218, "EOS 5D Mark II" }, - { 0x232, "EOS-1D Mark II N" }, - { 0x234, "EOS 30D" }, - { 0x236, "EOS 400D" }, - { 0x250, "EOS 7D" }, - { 0x252, "EOS 500D" }, - { 0x254, "EOS 1000D" }, - { 0x261, "EOS 50D" }, - { 0x269, "EOS-1D X" }, - { 0x270, "EOS 550D" }, - { 0x281, "EOS-1D Mark IV" }, - { 0x285, "EOS 5D Mark III" }, - { 0x286, "EOS 600D" }, - { 0x287, "EOS 60D" }, - { 0x288, "EOS 1100D" }, - { 0x289, "EOS 7D Mark II" }, - { 0x301, "EOS 650D" }, - { 0x302, "EOS 6D" }, - { 0x324, "EOS-1D C" }, - { 0x325, "EOS 70D" }, - { 0x326, "EOS 700D" }, - { 0x327, "EOS 1200D" }, - { 0x328, "EOS-1D X Mark II" }, - { 0x331, "EOS M" }, - { 0x335, "EOS M2" }, - { 0x374, "EOS M3"}, /* temp */ - { 0x384, "EOS M10"}, /* temp */ - { 0x394, "EOS M5"}, /* temp */ - { 0x346, "EOS 100D" }, - { 0x347, "EOS 760D" }, - { 0x349, "EOS 5D Mark IV" }, - { 0x350, "EOS 80D"}, - { 0x382, "EOS 5DS" }, - { 0x393, "EOS 750D" }, - { 0x401, "EOS 5DS R" }, - { 0x404, "EOS 1300D" }, - }, sonique[] = { - { 0x002, "DSC-R1" }, - { 0x100, "DSLR-A100" }, - { 0x101, "DSLR-A900" }, - { 0x102, "DSLR-A700" }, - { 0x103, "DSLR-A200" }, - { 0x104, "DSLR-A350" }, - { 0x105, "DSLR-A300" }, - { 0x106, "DSLR-A900" }, - { 0x107, "DSLR-A380" }, - { 0x108, "DSLR-A330" }, - { 0x109, "DSLR-A230" }, - { 0x10a, "DSLR-A290" }, - { 0x10d, "DSLR-A850" }, - { 0x10e, "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" }, - { 0x122, "NEX-VG20E"}, - { 0x123, "SLT-A37" }, - { 0x124, "SLT-A57" }, - { 0x125, "NEX-F3" }, - { 0x126, "SLT-A99V" }, - { 0x127, "NEX-6" }, - { 0x128, "NEX-5R" }, - { 0x129, "DSC-RX100" }, - { 0x12a, "DSC-RX1" }, - { 0x12b, "NEX-VG900" }, - { 0x12c, "NEX-VG30E" }, - { 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" }, - { 0x155, "DSC-RX100M4" }, - { 0x156, "DSC-RX10M2" }, - { 0x158, "DSC-RX1RM2" }, - { 0x15a, "ILCE-QX1" }, - { 0x15b, "ILCE-7RM2" }, - { 0x15e, "ILCE-7SM2" }, - { 0x161, "ILCA-68" }, - { 0x162, "ILCA-99M2" }, - { 0x163, "DSC-RX10M3" }, - { 0x164, "DSC-RX100M5"}, - { 0x165, "ILCE-6300" }, - { 0x168, "ILCE-6500"}, - }; - -#ifdef LIBRAW_LIBRARY_BUILD - static const libraw_custom_camera_t - const_table[] + } unique[] = + { + {0x001, "EOS-1D"}, + {0x167, "EOS-1DS"}, + {0x168, "EOS 10D"}, + {0x169, "EOS-1D Mark III"}, + {0x170, "EOS 300D"}, + {0x174, "EOS-1D Mark II"}, + {0x175, "EOS 20D"}, + {0x176, "EOS 450D"}, + {0x188, "EOS-1Ds Mark II"}, + {0x189, "EOS 350D"}, + {0x190, "EOS 40D"}, + {0x213, "EOS 5D"}, + {0x215, "EOS-1Ds Mark III"}, + {0x218, "EOS 5D Mark II"}, + {0x232, "EOS-1D Mark II N"}, + {0x234, "EOS 30D"}, + {0x236, "EOS 400D"}, + {0x250, "EOS 7D"}, + {0x252, "EOS 500D"}, + {0x254, "EOS 1000D"}, + {0x261, "EOS 50D"}, + {0x269, "EOS-1D X"}, + {0x270, "EOS 550D"}, + {0x281, "EOS-1D Mark IV"}, + {0x285, "EOS 5D Mark III"}, + {0x286, "EOS 600D"}, + {0x287, "EOS 60D"}, + {0x288, "EOS 1100D"}, + {0x289, "EOS 7D Mark II"}, + {0x301, "EOS 650D"}, + {0x302, "EOS 6D"}, + {0x324, "EOS-1D C"}, + {0x325, "EOS 70D"}, + {0x326, "EOS 700D"}, + {0x327, "EOS 1200D"}, + {0x328, "EOS-1D X Mark II"}, + {0x331, "EOS M"}, + {0x335, "EOS M2"}, + {0x374, "EOS M3"}, /* temp */ + {0x384, "EOS M10"}, /* temp */ + {0x394, "EOS M5"}, /* temp */ + {0x398, "EOS M100"}, /* temp */ + {0x346, "EOS 100D"}, + {0x347, "EOS 760D"}, + {0x349, "EOS 5D Mark IV"}, + {0x350, "EOS 80D"}, + {0x382, "EOS 5DS"}, + {0x393, "EOS 750D"}, + {0x401, "EOS 5DS R"}, + {0x404, "EOS 1300D"}, + {0x405, "EOS 800D"}, + {0x406, "EOS 6D Mark II"}, + {0x407, "EOS M6"}, + {0x408, "EOS 77D"}, + {0x417, "EOS 200D"}, + }, + sonique[] = { + {0x002, "DSC-R1"}, {0x100, "DSLR-A100"}, {0x101, "DSLR-A900"}, {0x102, "DSLR-A700"}, + {0x103, "DSLR-A200"}, {0x104, "DSLR-A350"}, {0x105, "DSLR-A300"}, {0x106, "DSLR-A900"}, + {0x107, "DSLR-A380"}, {0x108, "DSLR-A330"}, {0x109, "DSLR-A230"}, {0x10a, "DSLR-A290"}, + {0x10d, "DSLR-A850"}, {0x10e, "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"}, {0x122, "NEX-VG20E"}, {0x123, "SLT-A37"}, {0x124, "SLT-A57"}, + {0x125, "NEX-F3"}, {0x126, "SLT-A99V"}, {0x127, "NEX-6"}, {0x128, "NEX-5R"}, + {0x129, "DSC-RX100"}, {0x12a, "DSC-RX1"}, {0x12b, "NEX-VG900"}, {0x12c, "NEX-VG30E"}, + {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"}, + {0x155, "DSC-RX100M4"}, {0x156, "DSC-RX10M2"}, {0x158, "DSC-RX1RM2"}, {0x15a, "ILCE-QX1"}, + {0x15b, "ILCE-7RM2"}, {0x15e, "ILCE-7SM2"}, {0x161, "ILCA-68"}, {0x162, "ILCA-99M2"}, + {0x163, "DSC-RX10M3"}, {0x164, "DSC-RX100M5"}, {0x165, "ILCE-6300"}, {0x166, "ILCE-9"}, + {0x168, "ILCE-6500"}, {0x16a, "ILCE-7RM3"}, {0x16c, "DSC-RX0"}, {0x16d, "DSC-RX10M4"}, + }; + +#ifdef LIBRAW_LIBRARY_BUILD + static const libraw_custom_camera_t const_table[] #else - static const struct { + static const struct + { unsigned fsize; ushort rw, rh; uchar lm, tm, rm, bm, lf, cf, max, flags; char t_make[10], t_model[20]; ushort offset; - } - table[] -#endif - = { - { 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" }, - { 31850496,4608,3456, 0, 0, 0, 0,0,0x94,0,0,"GITUP","GIT2 4:3" }, - { 23887872,4608,2592, 0, 0, 0, 0,0,0x94,0,0,"GITUP","GIT2 16:9" }, -// Android Raw dumps id start -// File Size in bytes Horizontal Res Vertical Flag then bayer order eg 0x16 bbgr 0x94 rggb - { 1540857,2688,1520, 0, 0, 0, 0, 1,0x61,0,0,"Samsung","S3" }, - { 2658304,1212,1096, 0, 0, 0, 0, 1 ,0x16,0,0,"LG","G3FrontMipi" }, - { 2842624,1296,1096, 0, 0, 0, 0, 1 ,0x16,0,0,"LG","G3FrontQCOM" }, - { 2969600,1976,1200, 0, 0, 0, 0, 1 ,0x16,0,0,"Xiaomi","MI3wMipi" }, - { 3170304,1976,1200, 0, 0, 0, 0, 1 ,0x16,0,0,"Xiaomi","MI3wQCOM" }, - { 3763584,1584,1184, 0, 0, 0, 0, 96,0x61,0,0,"I_Mobile","I_StyleQ6" }, - { 5107712,2688,1520, 0, 0, 0, 0, 1 ,0x61,0,0,"OmniVisi","UltraPixel1" }, - { 5382640,2688,1520, 0, 0, 0, 0, 1 ,0x61,0,0,"OmniVisi","UltraPixel2" }, - { 5664912,2688,1520, 0, 0, 0, 0, 1 ,0x61,0,0,"OmniVisi","4688" }, - { 5664912,2688,1520, 0, 0, 0, 0, 1 ,0x61,0,0,"OmniVisi","4688" }, - { 5364240,2688,1520, 0, 0, 0, 0, 1 ,0x61,0,0,"OmniVisi","4688" }, - { 6299648,2592,1944, 0, 0, 0, 0, 1 ,0x16,0,0,"OmniVisi","OV5648" }, - { 6721536,2592,1944, 0, 0, 0, 0, 0 ,0x16,0,0,"OmniVisi","OV56482" }, - { 6746112,2592,1944, 0, 0, 0, 0, 0 ,0x16,0,0,"HTC","OneSV" }, - { 9631728,2532,1902, 0, 0, 0, 0, 96,0x61,0,0,"Sony","5mp" }, - { 9830400,2560,1920, 0, 0, 0, 0, 96,0x61,0,0,"NGM","ForwardArt" }, - { 10186752,3264,2448, 0, 0, 0, 0, 1,0x94,0,0,"Sony","IMX219-mipi 8mp" }, - { 10223360,2608,1944, 0, 0, 0, 0, 96,0x16,0,0,"Sony","IMX" }, - { 10782464,3282,2448, 0, 0, 0, 0, 0 ,0x16,0,0,"HTC","MyTouch4GSlide" }, - { 10788864,3282,2448, 0, 0, 0, 0, 0, 0x16,0,0,"Xperia","L" }, - { 15967488,3264,2446, 0, 0, 0, 0, 96,0x16,0,0,"OmniVison","OV8850" }, - { 16224256,4208,3082, 0, 0, 0, 0, 1, 0x16,0,0,"LG","G3MipiL" }, - { 16424960,4208,3120, 0, 0, 0, 0, 1, 0x16,0,0,"IMX135","MipiL" }, - { 17326080,4164,3120, 0, 0, 0, 0, 1, 0x16,0,0,"LG","G3LQCom" }, - { 17522688,4212,3120, 0, 0, 0, 0, 0,0x16,0,0,"Sony","IMX135-QCOM" }, - { 19906560,4608,3456, 0, 0, 0, 0, 1, 0x16,0,0,"Gione","E7mipi" }, - { 19976192,5312,2988, 0, 0, 0, 0, 1, 0x16,0,0,"LG","G4" }, - { 20389888,4632,3480, 0, 0, 0, 0, 1, 0x16,0,0,"Xiaomi","RedmiNote3Pro" }, - { 20500480,4656,3496, 0, 0, 0, 0, 1,0x94,0,0,"Sony","IMX298-mipi 16mp" }, - { 21233664,4608,3456, 0, 0, 0, 0, 1, 0x16,0,0,"Gione","E7qcom" }, - { 26023936,4192,3104, 0, 0, 0, 0, 96,0x94,0,0,"THL","5000" }, - { 26257920,4208,3120, 0, 0, 0, 0, 96,0x94,0,0,"Sony","IMX214" }, - { 26357760,4224,3120, 0, 0, 0, 0, 96,0x61,0,0,"OV","13860" }, - { 41312256,5248,3936, 0, 0, 0, 0, 96,0x61,0,0,"Meizu","MX4" }, - { 42923008,5344,4016, 0, 0, 0, 0, 96,0x61,0,0,"Sony","IMX230" }, - // Android Raw dumps id end - { 20137344,3664,2748,0, 0, 0, 0,0x40,0x49,0,0,"Aptina","MT9J003",0xffff }, - { 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,0x49,0,2,"Canon","PowerShot A3300 IS" }, - { 30858240,5248,3920, 8,16,56,16,40,0x94,0,2,"Canon","IXUS 160" }, - { 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" }, - { 4147200,1920,1080, 0, 0, 0, 0, 0,0x49,0,0,"Photron","BC2-HD" }, - { 4151666,1920,1080, 0, 0, 0, 0, 0,0x49,0,0,"Photron","BC2-HD",8 }, - { 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" }, - }; -#ifdef LIBRAW_LIBRARY_BUILD - libraw_custom_camera_t - table[64 + sizeof(const_table)/sizeof(const_table[0])]; -#endif - - 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" }; + } table[] +#endif + = { + {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"}, + {31850496, 4608, 3456, 0, 0, 0, 0, 0, 0x94, 0, 0, "GITUP", "GIT2 4:3"}, + {23887872, 4608, 2592, 0, 0, 0, 0, 0, 0x94, 0, 0, "GITUP", "GIT2 16:9"}, + {32257024, 4624, 3488, 8, 2, 16, 2, 0, 0x94, 0, 0, "GITUP", "GIT2P 4:3"}, + // Android Raw dumps id start + // File Size in bytes Horizontal Res Vertical Flag then bayer order eg 0x16 bbgr 0x94 rggb + {1540857, 2688, 1520, 0, 0, 0, 0, 1, 0x61, 0, 0, "Samsung", "S3"}, + {2658304, 1212, 1096, 0, 0, 0, 0, 1, 0x16, 0, 0, "LG", "G3FrontMipi"}, + {2842624, 1296, 1096, 0, 0, 0, 0, 1, 0x16, 0, 0, "LG", "G3FrontQCOM"}, + {2969600, 1976, 1200, 0, 0, 0, 0, 1, 0x16, 0, 0, "Xiaomi", "MI3wMipi"}, + {3170304, 1976, 1200, 0, 0, 0, 0, 1, 0x16, 0, 0, "Xiaomi", "MI3wQCOM"}, + {3763584, 1584, 1184, 0, 0, 0, 0, 96, 0x61, 0, 0, "I_Mobile", "I_StyleQ6"}, + {5107712, 2688, 1520, 0, 0, 0, 0, 1, 0x61, 0, 0, "OmniVisi", "UltraPixel1"}, + {5382640, 2688, 1520, 0, 0, 0, 0, 1, 0x61, 0, 0, "OmniVisi", "UltraPixel2"}, + {5664912, 2688, 1520, 0, 0, 0, 0, 1, 0x61, 0, 0, "OmniVisi", "4688"}, + {5664912, 2688, 1520, 0, 0, 0, 0, 1, 0x61, 0, 0, "OmniVisi", "4688"}, + {5364240, 2688, 1520, 0, 0, 0, 0, 1, 0x61, 0, 0, "OmniVisi", "4688"}, + {6299648, 2592, 1944, 0, 0, 0, 0, 1, 0x16, 0, 0, "OmniVisi", "OV5648"}, + {6721536, 2592, 1944, 0, 0, 0, 0, 0, 0x16, 0, 0, "OmniVisi", "OV56482"}, + {6746112, 2592, 1944, 0, 0, 0, 0, 0, 0x16, 0, 0, "HTC", "OneSV"}, + {9631728, 2532, 1902, 0, 0, 0, 0, 96, 0x61, 0, 0, "Sony", "5mp"}, + {9830400, 2560, 1920, 0, 0, 0, 0, 96, 0x61, 0, 0, "NGM", "ForwardArt"}, + {10186752, 3264, 2448, 0, 0, 0, 0, 1, 0x94, 0, 0, "Sony", "IMX219-mipi 8mp"}, + {10223360, 2608, 1944, 0, 0, 0, 0, 96, 0x16, 0, 0, "Sony", "IMX"}, + {10782464, 3282, 2448, 0, 0, 0, 0, 0, 0x16, 0, 0, "HTC", "MyTouch4GSlide"}, + {10788864, 3282, 2448, 0, 0, 0, 0, 0, 0x16, 0, 0, "Xperia", "L"}, + {15967488, 3264, 2446, 0, 0, 0, 0, 96, 0x16, 0, 0, "OmniVison", "OV8850"}, + {16224256, 4208, 3082, 0, 0, 0, 0, 1, 0x16, 0, 0, "LG", "G3MipiL"}, + {16424960, 4208, 3120, 0, 0, 0, 0, 1, 0x16, 0, 0, "IMX135", "MipiL"}, + {17326080, 4164, 3120, 0, 0, 0, 0, 1, 0x16, 0, 0, "LG", "G3LQCom"}, + {17522688, 4212, 3120, 0, 0, 0, 0, 0, 0x16, 0, 0, "Sony", "IMX135-QCOM"}, + {19906560, 4608, 3456, 0, 0, 0, 0, 1, 0x16, 0, 0, "Gione", "E7mipi"}, + {19976192, 5312, 2988, 0, 0, 0, 0, 1, 0x16, 0, 0, "LG", "G4"}, + {20389888, 4632, 3480, 0, 0, 0, 0, 1, 0x16, 0, 0, "Xiaomi", "RedmiNote3Pro"}, + {20500480, 4656, 3496, 0, 0, 0, 0, 1, 0x94, 0, 0, "Sony", "IMX298-mipi 16mp"}, + {21233664, 4608, 3456, 0, 0, 0, 0, 1, 0x16, 0, 0, "Gione", "E7qcom"}, + {26023936, 4192, 3104, 0, 0, 0, 0, 96, 0x94, 0, 0, "THL", "5000"}, + {26257920, 4208, 3120, 0, 0, 0, 0, 96, 0x94, 0, 0, "Sony", "IMX214"}, + {26357760, 4224, 3120, 0, 0, 0, 0, 96, 0x61, 0, 0, "OV", "13860"}, + {41312256, 5248, 3936, 0, 0, 0, 0, 96, 0x61, 0, 0, "Meizu", "MX4"}, + {42923008, 5344, 4016, 0, 0, 0, 0, 96, 0x61, 0, 0, "Sony", "IMX230"}, + // Android Raw dumps id end + {20137344, 3664, 2748, 0, 0, 0, 0, 0x40, 0x49, 0, 0, "Aptina", "MT9J003", 0xffff}, + {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"}, + {18763488, 4104, 3048, 10, 22, 82, 22, 8, 0x49, 0, 0, "Canon", "PowerShot D10"}, + {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, 0x49, 0, 2, "Canon", "PowerShot A3300 IS"}, + {30858240, 5248, 3920, 8, 16, 56, 16, 40, 0x94, 0, 2, "Canon", "IXUS 160"}, + {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"}, + {4147200, 1920, 1080, 0, 0, 0, 0, 0, 0x49, 0, 0, "Photron", "BC2-HD"}, + {4151666, 1920, 1080, 0, 0, 0, 0, 0, 0x49, 0, 0, "Photron", "BC2-HD", 8}, + {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"}, + }; +#ifdef LIBRAW_LIBRARY_BUILD + libraw_custom_camera_t table[64 + sizeof(const_table) / sizeof(const_table[0])]; +#endif + + 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"}; #ifdef LIBRAW_LIBRARY_BUILD char head[64], *cp; #else char head[32], *cp; #endif - int hlen, flen, fsize, zero_fsize=1, i, c; + int hlen, flen, fsize, zero_fsize = 1, i, c; struct jhead jh; #ifdef LIBRAW_LIBRARY_BUILD - unsigned camera_count = parse_custom_cameras(64,table,imgdata.params.custom_camera_strings); - for(int q = 0; q < sizeof(const_table)/sizeof(const_table[0]); q++) - memmove(&table[q+camera_count],&const_table[q],sizeof(const_table[0])); - camera_count += sizeof(const_table)/sizeof(const_table[0]); + unsigned camera_count = parse_custom_cameras(64, table, imgdata.params.custom_camera_strings); + for (int q = 0; q < sizeof(const_table) / sizeof(const_table[0]); q++) + memmove(&table[q + camera_count], &const_table[q], sizeof(const_table[0])); + camera_count += sizeof(const_table) / sizeof(const_table[0]); #endif - tiff_flip = flip = filters = UINT_MAX; /* unknown */ + 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); + memset(tiff_ifd, 0, sizeof tiff_ifd); + +#ifdef LIBRAW_LIBRARY_BUILD + imgdata.other.CameraTemperature = imgdata.other.SensorTemperature = imgdata.other.SensorTemperature2 = + imgdata.other.LensTemperature = imgdata.other.AmbientTemperature = imgdata.other.BatteryTemperature = + imgdata.other.exifAmbientTemperature = -1000.0f; + + for (i = 0; i < LIBRAW_IFD_MAXCOUNT; i++) + { + tiff_ifd[i].dng_color[0].illuminant = tiff_ifd[i].dng_color[1].illuminant = 0xffff; + for (int c = 0; c < 4; c++) + tiff_ifd[i].dng_levels.analogbalance[c] = 1.0f; + } +#endif + 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++) { + 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; + for (i = 0; i < 0x10000; i++) + curve[i] = i; order = get2(); hlen = get4(); - fseek (ifp, 0, SEEK_SET); + fseek(ifp, 0, SEEK_SET); #ifdef LIBRAW_LIBRARY_BUILD - fread (head, 1, 64, ifp); + if(fread(head, 1, 64, ifp) < 64) throw LIBRAW_EXCEPTION_IO_CORRUPT; libraw_internal_data.unpacker_data.lenRAFData = libraw_internal_data.unpacker_data.posRAFData = 0; #else - fread (head, 1, 32, ifp); + fread(head, 1, 32, ifp); #endif - fseek (ifp, 0, SEEK_END); + fseek(ifp, 0, SEEK_END); flen = fsize = ftell(ifp); - if ((cp = (char *) memmem (head, 32, (char*)"MMMM", 4)) || - (cp = (char *) memmem (head, 32, (char*)"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)) { + if ((cp = (char *)memmem(head, 32, (char *)"MMMM", 4)) || (cp = (char *)memmem(head, 32, (char *)"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; #ifdef LIBRAW_LIBRARY_BUILD imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; #endif - parse_ciff (hlen, flen-hlen, 0); + 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); + } + 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); + 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); + } + else if (!memcmp(head + 25, "ARECOYK", 7)) + { + strcpy(make, "Contax"); + strcpy(model, "N Digital"); + fseek(ifp, 33, SEEK_SET); get_timestamp(1); - fseek (ifp, 52, SEEK_SET); - switch (get4()) { - case 7: iso_speed = 25; break; - case 8: iso_speed = 32; break; - case 9: iso_speed = 40; break; - case 10: iso_speed = 50; break; - case 11: iso_speed = 64; break; - case 12: iso_speed = 80; break; - case 13: iso_speed = 100; break; - case 14: iso_speed = 125; break; - case 15: iso_speed = 160; break; - case 16: iso_speed = 200; break; - case 17: iso_speed = 250; break; - case 18: iso_speed = 320; break; - case 19: iso_speed = 400; break; - } - shutter = libraw_powf64(2.0f, (((float)get4())/8.0f)) / 16000.0f; + fseek(ifp, 52, SEEK_SET); + switch (get4()) + { + case 7: + iso_speed = 25; + break; + case 8: + iso_speed = 32; + break; + case 9: + iso_speed = 40; + break; + case 10: + iso_speed = 50; + break; + case 11: + iso_speed = 64; + break; + case 12: + iso_speed = 80; + break; + case 13: + iso_speed = 100; + break; + case 14: + iso_speed = 125; + break; + case 15: + iso_speed = 160; + break; + case 16: + iso_speed = 200; + break; + case 17: + iso_speed = 250; + break; + case 18: + iso_speed = 320; + break; + case 19: + iso_speed = 400; + break; + } + shutter = libraw_powf64l(2.0f, (((float)get4()) / 8.0f)) / 16000.0f; FORC4 cam_mul[c ^ (c >> 1)] = get4(); - fseek (ifp, 88, SEEK_SET); - aperture = libraw_powf64(2.0f, ((float)get4())/16.0f); - fseek (ifp, 112, SEEK_SET); + fseek(ifp, 88, SEEK_SET); + aperture = libraw_powf64l(2.0f, ((float)get4()) / 16.0f); + fseek(ifp, 112, SEEK_SET); focal_len = get4(); #ifdef LIBRAW_LIBRARY_BUILD - fseek (ifp, 104, SEEK_SET); - imgdata.lens.makernotes.MaxAp4CurFocal = libraw_powf64(2.0f, ((float)get4())/16.0f); - fseek (ifp, 124, SEEK_SET); + fseek(ifp, 104, SEEK_SET); + imgdata.lens.makernotes.MaxAp4CurFocal = libraw_powf64l(2.0f, ((float)get4()) / 16.0f); + fseek(ifp, 124, SEEK_SET); stmread(imgdata.lens.makernotes.Lens, 32, ifp); imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_Contax_N; if (imgdata.lens.makernotes.Lens[0]) imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_Contax_N; #endif - } else if (!strcmp (head, "PXN")) { - strcpy (make, "Logitech"); - strcpy (model,"Fotoman Pixtura"); - } else if (!strcmp (head, "qktk")) { - strcpy (make, "Apple"); - strcpy (model,"QuickTake 100"); + } + else if (!strcmp(head, "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"); + } + 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)) { + } + else if (!memcmp(head, "FUJIFILM", 8)) + { #ifdef LIBRAW_LIBRARY_BUILD - strcpy(model, head+0x1c); - memcpy(model2, head+0x3c, 4); - model2[4]=0; + strncpy(model, head + 0x1c,0x20); + model[0x20]=0; + memcpy(model2, head + 0x3c, 4); + model2[4] = 0; #endif - fseek (ifp, 84, SEEK_SET); + 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:0; + fseek(ifp, 92, SEEK_SET); + parse_fuji(get4()); + if (thumb_offset > 120) + { + fseek(ifp, 120, SEEK_SET); + is_raw += (i = get4()) ? 1 : 0; if (is_raw == 2 && shot_select) - parse_fuji (i); + 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); + 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); + } + 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); + } + 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); + } + 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"); + } + else if (!memcmp(head, "NOKIARAW", 8)) + { + strcpy(make, "NOKIA"); order = 0x4949; - fseek (ifp, 300, SEEK_SET); + fseek(ifp, 300, SEEK_SET); data_offset = get4(); - i = get4(); + i = get4(); // bytes count width = get2(); height = get2(); #ifdef LIBRAW_LIBRARY_BUILD - // data length should be in range w*h..w*h*2 - if(width*height < (LIBRAW_MAX_ALLOC_MB*1024*512L) && width*height>1 - && i >= width * height && i <= width*height*2) - { -#endif - 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; break; -#ifdef LIBRAW_LIBRARY_BUILD - case 0: throw LIBRAW_EXCEPTION_IO_CORRUPT; break; -#endif - } - raw_height = height + (top_margin = i / (width * tiff_bps/8) - height); - mask[0][3] = 1; - filters = 0x61616161; -#ifdef LIBRAW_LIBRARY_BUILD - } - else - is_raw = 0; + // Data integrity check + if (width < 1 || width > 16000 || height < 1 || height > 16000 || i < (width * height) || i > (2 * width * height)) + throw LIBRAW_EXCEPTION_IO_CORRUPT; #endif - } else if (!memcmp (head,"ARRI",4)) { + 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; + break; + case 0: + throw LIBRAW_EXCEPTION_IO_CORRUPT; + break; + } + 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); + fseek(ifp, 20, SEEK_SET); width = get4(); height = get4(); - strcpy (make, "ARRI"); - fseek (ifp, 668, SEEK_SET); - fread (model, 1, 64, ifp); + 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)) { + } + else if (!memcmp(head, "XPDS", 4)) + { order = 0x4949; - fseek (ifp, 0x800, SEEK_SET); - fread (make, 1, 41, ifp); + 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); + 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"); + 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); + gamma_curve(1 / 2.4, 12.92, 1, 4095); filters = 0x49494949; - } else if (!memcmp (head,"DSC-Image",9)) + } + else if (!memcmp(head, "DSC-Image", 9)) parse_rollei(); - else if (!memcmp (head,"PWAD",4)) + else if (!memcmp(head, "PWAD", 4)) parse_sinar_ia(); - else if (!memcmp (head,"\0MRM",4)) + else if (!memcmp(head, "\0MRM", 4)) parse_minolta(0); - else if (!memcmp (head,"FOVb",4)) - { + else if (!memcmp(head, "FOVb", 4)) + { #ifdef LIBRAW_LIBRARY_BUILD -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 - if(!(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_FORCE_FOVEON_X3F)) - parse_foveon(); - else + /* no foveon support for dcraw build from libraw source */ + parse_x3f(); #endif - parse_x3f(); -#else -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 - parse_foveon(); -#endif -#endif - } - else if (!memcmp (head,"CI",2)) + } + else if (!memcmp(head, "CI", 2)) parse_cine(); - if(make[0] == 0) + if (make[0] == 0) #ifdef LIBRAW_LIBRARY_BUILD - for (zero_fsize=i=0; i < camera_count; i++) + for (zero_fsize = i = 0; i < camera_count; i++) #else - for (zero_fsize=i=0; i < sizeof table / sizeof *table; i++) + for (zero_fsize = i = 0; i < sizeof table / sizeof *table; i++) #endif - if (fsize == table[i].fsize) { - strcpy (make, table[i].t_make ); + if (fsize == table[i].fsize) + { + strcpy(make, table[i].t_make); #ifdef LIBRAW_LIBRARY_BUILD - if (!strncmp(make, "Canon",5)) + if (!strncmp(make, "Canon", 5)) + { + imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; + imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; + } +#endif + strcpy(model, table[i].t_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 == 0xffff ? 0 : 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 = 0x1010101U * 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: + if ((fsize - data_offset) / raw_height * 3 >= raw_width * 4) + { + load_raw = &CLASS android_loose_load_raw; + break; + } + else if (load_flags & 1) { - imgdata.lens.makernotes.CameraMount = LIBRAW_MOUNT_FixedLens; - imgdata.lens.makernotes.LensMount = LIBRAW_MOUNT_FixedLens; + load_raw = &CLASS android_tight_load_raw; + break; } -#endif - strcpy (model, table[i].t_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 == 0xffff?0: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: - if ((fsize-data_offset)/raw_height*3 >= raw_width*4) { - load_raw = &CLASS android_loose_load_raw; break; - } else if (load_flags & 1) { - load_raw = &CLASS android_tight_load_raw; break; - } - 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 = table[i].offset == 0xffff ? &CLASS unpacked_load_raw_reversed : &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) { + 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 = table[i].offset == 0xffff ? &CLASS unpacked_load_raw_reversed : &CLASS unpacked_load_raw; + } + maximum = (1 << tiff_bps) - (1 << table[i].max); + break; + } + if (zero_fsize) + fsize = 0; + if (make[0] == 0) + parse_smal(0, flen); + if (make[0] == 0) + { parse_jpeg(0); - fseek(ifp,0,SEEK_END); + fseek(ifp, 0, SEEK_END); int sz = ftell(ifp); #ifdef LIBRAW_LIBRARY_BUILD - if (!strncmp(model,"RP_imx219",9) && sz >= 0x9cb600 && - !fseek (ifp, -0x9cb600, SEEK_END) && - fread (head, 1, 0x20, ifp) && !strncmp(head, "BRCM", 4)) { - strcpy (make, "Broadcom"); - strcpy (model, "RPi IMX219"); - if (raw_height > raw_width) flip = 5; - data_offset = ftell(ifp) + 0x8000 - 0x20; - parse_broadcom(); - black = 66; - maximum = 0x3ff; - load_raw = &CLASS broadcom_load_raw; + if (!strncmp(model, "RP_imx219", 9) && sz >= 0x9cb600 && !fseek(ifp, -0x9cb600, SEEK_END) && + fread(head, 1, 0x20, ifp) && !strncmp(head, "BRCM", 4)) + { + strcpy(make, "Broadcom"); + strcpy(model, "RPi IMX219"); + if (raw_height > raw_width) + flip = 5; + data_offset = ftell(ifp) + 0x8000 - 0x20; + parse_broadcom(); + black = 66; + maximum = 0x3ff; + load_raw = &CLASS broadcom_load_raw; thumb_offset = 0; thumb_length = sz - 0x9cb600 - 1; - } else - if (!(strncmp(model,"ov5647",6) && strncmp(model,"RP_OV5647",9)) && sz >= 0x61b800 && - !fseek (ifp, -0x61b800, SEEK_END) && - fread (head, 1, 0x20, ifp) && !strncmp(head, "BRCM", 4)) { - strcpy (make, "Broadcom"); - if (!strncmp(model,"ov5647",6)) - strcpy (model, "RPi OV5647 v.1"); + } + else if (!(strncmp(model, "ov5647", 6) && strncmp(model, "RP_OV5647", 9)) && sz >= 0x61b800 && + !fseek(ifp, -0x61b800, SEEK_END) && fread(head, 1, 0x20, ifp) && !strncmp(head, "BRCM", 4)) + { + strcpy(make, "Broadcom"); + if (!strncmp(model, "ov5647", 6)) + strcpy(model, "RPi OV5647 v.1"); else - strcpy (model, "RPi OV5647 v.2"); - if (raw_height > raw_width) flip = 5; + strcpy(model, "RPi OV5647 v.2"); + if (raw_height > raw_width) + flip = 5; data_offset = ftell(ifp) + 0x8000 - 0x20; parse_broadcom(); - black = 16; - maximum = 0x3ff; - load_raw = &CLASS broadcom_load_raw; + black = 16; + maximum = 0x3ff; + load_raw = &CLASS broadcom_load_raw; thumb_offset = 0; thumb_length = sz - 0x61b800 - 1; #else - if (!(strncmp(model,"ov",2) && strncmp(model,"RP_OV",5)) && sz>=6404096 && - !fseek (ifp, -6404096, SEEK_END) && - fread (head, 1, 32, ifp) && !strcmp(head,"BRCMn")) { - strcpy (make, "OmniVision"); - data_offset = ftell(ifp) + 0x8000-32; + if (!(strncmp(model, "ov", 2) && strncmp(model, "RP_OV", 5)) && sz >= 6404096 && !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; #endif - } else is_raw = 0; + } + else + is_raw = 0; } #ifdef LIBRAW_LIBRARY_BUILD // make sure strings are terminated desc[511] = artist[63] = make[63] = model[63] = model2[63] = 0; #endif - for (i=0; i < sizeof corp / sizeof *corp; i++) - if (strcasestr (make, corp[i])) /* Simplify company names */ - strcpy (make, corp[i]); - if ((!strncmp(make,"Kodak",5) || !strncmp(make,"Leica",5)) && - ((cp = strcasestr(model," DIGITAL CAMERA")) || - (cp = strstr(model,"FILE VERSION")))) - *cp = 0; - if (!strncasecmp(model,"PENTAX",6)) - strcpy (make, "Pentax"); -#ifdef LIBRAW_LIBRARY_BUILD - remove_trailing_spaces(make,sizeof(make)); - remove_trailing_spaces(model,sizeof(model)); + for (i = 0; i < sizeof corp / sizeof *corp; i++) + if (strcasestr(make, corp[i])) /* Simplify company names */ + strcpy(make, corp[i]); + if ((!strncmp(make, "Kodak", 5) || !strncmp(make, "Leica", 5)) && + ((cp = strcasestr(model, " DIGITAL CAMERA")) || (cp = strstr(model, "FILE VERSION")))) + *cp = 0; + if (!strncasecmp(model, "PENTAX", 6)) + strcpy(make, "Pentax"); +#ifdef LIBRAW_LIBRARY_BUILD + remove_trailing_spaces(make, sizeof(make)); + remove_trailing_spaces(model, sizeof(model)); #else - cp = make + strlen(make); /* Remove trailing spaces */ - while (*--cp == ' ') *cp = 0; + cp = make + strlen(make); /* Remove trailing spaces */ + while (*--cp == ' ') + *cp = 0; cp = model + strlen(model); - while (*--cp == ' ') *cp = 0; -#endif - i = strbuflen(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); + while (*--cp == ' ') + *cp = 0; +#endif + i = strbuflen(make); /* Remove make from model */ + if (!strncasecmp(model, make, i) && model[i++] == ' ') + memmove(model, model + i, 64 - i); + if (!strncmp(model, "FinePix ", 8)) + memmove(model, model + 8,strlen(model)-7); + if (!strncmp(model, "Digital Camera ", 15)) + memmove(model, model + 15,strlen(model)-14); 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 == 6080 && !strcmp(model,"K-70")) - { height = 4016; top_margin=32; width=6020; left_margin = 60; } - if (width == 4736 && !strcmp(model,"K-7")) - { height = 3122; width = 4684; filters = 0x16161616; top_margin = 2; } - if (width == 6080 && !strcmp(model,"K-3 II")) /* moved back */ - { left_margin = 4; width = 6040; } - 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 0: /* Compression not set, assuming uncompressed */ - case 1: load_raw = &CLASS packed_dng_load_raw; break; - case 7: load_raw = &CLASS lossless_dng_load_raw; break; -#ifdef LIBRAW_LIBRARY_BUILD - case 8: load_raw = &CLASS deflate_dng_load_raw; break; -#endif - case 34892: load_raw = &CLASS lossy_dng_load_raw; break; - default: load_raw = 0; - } - if (!strncmp(make, "Canon",5) && unique_id) - { - for (i = 0; i < sizeof unique / sizeof *unique; i++) - if (unique_id == 0x80000000 + unique[i].id) - { - strcpy(model, unique[i].t_model); - break; - } - } - if (!strncasecmp(make, "Sony",4) && unique_id) - { - for (i = 0; i < sizeof sonique / sizeof *sonique; i++) - if (unique_id == sonique[i].id) - { - strcpy(model, sonique[i].t_model); - break; - } - } - goto dng_skip; + 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 (!strncmp(make,"Canon",5) && !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; - } + 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 == 6080 && !strcmp(model, "K-70")) + { + height = 4016; + top_margin = 32; + width = 6020; + left_margin = 60; + } + if (width == 4736 && !strcmp(model, "K-7")) + { + height = 3122; + width = 4684; + filters = 0x16161616; + top_margin = 2; + } + if (width == 6080 && !strcmp(model, "K-3 II")) /* moved back */ + { + left_margin = 4; + width = 6040; + } + if (width == 6112 && !strcmp(model, "KP")) + { + /* From DNG, maybe too strict */ + left_margin = 54; + top_margin = 28; + width = 6028; + height = raw_height - top_margin; + } + 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 (!strncmp(make,"Canon",5) && unique_id) + 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 0: /* Compression not set, assuming uncompressed */ + case 1: + load_raw = &CLASS packed_dng_load_raw; + break; + case 7: + load_raw = &CLASS lossless_dng_load_raw; + break; +#ifdef LIBRAW_LIBRARY_BUILD + case 8: + load_raw = &CLASS deflate_dng_load_raw; + break; +#endif + case 34892: + load_raw = &CLASS lossy_dng_load_raw; + break; + default: + load_raw = 0; + } + if (!strncmp(make, "Canon", 5) && unique_id) { - for (i=0; i < sizeof unique / sizeof *unique; i++) + for (i = 0; i < sizeof unique / sizeof *unique; i++) if (unique_id == 0x80000000 + unique[i].id) - { - adobe_coeff ("Canon", unique[i].t_model); - strcpy(model,unique[i].t_model); - } + { + strcpy(model, unique[i].t_model); + break; + } } - - if (!strncasecmp(make,"Sony",4) && unique_id) + if (!strncasecmp(make, "Sony", 4) && unique_id) { - for (i=0; i < sizeof sonique / sizeof *sonique; i++) + for (i = 0; i < sizeof sonique / sizeof *sonique; i++) if (unique_id == sonique[i].id) - { - adobe_coeff ("Sony", sonique[i].t_model); - strcpy(model,sonique[i].t_model); - } + { + strcpy(model, sonique[i].t_model); + break; + } + } + goto dng_skip; + } + if (!strncmp(make, "Canon", 5) && !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] * 0x01010101U; + } + if ((unique_id | 0x20000) == 0x2720000) + { + left_margin = 8; + top_margin = 16; } + } + if (!strncmp(make, "Canon", 5) && unique_id) + { + for (i = 0; i < sizeof unique / sizeof *unique; i++) + if (unique_id == 0x80000000 + unique[i].id) + { + adobe_coeff("Canon", unique[i].t_model); + strcpy(model, unique[i].t_model); + } + } + + if (!strncasecmp(make, "Sony", 4) && unique_id) + { + for (i = 0; i < sizeof sonique / sizeof *sonique; i++) + if (unique_id == sonique[i].id) + { + adobe_coeff("Sony", sonique[i].t_model); + strcpy(model, sonique[i].t_model); + } + } - if (!strncmp(make,"Nikon",5)) { + if (!strncmp(make, "Nikon", 5)) + { 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). */ + /* Set parameters based on camera name (for non-DNG files). */ - if (!strcmp(model,"KAI-0340") - && find_green (16, 16, 3840, 5120) < 25) { + if (!strcmp(model, "KAI-0340") && find_green(16, 16, 3840, 5120) < 25) + { height = 480; top_margin = filters = 0; - strcpy (model,"C603"); + strcpy(model, "C603"); } - +#ifndef LIBRAW_LIBRARY_BUILD if (!strcmp(make, "Sony") && raw_width > 3888 && !black && !cblack[0]) black = 128 << (tiff_bps - 12); +#else + /* Always 512 for arw2_load_raw */ + if (!strcmp(make, "Sony") && raw_width > 3888 && !black && !cblack[0]) + black = (load_raw == &LibRaw::sony_arw2_load_raw) ? 512 : (128 << (tiff_bps - 12)); +#endif - if (is_foveon) { - if (height*2 < width) pixel_aspect = 0.5; - if (height > width) pixel_aspect = 2; + if (is_foveon) + { + if (height * 2 < width) + pixel_aspect = 0.5; + if (height > width) + pixel_aspect = 2; filters = 0; -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 - if(!(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_FORCE_FOVEON_X3F)) - simple_coeff(0); -#endif } - else if(!strncmp(make,"Pentax",6)) + else if (!strncmp(make, "Pentax", 6) && !strncmp(model, "K-1", 3)) { - if(!strncmp(model,"K-1",3)) + top_margin = 18; + height = raw_height - top_margin; + if (raw_width == 7392) { - top_margin = 18; - height = raw_height - top_margin; - if(raw_width == 7392) - { - left_margin = 6; - width = 7376; - } + left_margin = 6; + width = 7376; } } - else if (!strncmp(make,"Canon",5) && tiff_bps == 15) { - switch (width) { - case 3344: width -= 66; - case 3872: width -= 6; + else if (!strncmp(make, "Canon", 5) && tiff_bps == 15) + { + switch (width) + { + case 3344: + width -= 66; + case 3872: + width -= 6; } - if (height > width) { - SWAP(height,width); - SWAP(raw_height,raw_width); + if (height > width) + { + SWAP(height, width); + SWAP(raw_height, raw_width); } if (width == 7200 && height == 3888) - { - raw_width = width = 6480; - raw_height = height = 4320; - } + { + raw_width = width = 6480; + raw_height = height = 4320; + } filters = 0; tiff_samples = colors = 3; load_raw = &CLASS canon_sraw_load_raw; - } else if (!strcmp(model,"PowerShot 600")) { + } + else if (!strcmp(model, "PowerShot 600")) + { height = 613; - width = 854; + 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")) { + } + else if (!strcmp(model, "PowerShot A5") || !strcmp(model, "PowerShot A5 Zoom")) + { height = 773; - width = 960; + width = 960; raw_width = 992; - pixel_aspect = 256/235.0; + pixel_aspect = 256 / 235.0; filters = 0x1e4e1e4e; goto canon_a5; - } else if (!strcmp(model,"PowerShot A50")) { - height = 968; - width = 1290; + } + else if (!strcmp(model, "PowerShot A50")) + { + height = 968; + width = 1290; raw_width = 1320; filters = 0x1b4e4b1e; goto canon_a5; - } else if (!strcmp(model,"PowerShot Pro70")) { + } + else if (!strcmp(model, "PowerShot Pro70")) + { height = 1024; - width = 1552; + width = 1552; filters = 0x1e4b4e1b; -canon_a5: + 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")) { + } + 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")) { + } + 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; - top_margin=16; + top_margin = 16; left_margin = 92; - } else if (!strcmp(model,"PowerShot S120")) { - raw_width = 4192; - raw_height = 3062; - width = 4022; - height = 3016; - mask[0][0] = top_margin = 31; - mask[0][2] = top_margin + height; - left_margin = 120; - mask[0][1] = 23; - mask[0][3] = 72; - } else if (!strcmp(model,"PowerShot G16")) { - mask[0][0] = 0; - mask[0][2] = 80; - mask[0][1] = 0; - mask[0][3] = 16; - top_margin = 29; - left_margin = 120; - width = raw_width-left_margin-48; - height = raw_height-top_margin-14; - } else if (!strcmp(model,"PowerShot SX50 HS")) { + } + else if (!strcmp(model, "PowerShot S120")) + { + raw_width = 4192; + raw_height = 3062; + width = 4022; + height = 3016; + mask[0][0] = top_margin = 31; + mask[0][2] = top_margin + height; + left_margin = 120; + mask[0][1] = 23; + mask[0][3] = 72; + } + else if (!strcmp(model, "PowerShot G16")) + { + mask[0][0] = 0; + mask[0][2] = 80; + mask[0][1] = 0; + mask[0][3] = 16; + top_margin = 29; + left_margin = 120; + width = raw_width - left_margin - 48; + height = raw_height - top_margin - 14; + } + else if (!strcmp(model, "PowerShot SX50 HS")) + { top_margin = 17; - } else if (!strcmp(model,"EOS D2000C")) { + } + 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")) { + if (!black) + 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")) { + } + 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; + } + else if (!strcmp(model, "D3") || !strcmp(model, "D3S") || !strcmp(model, "D700")) + { width -= 4; left_margin = 2; - } else if (!strcmp(model,"D3100")) { + } + else if (!strcmp(model, "D3100")) + { width -= 28; left_margin = 6; - } else if (!strcmp(model,"D5000") || - !strcmp(model,"D90")) { + } + else if (!strcmp(model, "D5000") || !strcmp(model, "D90")) + { width -= 42; - } else if (!strcmp(model,"D5100") || - !strcmp(model,"D7000") || - !strcmp(model,"COOLPIX A")) { + } + 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)) { + } + else if (!strcmp(model, "D3200") || !strncmp(model, "D6", 2) || !strncmp(model, "D800", 4)) + { width -= 46; - } else if (!strcmp(model,"D4") || - !strcmp(model,"Df")) { + } + 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)) { + } + else if (!strcmp(model, "D500")) + { + // Empty - to avoid width-1 below + } + else if (!strncmp(model, "D40", 3) || !strncmp(model, "D50", 3) || !strncmp(model, "D70", 3)) + { width--; - } else if (!strcmp(model,"D100")) { + } + else if (!strcmp(model, "D100")) + { if (load_flags) raw_width = (width += 3) + 3; - } else if (!strcmp(model,"D200")) { + } + else if (!strcmp(model, "D200")) + { left_margin = 1; width -= 4; filters = 0x94949494; - } else if (!strncmp(model,"D2H",3)) { + } + 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)) { + } + 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(make,"Nikon",5) && raw_width == 4032) { - if(!strcmp(model,"COOLPIX P7700")) - { - adobe_coeff ("Nikon","COOLPIX P7700"); - maximum = 65504; - load_flags = 0; - } - else if(!strcmp(model,"COOLPIX P7800")) - { - adobe_coeff ("Nikon","COOLPIX P7800"); - maximum = 65504; - load_flags = 0; - } - else if(!strcmp(model,"COOLPIX P340")) - load_flags=0; - } else if (!strncmp(model,"COOLPIX P",9) && raw_width != 4032) { + } + else if (!strncmp(make, "Nikon", 5) && raw_width == 4032) + { + if (!strcmp(model, "COOLPIX P7700")) + { + adobe_coeff("Nikon", "COOLPIX P7700"); + maximum = 65504; + load_flags = 0; + } + else if (!strcmp(model, "COOLPIX P7800")) + { + adobe_coeff("Nikon", "COOLPIX P7800"); + maximum = 65504; + load_flags = 0; + } + else if (!strcmp(model, "COOLPIX P340")) + load_flags = 0; + } + else if (!strncmp(model, "COOLPIX P", 9) && raw_width != 4032) + { load_flags = 24; filters = 0x94949494; - if (model[9] == '7' && (iso_speed >= 400 || iso_speed==0) && !strstr(software,"V1.2") ) + if (model[9] == '7' && (iso_speed >= 400 || iso_speed == 0) && !strstr(software, "V1.2")) black = 255; - } else if (!strncmp(model,"1 ",2)) { + } + else if (!strncmp(model, "COOLPIX B700", 12)) + { + load_flags = 24; + black = 200; + } + else if (!strncmp(model, "1 ", 2)) + { height -= 2; - } else if (fsize == 1581060) { + } + 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) { + } + else if (fsize == 3178560) + { cam_mul[0] *= 4; cam_mul[2] *= 4; - } else if (fsize == 4771840) { + } + else if (fsize == 4771840) + { if (!timestamp && nikon_e995()) - strcpy (model, "E995"); - if (strcmp(model,"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) { + } + else if (fsize == 2940928) + { if (!timestamp && !nikon_e2100()) - strcpy (model,"E2500"); - if (!strcmp(model,"E2500")) { + 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) + } + else if (fsize == 4775936) + { + if (!timestamp) + nikon_3700(); + if (model[0] == 'E' && atoi(model + 1) < 3700) filters = 0x49494949; - if (!strcmp(model,"Optio 33WR")) { + 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 (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; + if (i < 0) + filters = 0x61616161; } - } else if (fsize == 5869568) { - if (!timestamp && minolta_z2()) { - strcpy (make, "Minolta"); - strcpy (model,"DiMAGE Z2"); + } + 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) { + 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"); + strcpy(make, "ISG"); model[0] = 0; } - } else if (!strncmp(make,"Fujifilm",8)) { - if (!strcmp(model+7,"S2Pro")) { - strcpy (model,"S2Pro"); + } + else if (!strncmp(make, "Fujifilm", 8)) + { + if (!strcmp(model, "X-A3") || !strcmp(model, "X-A10") + || !strcmp(model, "X-A5") || !strcmp(model, "X-A20")) + { + left_margin = 0; + top_margin = 0; + width = raw_width; + height = raw_height; + } + if (!strcmp(model + 7, "S2Pro")) + { + strcpy(model, "S2Pro"); height = 2144; - width = 2880; + width = 2880; flip = 6; - } else if (load_raw != &CLASS packed_load_raw) + } + else if (load_raw != &CLASS packed_load_raw && strncmp(model, "X-", 2) && filters >=1000) // Bayer and not X-models 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 (width == 6032) left_margin = 0; - if (!strcmp(model,"HS50EXR") || - !strcmp(model,"F900EXR")) { + 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 (width == 6032) + left_margin = 0; + if (!strcmp(model, "HS50EXR") || !strcmp(model, "F900EXR")) + { width += 2; left_margin = 0; filters = 0x16161616; } - if(!strcmp(model,"S5500")) - { - height -= (top_margin=6); - } - if (fuji_layout) raw_width *= is_raw; + if (!strcmp(model, "GFX 50S")) + { + left_margin = 0; + top_margin = 0; + } + if (!strcmp(model, "S5500")) + { + height -= (top_margin = 6); + } + if (fuji_layout) + raw_width *= is_raw; if (filters == 9) - FORC(36) ((char *)xtrans)[c] = - xtrans_abs[(c/6+top_margin) % 6][(c+left_margin) % 6]; - } else if (!strcmp(model,"KD-400Z")) { + FORC(36)((char *)xtrans)[c] = xtrans_abs[(c / 6 + top_margin) % 6][(c + left_margin) % 6]; + } + else if (!strcmp(model, "KD-400Z")) + { height = 1712; - width = 2312; + width = 2312; raw_width = 2336; goto konica_400z; - } else if (!strcmp(model,"KD-510Z")) { + } + else if (!strcmp(model, "KD-510Z")) + { goto konica_510z; - } else if (!strncasecmp(make,"Minolta",7)) { + } + else if (!strncasecmp(make, "Minolta", 7)) + { if (!load_raw && (maximum = 0xfff)) load_raw = &CLASS unpacked_load_raw; - if (!strncmp(model,"DiMAGE A",8)) { - if (!strcmp(model,"DiMAGE A200")) - filters = 0x49494949; + if (!strncmp(model, "DiMAGE A", 8)) + { + if (!strcmp(model, "DiMAGE A200")) + filters = 0x49494949; tiff_bps = 12; load_raw = &CLASS packed_load_raw; - } else if (!strncmp(model,"ALPHA",5) || - !strncmp(model,"DYNAX",5) || - !strncmp(model,"MAXXUM",6)) { - sprintf (model+20, "DYNAX %-10s", model+6+(model[0]=='M')); - adobe_coeff (make, model+20); + } + else if (!strncmp(model, "ALPHA", 5) || !strncmp(model, "DYNAX", 5) || !strncmp(model, "MAXXUM", 6)) + { + sprintf(model + 20, "DYNAX %-10s", model + 6 + (model[0] == 'M')); + adobe_coeff(make, model + 20); load_raw = &CLASS packed_load_raw; - } else if (!strncmp(model,"DiMAGE G",8)) { - if (model[8] == '4') { - height = 1716; - width = 2304; - } else if (model[8] == '5') { -konica_510z: - height = 1956; - width = 2607; - raw_width = 2624; - } else if (model[8] == '6') { - height = 2136; - width = 2848; + } + else if (!strncmp(model, "DiMAGE G", 8)) + { + if (model[8] == '4') + { + height = 1716; + width = 2304; + } + else if (model[8] == '5') + { + konica_510z: + height = 1956; + width = 2607; + raw_width = 2624; + } + else if (model[8] == '6') + { + height = 2136; + width = 2848; } data_offset += 14; filters = 0x61616161; -konica_400z: + konica_400z: load_raw = &CLASS unpacked_load_raw; maximum = 0x3df; order = 0x4d4d; } - } else if (!strcmp(model,"*ist D")) { + } + else if (!strcmp(model, "*ist D")) + { load_raw = &CLASS unpacked_load_raw; data_error = -1; - } else if (!strcmp(model,"*ist DS")) { + } + else if (!strcmp(model, "*ist DS")) + { height -= 2; - } else if (!strncmp(make,"Samsung",7) && raw_width == 4704) { + } + else if (!strncmp(make, "Samsung", 7) && raw_width == 4704) + { height -= top_margin = 8; width -= 2 * (left_margin = 8); load_flags = 32; - } else if (!strncmp(make,"Samsung",7) && !strcmp(model,"NX3000")) { - top_margin = 24; - left_margin = 64; - width = 5472; - height = 3648; + } + else if (!strncmp(make, "Samsung", 7) && !strcmp(model, "NX3000")) + { + top_margin = 38; + left_margin = 92; + width = 5456; + height = 3634; filters = 0x61616161; colors = 3; - } else if (!strncmp(make,"Samsung",7) && raw_height == 3714) { + } + else if (!strncmp(make, "Samsung", 7) && raw_height == 3714) + { height -= top_margin = 18; left_margin = raw_width - (width = 5536); if (raw_width != 5600) left_margin = top_margin = 0; filters = 0x61616161; colors = 3; - } else if (!strncmp(make,"Samsung",7) && raw_width == 5632) { + } + else if (!strncmp(make, "Samsung", 7) && raw_width == 5632) + { order = 0x4949; height = 3694; top_margin = 2; - width = 5574 - (left_margin = 32 + tiff_bps); - if (tiff_bps == 12) load_flags = 80; - } else if (!strncmp(make,"Samsung",7) && raw_width == 5664) { + width = 5574 - (left_margin = 32 + tiff_bps); + if (tiff_bps == 12) + load_flags = 80; + } + else if (!strncmp(make, "Samsung", 7) && raw_width == 5664) + { height -= top_margin = 17; left_margin = 96; width = 5544; filters = 0x49494949; - } else if (!strncmp(make,"Samsung",7) && raw_width == 6496) { + } + else if (!strncmp(make, "Samsung", 7) && raw_width == 6496) + { filters = 0x61616161; #ifdef LIBRAW_LIBRARY_BUILD - if(!black && !cblack[0] && !cblack[1] && !cblack[2] && !cblack[3]) + if (!black && !cblack[0] && !cblack[1] && !cblack[2] && !cblack[3]) #endif - black = 1 << (tiff_bps - 7); - } else if (!strcmp(model,"EX1")) { + black = 1 << (tiff_bps - 7); + } + else if (!strcmp(model, "EX1")) + { order = 0x4949; height -= 20; top_margin = 2; - if ((width -= 6) > 3682) { + if ((width -= 6) > 3682) + { height -= 10; - width -= 46; + width -= 46; top_margin = 8; } - } else if (!strcmp(model,"WB2000")) { + } + else if (!strcmp(model, "WB2000")) + { order = 0x4949; height -= 3; top_margin = 2; - if ((width -= 10) > 3718) { + if ((width -= 10) > 3718) + { height -= 28; - width -= 56; + width -= 56; top_margin = 8; } - } else if (strstr(model,"WB550")) { - strcpy (model, "WB550"); - } else if (!strcmp(model,"EX2F")) { + } + else if (strstr(model, "WB550")) + { + strcpy(model, "WB550"); + } + else if (!strcmp(model, "EX2F")) + { height = 3030; - width = 4040; + width = 4040; top_margin = 15; - left_margin=24; + left_margin = 24; order = 0x4949; filters = 0x49494949; load_raw = &CLASS unpacked_load_raw; - } else if (!strcmp(model,"STV680 VGA")) { + } + else if (!strcmp(model, "STV680 VGA")) + { black = 16; - } else if (!strcmp(model,"N95")) { + } + else if (!strcmp(model, "N95")) + { height = raw_height - (top_margin = 2); - } else if (!strcmp(model,"640x480")) { - gamma_curve (0.45, 4.5, 1, 255); - } else if (!strncmp(make,"Hasselblad",10)) { + } + else if (!strcmp(model, "640x480")) + { + gamma_curve(0.45, 4.5, 1, 255); + } + else if (!strncmp(make, "Hasselblad", 10)) + { if (load_raw == &CLASS lossless_jpeg_load_raw) load_raw = &CLASS hasselblad_load_raw; - if (raw_width == 7262) { + if (raw_width == 7262) + { height = 5444; - width = 7248; - top_margin = 4; + width = 7248; + top_margin = 4; left_margin = 7; filters = 0x61616161; - if(!strncasecmp(model,"H3D",3)) - { - adobe_coeff("Hasselblad","H3DII-39"); - strcpy(model,"H3DII-39"); - } - } else if (raw_width == 7410 || raw_width == 8282) { + if (!strncasecmp(model, "H3D", 3)) + { + adobe_coeff("Hasselblad", "H3DII-39"); + strcpy(model, "H3DII-39"); + } + } + else if (raw_width == 12000) // H6D 100c, A6D 100c + { + left_margin = 64; + width = 11608; + top_margin = 108; + height = raw_height - top_margin; + adobe_coeff("Hasselblad", "H6D-100c"); + } + else if (raw_width == 7410 || raw_width == 8282) + { height -= 84; - width -= 82; - top_margin = 4; + width -= 82; + top_margin = 4; left_margin = 41; filters = 0x61616161; - adobe_coeff("Hasselblad","H4D-40"); - strcpy(model,"H4D-40"); + adobe_coeff("Hasselblad", "H4D-40"); + strcpy(model, "H4D-40"); } - else if( raw_width == 8384) // X1D + else if (raw_width == 8384) // X1D { - top_margin = 96; - height -= 96; - left_margin = 48; - width -= 106; - adobe_coeff("Hasselblad","X1D"); - } - else if (raw_width == 9044) { - if(black > 500) - { - top_margin = 12; - left_margin = 44; - width = 8956; - height = 6708; - memset(cblack,0,sizeof(cblack)); - adobe_coeff("Hasselblad","H4D-60"); - strcpy(model,"H4D-60"); - black = 512; - } + top_margin = 96; + height -= 96; + left_margin = 48; + width -= 106; + adobe_coeff("Hasselblad", "X1D"); + maximum = 0xffff; + tiff_bps = 16; + } + else if (raw_width == 9044) + { + if (black > 500) + { + top_margin = 12; + left_margin = 44; + width = 8956; + height = 6708; + memset(cblack, 0, sizeof(cblack)); + adobe_coeff("Hasselblad", "H4D-60"); + strcpy(model, "H4D-60"); + black = 512; + } else - { - height = 6716; - width = 8964; - top_margin = 8; - left_margin = 40; - black += load_flags = 256; - maximum = 0x8101; - strcpy(model,"H3DII-60"); - } - } else if (raw_width == 4090) { - strcpy (model, "V96C"); + { + height = 6716; + width = 8964; + top_margin = 8; + left_margin = 40; + black += load_flags = 256; + maximum = 0x8101; + strcpy(model, "H3DII-60"); + } + } + else if (raw_width == 4090) + { + strcpy(model, "V96C"); height -= (top_margin = 6); width -= (left_margin = 3) + 7; filters = 0x61616161; - } else if (raw_width == 8282 && raw_height == 6240) { - if(!strncasecmp(model,"H5D",3)) - { - /* H5D 50*/ - left_margin = 54; - top_margin = 16; - width = 8176; - height = 6132; - black = 256; - strcpy(model,"H5D-50"); - } - else if(!strncasecmp(model,"H3D",3)) - { - black=0; - left_margin = 54; - top_margin = 16; - width = 8176; - height = 6132; - memset(cblack,0,sizeof(cblack)); - adobe_coeff("Hasselblad","H3D-50"); - strcpy(model,"H3D-50"); - } - } else if (raw_width == 8374 && raw_height == 6304) { + } + else if (raw_width == 8282 && raw_height == 6240) + { + if (!strncasecmp(model, "H5D", 3)) + { + /* H5D 50*/ + left_margin = 54; + top_margin = 16; + width = 8176; + height = 6132; + black = 256; + strcpy(model, "H5D-50"); + } + else if (!strncasecmp(model, "H3D", 3)) + { + black = 0; + left_margin = 54; + top_margin = 16; + width = 8176; + height = 6132; + memset(cblack, 0, sizeof(cblack)); + adobe_coeff("Hasselblad", "H3D-50"); + strcpy(model, "H3D-50"); + } + } + else if (raw_width == 8374 && raw_height == 6304) + { /* H5D 50c*/ left_margin = 52; top_margin = 100; width = 8272; height = 6200; black = 256; - strcpy(model,"H5D-50c"); + strcpy(model, "H5D-50c"); } - if (tiff_samples > 1) { - is_raw = tiff_samples+1; - if (!shot_select && !half_size) filters = 0; + if (tiff_samples > 1) + { + is_raw = tiff_samples + 1; + if (!shot_select && !half_size) + filters = 0; } - } else if (!strncmp(make,"Sinar",5)) { - if (!load_raw) load_raw = &CLASS unpacked_load_raw; - if (is_raw > 1 && !shot_select && !half_size) filters = 0; + } + else if (!strncmp(make, "Sinar", 5)) + { + if (!load_raw) + load_raw = &CLASS unpacked_load_raw; + if (is_raw > 1 && !shot_select && !half_size) + filters = 0; maximum = 0x3fff; - } else if (!strncmp(make,"Leaf",4)) { + } + else if (!strncmp(make, "Leaf", 4)) + { maximum = 0x3fff; - fseek (ifp, data_offset, SEEK_SET); - if (ljpeg_start (&jh, 1) && jh.bits == 15) + fseek(ifp, data_offset, SEEK_SET); + if (ljpeg_start(&jh, 1) && jh.bits == 15) maximum = 0x1fff; - if (tiff_samples > 1) filters = 0; - if (tiff_samples > 1 || tile_length < raw_height) { + if (tiff_samples > 1) + filters = 0; + if (tiff_samples > 1 || tile_length < raw_height) + { load_raw = &CLASS leaf_hdr_load_raw; raw_width = tile_width; } - if ((width | height) == 2048) { - if (tiff_samples == 1) { - filters = 1; - strcpy (cdesc, "RBTG"); - strcpy (model, "CatchLight"); - top_margin = 8; left_margin = 18; height = 2032; width = 2016; - } else { - strcpy (model, "DCB2"); - top_margin = 10; left_margin = 16; height = 2028; width = 2022; - } - } else if (width+height == 3144+2060) { - if (!model[0]) strcpy (model, "Cantare"); - if (width > height) { - top_margin = 6; left_margin = 32; height = 2048; width = 3072; - filters = 0x61616161; - } else { - left_margin = 6; top_margin = 32; width = 2048; height = 3072; - filters = 0x16161616; - } - if (!cam_mul[0] || model[0] == 'V') filters = 0; - else is_raw = tiff_samples; - } else if (width == 2116) { - strcpy (model, "Valeo 6"); + if ((width | height) == 2048) + { + if (tiff_samples == 1) + { + filters = 1; + strcpy(cdesc, "RBTG"); + strcpy(model, "CatchLight"); + top_margin = 8; + left_margin = 18; + height = 2032; + width = 2016; + } + else + { + strcpy(model, "DCB2"); + top_margin = 10; + left_margin = 16; + height = 2028; + width = 2022; + } + } + else if (width + height == 3144 + 2060) + { + if (!model[0]) + strcpy(model, "Cantare"); + if (width > height) + { + top_margin = 6; + left_margin = 32; + height = 2048; + width = 3072; + filters = 0x61616161; + } + else + { + left_margin = 6; + top_margin = 32; + width = 2048; + height = 3072; + filters = 0x16161616; + } + if (!cam_mul[0] || model[0] == 'V') + filters = 0; + else + is_raw = tiff_samples; + } + else if (width == 2116) + { + strcpy(model, "Valeo 6"); height -= 2 * (top_margin = 30); width -= 2 * (left_margin = 55); filters = 0x49494949; - } else if (width == 3171) { - strcpy (model, "Valeo 6"); + } + else if (width == 3171) + { + strcpy(model, "Valeo 6"); height -= 2 * (top_margin = 24); width -= 2 * (left_margin = 24); filters = 0x16161616; } - } else if (!strncmp(make,"Leica",5) || !strncmp(make,"Panasonic",9) - || !strncasecmp(make,"YUNEEC",6)) { - if (raw_width > 0&& ((flen - data_offset) / (raw_width*8/7) == raw_height) ) + } + else if (!strncmp(make, "Leica", 5) || !strncmp(make, "Panasonic", 9) || !strncasecmp(make, "YUNEEC", 6)) + { + + if (raw_width > 0 && ((flen - data_offset) / (raw_width * 8 / 7) == raw_height)) load_raw = &CLASS panasonic_load_raw; - if (!load_raw) { + if (!load_raw) + { load_raw = &CLASS unpacked_load_raw; load_flags = 4; } zero_is_bad = 1; - if ((height += 12) > raw_height) height = raw_height; - for (i=0; i < sizeof pana / sizeof *pana; i++) - if (raw_width == pana[i][0] && raw_height == pana[i][1]) { - left_margin = pana[i][2]; - top_margin = pana[i][3]; - width += pana[i][4]; - height += pana[i][5]; - } - filters = 0x01010101 * (uchar) "\x94\x61\x49\x16" - [((filters-1) ^ (left_margin & 1) ^ (top_margin << 1)) & 3]; - } else if (!strcmp(model,"C770UZ")) { + if ((height += 12) > raw_height) + height = raw_height; + for (i = 0; i < sizeof pana / sizeof *pana; i++) + if (raw_width == pana[i][0] && raw_height == pana[i][1]) + { + left_margin = pana[i][2]; + top_margin = pana[i][3]; + width += pana[i][4]; + height += pana[i][5]; + } + filters = 0x01010101U * (uchar) "\x94\x61\x49\x16"[((filters - 1) ^ (left_margin & 1) ^ (top_margin << 1)) & 3]; + } + else if (!strcmp(model, "C770UZ")) + { height = 1718; - width = 2304; + width = 2304; filters = 0x16161616; load_raw = &CLASS packed_load_raw; load_flags = 30; - } else if (!strncmp(make,"Olympus",7)) { + } + else if (!strncmp(make, "Olympus", 7)) + { height += height & 1; - if (exif_cfa) filters = exif_cfa; - if (width == 4100) width -= 4; - if (width == 4080) width -= 24; - if (width == 9280) { width -= 6; height -= 6; } + if (exif_cfa) + filters = exif_cfa; + if (width == 4100) + width -= 4; + if (width == 4080) + width -= 24; + if (width == 9280) + { + width -= 6; + height -= 6; + } if (load_raw == &CLASS unpacked_load_raw) load_flags = 4; tiff_bps = 12; - if (!strcmp(model,"E-300") || - !strcmp(model,"E-500")) { + if (!strcmp(model, "E-300") || !strcmp(model, "E-500")) + { width -= 20; - if (load_raw == &CLASS unpacked_load_raw) { - maximum = 0xfc3; - memset (cblack, 0, sizeof cblack); + if (load_raw == &CLASS unpacked_load_raw) + { + maximum = 0xfc3; + memset(cblack, 0, sizeof cblack); } - } else if (!strcmp(model,"STYLUS1")) { + } + else if (!strcmp(model, "STYLUS1")) + { width -= 14; maximum = 0xfff; - } else if (!strcmp(model,"E-330")) { + } + else if (!strcmp(model, "E-330")) + { width -= 30; if (load_raw == &CLASS unpacked_load_raw) - maximum = 0xf79; - } else if (!strcmp(model,"SP550UZ")) { + maximum = 0xf79; + } + else if (!strcmp(model, "SP550UZ")) + { thumb_length = flen - (thumb_offset = 0xa39800); thumb_height = 480; - thumb_width = 640; - } else if (!strcmp(model,"TG-4")) { + thumb_width = 640; + } + else if (!strcmp(model, "TG-4")) + { width -= 16; } - } else if (!strcmp(model,"N Digital")) { + else if (!strcmp(model, "TG-5")) + { + width -= 26; + } + } + else if (!strcmp(model, "N Digital")) + { height = 2047; - width = 3072; + width = 3072; filters = 0x61616161; data_offset = 0x1a00; load_raw = &CLASS packed_load_raw; - } else if (!strcmp(model,"DSC-F828")) { + } + else if (!strcmp(model, "DSC-F828")) + { width = 3288; left_margin = 5; mask[1][3] = -17; data_offset = 862144; load_raw = &CLASS sony_load_raw; filters = 0x9c9c9c9c; colors = 4; - strcpy (cdesc, "RGBE"); - } else if (!strcmp(model,"DSC-V3")) { + strcpy(cdesc, "RGBE"); + } + else if (!strcmp(model, "DSC-V3")) + { width = 3109; left_margin = 59; mask[0][1] = 9; data_offset = 787392; load_raw = &CLASS sony_load_raw; - } else if (!strncmp(make,"Sony",4) && raw_width == 3984) { + } + else if (!strncmp(make, "Sony", 4) && raw_width == 3984) + { width = 3925; order = 0x4d4d; - } else if (!strncmp(make,"Sony",4) && raw_width == 4288) { + } + else if (!strncmp(make, "Sony", 4) && raw_width == 4288) + { width -= 32; - } else if (!strcmp(make, "Sony") && raw_width == 4600) { + } + else if (!strcmp(make, "Sony") && raw_width == 4600) + { if (!strcmp(model, "DSLR-A350")) height -= 4; black = 0; - } else if (!strncmp(make,"Sony",4) && raw_width == 4928) { - if (height < 3280) width -= 8; - } else if (!strncmp(make,"Sony",4) && raw_width == 5504) { // ILCE-3000//5000 + } + else if (!strncmp(make, "Sony", 4) && raw_width == 4928) + { + if (height < 3280) + width -= 8; + } + else if (!strncmp(make, "Sony", 4) && raw_width == 5504) + { // ILCE-3000//5000 width -= height > 3664 ? 8 : 32; - } else if (!strncmp(make,"Sony",4) && raw_width == 6048) { + } + else if (!strncmp(make, "Sony", 4) && raw_width == 6048) + { width -= 24; - if (strstr(model,"RX1") || strstr(model,"A99")) + if (strstr(model, "RX1") || strstr(model, "A99")) width -= 6; - } else if (!strncmp(make,"Sony",4) && raw_width == 7392) { + } + else if (!strncmp(make, "Sony", 4) && raw_width == 7392) + { width -= 30; - } else if (!strncmp(make,"Sony",4) && raw_width == 8000) { + } + else if (!strncmp(make, "Sony", 4) && raw_width == 8000) + { width -= 32; - if (!strncmp(model, "DSC", 3)) { - tiff_bps = 14; - load_raw = &CLASS unpacked_load_raw; - } - } else if (!strcmp(model,"DSLR-A100")) { - if (width == 3880) { + } + else if (!strcmp(model, "DSLR-A100")) + { + if (width == 3880) + { height--; width = ++raw_width; - } else { + } + else + { height -= 4; - width -= 4; + width -= 4; order = 0x4d4d; load_flags = 2; } filters = 0x61616161; - } else if (!strcmp(model,"PIXL")) { + } + else if (!strcmp(model, "PIXL")) + { height -= top_margin = 4; width -= left_margin = 32; - gamma_curve (0, 7, 1, 255); - } else if (!strcmp(model,"C603") || !strcmp(model,"C330") - || !strcmp(model,"12MP")) { + gamma_curve(0, 7, 1, 255); + } + else if (!strcmp(model, "C603") || !strcmp(model, "C330") || !strcmp(model, "12MP")) + { order = 0x4949; - if (filters && data_offset) { - fseek (ifp, data_offset < 4096 ? 168 : 5252, SEEK_SET); - read_shorts (curve, 256); - } else gamma_curve (0, 3.875, 1, 255); - load_raw = filters ? &CLASS eight_bit_load_raw : - strcmp(model,"C330") ? &CLASS kodak_c603_load_raw : - &CLASS kodak_c330_load_raw; + if (filters && data_offset) + { + fseek(ifp, data_offset < 4096 ? 168 : 5252, SEEK_SET); + read_shorts(curve, 256); + } + else + gamma_curve(0, 3.875, 1, 255); + load_raw = filters ? &CLASS eight_bit_load_raw + : strcmp(model, "C330") ? &CLASS kodak_c603_load_raw : &CLASS kodak_c330_load_raw; load_flags = tiff_bps > 16; tiff_bps = 8; - } else if (!strncasecmp(model,"EasyShare",9)) { + } + else if (!strncasecmp(model, "EasyShare", 9)) + { data_offset = data_offset < 0x15000 ? 0x15000 : 0x17000; load_raw = &CLASS packed_load_raw; - } else if (!strncasecmp(make,"Kodak",5)) { - if (filters == UINT_MAX) filters = 0x61616161; - if (!strncmp(model,"NC2000",6) || - !strncmp(model,"EOSDCS",6) || - !strncmp(model,"DCS4",4)) { + } + else if (!strncasecmp(make, "Kodak", 5)) + { + if (filters == UINT_MAX) + filters = 0x61616161; + if (!strncmp(model, "NC2000", 6) || !strncmp(model, "EOSDCS", 6) || !strncmp(model, "DCS4", 4)) + { width -= 4; left_margin = 2; - if (model[6] == ' ') model[6] = 0; - if (!strcmp(model,"DCS460A")) goto bw; - } else if (!strcmp(model,"DCS660M")) { + if (model[6] == ' ') + model[6] = 0; + if (!strcmp(model, "DCS460A")) + goto bw; + } + else if (!strcmp(model, "DCS660M")) + { black = 214; goto bw; - } else if (!strcmp(model,"DCS760M")) { -bw: colors = 1; + } + else if (!strcmp(model, "DCS760M")) + { + bw: + colors = 1; filters = 0; } - if (!strcmp(model+4,"20X")) - strcpy (cdesc, "MYCY"); - if (strstr(model,"DC25")) { - strcpy (model, "DC25"); + if (!strcmp(model + 4, "20X")) + strcpy(cdesc, "MYCY"); + if (strstr(model, "DC25")) + { + strcpy(model, "DC25"); data_offset = 15424; } - if (!strncmp(model,"DC2",3)) { + if (!strncmp(model, "DC2", 3)) + { raw_height = 2 + (height = 242); if (!strncmp(model, "DC290", 5)) iso_speed = 100; if (!strncmp(model, "DC280", 5)) iso_speed = 70; - if (flen < 100000) { - raw_width = 256; width = 249; - pixel_aspect = (4.0*height) / (3.0*width); - } else { - raw_width = 512; width = 501; - pixel_aspect = (493.0*height) / (373.0*width); + if (flen < 100000) + { + raw_width = 256; + width = 249; + pixel_aspect = (4.0 * height) / (3.0 * width); + } + else + { + raw_width = 512; + width = 501; + pixel_aspect = (493.0 * height) / (373.0 * width); } top_margin = left_margin = 1; colors = 4; filters = 0x8d8d8d8d; simple_coeff(1); pre_mul[1] = 1.179; pre_mul[2] = 1.209; pre_mul[3] = 1.036; load_raw = &CLASS eight_bit_load_raw; - } else if (!strcmp(model,"40")) { - strcpy (model, "DC40"); + } + else if (!strcmp(model, "40")) + { + strcpy(model, "DC40"); height = 512; - width = 768; + width = 768; data_offset = 1152; load_raw = &CLASS kodak_radc_load_raw; tiff_bps = 12; - } else if (strstr(model,"DC50")) { - strcpy (model, "DC50"); + } + else if (strstr(model, "DC50")) + { + strcpy(model, "DC50"); height = 512; - width = 768; - iso_speed=84; + width = 768; + iso_speed = 84; data_offset = 19712; load_raw = &CLASS kodak_radc_load_raw; - } else if (strstr(model,"DC120")) { - strcpy (model, "DC120"); - height = 976; - width = 848; - iso_speed=160; - pixel_aspect = height/0.75/width; - load_raw = tiff_compress == 7 ? - &CLASS kodak_jpeg_load_raw : &CLASS kodak_dc120_load_raw; - } else if (!strcmp(model,"DCS200")) { + } + else if (strstr(model, "DC120")) + { + strcpy(model, "DC120"); + raw_height = height = 976; + raw_width = width = 848; + iso_speed = 160; + pixel_aspect = height / 0.75 / width; + load_raw = tiff_compress == 7 ? &CLASS kodak_jpeg_load_raw : &CLASS kodak_dc120_load_raw; + } + else if (!strcmp(model, "DCS200")) + { thumb_height = 128; - thumb_width = 192; + thumb_width = 192; thumb_offset = 6144; - thumb_misc = 360; - iso_speed=140; + thumb_misc = 360; + iso_speed = 140; write_thumb = &CLASS layer_thumb; black = 17; } - } else if (!strcmp(model,"Fotoman Pixtura")) { + } + else if (!strcmp(model, "Fotoman Pixtura")) + { height = 512; - width = 768; + width = 768; data_offset = 3632; load_raw = &CLASS kodak_radc_load_raw; filters = 0x61616161; simple_coeff(2); - } else if (!strncmp(model,"QuickTake",9)) { - if (head[5]) strcpy (model+10, "200"); - fseek (ifp, 544, SEEK_SET); + } + else if (!strncmp(model, "QuickTake", 9)) + { + if (head[5]) + strcpy(model + 10, "200"); + fseek(ifp, 544, SEEK_SET); height = get2(); - width = get2(); - data_offset = (get4(),get2()) == 30 ? 738:736; - if (height > width) { - SWAP(height,width); - fseek (ifp, data_offset-6, SEEK_SET); - flip = ~get2() & 3 ? 5:6; + width = get2(); + data_offset = (get4(), get2()) == 30 ? 738 : 736; + if (height > width) + { + SWAP(height, width); + fseek(ifp, data_offset - 6, SEEK_SET); + flip = ~get2() & 3 ? 5 : 6; } filters = 0x61616161; - } else if (!strncmp(make,"Rollei",6) && !load_raw) { - switch (raw_width) { - case 1316: - height = 1030; - width = 1300; - top_margin = 1; - left_margin = 6; - break; - case 2568: - height = 1960; - width = 2560; - top_margin = 2; - left_margin = 8; + } + else if (!strncmp(make, "Rollei", 6) && !load_raw) + { + switch (raw_width) + { + case 1316: + height = 1030; + width = 1300; + top_margin = 1; + left_margin = 6; + break; + case 2568: + height = 1960; + width = 2560; + top_margin = 2; + left_margin = 8; } filters = 0x16161616; load_raw = &CLASS rollei_load_raw; } - else if (!strcmp(model,"GRAS-50S5C")) { - height = 2048; - width = 2440; - load_raw = &CLASS unpacked_load_raw; - data_offset = 0; - filters = 0x49494949; - order = 0x4949; - maximum = 0xfffC; - } else if (!strcmp(model,"BB-500CL")) { - height = 2058; - width = 2448; - load_raw = &CLASS unpacked_load_raw; - data_offset = 0; - filters = 0x94949494; - order = 0x4949; - maximum = 0x3fff; - } else if (!strcmp(model,"BB-500GE")) { - height = 2058; - width = 2456; - load_raw = &CLASS unpacked_load_raw; - data_offset = 0; - filters = 0x94949494; - order = 0x4949; - maximum = 0x3fff; - } else if (!strcmp(model,"SVS625CL")) { - height = 2050; - width = 2448; - load_raw = &CLASS unpacked_load_raw; - data_offset = 0; - filters = 0x94949494; - order = 0x4949; - maximum = 0x0fff; + else if (!strcmp(model, "GRAS-50S5C")) + { + height = 2048; + width = 2440; + load_raw = &CLASS unpacked_load_raw; + data_offset = 0; + filters = 0x49494949; + order = 0x4949; + maximum = 0xfffC; + } + else if (!strcmp(model, "BB-500CL")) + { + height = 2058; + width = 2448; + load_raw = &CLASS unpacked_load_raw; + data_offset = 0; + filters = 0x94949494; + order = 0x4949; + maximum = 0x3fff; + } + else if (!strcmp(model, "BB-500GE")) + { + height = 2058; + width = 2456; + load_raw = &CLASS unpacked_load_raw; + data_offset = 0; + filters = 0x94949494; + order = 0x4949; + maximum = 0x3fff; + } + else if (!strcmp(model, "SVS625CL")) + { + height = 2050; + width = 2448; + load_raw = &CLASS unpacked_load_raw; + data_offset = 0; + filters = 0x94949494; + order = 0x4949; + maximum = 0x0fff; } /* Early reject for damaged images */ if (!load_raw || height < 22 || width < 22 || #ifdef LIBRAW_LIBRARY_BUILD (tiff_bps > 16 && load_raw != &LibRaw::deflate_dng_load_raw) #else - tiff_bps > 16 + tiff_bps > 16 #endif || tiff_samples > 4 || colors > 4 || colors < 1 - /* alloc in unpack() may be fooled by size adjust */ - || ( (int)width + (int)left_margin > 65535) - || ( (int)height + (int)top_margin > 65535) - ) - { - is_raw = 0; + /* alloc in unpack() may be fooled by size adjust */ + || ((int)width + (int)left_margin > 65535) || ((int)height + (int)top_margin > 65535)) + { + is_raw = 0; #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY,1,2); + RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY, 1, 2); #endif - return; - } + return; + } if (!model[0]) - sprintf (model, "%dx%d", width, height); - if (filters == UINT_MAX) filters = 0x94949494; - if (thumb_offset && !thumb_height) { - fseek (ifp, thumb_offset, SEEK_SET); - if (ljpeg_start (&jh, 1)) { - thumb_width = jh.wide; + sprintf(model, "%dx%d", width, height); + if (filters == UINT_MAX) + filters = 0x94949494; + if (thumb_offset && !thumb_height) + { + fseek(ifp, thumb_offset, SEEK_SET); + if (ljpeg_start(&jh, 1)) + { + thumb_width = jh.wide; thumb_height = jh.high; } } dng_skip: #ifdef LIBRAW_LIBRARY_BUILD - if(dng_version) /* Override black level by DNG tags */ + if (dng_version) /* Override black level by DNG tags */ { + /* copy DNG data from per-IFD field to color.dng */ + int iifd = 0; // Active IFD we'll show to user. + for (; iifd < tiff_nifds; iifd++) + if (tiff_ifd[iifd].offset == data_offset) // found + break; + int pifd = -1; + for (int ii = 0; ii < tiff_nifds; ii++) + if (tiff_ifd[ii].offset == thumb_offset) // found + { + pifd = ii; + break; + } + +#define CFAROUND(value, filters) filters ? (filters >= 1000 ? ((value + 1) / 2) * 2 : ((value + 5) / 6) * 6) : value + +#define IFDCOLORINDEX(ifd, subset, bit) \ + (tiff_ifd[ifd].dng_color[subset].parsedfields & bit) ? ifd \ + : ((tiff_ifd[0].dng_color[subset].parsedfields & bit) ? 0 : -1) + +#define IFDLEVELINDEX(ifd, bit) \ + (tiff_ifd[ifd].dng_levels.parsedfields & bit) ? ifd : ((tiff_ifd[0].dng_levels.parsedfields & bit) ? 0 : -1) + +#define COPYARR(to, from) memmove(&to, &from, sizeof(from)) + + if (iifd < tiff_nifds) + { + int sidx; + // Per field, not per structure + if (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_CHECK_DNG_ILLUMINANT) + { + int illidx[2], cmidx[2],calidx[2], abidx; + for(int i = 0; i < 2; i++) + { + illidx[i] = IFDCOLORINDEX(iifd, i, LIBRAW_DNGFM_ILLUMINANT); + cmidx[i] = IFDCOLORINDEX(iifd, i, LIBRAW_DNGFM_COLORMATRIX); + calidx[i] = IFDCOLORINDEX(iifd, i, LIBRAW_DNGFM_CALIBRATION); + } + abidx = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_ANALOGBALANCE); + // Data found, all in same ifd, illuminants are inited + if (illidx[0] >= 0 && illidx[0] < tiff_nifds && illidx[0] == illidx[1] && illidx[0] == cmidx[0] && illidx[0] == cmidx[1] + && tiff_ifd[illidx[0]].dng_color[0].illuminant>0 && tiff_ifd[illidx[0]].dng_color[1].illuminant>0) + { + sidx = illidx[0]; // => selected IFD + double cc[4][4], cm[4][3], cam_xyz[4][3]; + // CM -> Color Matrix + // CC -> Camera calibration + for (int j = 0; j < 4; j++) for (int i = 0; i < 4; i++) cc[j][i] = i == j; + int colidx = -1; + + // IS D65 here? + for(int i = 0; i < 2; i++) + { + int ill = tiff_ifd[sidx].dng_color[i].illuminant; + if (tiff_ifd[sidx].dng_color[i].illuminant == LIBRAW_WBI_D65) + { + colidx = i; break; + } + } + + // Other daylight-type ill + if(colidx<0) + for(int i = 0; i < 2; i++) + { + int ill = tiff_ifd[sidx].dng_color[i].illuminant; + if (ill == LIBRAW_WBI_Daylight || ill == LIBRAW_WBI_D55 || ill == LIBRAW_WBI_D75 || ill == LIBRAW_WBI_D50 || ill == LIBRAW_WBI_Flash) + { + colidx = i; break; + } + } + if(colidx>=0) // Selected + { + // Init camera matrix from DNG + FORCC for (int j = 0; j < 3; j++) + cm[c][j] = tiff_ifd[sidx].dng_color[colidx].colormatrix[c][j]; + + if(calidx[colidx] == sidx) + { + for (int i = 0; i < colors; i++) + FORCC + cc[i][c] = tiff_ifd[sidx].dng_color[colidx].calibration[i][c]; + } + + if(abidx == sidx) + for (int i = 0; i < colors; i++) + FORCC cc[i][c] *= tiff_ifd[sidx].dng_levels.analogbalance[i]; + int j; + FORCC for (int 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];// add AsShotXY later * xyz[i]; + cam_xyz_coeff(cmatrix, cam_xyz); + } + } + } + + if (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_USE_DNG_DEFAULT_CROP) + { + sidx = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_CROPORIGIN); + int sidx2 = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_CROPSIZE); + if (sidx >= 0 && sidx == sidx2 && tiff_ifd[sidx].dng_levels.default_crop[2] > 0 && + tiff_ifd[sidx].dng_levels.default_crop[3] > 0) + { + int lm = tiff_ifd[sidx].dng_levels.default_crop[0]; + int lmm = CFAROUND(lm, filters); + int tm = tiff_ifd[sidx].dng_levels.default_crop[1]; + int tmm = CFAROUND(tm, filters); + int ww = tiff_ifd[sidx].dng_levels.default_crop[2]; + int hh = tiff_ifd[sidx].dng_levels.default_crop[3]; + if (lmm > lm) + ww -= (lmm - lm); + if (tmm > tm) + hh -= (tmm - tm); + if (left_margin + lm + ww <= raw_width && top_margin + tm + hh <= raw_height) + { + left_margin += lmm; + top_margin += tmm; + width = ww; + height = hh; + } + } + } + if (!(imgdata.color.dng_color[0].parsedfields & LIBRAW_DNGFM_FORWARDMATRIX)) // Not set already (Leica makernotes) + { + sidx = IFDCOLORINDEX(iifd, 0, LIBRAW_DNGFM_FORWARDMATRIX); + if (sidx >= 0) + COPYARR(imgdata.color.dng_color[0].forwardmatrix, tiff_ifd[sidx].dng_color[0].forwardmatrix); + } + if (!(imgdata.color.dng_color[1].parsedfields & LIBRAW_DNGFM_FORWARDMATRIX)) // Not set already (Leica makernotes) + { + sidx = IFDCOLORINDEX(iifd, 1, LIBRAW_DNGFM_FORWARDMATRIX); + if (sidx >= 0) + COPYARR(imgdata.color.dng_color[1].forwardmatrix, tiff_ifd[sidx].dng_color[1].forwardmatrix); + } + for (int ss = 0; ss < 2; ss++) + { + sidx = IFDCOLORINDEX(iifd, ss, LIBRAW_DNGFM_COLORMATRIX); + if (sidx >= 0) + COPYARR(imgdata.color.dng_color[ss].colormatrix, tiff_ifd[sidx].dng_color[ss].colormatrix); + + sidx = IFDCOLORINDEX(iifd, ss, LIBRAW_DNGFM_CALIBRATION); + if (sidx >= 0) + COPYARR(imgdata.color.dng_color[ss].calibration, tiff_ifd[sidx].dng_color[ss].calibration); + + sidx = IFDCOLORINDEX(iifd, ss, LIBRAW_DNGFM_ILLUMINANT); + if (sidx >= 0) + imgdata.color.dng_color[ss].illuminant = tiff_ifd[sidx].dng_color[ss].illuminant; + } + // Levels + sidx = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_ANALOGBALANCE); + if (sidx >= 0) + COPYARR(imgdata.color.dng_levels.analogbalance, tiff_ifd[sidx].dng_levels.analogbalance); + sidx = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_WHITE); + if (sidx >= 0) + COPYARR(imgdata.color.dng_levels.dng_whitelevel, tiff_ifd[sidx].dng_levels.dng_whitelevel); + sidx = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_BLACK); + if (sidx >= 0) + { + imgdata.color.dng_levels.dng_black = tiff_ifd[sidx].dng_levels.dng_black; + COPYARR(imgdata.color.dng_levels.dng_cblack, tiff_ifd[sidx].dng_levels.dng_cblack); + } + if (pifd >= 0) + { + sidx = IFDLEVELINDEX(pifd, LIBRAW_DNGFM_PREVIEWCS); + if (sidx >= 0) + imgdata.color.dng_levels.preview_colorspace = tiff_ifd[sidx].dng_levels.preview_colorspace; + } + sidx = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_OPCODE2); + if (sidx >= 0) + meta_offset = tiff_ifd[sidx].opcode2_offset; + + sidx = IFDLEVELINDEX(iifd, LIBRAW_DNGFM_LINTABLE); + INT64 linoff = -1; + int linlen = 0; + if (sidx >= 0) + { + linoff = tiff_ifd[sidx].lineartable_offset; + linlen = tiff_ifd[sidx].lineartable_len; + } + + if (linoff >= 0 && linlen > 0) + { + INT64 pos = ftell(ifp); + fseek(ifp, linoff, SEEK_SET); + linear_table(linlen); + fseek(ifp, pos, SEEK_SET); + } + // Need to add curve too + } + /* Copy DNG black level to LibRaw's */ + maximum = imgdata.color.dng_levels.dng_whitelevel[0]; black = imgdata.color.dng_levels.dng_black; - int ll = LIM(0, - (sizeof(cblack)/sizeof(cblack[0])), - (sizeof(imgdata.color.dng_levels.dng_cblack)/sizeof(imgdata.color.dng_levels.dng_cblack[0]))); - for(int i=0; i < ll; i++) + int ll = LIM(0, (sizeof(cblack) / sizeof(cblack[0])), + (sizeof(imgdata.color.dng_levels.dng_cblack) / sizeof(imgdata.color.dng_levels.dng_cblack[0]))); + for (int i = 0; i < ll; i++) cblack[i] = imgdata.color.dng_levels.dng_cblack[i]; } #endif /* Early reject for damaged images */ if (!load_raw || height < 22 || width < 22 || #ifdef LIBRAW_LIBRARY_BUILD (tiff_bps > 16 && load_raw != &LibRaw::deflate_dng_load_raw) #else - tiff_bps > 16 + tiff_bps > 16 #endif || tiff_samples > 4 || colors > 4 || colors < 1) - { - is_raw = 0; + { + is_raw = 0; #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY,1,2); + RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY, 1, 2); #endif - return; - } - if ((use_camera_matrix & ((use_camera_wb || dng_version) | 0x2) ) - && cmatrix[0][0] > 0.125) { - memcpy (rgb_cam, cmatrix, sizeof cmatrix); + return; + } + { + // Check cam_mul range + int cmul_ok =1; + FORCC if(cam_mul[c] <= 0.001f) cmul_ok = 0;; + + if(cmul_ok) + { + double cmin = cam_mul[0],cmax; + double cnorm[4]; + FORCC cmin = MIN(cmin,cam_mul[c]); + FORCC cnorm[c] = cam_mul[c]/cmin; + cmax = cmin = cnorm[0]; + FORCC + { + cmin = MIN(cmin,cnorm[c]); + cmax = MIN(cmax,cnorm[c]); + } + if(cmin <= 0.01f || cmax > 100.f) + cmul_ok = false; + } + if(!cmul_ok) + cam_mul[0] = cam_mul[3] = 0; + + } + if ((use_camera_matrix & ((use_camera_wb || dng_version) | 0x2)) && cmatrix[0][0] > 0.125) + { + memcpy(rgb_cam, cmatrix, sizeof cmatrix); raw_color = 0; } - if (raw_color) adobe_coeff (make, model); + if (raw_color) + adobe_coeff(make, model); #ifdef LIBRAW_LIBRARY_BUILD - else if(imgdata.color.cam_xyz[0][0]<0.01) - adobe_coeff (make, model,1); + else if (imgdata.color.cam_xyz[0][0] < 0.01) + adobe_coeff(make, model, 1); #endif if (load_raw == &CLASS kodak_radc_load_raw) - if (raw_color) adobe_coeff ("Apple","Quicktake"); + if (raw_color) + adobe_coeff("Apple", "Quicktake"); #ifdef LIBRAW_LIBRARY_BUILD // Clear erorneus fuji_width if not set through parse_fuji or for DNG - if(fuji_width && !dng_version && !(imgdata.process_warnings & LIBRAW_WARN_PARSEFUJI_PROCESSED )) - fuji_width = 0; + if (fuji_width && !dng_version && !(imgdata.process_warnings & LIBRAW_WARN_PARSEFUJI_PROCESSED)) + fuji_width = 0; #endif if (fuji_width) { fuji_width = width >> !fuji_layout; filters = fuji_width & 1 ? 0x94949494 : 0x49494949; width = (height >> fuji_layout) + fuji_width; height = width - 1; pixel_aspect = 1; - } else { - if (raw_height < height) raw_height = height; - if (raw_width < width ) raw_width = width; } - if (!tiff_bps) tiff_bps = 12; + else + { + if (raw_height < height) + raw_height = height; + if (raw_width < width) + raw_width = width; + } + if (!tiff_bps) + tiff_bps = 12; if (!maximum) - { - maximum = (1 << tiff_bps) - 1; - if(maximum < 0x10000 && curve[maximum]>0 && load_raw == &CLASS sony_arw2_load_raw) - maximum = curve[maximum]; - } + { + maximum = (1 << tiff_bps) - 1; + if (maximum < 0x10000 && curve[maximum] > 0 && load_raw == &CLASS sony_arw2_load_raw) + maximum = curve[maximum]; + } if (!load_raw || height < 22 || width < 22 || #ifdef LIBRAW_LIBRARY_BUILD (tiff_bps > 16 && load_raw != &LibRaw::deflate_dng_load_raw) #else - tiff_bps > 16 + tiff_bps > 16 #endif || tiff_samples > 6 || colors > 4) is_raw = 0; - if(raw_width < 22 || raw_width > 64000 || raw_height < 22 || raw_width > 64000) + if (raw_width < 22 || raw_width > 64000 || raw_height < 22 || raw_height > 64000) is_raw = 0; #ifdef NO_JASPER - if (load_raw == &CLASS redcine_load_raw) { + if (load_raw == &CLASS redcine_load_raw) + { #ifdef DCRAW_VERBOSE - fprintf (stderr,_("%s: You must link dcraw with %s!!\n"), - ifname, "libjasper"); + fprintf(stderr, _("%s: You must link dcraw with %s!!\n"), ifname, "libjasper"); #endif is_raw = 0; #ifdef LIBRAW_LIBRARY_BUILD imgdata.process_warnings |= LIBRAW_WARN_NO_JASPER; #endif } #endif #ifdef NO_JPEG - if (load_raw == &CLASS kodak_jpeg_load_raw || - load_raw == &CLASS lossy_dng_load_raw) { + if (load_raw == &CLASS kodak_jpeg_load_raw || load_raw == &CLASS lossy_dng_load_raw) + { #ifdef DCRAW_VERBOSE - fprintf (stderr,_("%s: You must link dcraw with %s!!\n"), - ifname, "libjpeg"); + fprintf(stderr, _("%s: You must link dcraw with %s!!\n"), ifname, "libjpeg"); #endif is_raw = 0; #ifdef LIBRAW_LIBRARY_BUILD imgdata.process_warnings |= LIBRAW_WARN_NO_JPEGLIB; #endif } #endif if (!cdesc[0]) - strcpy (cdesc, colors == 3 ? "RGBG":"GMCY"); - if (!raw_height) raw_height = height; - if (!raw_width ) raw_width = width; + strcpy(cdesc, colors == 3 ? "RGBG" : "GMCY"); + if (!raw_height) + raw_height = height; + if (!raw_width) + raw_width = width; if (filters > 999 && colors == 3) - filters |= ((filters >> 2 & 0x22222222) | - (filters << 2 & 0x88888888)) & filters << 1; + filters |= ((filters >> 2 & 0x22222222) | (filters << 2 & 0x88888888)) & filters << 1; notraw: - if (flip == UINT_MAX) flip = tiff_flip; - if (flip == UINT_MAX) flip = 0; + if (flip == UINT_MAX) + flip = tiff_flip; + if (flip == UINT_MAX) + flip = 0; // Convert from degrees to bit-field if needed - if(flip > 89 || flip < -89) - { - switch ((flip+3600) % 360) - { - case 270: flip = 5; break; - case 180: flip = 3; break; - case 90: flip = 6; break; - } - } + if (flip > 89 || flip < -89) + { + switch ((flip + 3600) % 360) + { + case 270: + flip = 5; + break; + case 180: + flip = 3; + break; + case 90: + flip = 6; + break; + } + } #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY,1,2); + RUN_CALLBACK(LIBRAW_PROGRESS_IDENTIFY, 1, 2); #endif } - void CLASS convert_to_rgb() { #ifndef LIBRAW_LIBRARY_BUILD int row, col, c; #endif - int i, j, k; + int i, j, k; #ifndef LIBRAW_LIBRARY_BUILD ushort *img; float out[3]; #endif float out_cam[3][4]; double num, inverse[3][3]; - static const double xyzd50_srgb[3][3] = - { { 0.436083, 0.385083, 0.143055 }, - { 0.222507, 0.716888, 0.060608 }, - { 0.013930, 0.097097, 0.714022 } }; - static const double rgb_rgb[3][3] = - { { 1,0,0 }, { 0,1,0 }, { 0,0,1 } }; - static const double adobe_rgb[3][3] = - { { 0.715146, 0.284856, 0.000000 }, - { 0.000000, 1.000000, 0.000000 }, - { 0.000000, 0.041166, 0.958839 } }; - static const double wide_rgb[3][3] = - { { 0.593087, 0.404710, 0.002206 }, - { 0.095413, 0.843149, 0.061439 }, - { 0.011621, 0.069091, 0.919288 } }; - static const double prophoto_rgb[3][3] = - { { 0.529317, 0.330092, 0.140588 }, - { 0.098368, 0.873465, 0.028169 }, - { 0.016879, 0.117663, 0.865457 } }; - static const double aces_rgb[3][3] = - { { 0.432996, 0.375380, 0.189317 }, - { 0.089427, 0.816523, 0.102989 }, - { 0.019165, 0.118150, 0.941914 } }; - static const double (*out_rgb[])[3] = - { rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb, aces_rgb }; - static const char *name[] = - { "sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ", "ACES" }; - static const unsigned phead[] = - { 1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0, 0, 0, - 0x61637370, 0, 0, 0x6e6f6e65, 0, 0, 0, 0, 0xf6d6, 0x10000, 0xd32d }; - unsigned pbody[] = - { 10, 0x63707274, 0, 36, /* cprt */ - 0x64657363, 0, 40, /* desc */ - 0x77747074, 0, 20, /* wtpt */ - 0x626b7074, 0, 20, /* bkpt */ - 0x72545243, 0, 14, /* rTRC */ - 0x67545243, 0, 14, /* gTRC */ - 0x62545243, 0, 14, /* bTRC */ - 0x7258595a, 0, 20, /* rXYZ */ - 0x6758595a, 0, 20, /* gXYZ */ - 0x6258595a, 0, 20 }; /* bXYZ */ - static const unsigned pwhite[] = { 0xf351, 0x10000, 0x116cc }; - unsigned pcurve[] = { 0x63757276, 0, 1, 0x1000000 }; - -#ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_CONVERT_RGB,0,2); -#endif - gamma_curve (gamm[0], gamm[1], 0, 0); - memcpy (out_cam, rgb_cam, sizeof out_cam); + static const double xyzd50_srgb[3][3] = { + {0.436083, 0.385083, 0.143055}, {0.222507, 0.716888, 0.060608}, {0.013930, 0.097097, 0.714022}}; + static const double rgb_rgb[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; + static const double adobe_rgb[3][3] = { + {0.715146, 0.284856, 0.000000}, {0.000000, 1.000000, 0.000000}, {0.000000, 0.041166, 0.958839}}; + static const double wide_rgb[3][3] = { + {0.593087, 0.404710, 0.002206}, {0.095413, 0.843149, 0.061439}, {0.011621, 0.069091, 0.919288}}; + static const double prophoto_rgb[3][3] = { + {0.529317, 0.330092, 0.140588}, {0.098368, 0.873465, 0.028169}, {0.016879, 0.117663, 0.865457}}; + static const double aces_rgb[3][3] = { + {0.432996, 0.375380, 0.189317}, {0.089427, 0.816523, 0.102989}, {0.019165, 0.118150, 0.941914}}; + static const double(*out_rgb[])[3] = {rgb_rgb, adobe_rgb, wide_rgb, prophoto_rgb, xyz_rgb, aces_rgb}; + static const char *name[] = {"sRGB", "Adobe RGB (1998)", "WideGamut D65", "ProPhoto D65", "XYZ", "ACES"}; + static const unsigned phead[] = {1024, 0, 0x2100000, 0x6d6e7472, 0x52474220, 0x58595a20, 0, + 0, 0, 0x61637370, 0, 0, 0x6e6f6e65, 0, + 0, 0, 0, 0xf6d6, 0x10000, 0xd32d}; + unsigned pbody[] = {10, 0x63707274, 0, 36, /* cprt */ + 0x64657363, 0, 40, /* desc */ + 0x77747074, 0, 20, /* wtpt */ + 0x626b7074, 0, 20, /* bkpt */ + 0x72545243, 0, 14, /* rTRC */ + 0x67545243, 0, 14, /* gTRC */ + 0x62545243, 0, 14, /* bTRC */ + 0x7258595a, 0, 20, /* rXYZ */ + 0x6758595a, 0, 20, /* gXYZ */ + 0x6258595a, 0, 20}; /* bXYZ */ + static const unsigned pwhite[] = {0xf351, 0x10000, 0x116cc}; + unsigned pcurve[] = {0x63757276, 0, 1, 0x1000000}; + +#ifdef LIBRAW_LIBRARY_BUILD + RUN_CALLBACK(LIBRAW_PROGRESS_CONVERT_RGB, 0, 2); +#endif + gamma_curve(gamm[0], gamm[1], 0, 0); + memcpy(out_cam, rgb_cam, sizeof out_cam); #ifndef LIBRAW_LIBRARY_BUILD - raw_color |= colors == 1 || document_mode || - output_color < 1 || output_color > 6; + raw_color |= colors == 1 || document_mode || output_color < 1 || output_color > 6; #else - raw_color |= colors == 1 || - output_color < 1 || output_color > 6; -#endif - if (!raw_color) { - oprof = (unsigned *) calloc (phead[0], 1); - merror (oprof, "convert_to_rgb()"); - memcpy (oprof, phead, sizeof phead); - if (output_color == 5) oprof[4] = oprof[5]; - oprof[0] = 132 + 12*pbody[0]; - for (i=0; i < pbody[0]; i++) { - oprof[oprof[0]/4] = i ? (i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874; - pbody[i*3+2] = oprof[0]; - oprof[0] += (pbody[i*3+3] + 3) & -4; - } - memcpy (oprof+32, pbody, sizeof pbody); - oprof[pbody[5]/4+2] = strlen(name[output_color-1]) + 1; - memcpy ((char *)oprof+pbody[8]+8, pwhite, sizeof pwhite); - pcurve[3] = (short)(256/gamm[5]+0.5) << 16; - for (i=4; i < 7; i++) - memcpy ((char *)oprof+pbody[i*3+2], pcurve, sizeof pcurve); - pseudoinverse ((double (*)[3]) out_rgb[output_color-1], inverse, 3); - for (i=0; i < 3; i++) - for (j=0; j < 3; j++) { - for (num = k=0; k < 3; k++) - num += xyzd50_srgb[i][k] * inverse[j][k]; - oprof[pbody[j*3+23]/4+i+2] = num * 0x10000 + 0.5; - } - for (i=0; i < phead[0]/4; i++) + raw_color |= colors == 1 || output_color < 1 || output_color > 6; +#endif + if (!raw_color) + { + oprof = (unsigned *)calloc(phead[0], 1); + merror(oprof, "convert_to_rgb()"); + memcpy(oprof, phead, sizeof phead); + if (output_color == 5) + oprof[4] = oprof[5]; + oprof[0] = 132 + 12 * pbody[0]; + for (i = 0; i < pbody[0]; i++) + { + oprof[oprof[0] / 4] = i ? (i > 1 ? 0x58595a20 : 0x64657363) : 0x74657874; + pbody[i * 3 + 2] = oprof[0]; + oprof[0] += (pbody[i * 3 + 3] + 3) & -4; + } + memcpy(oprof + 32, pbody, sizeof pbody); + oprof[pbody[5] / 4 + 2] = strlen(name[output_color - 1]) + 1; + memcpy((char *)oprof + pbody[8] + 8, pwhite, sizeof pwhite); + pcurve[3] = (short)(256 / gamm[5] + 0.5) << 16; + for (i = 4; i < 7; i++) + memcpy((char *)oprof + pbody[i * 3 + 2], pcurve, sizeof pcurve); + pseudoinverse((double(*)[3])out_rgb[output_color - 1], inverse, 3); + for (i = 0; i < 3; i++) + for (j = 0; j < 3; j++) + { + for (num = k = 0; k < 3; k++) + num += xyzd50_srgb[i][k] * inverse[j][k]; + oprof[pbody[j * 3 + 23] / 4 + i + 2] = num * 0x10000 + 0.5; + } + for (i = 0; i < phead[0] / 4; i++) oprof[i] = htonl(oprof[i]); - strcpy ((char *)oprof+pbody[2]+8, "auto-generated by dcraw"); - strcpy ((char *)oprof+pbody[5]+12, name[output_color-1]); - for (i=0; i < 3; i++) - for (j=0; j < colors; j++) - for (out_cam[i][j] = k=0; k < 3; k++) - out_cam[i][j] += out_rgb[output_color-1][i][k] * rgb_cam[k][j]; + strcpy((char *)oprof + pbody[2] + 8, "auto-generated by dcraw"); + strcpy((char *)oprof + pbody[5] + 12, name[output_color - 1]); + for (i = 0; i < 3; i++) + for (j = 0; j < colors; j++) + for (out_cam[i][j] = k = 0; k < 3; k++) + out_cam[i][j] += out_rgb[output_color - 1][i][k] * rgb_cam[k][j]; } #ifdef DCRAW_VERBOSE if (verbose) - fprintf (stderr, raw_color ? _("Building histograms...\n") : - _("Converting to %s colorspace...\n"), name[output_color-1]); + fprintf(stderr, raw_color ? _("Building histograms...\n") : _("Converting to %s colorspace...\n"), + name[output_color - 1]); #endif #ifdef LIBRAW_LIBRARY_BUILD convert_to_rgb_loop(out_cam); #else - memset (histogram, 0, sizeof histogram); - for (img=image[0], row=0; row < height; row++) - for (col=0; col < width; col++, img+=4) { - if (!raw_color) { - out[0] = out[1] = out[2] = 0; - FORCC { - out[0] += out_cam[0][c] * img[c]; - out[1] += out_cam[1][c] * img[c]; - out[2] += out_cam[2][c] * img[c]; - } - FORC3 img[c] = CLIP((int) out[c]); + memset(histogram, 0, sizeof histogram); + for (img = image[0], row = 0; row < height; row++) + for (col = 0; col < width; col++, img += 4) + { + if (!raw_color) + { + out[0] = out[1] = out[2] = 0; + FORCC + { + out[0] += out_cam[0][c] * img[c]; + out[1] += out_cam[1][c] * img[c]; + out[2] += out_cam[2][c] * img[c]; + } + FORC3 img[c] = CLIP((int)out[c]); } else if (document_mode) - img[0] = img[fcol(row,col)]; + img[0] = img[fcol(row, col)]; FORCC histogram[c][img[c] >> 3]++; } #endif - if (colors == 4 && output_color) colors = 3; + if (colors == 4 && output_color) + colors = 3; #ifndef LIBRAW_LIBRARY_BUILD - if (document_mode && filters) colors = 1; + if (document_mode && filters) + colors = 1; #endif #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_CONVERT_RGB,1,2); + RUN_CALLBACK(LIBRAW_PROGRESS_CONVERT_RGB, 1, 2); #endif } void CLASS fuji_rotate() { int i, row, col; double step; float r, c, fr, fc; unsigned ur, uc; ushort wide, high, (*img)[4], (*pix)[4]; - if (!fuji_width) return; + if (!fuji_width) + return; #ifdef DCRAW_VERBOSE if (verbose) - fprintf (stderr,_("Rotating image 45 degrees...\n")); + fprintf(stderr, _("Rotating image 45 degrees...\n")); #endif fuji_width = (fuji_width - 1 + shrink) >> shrink; step = sqrt(0.5); wide = fuji_width / step; high = (height - fuji_width) / step; - img = (ushort (*)[4]) calloc (high, wide*sizeof *img); - merror (img, "fuji_rotate()"); + img = (ushort(*)[4])calloc(high, wide * sizeof *img); + merror(img, "fuji_rotate()"); #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_FUJI_ROTATE,0,2); + RUN_CALLBACK(LIBRAW_PROGRESS_FUJI_ROTATE, 0, 2); #endif - for (row=0; row < high; row++) - for (col=0; col < wide; col++) { - ur = r = fuji_width + (row-col)*step; - uc = c = (row+col)*step; - if (ur > height-2 || uc > width-2) continue; + for (row = 0; row < high; row++) + for (col = 0; col < wide; col++) + { + ur = r = fuji_width + (row - col) * step; + uc = c = (row + col) * step; + if (ur > height - 2 || uc > width - 2) + continue; fr = r - ur; fc = c - uc; - pix = image + ur*width + uc; - for (i=0; i < colors; i++) - img[row*wide+col][i] = - (pix[ 0][i]*(1-fc) + pix[ 1][i]*fc) * (1-fr) + - (pix[width][i]*(1-fc) + pix[width+1][i]*fc) * fr; + pix = image + ur * width + uc; + for (i = 0; i < colors; i++) + img[row * wide + col][i] = (pix[0][i] * (1 - fc) + pix[1][i] * fc) * (1 - fr) + + (pix[width][i] * (1 - fc) + pix[width + 1][i] * fc) * fr; } - free (image); - width = wide; + free(image); + width = wide; height = high; - image = img; + image = img; fuji_width = 0; #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_FUJI_ROTATE,1,2); + RUN_CALLBACK(LIBRAW_PROGRESS_FUJI_ROTATE, 1, 2); #endif } void CLASS stretch() { ushort newdim, (*img)[4], *pix0, *pix1; int row, col, c; double rc, frac; - if (pixel_aspect == 1) return; + if (pixel_aspect == 1) + return; #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_STRETCH,0,2); + RUN_CALLBACK(LIBRAW_PROGRESS_STRETCH, 0, 2); #endif #ifdef DCRAW_VERBOSE - if (verbose) fprintf (stderr,_("Stretching the image...\n")); + if (verbose) + fprintf(stderr, _("Stretching the image...\n")); #endif - if (pixel_aspect < 1) { + if (pixel_aspect < 1) + { newdim = height / pixel_aspect + 0.5; - img = (ushort (*)[4]) calloc (width, newdim*sizeof *img); - merror (img, "stretch()"); - for (rc=row=0; row < newdim; row++, rc+=pixel_aspect) { + img = (ushort(*)[4])calloc(width, newdim * sizeof *img); + merror(img, "stretch()"); + for (rc = row = 0; row < newdim; row++, rc += pixel_aspect) + { frac = rc - (c = rc); - pix0 = pix1 = image[c*width]; - if (c+1 < height) pix1 += width*4; - for (col=0; col < width; col++, pix0+=4, pix1+=4) - FORCC img[row*width+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5; + pix0 = pix1 = image[c * width]; + if (c + 1 < height) + pix1 += width * 4; + for (col = 0; col < width; col++, pix0 += 4, pix1 += 4) + FORCC img[row * width + col][c] = pix0[c] * (1 - frac) + pix1[c] * frac + 0.5; } height = newdim; - } else { + } + else + { newdim = width * pixel_aspect + 0.5; - img = (ushort (*)[4]) calloc (height, newdim*sizeof *img); - merror (img, "stretch()"); - for (rc=col=0; col < newdim; col++, rc+=1/pixel_aspect) { + img = (ushort(*)[4])calloc(height, newdim * sizeof *img); + merror(img, "stretch()"); + for (rc = col = 0; col < newdim; col++, rc += 1 / pixel_aspect) + { frac = rc - (c = rc); pix0 = pix1 = image[c]; - if (c+1 < width) pix1 += 4; - for (row=0; row < height; row++, pix0+=width*4, pix1+=width*4) - FORCC img[row*newdim+col][c] = pix0[c]*(1-frac) + pix1[c]*frac + 0.5; + if (c + 1 < width) + pix1 += 4; + for (row = 0; row < height; row++, pix0 += width * 4, pix1 += width * 4) + FORCC img[row * newdim + col][c] = pix0[c] * (1 - frac) + pix1[c] * frac + 0.5; } width = newdim; } - free (image); + free(image); image = img; #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_STRETCH,1,2); + RUN_CALLBACK(LIBRAW_PROGRESS_STRETCH, 1, 2); #endif } -int CLASS flip_index (int row, int col) +int CLASS flip_index(int row, int col) { - if (flip & 4) SWAP(row,col); - if (flip & 2) row = iheight - 1 - row; - if (flip & 1) col = iwidth - 1 - col; + if (flip & 4) + SWAP(row, col); + if (flip & 2) + row = iheight - 1 - row; + if (flip & 1) + col = iwidth - 1 - col; return row * iwidth + col; } -void CLASS tiff_set (struct tiff_hdr *th, ushort *ntag, - ushort tag, ushort type, int count, int val) +void CLASS tiff_set(struct tiff_hdr *th, ushort *ntag, ushort tag, ushort type, int count, int val) { - struct tiff_tag *tt; + struct libraw_tiff_tag *tt; int c; - tt = (struct tiff_tag *)(ntag+1) + (*ntag)++; + tt = (struct libraw_tiff_tag *)(ntag + 1) + (*ntag)++; tt->val.i = val; if (type == 1 && count <= 4) FORC(4) tt->val.c[c] = val >> (c << 3); - else if (type == 2) { - count = strnlen((char *)th + val, count-1) + 1; + else if (type == 2) + { + count = strnlen((char *)th + val, count - 1) + 1; if (count <= 4) - FORC(4) tt->val.c[c] = ((char *)th)[val+c]; - } else if (type == 3 && count <= 2) + FORC(4) tt->val.c[c] = ((char *)th)[val + c]; + } + else if (type == 3 && count <= 2) FORC(2) tt->val.s[c] = val >> (c << 4); tt->count = count; tt->type = type; tt->tag = tag; } #define TOFF(ptr) ((char *)(&(ptr)) - (char *)th) -void CLASS tiff_head (struct tiff_hdr *th, int full) +void CLASS tiff_head(struct tiff_hdr *th, int full) { - int c, psize=0; + int c, psize = 0; struct tm *t; - memset (th, 0, sizeof *th); + memset(th, 0, sizeof *th); th->t_order = htonl(0x4d4d4949) >> 16; th->magic = 42; th->ifd = 10; th->rat[0] = th->rat[2] = 300; th->rat[1] = th->rat[3] = 1; - FORC(6) th->rat[4+c] = 1000000; + FORC(6) th->rat[4 + c] = 1000000; th->rat[4] *= shutter; th->rat[6] *= aperture; th->rat[8] *= focal_len; - strncpy (th->t_desc, desc, 512); - strncpy (th->t_make, make, 64); - strncpy (th->t_model, model, 64); - strcpy (th->soft, "dcraw v" DCRAW_VERSION); - t = localtime (×tamp); - sprintf (th->date, "%04d:%02d:%02d %02d:%02d:%02d", - t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec); - strncpy (th->t_artist, artist, 64); - if (full) { - tiff_set (th, &th->ntag, 254, 4, 1, 0); - tiff_set (th, &th->ntag, 256, 4, 1, width); - tiff_set (th, &th->ntag, 257, 4, 1, height); - tiff_set (th, &th->ntag, 258, 3, colors, output_bps); + strncpy(th->t_desc, desc, 512); + strncpy(th->t_make, make, 64); + strncpy(th->t_model, model, 64); + strcpy(th->soft, "dcraw v" DCRAW_VERSION); + t = localtime(×tamp); + sprintf(th->date, "%04d:%02d:%02d %02d:%02d:%02d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, + t->tm_min, t->tm_sec); + strncpy(th->t_artist, artist, 64); + if (full) + { + tiff_set(th, &th->ntag, 254, 4, 1, 0); + tiff_set(th, &th->ntag, 256, 4, 1, width); + tiff_set(th, &th->ntag, 257, 4, 1, height); + tiff_set(th, &th->ntag, 258, 3, colors, output_bps); if (colors > 2) - th->tag[th->ntag-1].val.i = TOFF(th->bps); + th->tag[th->ntag - 1].val.i = TOFF(th->bps); FORC4 th->bps[c] = output_bps; - tiff_set (th, &th->ntag, 259, 3, 1, 1); - tiff_set (th, &th->ntag, 262, 3, 1, 1 + (colors > 1)); - } - tiff_set (th, &th->ntag, 270, 2, 512, TOFF(th->t_desc)); - tiff_set (th, &th->ntag, 271, 2, 64, TOFF(th->t_make)); - tiff_set (th, &th->ntag, 272, 2, 64, TOFF(th->t_model)); - if (full) { - if (oprof) psize = ntohl(oprof[0]); - tiff_set (th, &th->ntag, 273, 4, 1, sizeof *th + psize); - tiff_set (th, &th->ntag, 277, 3, 1, colors); - tiff_set (th, &th->ntag, 278, 4, 1, height); - tiff_set (th, &th->ntag, 279, 4, 1, height*width*colors*output_bps/8); - } else - tiff_set (th, &th->ntag, 274, 3, 1, "12435867"[flip]-'0'); - tiff_set (th, &th->ntag, 282, 5, 1, TOFF(th->rat[0])); - tiff_set (th, &th->ntag, 283, 5, 1, TOFF(th->rat[2])); - tiff_set (th, &th->ntag, 284, 3, 1, 1); - tiff_set (th, &th->ntag, 296, 3, 1, 2); - tiff_set (th, &th->ntag, 305, 2, 32, TOFF(th->soft)); - tiff_set (th, &th->ntag, 306, 2, 20, TOFF(th->date)); - tiff_set (th, &th->ntag, 315, 2, 64, TOFF(th->t_artist)); - tiff_set (th, &th->ntag, 34665, 4, 1, TOFF(th->nexif)); - if (psize) tiff_set (th, &th->ntag, 34675, 7, psize, sizeof *th); - tiff_set (th, &th->nexif, 33434, 5, 1, TOFF(th->rat[4])); - tiff_set (th, &th->nexif, 33437, 5, 1, TOFF(th->rat[6])); - tiff_set (th, &th->nexif, 34855, 3, 1, iso_speed); - tiff_set (th, &th->nexif, 37386, 5, 1, TOFF(th->rat[8])); - if (gpsdata[1]) { - tiff_set (th, &th->ntag, 34853, 4, 1, TOFF(th->ngps)); - tiff_set (th, &th->ngps, 0, 1, 4, 0x202); - tiff_set (th, &th->ngps, 1, 2, 2, gpsdata[29]); - tiff_set (th, &th->ngps, 2, 5, 3, TOFF(th->gps[0])); - tiff_set (th, &th->ngps, 3, 2, 2, gpsdata[30]); - tiff_set (th, &th->ngps, 4, 5, 3, TOFF(th->gps[6])); - tiff_set (th, &th->ngps, 5, 1, 1, gpsdata[31]); - tiff_set (th, &th->ngps, 6, 5, 1, TOFF(th->gps[18])); - tiff_set (th, &th->ngps, 7, 5, 3, TOFF(th->gps[12])); - tiff_set (th, &th->ngps, 18, 2, 12, TOFF(th->gps[20])); - tiff_set (th, &th->ngps, 29, 2, 12, TOFF(th->gps[23])); - memcpy (th->gps, gpsdata, sizeof th->gps); - } -} - -#ifdef LIBRAW_LIBRARY_BUILD -void CLASS jpeg_thumb_writer (FILE *tfp,char *t_humb,int t_humb_length) + tiff_set(th, &th->ntag, 259, 3, 1, 1); + tiff_set(th, &th->ntag, 262, 3, 1, 1 + (colors > 1)); + } + tiff_set(th, &th->ntag, 270, 2, 512, TOFF(th->t_desc)); + tiff_set(th, &th->ntag, 271, 2, 64, TOFF(th->t_make)); + tiff_set(th, &th->ntag, 272, 2, 64, TOFF(th->t_model)); + if (full) + { + if (oprof) + psize = ntohl(oprof[0]); + tiff_set(th, &th->ntag, 273, 4, 1, sizeof *th + psize); + tiff_set(th, &th->ntag, 277, 3, 1, colors); + tiff_set(th, &th->ntag, 278, 4, 1, height); + tiff_set(th, &th->ntag, 279, 4, 1, height * width * colors * output_bps / 8); + } + else + tiff_set(th, &th->ntag, 274, 3, 1, "12435867"[flip] - '0'); + tiff_set(th, &th->ntag, 282, 5, 1, TOFF(th->rat[0])); + tiff_set(th, &th->ntag, 283, 5, 1, TOFF(th->rat[2])); + tiff_set(th, &th->ntag, 284, 3, 1, 1); + tiff_set(th, &th->ntag, 296, 3, 1, 2); + tiff_set(th, &th->ntag, 305, 2, 32, TOFF(th->soft)); + tiff_set(th, &th->ntag, 306, 2, 20, TOFF(th->date)); + tiff_set(th, &th->ntag, 315, 2, 64, TOFF(th->t_artist)); + tiff_set(th, &th->ntag, 34665, 4, 1, TOFF(th->nexif)); + if (psize) + tiff_set(th, &th->ntag, 34675, 7, psize, sizeof *th); + tiff_set(th, &th->nexif, 33434, 5, 1, TOFF(th->rat[4])); + tiff_set(th, &th->nexif, 33437, 5, 1, TOFF(th->rat[6])); + tiff_set(th, &th->nexif, 34855, 3, 1, iso_speed); + tiff_set(th, &th->nexif, 37386, 5, 1, TOFF(th->rat[8])); + if (gpsdata[1]) + { + tiff_set(th, &th->ntag, 34853, 4, 1, TOFF(th->ngps)); + tiff_set(th, &th->ngps, 0, 1, 4, 0x202); + tiff_set(th, &th->ngps, 1, 2, 2, gpsdata[29]); + tiff_set(th, &th->ngps, 2, 5, 3, TOFF(th->gps[0])); + tiff_set(th, &th->ngps, 3, 2, 2, gpsdata[30]); + tiff_set(th, &th->ngps, 4, 5, 3, TOFF(th->gps[6])); + tiff_set(th, &th->ngps, 5, 1, 1, gpsdata[31]); + tiff_set(th, &th->ngps, 6, 5, 1, TOFF(th->gps[18])); + tiff_set(th, &th->ngps, 7, 5, 3, TOFF(th->gps[12])); + tiff_set(th, &th->ngps, 18, 2, 12, TOFF(th->gps[20])); + tiff_set(th, &th->ngps, 29, 2, 12, TOFF(th->gps[23])); + memcpy(th->gps, gpsdata, sizeof th->gps); + } +} + +#ifdef LIBRAW_LIBRARY_BUILD +void CLASS jpeg_thumb_writer(FILE *tfp, char *t_humb, int t_humb_length) { ushort exif[5]; struct tiff_hdr th; - fputc (0xff, tfp); - fputc (0xd8, tfp); - if (strcmp (t_humb+6, "Exif")) { - memcpy (exif, "\xff\xe1 Exif\0\0", 10); - exif[1] = htons (8 + sizeof th); - fwrite (exif, 1, sizeof exif, tfp); - tiff_head (&th, 0); - fwrite (&th, 1, sizeof th, tfp); + fputc(0xff, tfp); + fputc(0xd8, tfp); + if (strcmp(t_humb + 6, "Exif")) + { + memcpy(exif, "\xff\xe1 Exif\0\0", 10); + exif[1] = htons(8 + sizeof th); + fwrite(exif, 1, sizeof exif, tfp); + tiff_head(&th, 0); + fwrite(&th, 1, sizeof th, tfp); } - fwrite (t_humb+2, 1, t_humb_length-2, tfp); + fwrite(t_humb + 2, 1, t_humb_length - 2, tfp); } void CLASS jpeg_thumb() { char *thumb; - thumb = (char *) malloc (thumb_length); - merror (thumb, "jpeg_thumb()"); - fread (thumb, 1, thumb_length, ifp); - jpeg_thumb_writer(ofp,thumb,thumb_length); - free (thumb); + thumb = (char *)malloc(thumb_length); + merror(thumb, "jpeg_thumb()"); + fread(thumb, 1, thumb_length, ifp); + jpeg_thumb_writer(ofp, thumb, thumb_length); + free(thumb); } #else void CLASS jpeg_thumb() { char *thumb; ushort exif[5]; struct tiff_hdr th; - thumb = (char *) malloc (thumb_length); - merror (thumb, "jpeg_thumb()"); - fread (thumb, 1, thumb_length, ifp); - fputc (0xff, ofp); - fputc (0xd8, ofp); - if (strcmp (thumb+6, "Exif")) { - memcpy (exif, "\xff\xe1 Exif\0\0", 10); - exif[1] = htons (8 + sizeof th); - fwrite (exif, 1, sizeof exif, ofp); - tiff_head (&th, 0); - fwrite (&th, 1, sizeof th, ofp); + thumb = (char *)malloc(thumb_length); + merror(thumb, "jpeg_thumb()"); + fread(thumb, 1, thumb_length, ifp); + fputc(0xff, ofp); + fputc(0xd8, ofp); + if (strcmp(thumb + 6, "Exif")) + { + memcpy(exif, "\xff\xe1 Exif\0\0", 10); + exif[1] = htons(8 + sizeof th); + fwrite(exif, 1, sizeof exif, ofp); + tiff_head(&th, 0); + fwrite(&th, 1, sizeof th, ofp); } - fwrite (thumb+2, 1, thumb_length-2, ofp); - free (thumb); + fwrite(thumb + 2, 1, thumb_length - 2, ofp); + free(thumb); } #endif void CLASS write_ppm_tiff() { struct tiff_hdr th; uchar *ppm; ushort *ppm2; int c, row, col, soff, rstep, cstep; - int perc, val, total, t_white=0x2000; + int perc, val, total, t_white = 0x2000; #ifdef LIBRAW_LIBRARY_BUILD perc = width * height * auto_bright_thr; #else - perc = width * height * 0.01; /* 99th percentile white level */ + perc = width * height * 0.01; /* 99th percentile white level */ #endif - if (fuji_width) perc /= 2; + if (fuji_width) + perc /= 2; if (!((highlight & ~2) || no_auto_bright)) - for (t_white=c=0; c < colors; c++) { - for (val=0x2000, total=0; --val > 32; ) - if ((total += histogram[c][val]) > perc) break; - if (t_white < val) t_white = val; + for (t_white = c = 0; c < colors; c++) + { + for (val = 0x2000, total = 0; --val > 32;) + if ((total += histogram[c][val]) > perc) + break; + if (t_white < val) + t_white = val; } - gamma_curve (gamm[0], gamm[1], 2, (t_white << 3)/bright); + gamma_curve(gamm[0], gamm[1], 2, (t_white << 3) / bright); iheight = height; - iwidth = width; - if (flip & 4) SWAP(height,width); - ppm = (uchar *) calloc (width, colors*output_bps/8); - ppm2 = (ushort *) ppm; - merror (ppm, "write_ppm_tiff()"); - if (output_tiff) { - tiff_head (&th, 1); - fwrite (&th, sizeof th, 1, ofp); + iwidth = width; + if (flip & 4) + SWAP(height, width); + ppm = (uchar *)calloc(width, colors * output_bps / 8); + ppm2 = (ushort *)ppm; + merror(ppm, "write_ppm_tiff()"); + if (output_tiff) + { + tiff_head(&th, 1); + fwrite(&th, sizeof th, 1, ofp); if (oprof) - fwrite (oprof, ntohl(oprof[0]), 1, ofp); - } else if (colors > 3) - fprintf (ofp, - "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n", - width, height, colors, (1 << output_bps)-1, cdesc); + fwrite(oprof, ntohl(oprof[0]), 1, ofp); + } + else if (colors > 3) + fprintf(ofp, "P7\nWIDTH %d\nHEIGHT %d\nDEPTH %d\nMAXVAL %d\nTUPLTYPE %s\nENDHDR\n", width, height, colors, + (1 << output_bps) - 1, cdesc); else - fprintf (ofp, "P%d\n%d %d\n%d\n", - colors/2+5, width, height, (1 << output_bps)-1); - soff = flip_index (0, 0); - cstep = flip_index (0, 1) - soff; - rstep = flip_index (1, 0) - flip_index (0, width); - for (row=0; row < height; row++, soff += rstep) { - for (col=0; col < width; col++, soff += cstep) + fprintf(ofp, "P%d\n%d %d\n%d\n", colors / 2 + 5, width, height, (1 << output_bps) - 1); + soff = flip_index(0, 0); + cstep = flip_index(0, 1) - soff; + rstep = flip_index(1, 0) - flip_index(0, width); + for (row = 0; row < height; row++, soff += rstep) + { + for (col = 0; col < width; col++, soff += cstep) if (output_bps == 8) - FORCC ppm [col*colors+c] = curve[image[soff][c]] >> 8; - else FORCC ppm2[col*colors+c] = curve[image[soff][c]]; + FORCC ppm[col * colors + c] = curve[image[soff][c]] >> 8; + else + FORCC ppm2[col * colors + c] = curve[image[soff][c]]; if (output_bps == 16 && !output_tiff && htons(0x55aa) != 0x55aa) - swab ((char*)ppm2, (char*)ppm2, width*colors*2); - fwrite (ppm, colors*output_bps/8, width, ofp); + swab((char *)ppm2, (char *)ppm2, width * colors * 2); + fwrite(ppm, colors * output_bps / 8, width, ofp); } - free (ppm); + free(ppm); } diff --git a/core/libs/rawengine/libraw/internal/dcraw_fileio.cpp b/core/libs/rawengine/libraw/internal/dcraw_fileio.cpp index 2bf4590f5d..b9df61ccd4 100644 --- a/core/libs/rawengine/libraw/internal/dcraw_fileio.cpp +++ b/core/libs/rawengine/libraw/internal/dcraw_fileio.cpp @@ -1,233 +1,263 @@ /* - Copyright 2008-2017 LibRaw LLC (info@libraw.org) + Copyright 2008-2018 LibRaw LLC (info@libraw.org) LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). This file is generated from Dave Coffin's dcraw.c dcraw.c -- Dave Coffin's raw photo decoder Copyright 1997-2010 by Dave Coffin, dcoffin a cybercom o net Look into dcraw homepage (probably http://cybercom.net/~dcoffin/dcraw/) for more information */ #include #define CLASS LibRaw:: #include "libraw/libraw_types.h" #define LIBRAW_LIBRARY_BUILD #include "libraw/libraw.h" #include "internal/defines.h" #include "internal/var_defines.h" /* - Seach from the current directory up to the root looking for + Search 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) +void CLASS bad_pixels(const char *cfname) { - FILE *fp=NULL; + FILE *fp = NULL; #ifndef LIBRAW_LIBRARY_BUILD char *fname, *cp, line[128]; - int len, time, row, col, r, c, rad, tot, n, fixed=0; + int len, time, row, col, r, c, rad, tot, n, fixed = 0; #else char *cp, line[128]; int time, row, col, r, c, rad, tot, n; #ifdef DCRAW_VERBOSE int fixed = 0; #endif #endif - if (!filters) return; + if (!filters) + return; #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_BAD_PIXELS,0,2); + RUN_CALLBACK(LIBRAW_PROGRESS_BAD_PIXELS, 0, 2); #endif if (cfname) - fp = fopen (cfname, "r"); + fp = fopen(cfname, "r"); if (!fp) - { + { #ifdef LIBRAW_LIBRARY_BUILD - imgdata.process_warnings |= LIBRAW_WARN_NO_BADPIXELMAP; + imgdata.process_warnings |= LIBRAW_WARN_NO_BADPIXELMAP; #endif - return; - } - while (fgets (line, 128, fp)) { - cp = strchr (line, '#'); - if (cp) *cp = 0; - if (sscanf (line, "%d %d %d", &col, &row, &time) != 3) continue; - if ((unsigned) col >= width || (unsigned) row >= height) continue; - if (time > timestamp) continue; - for (tot=n=0, rad=1; rad < 3 && n==0; rad++) - for (r = row-rad; r <= row+rad; r++) - for (c = col-rad; c <= col+rad; c++) - if ((unsigned) r < height && (unsigned) c < width && - (r != row || c != col) && fcol(r,c) == fcol(row,col)) { - tot += BAYER2(r,c); - n++; - } - BAYER2(row,col) = tot/n; + 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; #ifdef DCRAW_VERBOSE - if (verbose) { + if (verbose) + { if (!fixed++) - fprintf (stderr,_("Fixed dead pixels at:")); - fprintf (stderr, " %d,%d", col, row); + fprintf(stderr, _("Fixed dead pixels at:")); + fprintf(stderr, " %d,%d", col, row); } #endif } #ifdef DCRAW_VERBOSE - if (fixed) fputc ('\n', stderr); + if (fixed) + fputc('\n', stderr); #endif - fclose (fp); + fclose(fp); #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_BAD_PIXELS,1,2); + RUN_CALLBACK(LIBRAW_PROGRESS_BAD_PIXELS, 1, 2); #endif } -void CLASS subtract (const char *fname) +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; + int dim[3] = {0, 0, 0}, comment = 0, number = 0, error = 0, nd = 0, c, row, col; ushort *pixel; #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_DARK_FRAME,0,2); + RUN_CALLBACK(LIBRAW_PROGRESS_DARK_FRAME, 0, 2); #endif - if (!(fp = fopen (fname, "rb"))) { + if (!(fp = fopen(fname, "rb"))) + { #ifdef DCRAW_VERBOSE - perror (fname); + perror(fname); #endif #ifdef LIBRAW_LIBRARY_BUILD imgdata.process_warnings |= LIBRAW_WARN_BAD_DARKFRAME_FILE; #endif return; } - if (fgetc(fp) != 'P' || fgetc(fp) != '5') error = 1; - while (!error && nd < 3 && (c = fgetc(fp)) != EOF) { - if (c == '#') comment = 1; - if (c == '\n') comment = 0; - if (comment) continue; - if (isdigit(c)) number = 1; - if (number) { - if (isdigit(c)) dim[nd] = dim[nd]*10 + c -'0'; - else if (isspace(c)) { - number = 0; nd++; - } else error = 1; + if (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) { + if (error || nd < 3) + { #ifdef DCRAW_VERBOSE - fprintf (stderr,_("%s is not a valid PGM file!\n"), fname); + fprintf(stderr, _("%s is not a valid PGM file!\n"), fname); #endif - fclose (fp); return; - } else if (dim[0] != width || dim[1] != height || dim[2] != 65535) { + fclose(fp); + return; + } + else if (dim[0] != width || dim[1] != height || dim[2] != 65535) + { #ifdef DCRAW_VERBOSE - fprintf (stderr,_("%s has the wrong dimensions!\n"), fname); + fprintf(stderr, _("%s has the wrong dimensions!\n"), fname); #endif #ifdef LIBRAW_LIBRARY_BUILD - imgdata.process_warnings |= LIBRAW_WARN_BAD_DARKFRAME_DIM; + imgdata.process_warnings |= LIBRAW_WARN_BAD_DARKFRAME_DIM; #endif - fclose (fp); return; + 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); + 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); + free(pixel); + fclose(fp); + memset(cblack, 0, sizeof cblack); black = 0; #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_DARK_FRAME,1,2); + RUN_CALLBACK(LIBRAW_PROGRESS_DARK_FRAME, 1, 2); #endif } #ifndef NO_LCMS -void CLASS apply_profile (const char *input, const char *output) +void CLASS apply_profile(const char *input, const char *output) { char *prof; - cmsHPROFILE hInProfile=0, hOutProfile=0; + cmsHPROFILE hInProfile = 0, hOutProfile = 0; cmsHTRANSFORM hTransform; FILE *fp; unsigned size; - if (strcmp (input, "embed")) - hInProfile = cmsOpenProfileFromFile (input, "r"); - else if (profile_length) { + if (strcmp(input, "embed")) + hInProfile = cmsOpenProfileFromFile(input, "r"); + else if (profile_length) + { #ifndef LIBRAW_LIBRARY_BUILD - prof = (char *) malloc (profile_length); - merror (prof, "apply_profile()"); - fseek (ifp, profile_offset, SEEK_SET); - fread (prof, 1, profile_length, ifp); - hInProfile = cmsOpenProfileFromMem (prof, profile_length); - free (prof); + prof = (char *)malloc(profile_length); + merror(prof, "apply_profile()"); + fseek(ifp, profile_offset, SEEK_SET); + fread(prof, 1, profile_length, ifp); + hInProfile = cmsOpenProfileFromMem(prof, profile_length); + free(prof); #else - hInProfile = cmsOpenProfileFromMem (imgdata.color.profile, profile_length); + hInProfile = cmsOpenProfileFromMem(imgdata.color.profile, profile_length); #endif - } else - { + } + else + { #ifdef LIBRAW_LIBRARY_BUILD - imgdata.process_warnings |= LIBRAW_WARN_NO_EMBEDDED_PROFILE; + imgdata.process_warnings |= LIBRAW_WARN_NO_EMBEDDED_PROFILE; #endif #ifdef DCRAW_VERBOSE - fprintf (stderr,_("%s has no embedded profile.\n"), ifname); + fprintf(stderr, _("%s has no embedded profile.\n"), ifname); #endif - } + } if (!hInProfile) - { + { #ifdef LIBRAW_LIBRARY_BUILD - imgdata.process_warnings |= LIBRAW_WARN_NO_INPUT_PROFILE; + imgdata.process_warnings |= LIBRAW_WARN_NO_INPUT_PROFILE; #endif - return; - } + return; + } if (!output) hOutProfile = cmsCreate_sRGBProfile(); - else if ((fp = fopen (output, "rb"))) { - fread (&size, 4, 1, fp); - fseek (fp, 0, SEEK_SET); - oprof = (unsigned *) malloc (size = ntohl(size)); - merror (oprof, "apply_profile()"); - fread (oprof, 1, size, fp); - fclose (fp); - if (!(hOutProfile = cmsOpenProfileFromMem (oprof, size))) { - free (oprof); + else if ((fp = fopen(output, "rb"))) + { + fread(&size, 4, 1, fp); + fseek(fp, 0, SEEK_SET); + oprof = (unsigned *)malloc(size = ntohl(size)); + merror(oprof, "apply_profile()"); + fread(oprof, 1, size, fp); + fclose(fp); + if (!(hOutProfile = cmsOpenProfileFromMem(oprof, size))) + { + free(oprof); oprof = 0; } } #ifdef DCRAW_VERBOSE - else - fprintf (stderr,_("Cannot open file %s!\n"), output); + else + fprintf(stderr, _("Cannot open file %s!\n"), output); #endif if (!hOutProfile) - { + { #ifdef LIBRAW_LIBRARY_BUILD - imgdata.process_warnings |= LIBRAW_WARN_BAD_OUTPUT_PROFILE; + imgdata.process_warnings |= LIBRAW_WARN_BAD_OUTPUT_PROFILE; #endif - goto quit; - } + goto quit; + } #ifdef DCRAW_VERBOSE if (verbose) - fprintf (stderr,_("Applying color profile...\n")); + fprintf(stderr, _("Applying color profile...\n")); #endif #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_APPLY_PROFILE,0,2); -#endif - hTransform = cmsCreateTransform (hInProfile, TYPE_RGBA_16, - hOutProfile, TYPE_RGBA_16, INTENT_PERCEPTUAL, 0); - cmsDoTransform (hTransform, image, image, width*height); - raw_color = 1; /* Don't use rgb_cam with a profile */ - cmsDeleteTransform (hTransform); - cmsCloseProfile (hOutProfile); + RUN_CALLBACK(LIBRAW_PROGRESS_APPLY_PROFILE, 0, 2); +#endif + hTransform = cmsCreateTransform(hInProfile, TYPE_RGBA_16, hOutProfile, TYPE_RGBA_16, INTENT_PERCEPTUAL, 0); + cmsDoTransform(hTransform, image, image, width * height); + raw_color = 1; /* Don't use rgb_cam with a profile */ + cmsDeleteTransform(hTransform); + cmsCloseProfile(hOutProfile); quit: - cmsCloseProfile (hInProfile); + cmsCloseProfile(hInProfile); #ifdef LIBRAW_LIBRARY_BUILD - RUN_CALLBACK(LIBRAW_PROGRESS_APPLY_PROFILE,1,2); + RUN_CALLBACK(LIBRAW_PROGRESS_APPLY_PROFILE, 1, 2); #endif } #endif diff --git a/core/libs/rawengine/libraw/internal/defines.h b/core/libs/rawengine/libraw/internal/defines.h index 06e171ec0c..da554446b9 100644 --- a/core/libs/rawengine/libraw/internal/defines.h +++ b/core/libs/rawengine/libraw/internal/defines.h @@ -1,163 +1,168 @@ /* - Copyright 2008-2017 LibRaw LLC (info@libraw.org) + Copyright 2008-2018 LibRaw LLC (info@libraw.org) LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). This file is generated from Dave Coffin's dcraw.c dcraw.c -- Dave Coffin's raw photo decoder Copyright 1997-2010 by Dave Coffin, dcoffin a cybercom o net Look into dcraw homepage (probably http://cybercom.net/~dcoffin/dcraw/) for more information */ #ifndef USE_JPEG #define NO_JPEG #endif #ifndef USE_JASPER #define NO_JASPER #endif #define DCRAW_VERSION "9.26" #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #define _USE_MATH_DEFINES #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __CYGWIN__ #include #endif -#if defined WIN32 || defined (__MINGW32__) +#if defined WIN32 || defined(__MINGW32__) #include #include #pragma comment(lib, "ws2_32.lib") #define snprintf _snprintf #define strcasecmp stricmp #define strncasecmp strnicmp #else #include #include #include typedef long long INT64; typedef unsigned long long UINT64; #endif #ifdef NODEPS #define NO_JASPER #define NO_JPEG #define NO_LCMS #endif #ifndef NO_JASPER -#include /* Decode Red camera movies */ +#include /* Decode Red camera movies */ #endif #ifndef NO_JPEG -#include /* Decode compressed Kodak DC120 photos */ -#endif /* and Adobe Lossy DNGs */ +#include /* Decode compressed Kodak DC120 photos */ +#endif /* and Adobe Lossy DNGs */ #ifndef NO_LCMS #ifdef USE_LCMS -#include /* Support color profiles */ +#include /* Support color profiles */ #else -#include /* Support color profiles */ +#include /* Support color profiles */ #endif #endif #ifdef LOCALEDIR #include #define _(String) gettext(String) #else #define _(String) (String) #endif #ifdef LJPEG_DECODE #error Please compile dcraw.c by itself. #error Do not link it with ljpeg_decode. #endif #ifndef LONG_BIT -#define LONG_BIT (8 * sizeof (long)) +#define LONG_BIT (8 * sizeof(long)) #endif -#define FORC(cnt) for (c=0; c < cnt; c++) +#define FORC(cnt) for (c = 0; c < cnt; c++) #define FORC3 FORC(3) #define FORC4 FORC(4) -#define FORCC for (c=0; c < colors && c < 4; c++) +#define FORCC for (c = 0; c < colors && c < 4; c++) -#define SQR(x) ((x)*(x)) +#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((int)(x),0,65535) -#define SWAP(a,b) { a=a+b; b=a-b; a=a-b; } - -#define my_swap(type, i, j) {type t = i; i = j; j = t;} - -static float fMAX(float a, float b) -{ - return MAX(a,b); -} +#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((int)(x), 0, 65535) +#define CLIP15(x) LIM((int)(x), 0, 32767) +#define SWAP(a, b) \ + { \ + a = a + b; \ + b = a - b; \ + a = a - b; \ + } + +#define my_swap(type, i, j) \ + { \ + type t = i; \ + i = j; \ + j = t; \ + } + +static float fMAX(float a, float b) { return MAX(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 + 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: + 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 + 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 RAWINDEX(row, col) ((row)*raw_width + (col)) -#define RAW(row,col) \ - raw_image[(row)*raw_width+(col)] -#define BAYER(row,col) \ - image[((row) >> shrink)*iwidth + ((col) >> shrink)][FC(row,col)] +#define RAW(row, col) raw_image[(row)*raw_width + (col)] +#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)] +#define BAYER2(row, col) image[((row) >> shrink) * iwidth + ((col) >> shrink)][fcol(row, col)] diff --git a/core/libs/rawengine/libraw/internal/demosaic_packs.cpp b/core/libs/rawengine/libraw/internal/demosaic_packs.cpp index 652c39c6f6..ff93d51636 100644 --- a/core/libs/rawengine/libraw/internal/demosaic_packs.cpp +++ b/core/libs/rawengine/libraw/internal/demosaic_packs.cpp @@ -1,90 +1,35 @@ /* Copyright 2008-2013 LibRaw LLC (info@libraw.org) LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #include #define CLASS LibRaw:: #include "libraw/libraw_types.h" #define LIBRAW_LIBRARY_BUILD #define LIBRAW_IO_REDEFINED #include "libraw/libraw.h" #include "internal/defines.h" #define SRC_USES_SHRINK #define SRC_USES_BLACK #define SRC_USES_CURVE -/* WF filtering is allowed to triple libraw license */ -#include "./wf_filtering.cpp" /* DHT and AAHD are LGPL licensed, so include them */ #include "./dht_demosaic.cpp" #include "./aahd_demosaic.cpp" - - #include "internal/var_defines.h" - -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 -/*AHD-Mod*/ -#include -/*LMMSE*/ -#include -/*AFD*/ -#include -#include -/* VCD*/ -#include -#include -#include -#include -#else -// fake implementations of all GPL2 demosaics - -void CLASS ahd_interpolate_mod() {ahd_interpolate();} -void CLASS afd_interpolate_pl(int, int) {ahd_interpolate();} -void CLASS vcd_interpolate(int) {ahd_interpolate();} -void CLASS lmmse_interpolate(int) {ahd_interpolate();} -void CLASS es_median_filter() {} -void CLASS median_filter_new() {} -void CLASS refinement() {} - -#endif - /* DCB is BSD licensed, so include it */ #include "./dcb_demosaicing.c" - -#ifdef LIBRAW_DEMOSAIC_PACK_GPL3 -/*AMaZE*/ -#include -#include -#include -#include -#include -#else -// fallback to AHD and no correction -void CLASS CA_correct_RT(float,float){} -void CLASS amaze_demosaic_RT() { ahd_interpolate();} -void CLASS green_equilibrate(float thresh) {} -void CLASS cfa_linedn(float linenoise){} -void CLASS cfa_impulse_gauss(float lclean, float cclean){} -#endif - -#define sget4(s) sget4((uchar *)s) -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 -#include -#endif diff --git a/core/libs/rawengine/libraw/internal/dht_demosaic.cpp b/core/libs/rawengine/libraw/internal/dht_demosaic.cpp index bb955dc614..be0ee4ccd9 100644 --- a/core/libs/rawengine/libraw/internal/dht_demosaic.cpp +++ b/core/libs/rawengine/libraw/internal/dht_demosaic.cpp @@ -1,870 +1,872 @@ /* -*- C++ -*- * File: dht_demosaic.cpp * Copyright 2013 Anton Petrusevich * Created: Tue Apr 9, 2013 * * This code is licensed under one of two licenses as you choose: * * 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 * (See file LICENSE.LGPL provided in LibRaw distribution archive for details). * * 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 * (See file LICENSE.CDDL provided in LibRaw distribution archive for details). * */ /* * Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ð²Ñ‹Ñ‡Ð¸ÑлÑет ÑркоÑтную диÑтанцию. * еÑли две ÑркоÑти отличаютÑÑ Ð² два раза, например 10 и 20, то они имеют такой же Ð²ÐµÑ * при принÑтии Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð¾Ð± интерполировании, как и 100 и 200 -- фотографичеÑÐºÐ°Ñ ÑркоÑÑ‚ÑŒ между ними 1 Ñтоп. * диÑÑ‚Ð°Ð½Ñ†Ð¸Ñ Ð²Ñегда >=1 */ static inline float calc_dist(float c1, float c2) { return c1 > c2 ? c1 / c2 : c2 / c1; } struct DHT { int nr_height, nr_width; static const int nr_topmargin = 4, nr_leftmargin = 4; float (*nraw)[3]; ushort channel_maximum[3]; float channel_minimum[3]; LibRaw &libraw; enum { HVSH = 1, HOR = 2, VER = 4, HORSH = HOR | HVSH, VERSH = VER | HVSH, DIASH = 8, LURD = 16, RULD = 32, LURDSH = LURD | DIASH, RULDSH = RULD | DIASH, HOT = 64 }; static inline float Thot(void) throw () { return 64.0f; } static inline float Tg(void) throw () { return 256.0f; } static inline float T(void) throw () { return 1.4f; } char *ndir; inline int nr_offset(int row, int col) throw () { return (row * nr_width + col); } int get_hv_grb(int x, int y, int kc) { float hv1 = 2 * nraw[nr_offset(y - 1, x)][1] / (nraw[nr_offset(y - 2, x)][kc] + nraw[nr_offset(y, x)][kc]); float hv2 = 2 * nraw[nr_offset(y + 1, x)][1] / (nraw[nr_offset(y + 2, x)][kc] + nraw[nr_offset(y, x)][kc]); float kv = calc_dist(hv1, hv2) * calc_dist(nraw[nr_offset(y, x)][kc] * nraw[nr_offset(y, x)][kc], (nraw[nr_offset(y - 2, x)][kc] * nraw[nr_offset(y + 2, x)][kc])); kv *= kv; kv *= kv; kv *= kv; float dv = kv * calc_dist(nraw[nr_offset(y - 3, x)][1] * nraw[nr_offset(y + 3, x)][1], nraw[nr_offset(y - 1, x)][1] * nraw[nr_offset(y + 1, x)][1]); float hh1 = 2 * nraw[nr_offset(y, x - 1)][1] / (nraw[nr_offset(y, x - 2)][kc] + nraw[nr_offset(y, x)][kc]); float hh2 = 2 * nraw[nr_offset(y, x + 1)][1] / (nraw[nr_offset(y, x + 2)][kc] + nraw[nr_offset(y, x)][kc]); float kh = calc_dist(hh1, hh2) * calc_dist(nraw[nr_offset(y, x)][kc] * nraw[nr_offset(y, x)][kc], (nraw[nr_offset(y, x - 2)][kc] * nraw[nr_offset(y, x + 2)][kc])); kh *= kh; kh *= kh; kh *= kh; float dh = kh * calc_dist(nraw[nr_offset(y, x - 3)][1] * nraw[nr_offset(y, x + 3)][1], nraw[nr_offset(y, x - 1)][1] * nraw[nr_offset(y, x + 1)][1]); float e = calc_dist(dh, dv); char d = dh < dv ? (e > Tg() ? HORSH : HOR) : (e > Tg() ? VERSH : VER); return d; } int get_hv_rbg(int x, int y, int hc) { float hv1 = 2 * nraw[nr_offset(y - 1, x)][hc ^ 2] / (nraw[nr_offset(y - 2, x)][1] + nraw[nr_offset(y, x)][1]); float hv2 = 2 * nraw[nr_offset(y + 1, x)][hc ^ 2] / (nraw[nr_offset(y + 2, x)][1] + nraw[nr_offset(y, x)][1]); float kv = calc_dist(hv1, hv2) * calc_dist(nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1], (nraw[nr_offset(y - 2, x)][1] * nraw[nr_offset(y + 2, x)][1])); kv *= kv; kv *= kv; kv *= kv; float dv = kv * calc_dist(nraw[nr_offset(y - 3, x)][hc ^ 2] * nraw[nr_offset(y + 3, x)][hc ^ 2], nraw[nr_offset(y - 1, x)][hc ^ 2] * nraw[nr_offset(y + 1, x)][hc ^ 2]); float hh1 = 2 * nraw[nr_offset(y, x - 1)][hc] / (nraw[nr_offset(y, x - 2)][1] + nraw[nr_offset(y, x)][1]); float hh2 = 2 * nraw[nr_offset(y, x + 1)][hc] / (nraw[nr_offset(y, x + 2)][1] + nraw[nr_offset(y, x)][1]); float kh = calc_dist(hh1, hh2) * calc_dist(nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1], (nraw[nr_offset(y, x - 2)][1] * nraw[nr_offset(y, x + 2)][1])); kh *= kh; kh *= kh; kh *= kh; float dh = kh * calc_dist(nraw[nr_offset(y, x - 3)][hc] * nraw[nr_offset(y, x + 3)][hc], nraw[nr_offset(y, x - 1)][hc] * nraw[nr_offset(y, x + 1)][hc]); float e = calc_dist(dh, dv); char d = dh < dv ? (e > Tg() ? HORSH : HOR) : (e > Tg() ? VERSH : VER); return d; } int get_diag_grb(int x, int y, int kc) { float hlu = nraw[nr_offset(y - 1, x - 1)][1] / nraw[nr_offset(y - 1, x - 1)][kc]; float hrd = nraw[nr_offset(y + 1, x + 1)][1] / nraw[nr_offset(y + 1, x + 1)][kc]; float hru = nraw[nr_offset(y - 1, x + 1)][1] / nraw[nr_offset(y - 1, x + 1)][kc]; float hld = nraw[nr_offset(y + 1, x - 1)][1] / nraw[nr_offset(y + 1, x - 1)][kc]; float dlurd = calc_dist(hlu, hrd) * calc_dist(nraw[nr_offset(y - 1, x - 1)][1] * nraw[nr_offset(y + 1, x + 1)][1], nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1]); float druld = calc_dist(hlu, hrd) * calc_dist(nraw[nr_offset(y - 1, x + 1)][1] * nraw[nr_offset(y + 1, x - 1)][1], nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1]); float e = calc_dist(dlurd, druld); char d = druld < dlurd ? (e > T() ? RULDSH : RULD) : (e > T() ? LURDSH : LURD); return d; } int get_diag_rbg(int x, int y, int hc) { float dlurd = calc_dist(nraw[nr_offset(y - 1, x - 1)][1] * nraw[nr_offset(y + 1, x + 1)][1], nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1]); float druld = calc_dist(nraw[nr_offset(y - 1, x + 1)][1] * nraw[nr_offset(y + 1, x - 1)][1], nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1]); float e = calc_dist(dlurd, druld); char d = druld < dlurd ? (e > T() ? RULDSH : RULD) : (e > T() ? LURDSH : LURD); return d; } static inline float scale_over(float ec, float base) { float s = base * .4; float o = ec - base; return base + sqrt(s * (o + s)) - s; } static inline float scale_under(float ec, float base) { float s = base * .6; float o = base - ec; return base - sqrt(s * (o + s)) + s; } ~DHT(); DHT(LibRaw &_libraw); void copy_to_image(); void make_greens(); void make_diag_dirs(); void make_hv_dirs(); void refine_hv_dirs(int i, int js); void refine_diag_dirs(int i, int js); void refine_ihv_dirs(int i); void refine_idiag_dirs(int i); void illustrate_dirs(); void illustrate_dline(int i); void make_hv_dline(int i); void make_diag_dline(int i); void make_gline(int i); void make_rbdiag(int i); void make_rbhv(int i); void make_rb(); void hide_hots(); void restore_hots(); }; typedef float float3[3]; /* * Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ цветах копируетÑÑ Ð²Ð¾ float в общем то Ñ Ð¾Ð´Ð½Ð¾Ð¹ целью -- чтобы вмеÑто 0 можно было пиÑать 0.5, * что больше подходит Ð´Ð»Ñ Ð²Ñ‹Ñ‡Ð¸ÑÐ»ÐµÐ½Ð¸Ñ ÑркоÑтной разницы. * причина: в целых чиÑлах разница в 1 Ñтоп ÑоÑтавлÑет Ñ€Ñд 8,4,2,1,0 -- поÑледнее чиÑло должно быть 0.5, * которое непредÑтвамио в целых чиÑлах. * так же Ñто изменение позволÑет не думать о Ñпециальных ÑлучаÑÑ… Ð´ÐµÐ»ÐµÐ½Ð¸Ñ Ð½Ð° ноль. * * альтернативное решение: умножить вÑе данные на 2 и в младший бит внеÑти 1. правда, * вÑÑ‘ равно придётÑÑ Ñледить, чтобы при интерпретации зелёного цвета не получилÑÑ 0 при округлении, * иначе проблема при интерпретации Ñиних и краÑных. * */ DHT::DHT(LibRaw& _libraw) : libraw(_libraw) { nr_height = libraw.imgdata.sizes.iheight + nr_topmargin * 2; nr_width = libraw.imgdata.sizes.iwidth + nr_leftmargin * 2; nraw = (float3*) malloc(nr_height * nr_width * sizeof(float3)); int iwidth = libraw.imgdata.sizes.iwidth; ndir = (char*) calloc(nr_height * nr_width, 1); channel_maximum[0] = channel_maximum[1] = channel_maximum[2] = 0; channel_minimum[0] = libraw.imgdata.image[0][0]; channel_minimum[1] = libraw.imgdata.image[0][1]; channel_minimum[2] = libraw.imgdata.image[0][2]; for (int i = 0; i < nr_height * nr_width; ++i) nraw[i][0] = nraw[i][1] = nraw[i][2] = 0.5; for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { int col_cache[48]; for (int j = 0; j < 48; ++j) { int l = libraw.COLOR(i, j); if (l == 3) l = 1; col_cache[j] = l; } for (int j = 0; j < iwidth; ++j) { int l = col_cache[j % 48]; unsigned short c = libraw.imgdata.image[i * iwidth + j][l]; if (c != 0) { if (channel_maximum[l] < c) channel_maximum[l] = c; if (channel_minimum[l] > c) channel_minimum[l] = c; nraw[nr_offset(i + nr_topmargin, j + nr_leftmargin)][l] = (float) c; } } } channel_minimum[0] += .5; channel_minimum[1] += .5; channel_minimum[2] += .5; } void DHT::hide_hots() { int iwidth = libraw.imgdata.sizes.iwidth; #if defined(LIBRAW_USE_OPENMP) #pragma omp parallel for schedule(guided) firstprivate(iwidth) #endif for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { int js = libraw.COLOR(i, 0) & 1; int kc = libraw.COLOR(i, js); /* * js -- Ð½Ð°Ñ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ñ…-координата, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¿Ð¾Ð¿Ð°Ð´Ð°ÐµÑ‚ мимо извеÑтного зелёного * kc -- извеÑтный цвет в точке Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ */ for (int j = js; j < iwidth; j += 2) { int x = j + nr_leftmargin; int y = i + nr_topmargin; float c = nraw[nr_offset(y, x)][kc]; if ((c > nraw[nr_offset(y, x + 2)][kc] && c > nraw[nr_offset(y, x - 2)][kc] && c > nraw[nr_offset(y - 2, x)][kc] && c > nraw[nr_offset(y + 2, x)][kc] && c > nraw[nr_offset(y, x + 1)][1] && c > nraw[nr_offset(y, x - 1)][1] && c > nraw[nr_offset(y - 1, x)][1] && c > nraw[nr_offset(y + 1, x)][1]) || (c < nraw[nr_offset(y, x + 2)][kc] && c < nraw[nr_offset(y, x - 2)][kc] && c < nraw[nr_offset(y - 2, x)][kc] && c < nraw[nr_offset(y + 2, x)][kc] && c < nraw[nr_offset(y, x + 1)][1] && c < nraw[nr_offset(y, x - 1)][1] && c < nraw[nr_offset(y - 1, x)][1] && c < nraw[nr_offset(y + 1, x)][1])) { float avg = 0; for (int k = -2; k < 3; k += 2) for (int m = -2; m < 3; m += 2) if (m == 0 && k == 0) continue; else avg += nraw[nr_offset(y + k, x + m)][kc]; avg /= 8; // float dev = 0; // for (int k = -2; k < 3; k += 2) // for (int l = -2; l < 3; l += 2) // if (k == 0 && l == 0) // continue; // else { // float t = nraw[nr_offset(y + k, x + l)][kc] - avg; // dev += t * t; // } // dev /= 8; // dev = sqrt(dev); if (calc_dist(c, avg) > Thot()) { ndir[nr_offset(y, x)] |= HOT; float dv = calc_dist( nraw[nr_offset(y - 2, x)][kc] * nraw[nr_offset(y - 1, x)][1], nraw[nr_offset(y + 2, x)][kc] * nraw[nr_offset(y + 1, x)][1]); float dh = calc_dist( nraw[nr_offset(y, x - 2)][kc] * nraw[nr_offset(y, x - 1)][1], nraw[nr_offset(y, x + 2)][kc] * nraw[nr_offset(y, x + 1)][1]); if (dv > dh) nraw[nr_offset(y, x)][kc] = (nraw[nr_offset(y, x + 2)][kc] + nraw[nr_offset(y, x - 2)][kc]) / 2; else nraw[nr_offset(y, x)][kc] = (nraw[nr_offset(y - 2, x)][kc] + nraw[nr_offset(y + 2, x)][kc]) / 2; } } } for (int j = js ^ 1; j < iwidth; j += 2) { int x = j + nr_leftmargin; int y = i + nr_topmargin; float c = nraw[nr_offset(y, x)][1]; if ((c > nraw[nr_offset(y, x + 2)][1] && c > nraw[nr_offset(y, x - 2)][1] && c > nraw[nr_offset(y - 2, x)][1] && c > nraw[nr_offset(y + 2, x)][1] && c > nraw[nr_offset(y, x + 1)][kc] && c > nraw[nr_offset(y, x - 1)][kc] && c > nraw[nr_offset(y - 1, x)][kc ^ 2] && c > nraw[nr_offset(y + 1, x)][kc ^ 2]) || (c < nraw[nr_offset(y, x + 2)][1] && c < nraw[nr_offset(y, x - 2)][1] && c < nraw[nr_offset(y - 2, x)][1] && c < nraw[nr_offset(y + 2, x)][1] && c < nraw[nr_offset(y, x + 1)][kc] && c < nraw[nr_offset(y, x - 1)][kc] && c < nraw[nr_offset(y - 1, x)][kc ^ 2] && c < nraw[nr_offset(y + 1, x)][kc ^ 2])) { float avg = 0; for (int k = -2; k < 3; k += 2) for (int m = -2; m < 3; m += 2) if (k == 0 && m == 0) continue; else avg += nraw[nr_offset(y + k, x + m)][1]; avg /= 8; // float dev = 0; // for (int k = -2; k < 3; k += 2) // for (int l = -2; l < 3; l += 2) // if (k == 0 && l == 0) // continue; // else { // float t = nraw[nr_offset(y + k, x + l)][1] - avg; // dev += t * t; // } // dev /= 8; // dev = sqrt(dev); if (calc_dist(c, avg) > Thot()) { ndir[nr_offset(y, x)] |= HOT; float dv = calc_dist( nraw[nr_offset(y - 2, x)][1] * nraw[nr_offset(y - 1, x)][kc ^ 2], nraw[nr_offset(y + 2, x)][1] * nraw[nr_offset(y + 1, x)][kc ^ 2]); float dh = calc_dist( nraw[nr_offset(y, x - 2)][1] * nraw[nr_offset(y, x - 1)][kc], nraw[nr_offset(y, x + 2)][1] * nraw[nr_offset(y, x + 1)][kc]); if (dv > dh) nraw[nr_offset(y, x)][1] = (nraw[nr_offset(y, x + 2)][1] + nraw[nr_offset(y, x - 2)][1]) / 2; else nraw[nr_offset(y, x)][1] = (nraw[nr_offset(y - 2, x)][1] + nraw[nr_offset(y + 2, x)][1]) / 2; } } } } } void DHT::restore_hots() { int iwidth = libraw.imgdata.sizes.iwidth; #if defined(LIBRAW_USE_OPENMP) #ifdef WIN32 #pragma omp parallel for firstprivate(iwidth) #else #pragma omp parallel for schedule(guided) firstprivate(iwidth) collapse(2) #endif #endif for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { for (int j = 0; j < iwidth; ++j) { int x = j + nr_leftmargin; int y = i + nr_topmargin; if (ndir[nr_offset(y, x)] & HOT) { int l = libraw.COLOR(i, j); nraw[nr_offset(i + nr_topmargin, j + nr_leftmargin)][l] = libraw.imgdata.image[i * iwidth + j][l]; } } } } void DHT::make_diag_dirs() { #if defined(LIBRAW_USE_OPENMP) #pragma omp parallel for schedule(guided) #endif for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { make_diag_dline(i); } //#if defined(LIBRAW_USE_OPENMP) //#pragma omp parallel for schedule(guided) //#endif // for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { // refine_diag_dirs(i, i & 1); // } //#if defined(LIBRAW_USE_OPENMP) //#pragma omp parallel for schedule(guided) //#endif // for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { // refine_diag_dirs(i, (i & 1) ^ 1); // } #if defined(LIBRAW_USE_OPENMP) #pragma omp parallel for schedule(guided) #endif for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { refine_idiag_dirs(i); } } void DHT::make_hv_dirs() { #if defined(LIBRAW_USE_OPENMP) #pragma omp parallel for schedule(guided) #endif for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { make_hv_dline(i); } #if defined(LIBRAW_USE_OPENMP) #pragma omp parallel for schedule(guided) #endif for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { refine_hv_dirs(i, i & 1); } #if defined(LIBRAW_USE_OPENMP) #pragma omp parallel for schedule(guided) #endif for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { refine_hv_dirs(i, (i & 1) ^ 1); } #if defined(LIBRAW_USE_OPENMP) #pragma omp parallel for schedule(guided) #endif for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { refine_ihv_dirs(i); } } void DHT::refine_hv_dirs(int i, int js) { int iwidth = libraw.imgdata.sizes.iwidth; for (int j = js; j < iwidth; j += 2) { int x = j + nr_leftmargin; int y = i + nr_topmargin; if (ndir[nr_offset(y, x)] & HVSH) continue; int nv = (ndir[nr_offset(y - 1, x)] & VER) + (ndir[nr_offset(y + 1, x)] & VER) + (ndir[nr_offset(y, x - 1)] & VER) + (ndir[nr_offset(y, x + 1)] & VER); int nh = (ndir[nr_offset(y - 1, x)] & HOR) + (ndir[nr_offset(y + 1, x)] & HOR) + (ndir[nr_offset(y, x - 1)] & HOR) + (ndir[nr_offset(y, x + 1)] & HOR); bool codir = (ndir[nr_offset(y, x)] & VER) ? ((ndir[nr_offset(y - 1, x)] & VER) || (ndir[nr_offset(y + 1, x)] & VER)) : ((ndir[nr_offset(y, x - 1)] & HOR) || (ndir[nr_offset(y, x + 1)] & HOR)); nv /= VER; nh /= HOR; if ((ndir[nr_offset(y, x)] & VER) && (nh > 2 && !codir)) { ndir[nr_offset(y, x)] &= ~VER; ndir[nr_offset(y, x)] |= HOR; } if ((ndir[nr_offset(y, x)] & HOR) && (nv > 2 && !codir)) { ndir[nr_offset(y, x)] &= ~HOR; ndir[nr_offset(y, x)] |= VER; } } } void DHT::refine_ihv_dirs(int i) { int iwidth = libraw.imgdata.sizes.iwidth; for (int j = 0; j < iwidth; j++) { int x = j + nr_leftmargin; int y = i + nr_topmargin; if (ndir[nr_offset(y, x)] & HVSH) continue; int nv = (ndir[nr_offset(y - 1, x)] & VER) + (ndir[nr_offset(y + 1, x)] & VER) + (ndir[nr_offset(y, x - 1)] & VER) + (ndir[nr_offset(y, x + 1)] & VER); int nh = (ndir[nr_offset(y - 1, x)] & HOR) + (ndir[nr_offset(y + 1, x)] & HOR) + (ndir[nr_offset(y, x - 1)] & HOR) + (ndir[nr_offset(y, x + 1)] & HOR); nv /= VER; nh /= HOR; if ((ndir[nr_offset(y, x)] & VER) && nh > 3) { ndir[nr_offset(y, x)] &= ~VER; ndir[nr_offset(y, x)] |= HOR; } if ((ndir[nr_offset(y, x)] & HOR) && nv > 3) { ndir[nr_offset(y, x)] &= ~HOR; ndir[nr_offset(y, x)] |= VER; } } } void DHT::make_hv_dline(int i) { int iwidth = libraw.imgdata.sizes.iwidth; int js = libraw.COLOR(i, 0) & 1; int kc = libraw.COLOR(i, js); /* * js -- Ð½Ð°Ñ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ñ…-координата, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¿Ð¾Ð¿Ð°Ð´Ð°ÐµÑ‚ мимо извеÑтного зелёного * kc -- извеÑтный цвет в точке Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ */ for (int j = 0; j < iwidth; j++) { int x = j + nr_leftmargin; int y = i + nr_topmargin; char d = 0; if ((j & 1) == js) { d = get_hv_grb(x, y, kc); } else { d = get_hv_rbg(x, y, kc); } ndir[nr_offset(y, x)] |= d; } } void DHT::make_diag_dline(int i) { int iwidth = libraw.imgdata.sizes.iwidth; int js = libraw.COLOR(i, 0) & 1; int kc = libraw.COLOR(i, js); /* * js -- Ð½Ð°Ñ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ñ…-координата, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¿Ð¾Ð¿Ð°Ð´Ð°ÐµÑ‚ мимо извеÑтного зелёного * kc -- извеÑтный цвет в точке Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ */ for (int j = 0; j < iwidth; j++) { int x = j + nr_leftmargin; int y = i + nr_topmargin; char d = 0; if ((j & 1) == js) { d = get_diag_grb(x, y, kc); } else { d = get_diag_rbg(x, y, kc); } ndir[nr_offset(y, x)] |= d; } } void DHT::refine_diag_dirs(int i, int js) { int iwidth = libraw.imgdata.sizes.iwidth; for (int j = js; j < iwidth; j += 2) { int x = j + nr_leftmargin; int y = i + nr_topmargin; if (ndir[nr_offset(y, x)] & DIASH) continue; int nv = (ndir[nr_offset(y - 1, x)] & LURD) + (ndir[nr_offset(y + 1, x)] & LURD) + (ndir[nr_offset(y, x - 1)] & LURD) + (ndir[nr_offset(y, x + 1)] & LURD) + (ndir[nr_offset(y - 1, x - 1)] & LURD) + (ndir[nr_offset(y - 1, x + 1)] & LURD) + (ndir[nr_offset(y + 1, x - 1)] & LURD) + (ndir[nr_offset(y + 1, x + 1)] & LURD); int nh = (ndir[nr_offset(y - 1, x)] & RULD) + (ndir[nr_offset(y + 1, x)] & RULD) + (ndir[nr_offset(y, x - 1)] & RULD) + (ndir[nr_offset(y, x + 1)] & RULD) + (ndir[nr_offset(y - 1, x - 1)] & RULD) + (ndir[nr_offset(y - 1, x + 1)] & RULD) + (ndir[nr_offset(y + 1, x - 1)] & RULD) + (ndir[nr_offset(y + 1, x + 1)] & RULD); bool codir = (ndir[nr_offset(y, x)] & LURD) ? ((ndir[nr_offset(y - 1, x - 1)] & LURD) || (ndir[nr_offset(y + 1, x + 1)] & LURD)) : ((ndir[nr_offset(y - 1, x + 1)] & RULD) || (ndir[nr_offset(y + 1, x - 1)] & RULD)); nv /= LURD; nh /= RULD; if ((ndir[nr_offset(y, x)] & LURD) && (nh > 4 && !codir)) { ndir[nr_offset(y, x)] &= ~LURD; ndir[nr_offset(y, x)] |= RULD; } if ((ndir[nr_offset(y, x)] & RULD) && (nv > 4 && !codir)) { ndir[nr_offset(y, x)] &= ~RULD; ndir[nr_offset(y, x)] |= LURD; } } } void DHT::refine_idiag_dirs(int i) { int iwidth = libraw.imgdata.sizes.iwidth; for (int j = 0; j < iwidth; j++) { int x = j + nr_leftmargin; int y = i + nr_topmargin; if (ndir[nr_offset(y, x)] & DIASH) continue; int nv = (ndir[nr_offset(y - 1, x)] & LURD) + (ndir[nr_offset(y + 1, x)] & LURD) + (ndir[nr_offset(y, x - 1)] & LURD) + (ndir[nr_offset(y, x + 1)] & LURD) + (ndir[nr_offset(y - 1, x - 1)] & LURD) + (ndir[nr_offset(y - 1, x + 1)] & LURD) + (ndir[nr_offset(y + 1, x - 1)] & LURD) + (ndir[nr_offset(y + 1, x + 1)] & LURD); int nh = (ndir[nr_offset(y - 1, x)] & RULD) + (ndir[nr_offset(y + 1, x)] & RULD) + (ndir[nr_offset(y, x - 1)] & RULD) + (ndir[nr_offset(y, x + 1)] & RULD) + (ndir[nr_offset(y - 1, x - 1)] & RULD) + (ndir[nr_offset(y - 1, x + 1)] & RULD) + (ndir[nr_offset(y + 1, x - 1)] & RULD) + (ndir[nr_offset(y + 1, x + 1)] & RULD); bool codir = (ndir[nr_offset(y, x)] & LURD) ? ((ndir[nr_offset(y - 1, x - 1)] & LURD) || (ndir[nr_offset(y + 1, x + 1)] & LURD)) : ((ndir[nr_offset(y - 1, x + 1)] & RULD) || (ndir[nr_offset(y + 1, x - 1)] & RULD)); nv /= LURD; nh /= RULD; if ((ndir[nr_offset(y, x)] & LURD) && nh > 7) { ndir[nr_offset(y, x)] &= ~LURD; ndir[nr_offset(y, x)] |= RULD; } if ((ndir[nr_offset(y, x)] & RULD) && nv > 7) { ndir[nr_offset(y, x)] &= ~RULD; ndir[nr_offset(y, x)] |= LURD; } } } /* * вычиÑление недоÑтающих зелёных точек. */ void DHT::make_greens() { #if defined(LIBRAW_USE_OPENMP) #pragma omp parallel for schedule(guided) #endif for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { make_gline(i); } } void DHT::make_gline(int i) { int iwidth = libraw.imgdata.sizes.iwidth; int js = libraw.COLOR(i, 0) & 1; int kc = libraw.COLOR(i, js); /* * js -- Ð½Ð°Ñ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ñ…-координата, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¿Ð¾Ð¿Ð°Ð´Ð°ÐµÑ‚ мимо извеÑтного зелёного * kc -- извеÑтный цвет в точке Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ */ for (int j = js; j < iwidth; j += 2) { int x = j + nr_leftmargin; int y = i + nr_topmargin; int dx, dy, dx2, dy2; float h1, h2; if (ndir[nr_offset(y, x)] & VER) { dx = dx2 = 0; dy = -1; dy2 = 1; h1 = 2 * nraw[nr_offset(y - 1, x)][1] / (nraw[nr_offset(y - 2, x)][kc] + nraw[nr_offset(y, x)][kc]); h2 = 2 * nraw[nr_offset(y + 1, x)][1] / (nraw[nr_offset(y + 2, x)][kc] + nraw[nr_offset(y, x)][kc]); } else { dy = dy2 = 0; dx = 1; dx2 = -1; h1 = 2 * nraw[nr_offset(y, x + 1)][1] / (nraw[nr_offset(y, x + 2)][kc] + nraw[nr_offset(y, x)][kc]); h2 = 2 * nraw[nr_offset(y, x - 1)][1] / (nraw[nr_offset(y, x - 2)][kc] + nraw[nr_offset(y, x)][kc]); } float b1 = 1 / calc_dist(nraw[nr_offset(y, x)][kc], nraw[nr_offset(y + dy * 2, x + dx * 2)][kc]); float b2 = 1 / calc_dist(nraw[nr_offset(y, x)][kc], nraw[nr_offset(y + dy2 * 2, x + dx2 * 2)][kc]); b1 *= b1; b2 *= b2; float eg = nraw[nr_offset(y, x)][kc] * (b1 * h1 + b2 * h2) / (b1 + b2); float min, max; min = MIN(nraw[nr_offset(y + dy, x + dx)][1], nraw[nr_offset(y + dy2, x + dx2)][1]); max = MAX(nraw[nr_offset(y + dy, x + dx)][1], nraw[nr_offset(y + dy2, x + dx2)][1]); min /= 1.2; max *= 1.2; if (eg < min) eg = scale_under(eg, min); else if (eg > max) eg = scale_over(eg, max); if (eg > channel_maximum[1]) eg = channel_maximum[1]; else if (eg < channel_minimum[1]) eg = channel_minimum[1]; nraw[nr_offset(y, x)][1] = eg; } } /* * Ð¾Ñ‚Ð»Ð°Ð´Ð¾Ñ‡Ð½Ð°Ñ Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ */ void DHT::illustrate_dirs() { #if defined(LIBRAW_USE_OPENMP) #pragma omp parallel for schedule(guided) #endif for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { illustrate_dline(i); } } void DHT::illustrate_dline(int i) { int iwidth = libraw.imgdata.sizes.iwidth; for (int j = 0; j < iwidth; j++) { int x = j + nr_leftmargin; int y = i + nr_topmargin; nraw[nr_offset(y, x)][0] = nraw[nr_offset(y, x)][1] = nraw[nr_offset(y, x)][2] = 0.5; int l = ndir[nr_offset(y, x)] & 8; // l >>= 3; // WTF? l = 1; if (ndir[nr_offset(y, x)] & HOT) nraw[nr_offset(y, x)][0] = l * channel_maximum[0] / 4 + channel_maximum[0] / 4; else nraw[nr_offset(y, x)][2] = l * channel_maximum[2] / 4 + channel_maximum[2] / 4; } } /* * интерполÑÑ†Ð¸Ñ ÐºÑ€Ð°Ñных и Ñиних. * * Ñначала интерполируютÑÑ Ð½ÐµÐ´Ð¾Ñтающие цвета, по диагональным направлениÑм от которых находÑÑ‚ÑÑ Ð¸Ð·Ð²ÐµÑтные, * затем ÑÐ¸Ñ‚ÑƒÐ°Ñ†Ð¸Ñ ÑводитÑÑ Ðº тому как интерполировалиÑÑŒ зелёные. */ void DHT::make_rbdiag(int i) { int iwidth = libraw.imgdata.sizes.iwidth; int js = libraw.COLOR(i, 0) & 1; int uc = libraw.COLOR(i, js); int cl = uc ^ 2; /* * js -- Ð½Ð°Ñ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ñ…-координата, ÐºÐ¾Ñ‚Ð¾Ñ€Ð°Ñ Ð¿Ð¾Ð¿Ð°Ð´Ð°ÐµÑ‚ на уже интерполированный зелёный * al -- извеÑтный цвет (кроме зелёного) в точке Ð¸Ð½Ñ‚ÐµÑ€Ð¿Ð¾Ð»Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ * cl -- неизвеÑтный цвет */ for (int j = js; j < iwidth; j += 2) { int x = j + nr_leftmargin; int y = i + nr_topmargin; int dx, dy, dx2, dy2; if (ndir[nr_offset(y, x)] & LURD) { dx = -1; dx2 = 1; dy = -1; dy2 = 1; } else { dx = -1; dx2 = 1; dy = 1; dy2 = -1; } float g1 = 1 / calc_dist(nraw[nr_offset(y, x)][1], nraw[nr_offset(y + dy, x + dx)][1]); float g2 = 1 / calc_dist(nraw[nr_offset(y, x)][1], nraw[nr_offset(y + dy2, x + dx2)][1]); g1 *= g1 * g1; g2 *= g2 * g2; float eg; eg = nraw[nr_offset(y, x)][1] * (g1 * nraw[nr_offset(y + dy, x + dx)][cl] / nraw[nr_offset(y + dy, x + dx)][1] + g2 * nraw[nr_offset(y + dy2, x + dx2)][cl] / nraw[nr_offset(y + dy2, x + dx2)][1]) / (g1 + g2); float min, max; min = MIN(nraw[nr_offset(y + dy, x + dx)][cl], nraw[nr_offset(y + dy2, x + dx2)][cl]); max = MAX(nraw[nr_offset(y + dy, x + dx)][cl], nraw[nr_offset(y + dy2, x + dx2)][cl]); min /= 1.2; max *= 1.2; if (eg < min) eg = scale_under(eg, min); else if (eg > max) eg = scale_over(eg, max); if (eg > channel_maximum[cl]) eg = channel_maximum[cl]; else if (eg < channel_minimum[cl]) eg = channel_minimum[cl]; nraw[nr_offset(y, x)][cl] = eg; } } /* * интерполÑÑ†Ð¸Ñ ÐºÑ€Ð°Ñных и Ñиних в точках где был извеÑтен только зелёный, * Ð½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð³Ð¾Ñ€Ð¸Ð·Ð¾Ð½Ñ‚Ð°Ð»ÑŒÐ½Ñ‹Ðµ или вертикальные */ void DHT::make_rbhv(int i) { int iwidth = libraw.imgdata.sizes.iwidth; int js = (libraw.COLOR(i, 0) & 1) ^ 1; for (int j = js; j < iwidth; j += 2) { int x = j + nr_leftmargin; int y = i + nr_topmargin; /* * поÑкольку Ñверху-Ñнизу и Ñправа-Ñлева уже еÑÑ‚ÑŒ вÑе необходимые краÑные и Ñиние, * то можно выбрать наилучшее направление иÑÑ…Ð¾Ð´Ñ Ð¸Ð· информации по обоим цветам. */ int dx, dy, dx2, dy2; float h1, h2; if (ndir[nr_offset(y, x)] & VER) { dx = dx2 = 0; dy = -1; dy2 = 1; } else { dy = dy2 = 0; dx = 1; dx2 = -1; } float g1 = 1 / calc_dist(nraw[nr_offset(y, x)][1], nraw[nr_offset(y + dy, x + dx)][1]); float g2 = 1 / calc_dist(nraw[nr_offset(y, x)][1], nraw[nr_offset(y + dy2, x + dx2)][1]); g1 *= g1; g2 *= g2; float eg_r, eg_b; eg_r = nraw[nr_offset(y, x)][1] * (g1 * nraw[nr_offset(y + dy, x + dx)][0] / nraw[nr_offset(y + dy, x + dx)][1] + g2 * nraw[nr_offset(y + dy2, x + dx2)][0] / nraw[nr_offset(y + dy2, x + dx2)][1]) / (g1 + g2); eg_b = nraw[nr_offset(y, x)][1] * (g1 * nraw[nr_offset(y + dy, x + dx)][2] / nraw[nr_offset(y + dy, x + dx)][1] + g2 * nraw[nr_offset(y + dy2, x + dx2)][2] / nraw[nr_offset(y + dy2, x + dx2)][1]) / (g1 + g2); float min_r, max_r; min_r = MIN(nraw[nr_offset(y + dy, x + dx)][0], nraw[nr_offset(y + dy2, x + dx2)][0]); max_r = MAX(nraw[nr_offset(y + dy, x + dx)][0], nraw[nr_offset(y + dy2, x + dx2)][0]); float min_b, max_b; min_b = MIN(nraw[nr_offset(y + dy, x + dx)][2], nraw[nr_offset(y + dy2, x + dx2)][2]); max_b = MAX(nraw[nr_offset(y + dy, x + dx)][2], nraw[nr_offset(y + dy2, x + dx2)][2]); min_r /= 1.2; max_r *= 1.2; min_b /= 1.2; max_b *= 1.2; if (eg_r < min_r) eg_r = scale_under(eg_r, min_r); else if (eg_r > max_r) eg_r = scale_over(eg_r, max_r); if (eg_b < min_b) eg_b = scale_under(eg_b, min_b); else if (eg_b > max_b) eg_b = scale_over(eg_b, max_b); if (eg_r > channel_maximum[0]) eg_r = channel_maximum[0]; else if (eg_r < channel_minimum[0]) eg_r = channel_minimum[0]; if (eg_b > channel_maximum[2]) eg_b = channel_maximum[2]; else if (eg_b < channel_minimum[2]) eg_b = channel_minimum[2]; nraw[nr_offset(y, x)][0] = eg_r; nraw[nr_offset(y, x)][2] = eg_b; } } void DHT::make_rb() { #if defined(LIBRAW_USE_OPENMP) #pragma omp barrier #pragma omp parallel for schedule(guided) #endif for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { make_rbdiag(i); } #if defined(LIBRAW_USE_OPENMP) #pragma omp barrier #pragma omp parallel for schedule(guided) #endif for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { make_rbhv(i); } } /* * Ð¿ÐµÑ€ÐµÐ½Ð¾Ñ Ð¸Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð¸Ñ Ð² выходной маÑÑив */ void DHT::copy_to_image() { int iwidth = libraw.imgdata.sizes.iwidth; #if defined(LIBRAW_USE_OPENMP) #ifdef WIN32 #pragma omp parallel for #else #pragma omp parallel for schedule(guided) collapse(2) #endif #endif for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { for (int j = 0; j < iwidth; ++j) { libraw.imgdata.image[i * iwidth + j][0] = (unsigned short) (nraw[nr_offset( i + nr_topmargin, j + nr_leftmargin)][0]); libraw.imgdata.image[i * iwidth + j][2] = (unsigned short) (nraw[nr_offset( i + nr_topmargin, j + nr_leftmargin)][2]); libraw.imgdata.image[i * iwidth + j][1] = libraw.imgdata.image[i * iwidth + j][3] = (unsigned short) (nraw[nr_offset(i + nr_topmargin, j + nr_leftmargin)][1]); } } } DHT::~DHT() { free(nraw); free(ndir); } void LibRaw::dht_interpolate() { +#ifdef DCRAW_VERBOSE printf("DHT interpolating\n"); +#endif DHT dht(*this); dht.hide_hots(); dht.make_hv_dirs(); // dht.illustrate_dirs(); dht.make_greens(); dht.make_diag_dirs(); // dht.illustrate_dirs(); dht.make_rb(); dht.restore_hots(); dht.copy_to_image(); } diff --git a/core/libs/rawengine/libraw/internal/libraw_internal_funcs.h b/core/libs/rawengine/libraw/internal/libraw_internal_funcs.h index e5254d7e04..54dd784c9d 100644 --- a/core/libs/rawengine/libraw/internal/libraw_internal_funcs.h +++ b/core/libs/rawengine/libraw/internal/libraw_internal_funcs.h @@ -1,304 +1,301 @@ /* -*- C++ -*- * File: libraw_internal_funcs.h - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) * Created: Sat Mar 14, 2008 LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #ifndef _LIBRAW_INTERNAL_FUNCS_H #define _LIBRAW_INTERNAL_FUNCS_H #ifndef LIBRAW_LIBRARY_BUILD #error "This file should be used only for libraw library build" #else /* WF */ void wf_bayer4_igauss_filter(int radius,void* src_image, int src_imgmode, void* dst_image, int dst_imgmode); void wf_bayer4_green_blur (int mode,void* src_image, int src_imgmode, void* dst_image, int dst_imgmode); void wf_bayer4_block_filter (int* radius_list, void* src_image, int src_imgmode, void* dst_image, int dst_imgmode); double wf_filter_energy (int r1_greenmode, int r1, int r2_greenmode, int r2); /* inline functions */ ushort sget2 (uchar *s); ushort sget2Rev(uchar *s); - void setCanonBodyFeatures (unsigned id); - void processCanonCameraInfo (unsigned id, uchar *CameraInfo, unsigned maxlen); + unsigned setCanonBodyFeatures (unsigned id); + void processCanonCameraInfo (unsigned id, uchar *CameraInfo, unsigned maxlen, unsigned type); void Canon_CameraSettings(); void Canon_WBpresets (int skip1, int skip2); void Canon_WBCTpresets (short WBCTversion); - void parseCanonMakernotes (unsigned tag, unsigned type, unsigned len); + void parseCanonMakernotes (unsigned tag, unsigned type, unsigned len); void processNikonLensData (uchar *LensData, unsigned len); void setOlympusBodyFeatures (unsigned long long id); void setPhaseOneFeatures (unsigned id); void setPentaxBodyFeatures (unsigned id); void PentaxISO (ushort c); void PentaxLensInfo (unsigned id, unsigned len); void setSonyBodyFeatures (unsigned id); void parseSonyLensType2 (uchar a, uchar b); void parseSonyLensFeatures (uchar a, uchar b); - void process_Sony_0x9050 (uchar * buf, unsigned id); - void process_Sony_0x940c (uchar * buf); - void parseFujiMakernotes (unsigned tag, unsigned type); + void process_Sony_0x0116 (uchar * buf, ushort, unsigned id); + void process_Sony_0x2010 (uchar * buf, ushort); + void process_Sony_0x9050 (uchar * buf, ushort, unsigned id); + void process_Sony_0x9400 (uchar * buf, ushort, unsigned id); + void process_Sony_0x9402 (uchar * buf, ushort); + void process_Sony_0x9403 (uchar * buf, ushort); + void process_Sony_0x9406 (uchar * buf, ushort); + void process_Sony_0x940c (uchar * buf, ushort); + void process_Sony_0x940e (uchar * buf, ushort, unsigned id); + void parseSonyMakernotes (unsigned tag, unsigned type, unsigned len, unsigned dng_writer, + uchar *&table_buf_0x0116, ushort &table_buf_0x0116_len, + uchar *&table_buf_0x2010, ushort &table_buf_0x2010_len, + uchar *&table_buf_0x9050, ushort &table_buf_0x9050_len, + uchar *&table_buf_0x9400, ushort &table_buf_0x9400_len, + uchar *&table_buf_0x9402, ushort &table_buf_0x9402_len, + uchar *&table_buf_0x9403, ushort &table_buf_0x9403_len, + uchar *&table_buf_0x9406, ushort &table_buf_0x9406_len, + uchar *&table_buf_0x940c, ushort &table_buf_0x940c_len, + uchar *&table_buf_0x940e, ushort &table_buf_0x940e_len); + + void parseFujiMakernotes (unsigned tag, unsigned type); ushort get2(); unsigned sget4 (uchar *s); unsigned getint (int type); float int_to_float (int i); double getreal (int type); void read_shorts (ushort *pixel, unsigned count); /* Canon P&S cameras */ void canon_600_fixed_wb (int temp); int canon_600_color (int ratio[2], int mar); void canon_600_auto_wb(); void canon_600_coeff(); void canon_600_load_raw(); void canon_600_correct(); int canon_s2is(); void parse_ciff (int offset, int length, int); void ciff_block_1030(); // LJPEG decoder unsigned getbithuff (int nbits, ushort *huff); ushort* make_decoder_ref (const uchar **source); ushort* make_decoder (const uchar *source); int ljpeg_start (struct jhead *jh, int info_only); void ljpeg_end(struct jhead *jh); int ljpeg_diff (ushort *huff); ushort * ljpeg_row (int jrow, struct jhead *jh); void ljpeg_idct (struct jhead *jh); unsigned ph1_bithuff (int nbits, ushort *huff); // Canon DSLRs void crw_init_tables (unsigned table, ushort *huff[2]); int canon_has_lowbits(); void canon_load_raw(); void lossless_jpeg_load_raw(); void canon_sraw_load_raw(); // Adobe DNG void adobe_copy_pixel (unsigned int row, unsigned int col, ushort **rp); void lossless_dng_load_raw(); void deflate_dng_load_raw(); void packed_dng_load_raw(); void lossy_dng_load_raw(); //void adobe_dng_load_raw_nc(); // Pentax void pentax_load_raw(); void pentax_4shot_load_raw(); void pentax_tree(); // Nikon (and Minolta Z2) void nikon_load_raw(); void nikon_load_striped_packed_raw(); void nikon_load_sraw(); void nikon_yuv_load_raw(); void nikon_coolscan_load_raw(); int nikon_e995(); int nikon_e2100(); void nikon_3700(); int minolta_z2(); void nikon_e2100_load_raw(); // Fuji //void fuji_load_raw(); void parse_fuji (int offset); // RedCine void parse_redcine(); void redcine_load_raw(); // Rollei void rollei_load_raw(); void parse_rollei(); // MF backs //int bayer (unsigned row, unsigned col); int raw(unsigned,unsigned); void phase_one_flat_field (int is_float, int nc); void phase_one_load_raw(); unsigned ph1_bits (int nbits); void phase_one_load_raw_c(); void hasselblad_load_raw(); void leaf_hdr_load_raw(); void sinar_4shot_load_raw(); void imacon_full_load_raw(); void hasselblad_full_load_raw(); void packed_load_raw(); float find_green(int,int,int,int); void unpacked_load_raw(); void unpacked_load_raw_reversed(); void unpacked_load_raw_fuji_f700s20(); void parse_sinar_ia(); void parse_phase_one (int base); // Misc P&S cameras void parse_broadcom(); void broadcom_load_raw(); void nokia_load_raw(); void android_loose_load_raw(); void android_tight_load_raw(); void canon_rmf_load_raw(); - unsigned pana_bits (int nbits); + unsigned pana_data (int nb, unsigned *bytes); void panasonic_load_raw(); + void panasonic_16x10_load_raw(); void olympus_load_raw(); void olympus_cseries_load_raw(); void minolta_rd175_load_raw(); void quicktake_100_load_raw(); const int* make_decoder_int (const int *source, int level); int radc_token (int tree); void kodak_radc_load_raw(); void kodak_jpeg_load_raw(); void kodak_dc120_load_raw(); void eight_bit_load_raw(); void smal_decode_segment (unsigned seg[2][2], int holes); void smal_v6_load_raw(); int median4 (int *p); void fill_holes (int holes); void smal_v9_load_raw(); void parse_riff(); void parse_cine(); void parse_smal (int offset, int fsize); int parse_jpeg (int offset); // Kodak void kodak_262_load_raw(); int kodak_65000_decode (short *out, int bsize); void kodak_65000_load_raw(); void kodak_rgb_load_raw(); void kodak_ycbcr_load_raw(); // void kodak_yrgb_load_raw(); void kodak_c330_load_raw(); void kodak_c603_load_raw(); void kodak_rgb_load_thumb(); void kodak_ycbcr_load_thumb(); // It's a Sony (and K&M) void sony_decrypt (unsigned *data, int len, int start, int key); void sony_load_raw(); void sony_arw_load_raw(); void sony_arw2_load_raw(); + void sony_arq_load_raw(); void samsung_load_raw(); void samsung2_load_raw(); void samsung3_load_raw(); void parse_minolta (int base); // Foveon/Sigma -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 - void foveon_sd_load_raw(); - void foveon_dp_load_raw(); - void foveon_huff (ushort *huff); - void foveon_load_camf(); - - const char* foveon_camf_param (const char *block, const char *param); - void * foveon_camf_matrix (unsigned dim[3], const char *name); - int foveon_fixed (void *ptr, int size, const char *name); - float foveon_avg (short *pix, int range[2], float cfilt); - short * foveon_make_curve (double max, double mul, double filt); - void foveon_make_curves(short **curvep, float dq[3], float div[3], float filt); - int foveon_apply_curve (short *curve, int i); - void foveon_interpolate(); - char * foveon_gets (int offset, char *str, int len); - void parse_foveon(); -#endif // We always have x3f code compiled in! void parse_x3f(); void x3f_load_raw(); void x3f_dpq_interpolate_rg(); void x3f_dpq_interpolate_af(int xstep, int ystep, int scale); // 1x1 af pixels void x3f_dpq_interpolate_af_sd(int xstart,int ystart, int xend, int yend, int xstep, int ystep, int scale); // sd Quattro interpolation // CAM/RGB void pseudoinverse (double (*in)[3], double (*out)[3], int size); void simple_coeff (int index); // Tiff/Exif parsers void tiff_get (unsigned base,unsigned *tag, unsigned *type, unsigned *len, unsigned *save); void parse_thumb_note (int base, unsigned toff, unsigned tlen); void parse_makernote (int base, int uptag); void parse_makernote_0xc634(int base, int uptag, unsigned dng_writer); void parse_exif (int base); void linear_table (unsigned len); - void Kodak_WB_0x08tags(int wb, unsigned type); + void Kodak_WB_0x08tags(int wb, unsigned type); void parse_kodak_ifd (int base); int parse_tiff_ifd (int base); int parse_tiff (int base); void apply_tiff(void); void parse_gps (int base); void parse_gps_libraw(int base); void romm_coeff(float romm_cam[3][3]); void parse_mos (int offset); void parse_qt (int end); void get_timestamp (int reversed); // External JPEGs, what cameras uses it ? void parse_external_jpeg(); // The identify short guess_byte_order (int words); // Tiff writer void tiff_set(struct tiff_hdr *th, ushort *ntag,ushort tag, ushort type, int count, int val); void tiff_head (struct tiff_hdr *th, int full); -// splitted AHD code +// split AHD code #define TS 512 void ahd_interpolate_green_h_and_v(int top, int left, ushort (*out_rgb)[TS][TS][3]); void ahd_interpolate_r_and_b_in_rgb_and_convert_to_cielab(int top, int left, ushort (*inout_rgb)[TS][3], short (*out_lab)[TS][3]); void ahd_interpolate_r_and_b_and_convert_to_cielab(int top, int left, ushort (*inout_rgb)[TS][TS][3], short (*out_lab)[TS][TS][3]); void ahd_interpolate_build_homogeneity_map(int top, int left, short (*lab)[TS][TS][3], char (*out_homogeneity_map)[TS][2]); void ahd_interpolate_combine_homogeneous_pixels(int top, int left, ushort (*rgb)[TS][TS][3], char (*homogeneity_map)[TS][2]); #undef TS + void init_fuji_compr(struct fuji_compressed_params* info); + void init_fuji_block(struct fuji_compressed_block* info, const struct fuji_compressed_params *params, INT64 raw_offset, unsigned dsize); + void copy_line_to_xtrans(struct fuji_compressed_block* info, int cur_line, int cur_block, int cur_block_width); + void copy_line_to_bayer(struct fuji_compressed_block* info, int cur_line, int cur_block, int cur_block_width); + void xtrans_decode_block(struct fuji_compressed_block* info, const struct fuji_compressed_params *params, int cur_line); + void fuji_bayer_decode_block(struct fuji_compressed_block* info, const struct fuji_compressed_params *params, int cur_line); + void fuji_compressed_load_raw(); + void fuji_14bit_load_raw(); + void parse_fuji_compressed_header(); - void parse_xtrans_header(); - void xtrans_compressed_load_raw(); - void init_xtrans(struct xtrans_params* info); - void init_xtrans_block(struct xtrans_block* info, const struct xtrans_params *params, INT64 raw_offset, unsigned dsize); - void copy_line_to_xtrans(struct xtrans_block* info, int cur_line, int cur_block, int cur_block_width); - void xtrans_decode_block(struct xtrans_block* info, const struct xtrans_params * params, int cur_line); - -// LibRaw demosaic packs functions -// AMaZe - int LinEqSolve(int, float*, float*, float*); // DCB void dcb_pp(); void dcb_copy_to_buffer(float (*image2)[3]); void dcb_restore_from_buffer(float (*image2)[3]); void dcb_color(); void dcb_color_full(); void dcb_map(); void dcb_correction(); void dcb_correction2(); void dcb_refinement(); void rgb_to_lch(double (*image3)[3]); void lch_to_rgb(double (*image3)[3]); void fbdd_correction(); void fbdd_correction2(double (*image3)[3]); void fbdd_green(); void dcb_ver(float (*image3)[3]); void dcb_hor(float (*image2)[3]); void dcb_color2(float (*image2)[3]); void dcb_color3(float (*image3)[3]); void dcb_decide(float (*image2)[3], float (*image3)[3]); void dcb_nyquist(); -// VCD/modified dcraw - void refinement(); - void ahd_partial_interpolate(int threshold_value); - void es_median_filter(); - void median_filter_new(); #endif #endif diff --git a/core/libs/rawengine/libraw/internal/libraw_x3f.cpp b/core/libs/rawengine/libraw/internal/libraw_x3f.cpp index 806e72c975..49918e99d2 100644 --- a/core/libs/rawengine/libraw/internal/libraw_x3f.cpp +++ b/core/libs/rawengine/libraw/internal/libraw_x3f.cpp @@ -1,2458 +1,2462 @@ /* Library for accessing X3F Files ---------------------------------------------------------------- BSD-style License ---------------------------------------------------------------- * Copyright (c) 2010, Roland Karlsson (roland@proxel.se) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the organization nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY ROLAND KARLSSON ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL ROLAND KARLSSON BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* From X3F_IO.H */ #include #include #include #include #include #include "../libraw/libraw_datastream.h" #define SIZE_UNIQUE_IDENTIFIER 16 #define SIZE_WHITE_BALANCE 32 #define SIZE_COLOR_MODE 32 #define NUM_EXT_DATA_2_1 32 #define NUM_EXT_DATA_3_0 64 #define NUM_EXT_DATA NUM_EXT_DATA_3_0 #define X3F_VERSION(MAJ,MIN) (uint32_t)(((MAJ)<<16) + MIN) #define X3F_VERSION_2_0 X3F_VERSION(2,0) #define X3F_VERSION_2_1 X3F_VERSION(2,1) #define X3F_VERSION_2_2 X3F_VERSION(2,2) #define X3F_VERSION_2_3 X3F_VERSION(2,3) #define X3F_VERSION_3_0 X3F_VERSION(3,0) #define X3F_VERSION_4_0 X3F_VERSION(4,0) /* Main file identifier */ #define X3F_FOVb (uint32_t)(0x62564f46) /* Directory identifier */ #define X3F_SECd (uint32_t)(0x64434553) /* Property section identifiers */ #define X3F_PROP (uint32_t)(0x504f5250) #define X3F_SECp (uint32_t)(0x70434553) /* Image section identifiers */ #define X3F_IMAG (uint32_t)(0x46414d49) #define X3F_IMA2 (uint32_t)(0x32414d49) #define X3F_SECi (uint32_t)(0x69434553) /* CAMF section identifiers */ #define X3F_CAMF (uint32_t)(0x464d4143) #define X3F_SECc (uint32_t)(0x63434553) /* CAMF entry identifiers */ #define X3F_CMbP (uint32_t)(0x50624d43) #define X3F_CMbT (uint32_t)(0x54624d43) #define X3F_CMbM (uint32_t)(0x4d624d43) #define X3F_CMb (uint32_t)(0x00624d43) /* SDQ section identifiers ? - TODO */ #define X3F_SPPA (uint32_t)(0x41505053) #define X3F_SECs (uint32_t)(0x73434553) #define X3F_IMAGE_THUMB_PLAIN (uint32_t)(0x00020003) #define X3F_IMAGE_THUMB_HUFFMAN (uint32_t)(0x0002000b) #define X3F_IMAGE_THUMB_JPEG (uint32_t)(0x00020012) #define X3F_IMAGE_THUMB_SDQ (uint32_t)(0x00020019) /* SDQ ? - TODO */ #define X3F_IMAGE_RAW_HUFFMAN_X530 (uint32_t)(0x00030005) #define X3F_IMAGE_RAW_HUFFMAN_10BIT (uint32_t)(0x00030006) #define X3F_IMAGE_RAW_TRUE (uint32_t)(0x0003001e) #define X3F_IMAGE_RAW_MERRILL (uint32_t)(0x0001001e) #define X3F_IMAGE_RAW_QUATTRO (uint32_t)(0x00010023) #define X3F_IMAGE_RAW_SDQ (uint32_t)(0x00010025) #define X3F_IMAGE_RAW_SDQH (uint32_t)(0x00010027) #define X3F_IMAGE_RAW_SDQH2 (uint32_t)(0x00010029) #define X3F_IMAGE_HEADER_SIZE 28 #define X3F_CAMF_HEADER_SIZE 28 #define X3F_PROPERTY_LIST_HEADER_SIZE 24 typedef uint16_t utf16_t; typedef int bool_t; typedef enum x3f_extended_types_e { X3F_EXT_TYPE_NONE=0, X3F_EXT_TYPE_EXPOSURE_ADJUST=1, X3F_EXT_TYPE_CONTRAST_ADJUST=2, X3F_EXT_TYPE_SHADOW_ADJUST=3, X3F_EXT_TYPE_HIGHLIGHT_ADJUST=4, X3F_EXT_TYPE_SATURATION_ADJUST=5, X3F_EXT_TYPE_SHARPNESS_ADJUST=6, X3F_EXT_TYPE_RED_ADJUST=7, X3F_EXT_TYPE_GREEN_ADJUST=8, X3F_EXT_TYPE_BLUE_ADJUST=9, X3F_EXT_TYPE_FILL_LIGHT_ADJUST=10 } x3f_extended_types_t; typedef struct x3f_property_s { /* Read from file */ uint32_t name_offset; uint32_t value_offset; /* Computed */ utf16_t *name; /* 0x0000 terminated UTF 16 */ utf16_t *value; /* 0x0000 terminated UTF 16 */ } x3f_property_t; typedef struct x3f_property_table_s { uint32_t size; x3f_property_t *element; } x3f_property_table_t; typedef struct x3f_property_list_s { /* 2.0 Fields */ uint32_t num_properties; uint32_t character_format; uint32_t reserved; uint32_t total_length; x3f_property_table_t property_table; void *data; uint32_t data_size; } x3f_property_list_t; typedef struct x3f_table8_s { uint32_t size; uint8_t *element; } x3f_table8_t; typedef struct x3f_table16_s { uint32_t size; uint16_t *element; } x3f_table16_t; typedef struct x3f_table32_s { uint32_t size; uint32_t *element; } x3f_table32_t; typedef struct { uint8_t *data; /* Pointer to actual image data */ void *buf; /* Pointer to allocated buffer for free() */ uint32_t rows; uint32_t columns; uint32_t channels; uint32_t row_stride; } x3f_area8_t; typedef struct { uint16_t *data; /* Pointer to actual image data */ void *buf; /* Pointer to allocated buffer for free() */ uint32_t rows; uint32_t columns; uint32_t channels; uint32_t row_stride; } x3f_area16_t; #define UNDEFINED_LEAF 0xffffffff typedef struct x3f_huffnode_s { struct x3f_huffnode_s *branch[2]; uint32_t leaf; } x3f_huffnode_t; typedef struct x3f_hufftree_s { uint32_t free_node_index; /* Free node index in huffman tree array */ x3f_huffnode_t *nodes; /* Coding tree */ } x3f_hufftree_t; typedef struct x3f_true_huffman_element_s { uint8_t code_size; uint8_t code; } x3f_true_huffman_element_t; typedef struct x3f_true_huffman_s { uint32_t size; x3f_true_huffman_element_t *element; } x3f_true_huffman_t; /* 0=bottom, 1=middle, 2=top */ #define TRUE_PLANES 3 typedef struct x3f_true_s { uint16_t seed[TRUE_PLANES]; /* Always 512,512,512 */ uint16_t unknown; /* Always 0 */ x3f_true_huffman_t table; /* Huffman table - zero terminated. size is the number of leaves plus 1.*/ x3f_table32_t plane_size; /* Size of the 3 planes */ uint8_t *plane_address[TRUE_PLANES]; /* computed offset to the planes */ x3f_hufftree_t tree; /* Coding tree */ x3f_area16_t x3rgb16; /* 3x16 bit X3-RGB data */ } x3f_true_t; typedef struct x3f_quattro_s { struct { uint16_t columns; uint16_t rows; } plane[TRUE_PLANES]; uint32_t unknown; bool_t quattro_layout; x3f_area16_t top16; /* Container for the bigger top layer */ } x3f_quattro_t; typedef struct x3f_huffman_s { x3f_table16_t mapping; /* Value Mapping = X3F lossy compression */ x3f_table32_t table; /* Coding Table */ x3f_hufftree_t tree; /* Coding tree */ x3f_table32_t row_offsets; /* Row offsets */ x3f_area8_t rgb8; /* 3x8 bit RGB data */ x3f_area16_t x3rgb16; /* 3x16 bit X3-RGB data */ } x3f_huffman_t; typedef struct x3f_image_data_s { /* 2.0 Fields */ /* ------------------------------------------------------------------ */ /* Known combinations of type and format are: 1-6, 2-3, 2-11, 2-18, 3-6 */ uint32_t type; /* 1 = RAW X3 (SD1) 2 = thumbnail or maybe just RGB 3 = RAW X3 */ uint32_t format; /* 3 = 3x8 bit pixmap 6 = 3x10 bit huffman with map table 11 = 3x8 bit huffman 18 = JPEG */ uint32_t type_format; /* type<<16 + format */ /* ------------------------------------------------------------------ */ uint32_t columns; /* width / row size in pixels */ uint32_t rows; /* height */ uint32_t row_stride; /* row size in bytes */ /* NULL if not used */ x3f_huffman_t *huffman; /* Huffman help data */ x3f_true_t *tru; /* TRUE help data */ x3f_quattro_t *quattro; /* Quattro help data */ void *data; /* Take from file if NULL. Otherwise, this is the actual data bytes in the file. */ uint32_t data_size; } x3f_image_data_t; typedef struct camf_dim_entry_s { uint32_t size; uint32_t name_offset; uint32_t n; /* 0,1,2,3... */ char *name; } camf_dim_entry_t; typedef enum {M_FLOAT, M_INT, M_UINT} matrix_type_t; typedef struct camf_entry_s { /* pointer into decoded data */ void *entry; /* entry header */ uint32_t id; uint32_t version; uint32_t entry_size; uint32_t name_offset; uint32_t value_offset; /* computed values */ char *name_address; void *value_address; uint32_t name_size; uint32_t value_size; /* extracted values for explicit CAMF entry types*/ uint32_t text_size; char *text; uint32_t property_num; char **property_name; uint8_t **property_value; uint32_t matrix_dim; camf_dim_entry_t *matrix_dim_entry; /* Offset, pointer and size and type of raw data */ uint32_t matrix_type; uint32_t matrix_data_off; void *matrix_data; uint32_t matrix_element_size; /* Pointer and type of copied data */ matrix_type_t matrix_decoded_type; void *matrix_decoded; /* Help data to try to estimate element size */ uint32_t matrix_elements; uint32_t matrix_used_space; double matrix_estimated_element_size; } camf_entry_t; typedef struct camf_entry_table_s { uint32_t size; camf_entry_t *element; } camf_entry_table_t; typedef struct x3f_camf_typeN_s { uint32_t val0; uint32_t val1; uint32_t val2; uint32_t val3; } x3f_camf_typeN_t; typedef struct x3f_camf_type2_s { uint32_t reserved; uint32_t infotype; uint32_t infotype_version; uint32_t crypt_key; } x3f_camf_type2_t; typedef struct x3f_camf_type4_s { uint32_t decoded_data_size; uint32_t decode_bias; uint32_t block_size; uint32_t block_count; } x3f_camf_type4_t; typedef struct x3f_camf_type5_s { uint32_t decoded_data_size; uint32_t decode_bias; uint32_t unknown2; uint32_t unknown3; } x3f_camf_type5_t; typedef struct x3f_camf_s { /* Header info */ uint32_t type; union { x3f_camf_typeN_t tN; x3f_camf_type2_t t2; x3f_camf_type4_t t4; x3f_camf_type5_t t5; }; /* The encrypted raw data */ void *data; uint32_t data_size; /* Help data for type 4 Huffman compression */ x3f_true_huffman_t table; x3f_hufftree_t tree; uint8_t *decoding_start; uint32_t decoding_size; /* The decrypted data */ void *decoded_data; uint32_t decoded_data_size; /* Pointers into the decrypted data */ camf_entry_table_t entry_table; } x3f_camf_t; typedef struct x3f_directory_entry_header_s { uint32_t identifier; /* Should be ´SECp´, "SECi", ... */ uint32_t version; /* 0x00020001 is version 2.1 */ union { x3f_property_list_t property_list; x3f_image_data_t image_data; x3f_camf_t camf; } data_subsection; } x3f_directory_entry_header_t; typedef struct x3f_directory_entry_s { struct { uint32_t offset; uint32_t size; } input, output; uint32_t type; x3f_directory_entry_header_t header; } x3f_directory_entry_t; typedef struct x3f_directory_section_s { uint32_t identifier; /* Should be ´SECd´ */ uint32_t version; /* 0x00020001 is version 2.1 */ /* 2.0 Fields */ uint32_t num_directory_entries; x3f_directory_entry_t *directory_entry; } x3f_directory_section_t; typedef struct x3f_header_s { /* 2.0 Fields */ uint32_t identifier; /* Should be ´FOVb´ */ uint32_t version; /* 0x00020001 means 2.1 */ uint8_t unique_identifier[SIZE_UNIQUE_IDENTIFIER]; uint32_t mark_bits; uint32_t columns; /* Columns and rows ... */ uint32_t rows; /* ... before rotation */ uint32_t rotation; /* 0, 90, 180, 270 */ char white_balance[SIZE_WHITE_BALANCE]; /* Introduced in 2.1 */ char color_mode[SIZE_COLOR_MODE]; /* Introduced in 2.3 */ /* Introduced in 2.1 and extended from 32 to 64 in 3.0 */ uint8_t extended_types[NUM_EXT_DATA]; /* x3f_extended_types_t */ float extended_data[NUM_EXT_DATA]; /* 32 bits, but do type differ? */ } x3f_header_t; typedef struct x3f_info_s { char *error; struct { LibRaw_abstract_datastream *file; /* Use if more data is needed */ } input, output; } x3f_info_t; typedef struct x3f_s { x3f_info_t info; x3f_header_t header; x3f_directory_section_t directory_section; } x3f_t; typedef enum x3f_return_e { X3F_OK=0, X3F_ARGUMENT_ERROR=1, X3F_INFILE_ERROR=2, X3F_OUTFILE_ERROR=3, X3F_INTERNAL_ERROR=4 } x3f_return_t; x3f_return_t x3f_delete(x3f_t *x3f); /* Hacky external flags */ /* --------------------------------------------------------------------- */ /* extern */ int legacy_offset = 0; /* extern */ bool_t auto_legacy_offset = 1; /* --------------------------------------------------------------------- */ /* Huffman Decode Macros */ /* --------------------------------------------------------------------- */ #define HUF_TREE_MAX_LENGTH 27 #define HUF_TREE_MAX_NODES(_leaves) ((HUF_TREE_MAX_LENGTH+1)*(_leaves)) #define HUF_TREE_GET_LENGTH(_v) (((_v)>>27)&0x1f) #define HUF_TREE_GET_CODE(_v) ((_v)&0x07ffffff) /* --------------------------------------------------------------------- */ /* Reading and writing - assuming little endian in the file */ /* --------------------------------------------------------------------- */ static int x3f_get1(LibRaw_abstract_datastream *f) { /* Little endian file */ return f->get_char(); } static int x3f_sget2 (uchar *s) { return s[0] | s[1] << 8; } static int x3f_get2(LibRaw_abstract_datastream *f) { uchar str[2] = { 0xff,0xff }; f->read (str, 1, 2); return x3f_sget2(str); } unsigned x3f_sget4 (uchar *s) { return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24; } unsigned x3f_get4(LibRaw_abstract_datastream *f) { uchar str[4] = { 0xff,0xff,0xff,0xff }; f->read (str, 1, 4); return x3f_sget4(str); } #define FREE(P) do { free(P); (P) = NULL; } while (0) #define PUT_GET_N(_buffer,_size,_file,_func) \ do \ { \ int _left = _size; \ while (_left != 0) { \ int _cur = _file->_func(_buffer,1,_left); \ if (_cur == 0) { \ throw LIBRAW_EXCEPTION_IO_CORRUPT; \ } \ _left -= _cur; \ } \ } while(0) #define GET1(_v) do {(_v) = x3f_get1(I->input.file);} while (0) #define GET2(_v) do {(_v) = x3f_get2(I->input.file);} while (0) #define GET4(_v) do {(_v) = x3f_get4(I->input.file);} while (0) #define GET4F(_v) \ do { \ union {int32_t i; float f;} _tmp; \ _tmp.i = x3f_get4(I->input.file); \ (_v) = _tmp.f; \ } while (0) #define GETN(_v,_s) PUT_GET_N(_v,_s,I->input.file,read) #define GET_TABLE(_T, _GETX, _NUM,_TYPE) \ do { \ int _i; \ (_T).size = (_NUM); \ (_T).element = (_TYPE *)realloc((_T).element, \ (_NUM)*sizeof((_T).element[0])); \ for (_i = 0; _i < (_T).size; _i++) \ _GETX((_T).element[_i]); \ } while (0) #define GET_PROPERTY_TABLE(_T, _NUM) \ do { \ int _i; \ (_T).size = (_NUM); \ (_T).element = (x3f_property_t *)realloc((_T).element, \ (_NUM)*sizeof((_T).element[0])); \ for (_i = 0; _i < (_T).size; _i++) { \ GET4((_T).element[_i].name_offset); \ GET4((_T).element[_i].value_offset); \ } \ } while (0) #define GET_TRUE_HUFF_TABLE(_T) \ do { \ int _i; \ (_T).element = NULL; \ for (_i = 0; ; _i++) { \ (_T).size = _i + 1; \ (_T).element = (x3f_true_huffman_element_t *)realloc((_T).element, \ (_i + 1)*sizeof((_T).element[0])); \ GET1((_T).element[_i].code_size); \ GET1((_T).element[_i].code); \ if ((_T).element[_i].code_size == 0) break; \ } \ } while (0) /* --------------------------------------------------------------------- */ /* Allocating Huffman tree help data */ /* --------------------------------------------------------------------- */ static void cleanup_huffman_tree(x3f_hufftree_t *HTP) { free(HTP->nodes); } static void new_huffman_tree(x3f_hufftree_t *HTP, int bits) { int leaves = 1<free_node_index = 0; HTP->nodes = (x3f_huffnode_t *) calloc(1, HUF_TREE_MAX_NODES(leaves)*sizeof(x3f_huffnode_t)); } /* --------------------------------------------------------------------- */ /* Allocating TRUE engine RAW help data */ /* --------------------------------------------------------------------- */ static void cleanup_true(x3f_true_t **TRUP) { x3f_true_t *TRU = *TRUP; if (TRU == NULL) return; FREE(TRU->table.element); FREE(TRU->plane_size.element); cleanup_huffman_tree(&TRU->tree); FREE(TRU->x3rgb16.buf); FREE(TRU); *TRUP = NULL; } static x3f_true_t *new_true(x3f_true_t **TRUP) { x3f_true_t *TRU = (x3f_true_t *)calloc(1, sizeof(x3f_true_t)); cleanup_true(TRUP); TRU->table.size = 0; TRU->table.element = NULL; TRU->plane_size.size = 0; TRU->plane_size.element = NULL; TRU->tree.nodes = NULL; TRU->x3rgb16.data = NULL; TRU->x3rgb16.buf = NULL; *TRUP = TRU; return TRU; } static void cleanup_quattro(x3f_quattro_t **QP) { x3f_quattro_t *Q = *QP; if (Q == NULL) return; FREE(Q->top16.buf); FREE(Q); *QP = NULL; } static x3f_quattro_t *new_quattro(x3f_quattro_t **QP) { x3f_quattro_t *Q = (x3f_quattro_t *)calloc(1, sizeof(x3f_quattro_t)); int i; cleanup_quattro(QP); for (i=0; iplane[i].columns = 0; Q->plane[i].rows = 0; } Q->unknown = 0; Q->top16.data = NULL; Q->top16.buf = NULL; *QP = Q; return Q; } /* --------------------------------------------------------------------- */ /* Allocating Huffman engine help data */ /* --------------------------------------------------------------------- */ static void cleanup_huffman(x3f_huffman_t **HUFP) { x3f_huffman_t *HUF = *HUFP; if (HUF == NULL) return; FREE(HUF->mapping.element); FREE(HUF->table.element); cleanup_huffman_tree(&HUF->tree); FREE(HUF->row_offsets.element); FREE(HUF->rgb8.buf); FREE(HUF->x3rgb16.buf); FREE(HUF); *HUFP = NULL; } static x3f_huffman_t *new_huffman(x3f_huffman_t **HUFP) { x3f_huffman_t *HUF = (x3f_huffman_t *)calloc(1, sizeof(x3f_huffman_t)); cleanup_huffman(HUFP); /* Set all not read data block pointers to NULL */ HUF->mapping.size = 0; HUF->mapping.element = NULL; HUF->table.size = 0; HUF->table.element = NULL; HUF->tree.nodes = NULL; HUF->row_offsets.size = 0; HUF->row_offsets.element = NULL; HUF->rgb8.data = NULL; HUF->rgb8.buf = NULL; HUF->x3rgb16.data = NULL; HUF->x3rgb16.buf = NULL; *HUFP = HUF; return HUF; } /* --------------------------------------------------------------------- */ /* Creating a new x3f structure from file */ /* --------------------------------------------------------------------- */ /* extern */ x3f_t *x3f_new_from_file(LibRaw_abstract_datastream *infile) { if (!infile) return NULL; INT64 fsize = infile->size(); x3f_t *x3f = (x3f_t *)calloc(1, sizeof(x3f_t)); if(!x3f) throw LIBRAW_EXCEPTION_ALLOC; try { x3f_info_t *I = NULL; x3f_header_t *H = NULL; x3f_directory_section_t *DS = NULL; int i, d; I = &x3f->info; I->error = NULL; I->input.file = infile; I->output.file = NULL; /* Read file header */ H = &x3f->header; infile->seek(0, SEEK_SET); GET4(H->identifier); if (H->identifier != X3F_FOVb) { free(x3f); return NULL; } GET4(H->version); GETN(H->unique_identifier, SIZE_UNIQUE_IDENTIFIER); /* TODO: the meaning of the rest of the header for version >= 4.0 (Quattro) is unknown */ if (H->version < X3F_VERSION_4_0) { GET4(H->mark_bits); GET4(H->columns); GET4(H->rows); GET4(H->rotation); if (H->version >= X3F_VERSION_2_1) { int num_ext_data = H->version >= X3F_VERSION_3_0 ? NUM_EXT_DATA_3_0 : NUM_EXT_DATA_2_1; GETN(H->white_balance, SIZE_WHITE_BALANCE); if (H->version >= X3F_VERSION_2_3) GETN(H->color_mode, SIZE_COLOR_MODE); GETN(H->extended_types, num_ext_data); for (i = 0; i < num_ext_data; i++) GET4F(H->extended_data[i]); } } /* Go to the beginning of the directory */ infile->seek(-4, SEEK_END); infile->seek(x3f_get4(infile), SEEK_SET); /* Read the directory header */ DS = &x3f->directory_section; GET4(DS->identifier); GET4(DS->version); GET4(DS->num_directory_entries); if (DS->num_directory_entries > 50) goto _err; // too much direntries, most likely broken file if (DS->num_directory_entries > 0) { size_t size = DS->num_directory_entries * sizeof(x3f_directory_entry_t); DS->directory_entry = (x3f_directory_entry_t *)calloc(1, size); } /* Traverse the directory */ for (d=0; dnum_directory_entries; d++) { x3f_directory_entry_t *DE = &DS->directory_entry[d]; x3f_directory_entry_header_t *DEH = &DE->header; uint32_t save_dir_pos; /* Read the directory entry info */ GET4(DE->input.offset); GET4(DE->input.size); if (DE->input.offset + DE->input.size > fsize * 2) goto _err; DE->output.offset = 0; DE->output.size = 0; GET4(DE->type); /* Save current pos and go to the entry */ save_dir_pos = infile->tell(); infile->seek(DE->input.offset, SEEK_SET); /* Read the type independent part of the entry header */ DEH = &DE->header; GET4(DEH->identifier); GET4(DEH->version); /* NOTE - the tests below could be made on DE->type instead */ if (DEH->identifier == X3F_SECp) { x3f_property_list_t *PL = &DEH->data_subsection.property_list; if (!PL) goto _err; /* Read the property part of the header */ GET4(PL->num_properties); GET4(PL->character_format); GET4(PL->reserved); GET4(PL->total_length); /* Set all not read data block pointers to NULL */ PL->data = NULL; PL->data_size = 0; } if (DEH->identifier == X3F_SECi) { x3f_image_data_t *ID = &DEH->data_subsection.image_data; if (!ID) goto _err; /* Read the image part of the header */ GET4(ID->type); GET4(ID->format); ID->type_format = (ID->type << 16) + (ID->format); GET4(ID->columns); GET4(ID->rows); GET4(ID->row_stride); /* Set all not read data block pointers to NULL */ ID->huffman = NULL; ID->data = NULL; ID->data_size = 0; } if (DEH->identifier == X3F_SECc) { x3f_camf_t *CAMF = &DEH->data_subsection.camf; if (!CAMF) goto _err; /* Read the CAMF part of the header */ GET4(CAMF->type); GET4(CAMF->tN.val0); GET4(CAMF->tN.val1); GET4(CAMF->tN.val2); GET4(CAMF->tN.val3); /* Set all not read data block pointers to NULL */ CAMF->data = NULL; CAMF->data_size = 0; /* Set all not allocated help pointers to NULL */ CAMF->table.element = NULL; CAMF->table.size = 0; CAMF->tree.nodes = NULL; CAMF->decoded_data = NULL; CAMF->decoded_data_size = 0; CAMF->entry_table.element = NULL; CAMF->entry_table.size = 0; } /* Reset the file pointer back to the directory */ infile->seek(save_dir_pos, SEEK_SET); } return x3f; _err: if (x3f) { DS = &x3f->directory_section; if (DS && DS->directory_entry) free(DS->directory_entry); free(x3f); } return NULL; } catch (...) { x3f_directory_section_t *DS = &x3f->directory_section; if (DS && DS->directory_entry) free(DS->directory_entry); free(x3f); return NULL; } } /* --------------------------------------------------------------------- */ /* Clean up an x3f structure */ /* --------------------------------------------------------------------- */ static void free_camf_entry(camf_entry_t *entry) { FREE(entry->property_name); FREE(entry->property_value); FREE(entry->matrix_decoded); FREE(entry->matrix_dim_entry); } /* extern */ x3f_return_t x3f_delete(x3f_t *x3f) { x3f_directory_section_t *DS; int d; if (x3f == NULL) return X3F_ARGUMENT_ERROR; DS = &x3f->directory_section; if (DS->num_directory_entries > 50) return X3F_ARGUMENT_ERROR; for (d=0; dnum_directory_entries; d++) { x3f_directory_entry_t *DE = &DS->directory_entry[d]; x3f_directory_entry_header_t *DEH = &DE->header; if (DEH->identifier == X3F_SECp) { x3f_property_list_t *PL = &DEH->data_subsection.property_list; + if (PL) + { + int i; + } FREE(PL->property_table.element); FREE(PL->data); } if (DEH->identifier == X3F_SECi) { x3f_image_data_t *ID = &DEH->data_subsection.image_data; if (ID) { cleanup_huffman(&ID->huffman); cleanup_true(&ID->tru); cleanup_quattro(&ID->quattro); FREE(ID->data); } } if (DEH->identifier == X3F_SECc) { x3f_camf_t *CAMF = &DEH->data_subsection.camf; int i; if (CAMF) { FREE(CAMF->data); FREE(CAMF->table.element); cleanup_huffman_tree(&CAMF->tree); FREE(CAMF->decoded_data); for (i = 0; i < CAMF->entry_table.size; i++) { free_camf_entry(&CAMF->entry_table.element[i]); } } FREE(CAMF->entry_table.element); } } FREE(DS->directory_entry); FREE(x3f); return X3F_OK; } /* --------------------------------------------------------------------- */ /* Getting a reference to a directory entry */ /* --------------------------------------------------------------------- */ /* TODO: all those only get the first instance */ static x3f_directory_entry_t *x3f_get(x3f_t *x3f, uint32_t type, uint32_t image_type) { x3f_directory_section_t *DS; int d; if (x3f == NULL) return NULL; DS = &x3f->directory_section; for (d=0; dnum_directory_entries; d++) { x3f_directory_entry_t *DE = &DS->directory_entry[d]; x3f_directory_entry_header_t *DEH = &DE->header; if (DEH->identifier == type) { switch (DEH->identifier) { case X3F_SECi: { x3f_image_data_t *ID = &DEH->data_subsection.image_data; if (ID->type_format == image_type) return DE; } break; default: return DE; } } } return NULL; } /* extern */ x3f_directory_entry_t *x3f_get_raw(x3f_t *x3f) { x3f_directory_entry_t *DE; if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_HUFFMAN_X530)) != NULL) return DE; if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_HUFFMAN_10BIT)) != NULL) return DE; if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_TRUE)) != NULL) return DE; if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_MERRILL)) != NULL) return DE; if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_QUATTRO)) != NULL) return DE; if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_SDQ)) != NULL) return DE; if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_SDQH)) != NULL) return DE; if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_SDQH2)) != NULL) return DE; return NULL; } /* extern */ x3f_directory_entry_t *x3f_get_thumb_plain(x3f_t *x3f) { return x3f_get(x3f, X3F_SECi, X3F_IMAGE_THUMB_PLAIN); } /* extern */ x3f_directory_entry_t *x3f_get_thumb_huffman(x3f_t *x3f) { return x3f_get(x3f, X3F_SECi, X3F_IMAGE_THUMB_HUFFMAN); } /* extern */ x3f_directory_entry_t *x3f_get_thumb_jpeg(x3f_t *x3f) { return x3f_get(x3f, X3F_SECi, X3F_IMAGE_THUMB_JPEG); } /* extern */ x3f_directory_entry_t *x3f_get_camf(x3f_t *x3f) { return x3f_get(x3f, X3F_SECc, 0); } /* extern */ x3f_directory_entry_t *x3f_get_prop(x3f_t *x3f) { return x3f_get(x3f, X3F_SECp, 0); } /* For some obscure reason, the bit numbering is weird. It is generally some kind of "big endian" style - e.g. the bit 7 is the first in a byte and bit 31 first in a 4 byte int. For patterns in the huffman pattern table, bit 27 is the first bit and bit 26 the next one. */ #define PATTERN_BIT_POS(_len, _bit) ((_len) - (_bit) - 1) #define MEMORY_BIT_POS(_bit) PATTERN_BIT_POS(8, _bit) /* --------------------------------------------------------------------- */ /* Huffman Decode */ /* --------------------------------------------------------------------- */ /* Make the huffman tree */ #ifdef DBG_PRNT static char *display_code(int length, uint32_t code, char *buffer) { int i; for (i=0; i>pos)&1) == 0 ? '0' : '1'; } buffer[i] = 0; return buffer; } #endif static x3f_huffnode_t *new_node(x3f_hufftree_t *tree) { x3f_huffnode_t *t = &tree->nodes[tree->free_node_index]; t->branch[0] = NULL; t->branch[1] = NULL; t->leaf = UNDEFINED_LEAF; tree->free_node_index++; return t; } static void add_code_to_tree(x3f_hufftree_t *tree, int length, uint32_t code, uint32_t value) { int i; x3f_huffnode_t *t = tree->nodes; for (i=0; i>pos)&1; x3f_huffnode_t *t_next = t->branch[bit]; if (t_next == NULL) t_next = t->branch[bit] = new_node(tree); t = t_next; } t->leaf = value; } static void populate_true_huffman_tree(x3f_hufftree_t *tree, x3f_true_huffman_t *table) { int i; new_node(tree); for (i=0; isize; i++) { x3f_true_huffman_element_t *element = &table->element[i]; uint32_t length = element->code_size; if (length != 0) { /* add_code_to_tree wants the code right adjusted */ uint32_t code = ((element->code) >> (8 - length)) & 0xff; uint32_t value = i; add_code_to_tree(tree, length, code, value); #ifdef DBG_PRNT { char buffer[100]; x3f_printf(DEBUG, "H %5d : %5x : %5d : %02x %08x (%08x) (%s)\n", i, i, value, length, code, value, display_code(length, code, buffer)); } #endif } } } static void populate_huffman_tree(x3f_hufftree_t *tree, x3f_table32_t *table, x3f_table16_t *mapping) { int i; new_node(tree); for (i=0; isize; i++) { uint32_t element = table->element[i]; if (element != 0) { uint32_t length = HUF_TREE_GET_LENGTH(element); uint32_t code = HUF_TREE_GET_CODE(element); uint32_t value; /* If we have a valid mapping table - then the value from the mapping table shall be used. Otherwise we use the current index in the table as value. */ if (table->size == mapping->size) value = mapping->element[i]; else value = i; add_code_to_tree(tree, length, code, value); #ifdef DBG_PRNT { char buffer[100]; x3f_printf(DEBUG, "H %5d : %5x : %5d : %02x %08x (%08x) (%s)\n", i, i, value, length, code, element, display_code(length, code, buffer)); } #endif } } } #ifdef DBG_PRNT static void print_huffman_tree(x3f_huffnode_t *t, int length, uint32_t code) { char buf1[100]; char buf2[100]; x3f_printf(DEBUG, "%*s (%s,%s) %s (%s)\n", length, length < 1 ? "-" : (code&1) ? "1" : "0", t->branch[0]==NULL ? "-" : "0", t->branch[1]==NULL ? "-" : "1", t->leaf==UNDEFINED_LEAF ? "-" : (sprintf(buf1, "%x", t->leaf),buf1), display_code(length, code, buf2)); code = code << 1; if (t->branch[0]) print_huffman_tree(t->branch[0], length+1, code+0); if (t->branch[1]) print_huffman_tree(t->branch[1], length+1, code+1); } #endif /* Help machinery for reading bits in a memory */ typedef struct bit_state_s { uint8_t *next_address; uint8_t bit_offset; uint8_t bits[8]; } bit_state_t; static void set_bit_state(bit_state_t *BS, uint8_t *address) { BS->next_address = address; BS->bit_offset = 8; } static uint8_t get_bit(bit_state_t *BS) { if (BS->bit_offset == 8) { uint8_t byte = *BS->next_address; int i; for (i=7; i>= 0; i--) { BS->bits[i] = byte&1; byte = byte >> 1; } BS->next_address++; BS->bit_offset = 0; } return BS->bits[BS->bit_offset++]; } /* Decode use the TRUE algorithm */ static int32_t get_true_diff(bit_state_t *BS, x3f_hufftree_t *HTP) { int32_t diff; x3f_huffnode_t *node = &HTP->nodes[0]; uint8_t bits; while (node->branch[0] != NULL || node->branch[1] != NULL) { uint8_t bit = get_bit(BS); x3f_huffnode_t *new_node = node->branch[bit]; node = new_node; if (node == NULL) { /* TODO: Shouldn't this be treated as a fatal error? */ return 0; } } bits = node->leaf; if (bits == 0) diff = 0; else { uint8_t first_bit = get_bit(BS); int i; diff = first_bit; for (i=1; itru; x3f_quattro_t *Q = ID->quattro; uint32_t seed = TRU->seed[color]; /* TODO : Is this correct ? */ int row; x3f_hufftree_t *tree = &TRU->tree; bit_state_t BS; int32_t row_start_acc[2][2]; uint32_t rows = ID->rows; uint32_t cols = ID->columns; x3f_area16_t *area = &TRU->x3rgb16; uint16_t *dst = area->data + color; set_bit_state(&BS, TRU->plane_address[color]); row_start_acc[0][0] = seed; row_start_acc[0][1] = seed; row_start_acc[1][0] = seed; row_start_acc[1][1] = seed; if (ID->type_format == X3F_IMAGE_RAW_QUATTRO || ID->type_format == X3F_IMAGE_RAW_SDQ || ID->type_format == X3F_IMAGE_RAW_SDQH || ID->type_format == X3F_IMAGE_RAW_SDQH2 ) { rows = Q->plane[color].rows; cols = Q->plane[color].columns; if (Q->quattro_layout && color == 2) { area = &Q->top16; dst = area->data; } } else { } if(rows != area->rows || cols < area->columns) throw LIBRAW_EXCEPTION_IO_CORRUPT; for (row = 0; row < rows; row++) { int col; bool_t odd_row = row&1; int32_t acc[2]; for (col = 0; col < cols; col++) { bool_t odd_col = col&1; int32_t diff = get_true_diff(&BS, tree); int32_t prev = col < 2 ? row_start_acc[odd_row][odd_col] : acc[odd_col]; int32_t value = prev + diff; acc[odd_col] = value; if (col < 2) row_start_acc[odd_row][odd_col] = value; /* Discard additional data at the right for binned Quattro plane 2 */ if (col >= area->columns) continue; *dst = value; dst += area->channels; } } } static void true_decode(x3f_info_t *I, x3f_directory_entry_t *DE) { x3f_directory_entry_header_t *DEH = &DE->header; x3f_image_data_t *ID = &DEH->data_subsection.image_data; int color; for (color = 0; color < 3; color++) { true_decode_one_color(ID, color); } } /* Decode use the huffman tree */ static int32_t get_huffman_diff(bit_state_t *BS, x3f_hufftree_t *HTP) { int32_t diff; x3f_huffnode_t *node = &HTP->nodes[0]; while (node->branch[0] != NULL || node->branch[1] != NULL) { uint8_t bit = get_bit(BS); x3f_huffnode_t *new_node = node->branch[bit]; node = new_node; if (node == NULL) { /* TODO: Shouldn't this be treated as a fatal error? */ throw LIBRAW_EXCEPTION_IO_CORRUPT; return 0; } } diff = node->leaf; return diff; } static void huffman_decode_row(x3f_info_t *I, x3f_directory_entry_t *DE, int bits, int row, int offset, int *minimum) { x3f_directory_entry_header_t *DEH = &DE->header; x3f_image_data_t *ID = &DEH->data_subsection.image_data; x3f_huffman_t *HUF = ID->huffman; - int16_t c[3] = {offset,offset,offset}; + int16_t c[3] = {(int16_t)offset,(int16_t)offset,(int16_t)offset}; int col; bit_state_t BS; set_bit_state(&BS, (uint8_t*)ID->data + HUF->row_offsets.element[row]); for (col = 0; col < ID->columns; col++) { int color; for (color = 0; color < 3; color++) { uint16_t c_fix; c[color] += get_huffman_diff(&BS, &HUF->tree); if (c[color] < 0) { c_fix = 0; if (c[color] < *minimum) *minimum = c[color]; } else { c_fix = c[color]; } switch (ID->type_format) { case X3F_IMAGE_RAW_HUFFMAN_X530: case X3F_IMAGE_RAW_HUFFMAN_10BIT: HUF->x3rgb16.data[3*(row*ID->columns + col) + color] = (uint16_t)c_fix; break; case X3F_IMAGE_THUMB_HUFFMAN: HUF->rgb8.data[3*(row*ID->columns + col) + color] = (uint8_t)c_fix; break; default: /* TODO: Shouldn't this be treated as a fatal error? */ throw LIBRAW_EXCEPTION_IO_CORRUPT; } } } } static void huffman_decode(x3f_info_t *I, x3f_directory_entry_t *DE, int bits) { x3f_directory_entry_header_t *DEH = &DE->header; x3f_image_data_t *ID = &DEH->data_subsection.image_data; int row; int minimum = 0; int offset = legacy_offset; for (row = 0; row < ID->rows; row++) huffman_decode_row(I, DE, bits, row, offset, &minimum); if (auto_legacy_offset && minimum < 0) { offset = -minimum; for (row = 0; row < ID->rows; row++) huffman_decode_row(I, DE, bits, row, offset, &minimum); } } static int32_t get_simple_diff(x3f_huffman_t *HUF, uint16_t index) { if (HUF->mapping.size == 0) return index; else return HUF->mapping.element[index]; } static void simple_decode_row(x3f_info_t *I, x3f_directory_entry_t *DE, int bits, int row, int row_stride) { x3f_directory_entry_header_t *DEH = &DE->header; x3f_image_data_t *ID = &DEH->data_subsection.image_data; x3f_huffman_t *HUF = ID->huffman; uint32_t *data = (uint32_t *)((unsigned char*)ID->data + row*row_stride); uint16_t c[3] = {0,0,0}; int col; uint32_t mask = 0; switch (bits) { case 8: mask = 0x0ff; break; case 9: mask = 0x1ff; break; case 10: mask = 0x3ff; break; case 11: mask = 0x7ff; break; case 12: mask = 0xfff; break; default: mask = 0; /* TODO: Shouldn't this be treated as a fatal error? */ throw LIBRAW_EXCEPTION_IO_CORRUPT; break; } for (col = 0; col < ID->columns; col++) { int color; uint32_t val = data[col]; for (color = 0; color < 3; color++) { uint16_t c_fix; c[color] += get_simple_diff(HUF, (val>>(color*bits))&mask); switch (ID->type_format) { case X3F_IMAGE_RAW_HUFFMAN_X530: case X3F_IMAGE_RAW_HUFFMAN_10BIT: c_fix = (int16_t)c[color] > 0 ? c[color] : 0; HUF->x3rgb16.data[3*(row*ID->columns + col) + color] = c_fix; break; case X3F_IMAGE_THUMB_HUFFMAN: c_fix = (int8_t)c[color] > 0 ? c[color] : 0; HUF->rgb8.data[3*(row*ID->columns + col) + color] = c_fix; break; default: /* TODO: Shouldn't this be treated as a fatal error? */ throw LIBRAW_EXCEPTION_IO_CORRUPT; } } } } static void simple_decode(x3f_info_t *I, x3f_directory_entry_t *DE, int bits, int row_stride) { x3f_directory_entry_header_t *DEH = &DE->header; x3f_image_data_t *ID = &DEH->data_subsection.image_data; int row; for (row = 0; row < ID->rows; row++) simple_decode_row(I, DE, bits, row, row_stride); } /* --------------------------------------------------------------------- */ /* Loading the data in a directory entry */ /* --------------------------------------------------------------------- */ /* First you set the offset to where to start reading the data ... */ static void read_data_set_offset(x3f_info_t *I, x3f_directory_entry_t *DE, uint32_t header_size) { uint32_t i_off = DE->input.offset + header_size; I->input.file->seek(i_off, SEEK_SET); } /* ... then you read the data, block for block */ static uint32_t read_data_block(void **data, x3f_info_t *I, x3f_directory_entry_t *DE, uint32_t footer) { INT64 fpos = I->input.file->tell(); uint32_t size = DE->input.size + DE->input.offset - fpos - footer; if (fpos + size > I->input.file->size()) throw LIBRAW_EXCEPTION_IO_CORRUPT; *data = (void *)malloc(size); GETN(*data, size); return size; } static uint32_t data_block_size(void **data, x3f_info_t *I, x3f_directory_entry_t *DE, uint32_t footer) { uint32_t size = DE->input.size + DE->input.offset - I->input.file->tell() - footer; return size; } static void x3f_load_image_verbatim(x3f_info_t *I, x3f_directory_entry_t *DE) { x3f_directory_entry_header_t *DEH = &DE->header; x3f_image_data_t *ID = &DEH->data_subsection.image_data; if (!ID->data_size) ID->data_size = read_data_block(&ID->data, I, DE, 0); } static int32_t x3f_load_image_verbatim_size(x3f_info_t *I, x3f_directory_entry_t *DE) { x3f_directory_entry_header_t *DEH = &DE->header; x3f_image_data_t *ID = &DEH->data_subsection.image_data; return data_block_size(&ID->data, I, DE, 0); } static void x3f_load_property_list(x3f_info_t *I, x3f_directory_entry_t *DE) { x3f_directory_entry_header_t *DEH = &DE->header; x3f_property_list_t *PL = &DEH->data_subsection.property_list; int i; read_data_set_offset(I, DE, X3F_PROPERTY_LIST_HEADER_SIZE); GET_PROPERTY_TABLE(PL->property_table, PL->num_properties); if (!PL->data_size) PL->data_size = read_data_block(&PL->data, I, DE, 0); - uint32_t maxoffset = PL->data_size/sizeof(utf16_t)-2; // at least 2 chars, value + terminating 0x0000 + uint32_t maxoffset = PL->data_size/sizeof(utf16_t)-2; // at least 2 chars, value + terminating 0x0000 for (i=0; inum_properties; i++) { x3f_property_t *P = &PL->property_table.element[i]; - if(P->name_offset > maxoffset || P->value_offset > maxoffset) - throw LIBRAW_EXCEPTION_IO_CORRUPT; + if(P->name_offset > maxoffset || P->value_offset > maxoffset) + throw LIBRAW_EXCEPTION_IO_CORRUPT; P->name = ((utf16_t *)PL->data + P->name_offset); P->value = ((utf16_t *)PL->data + P->value_offset); } } static void x3f_load_true(x3f_info_t *I, x3f_directory_entry_t *DE) { x3f_directory_entry_header_t *DEH = &DE->header; x3f_image_data_t *ID = &DEH->data_subsection.image_data; x3f_true_t *TRU = new_true(&ID->tru); x3f_quattro_t *Q = NULL; int i; if (ID->type_format == X3F_IMAGE_RAW_QUATTRO || ID->type_format == X3F_IMAGE_RAW_SDQ || ID->type_format == X3F_IMAGE_RAW_SDQH || ID->type_format == X3F_IMAGE_RAW_SDQH2 ) { Q = new_quattro(&ID->quattro); for (i=0; iplane[i].columns); GET2(Q->plane[i].rows); } if (Q->plane[0].rows == ID->rows/2) { Q->quattro_layout = 1; } else if (Q->plane[0].rows == ID->rows) { Q->quattro_layout = 0; } else { throw LIBRAW_EXCEPTION_IO_CORRUPT; } } /* Read TRUE header data */ GET2(TRU->seed[0]); GET2(TRU->seed[1]); GET2(TRU->seed[2]); GET2(TRU->unknown); GET_TRUE_HUFF_TABLE(TRU->table); if (ID->type_format == X3F_IMAGE_RAW_QUATTRO ||ID->type_format == X3F_IMAGE_RAW_SDQ ||ID->type_format == X3F_IMAGE_RAW_SDQH ||ID->type_format == X3F_IMAGE_RAW_SDQH2 ) { GET4(Q->unknown); } GET_TABLE(TRU->plane_size, GET4, TRUE_PLANES,uint32_t); /* Read image data */ if (!ID->data_size) ID->data_size = read_data_block(&ID->data, I, DE, 0); /* TODO: can it be fewer than 8 bits? Maybe taken from TRU->table? */ new_huffman_tree(&TRU->tree, 8); populate_true_huffman_tree(&TRU->tree, &TRU->table); #ifdef DBG_PRNT print_huffman_tree(TRU->tree.nodes, 0, 0); #endif TRU->plane_address[0] = (uint8_t*)ID->data; for (i=1; iplane_address[i] = TRU->plane_address[i-1] + (((TRU->plane_size.element[i-1] + 15) / 16) * 16); if ( (ID->type_format == X3F_IMAGE_RAW_QUATTRO || ID->type_format == X3F_IMAGE_RAW_SDQ || ID->type_format == X3F_IMAGE_RAW_SDQH || ID->type_format == X3F_IMAGE_RAW_SDQH2 ) && Q->quattro_layout) { uint32_t columns = Q->plane[0].columns; uint32_t rows = Q->plane[0].rows; uint32_t channels = 3; uint32_t size = columns * rows * channels; TRU->x3rgb16.columns = columns; TRU->x3rgb16.rows = rows; TRU->x3rgb16.channels = channels; TRU->x3rgb16.row_stride = columns * channels; TRU->x3rgb16.buf = malloc(sizeof(uint16_t)*size); TRU->x3rgb16.data = (uint16_t *) TRU->x3rgb16.buf; columns = Q->plane[2].columns; rows = Q->plane[2].rows; channels = 1; size = columns * rows * channels; Q->top16.columns = columns; Q->top16.rows = rows; Q->top16.channels = channels; Q->top16.row_stride = columns * channels; Q->top16.buf = malloc(sizeof(uint16_t)*size); Q->top16.data = (uint16_t *)Q->top16.buf; } else { uint32_t size = ID->columns * ID->rows * 3; TRU->x3rgb16.columns = ID->columns; TRU->x3rgb16.rows = ID->rows; TRU->x3rgb16.channels = 3; TRU->x3rgb16.row_stride = ID->columns * 3; TRU->x3rgb16.buf =malloc(sizeof(uint16_t)*size); TRU->x3rgb16.data = (uint16_t *)TRU->x3rgb16.buf; } true_decode(I, DE); } static void x3f_load_huffman_compressed(x3f_info_t *I, x3f_directory_entry_t *DE, int bits, int use_map_table) { x3f_directory_entry_header_t *DEH = &DE->header; x3f_image_data_t *ID = &DEH->data_subsection.image_data; x3f_huffman_t *HUF = ID->huffman; int table_size = 1<rows * sizeof(HUF->row_offsets.element[0]); GET_TABLE(HUF->table, GET4, table_size,uint32_t); if (!ID->data_size) ID->data_size = read_data_block(&ID->data, I, DE, row_offsets_size); GET_TABLE(HUF->row_offsets, GET4, ID->rows,uint32_t); new_huffman_tree(&HUF->tree, bits); populate_huffman_tree(&HUF->tree, &HUF->table, &HUF->mapping); huffman_decode(I, DE, bits); } static void x3f_load_huffman_not_compressed(x3f_info_t *I, x3f_directory_entry_t *DE, int bits, int use_map_table, int row_stride) { x3f_directory_entry_header_t *DEH = &DE->header; x3f_image_data_t *ID = &DEH->data_subsection.image_data; if (!ID->data_size) ID->data_size = read_data_block(&ID->data, I, DE, 0); simple_decode(I, DE, bits, row_stride); } static void x3f_load_huffman(x3f_info_t *I, x3f_directory_entry_t *DE, int bits, int use_map_table, int row_stride) { x3f_directory_entry_header_t *DEH = &DE->header; x3f_image_data_t *ID = &DEH->data_subsection.image_data; x3f_huffman_t *HUF = new_huffman(&ID->huffman); uint32_t size; if (use_map_table) { int table_size = 1<mapping, GET2, table_size,uint16_t); } switch (ID->type_format) { case X3F_IMAGE_RAW_HUFFMAN_X530: case X3F_IMAGE_RAW_HUFFMAN_10BIT: size = ID->columns * ID->rows * 3; HUF->x3rgb16.columns = ID->columns; HUF->x3rgb16.rows = ID->rows; HUF->x3rgb16.channels = 3; HUF->x3rgb16.row_stride = ID->columns * 3; HUF->x3rgb16.buf = malloc(sizeof(uint16_t)*size); HUF->x3rgb16.data = (uint16_t *)HUF->x3rgb16.buf; break; case X3F_IMAGE_THUMB_HUFFMAN: size = ID->columns * ID->rows * 3; HUF->rgb8.columns = ID->columns; HUF->rgb8.rows = ID->rows; HUF->rgb8.channels = 3; HUF->rgb8.row_stride = ID->columns * 3; HUF->rgb8.buf = malloc(sizeof(uint8_t)*size); HUF->rgb8.data = (uint8_t *)HUF->rgb8.buf; break; default: /* TODO: Shouldn't this be treated as a fatal error? */ throw LIBRAW_EXCEPTION_IO_CORRUPT; } if (row_stride == 0) return x3f_load_huffman_compressed(I, DE, bits, use_map_table); else return x3f_load_huffman_not_compressed(I, DE, bits, use_map_table, row_stride); } static void x3f_load_pixmap(x3f_info_t *I, x3f_directory_entry_t *DE) { x3f_load_image_verbatim(I, DE); } static uint32_t x3f_load_pixmap_size(x3f_info_t *I, x3f_directory_entry_t *DE) { return x3f_load_image_verbatim_size(I, DE); } static void x3f_load_jpeg(x3f_info_t *I, x3f_directory_entry_t *DE) { x3f_load_image_verbatim(I, DE); } static uint32_t x3f_load_jpeg_size(x3f_info_t *I, x3f_directory_entry_t *DE) { return x3f_load_image_verbatim_size(I, DE); } static void x3f_load_image(x3f_info_t *I, x3f_directory_entry_t *DE) { x3f_directory_entry_header_t *DEH = &DE->header; x3f_image_data_t *ID = &DEH->data_subsection.image_data; read_data_set_offset(I, DE, X3F_IMAGE_HEADER_SIZE); switch (ID->type_format) { case X3F_IMAGE_RAW_TRUE: case X3F_IMAGE_RAW_MERRILL: case X3F_IMAGE_RAW_QUATTRO: case X3F_IMAGE_RAW_SDQ: case X3F_IMAGE_RAW_SDQH: case X3F_IMAGE_RAW_SDQH2: x3f_load_true(I, DE); break; case X3F_IMAGE_RAW_HUFFMAN_X530: case X3F_IMAGE_RAW_HUFFMAN_10BIT: x3f_load_huffman(I, DE, 10, 1, ID->row_stride); break; case X3F_IMAGE_THUMB_PLAIN: x3f_load_pixmap(I, DE); break; case X3F_IMAGE_THUMB_HUFFMAN: x3f_load_huffman(I, DE, 8, 0, ID->row_stride); break; case X3F_IMAGE_THUMB_JPEG: x3f_load_jpeg(I, DE); break; default: /* TODO: Shouldn't this be treated as a fatal error? */ throw LIBRAW_EXCEPTION_IO_CORRUPT; } } // Used only for thumbnail size estimation static uint32_t x3f_load_image_size(x3f_info_t *I, x3f_directory_entry_t *DE) { x3f_directory_entry_header_t *DEH = &DE->header; x3f_image_data_t *ID = &DEH->data_subsection.image_data; read_data_set_offset(I, DE, X3F_IMAGE_HEADER_SIZE); switch (ID->type_format) { case X3F_IMAGE_THUMB_PLAIN: return x3f_load_pixmap_size(I, DE); case X3F_IMAGE_THUMB_JPEG: return x3f_load_jpeg_size(I, DE); break; default: return 0; } } static void x3f_load_camf_decode_type2(x3f_camf_t *CAMF) { uint32_t key = CAMF->t2.crypt_key; int i; CAMF->decoded_data_size = CAMF->data_size; CAMF->decoded_data = malloc(CAMF->decoded_data_size); for (i=0; idata_size; i++) { uint8_t old, _new; uint32_t tmp; old = ((uint8_t *)CAMF->data)[i]; key = (key * 1597 + 51749) % 244944; tmp = (uint32_t)(key * ((int64_t)301593171) >> 24); _new = (uint8_t)(old ^ (uint8_t)(((((key << 8) - tmp) >> 1) + tmp) >> 17)); ((uint8_t *)CAMF->decoded_data)[i] = _new; } } /* NOTE: the unpacking in this code is in big respects identical to true_decode_one_color(). The difference is in the output you build. It might be possible to make some parts shared. NOTE ALSO: This means that the meta data is obfuscated using an image compression algorithm. */ static void camf_decode_type4(x3f_camf_t *CAMF) { uint32_t seed = CAMF->t4.decode_bias; int row; uint8_t *dst; uint32_t dst_size = CAMF->t4.decoded_data_size; uint8_t *dst_end; bool_t odd_dst = 0; x3f_hufftree_t *tree = &CAMF->tree; bit_state_t BS; int32_t row_start_acc[2][2]; uint32_t rows = CAMF->t4.block_count; uint32_t cols = CAMF->t4.block_size; CAMF->decoded_data_size = dst_size; CAMF->decoded_data = malloc(CAMF->decoded_data_size); memset(CAMF->decoded_data, 0, CAMF->decoded_data_size); dst = (uint8_t *)CAMF->decoded_data; dst_end = dst + dst_size; set_bit_state(&BS, CAMF->decoding_start); row_start_acc[0][0] = seed; row_start_acc[0][1] = seed; row_start_acc[1][0] = seed; row_start_acc[1][1] = seed; for (row = 0; row < rows; row++) { int col; bool_t odd_row = row&1; int32_t acc[2]; /* We loop through all the columns and the rows. But the actual data is smaller than that, so we break the loop when reaching the end. */ for (col = 0; col < cols; col++) { bool_t odd_col = col&1; int32_t diff = get_true_diff(&BS, tree); int32_t prev = col < 2 ? row_start_acc[odd_row][odd_col] : acc[odd_col]; int32_t value = prev + diff; acc[odd_col] = value; if (col < 2) row_start_acc[odd_row][odd_col] = value; switch(odd_dst) { case 0: *dst++ = (uint8_t)((value>>4)&0xff); if (dst >= dst_end) { goto ready; } *dst = (uint8_t)((value<<4)&0xf0); break; case 1: *dst++ |= (uint8_t)((value>>8)&0x0f); if (dst >= dst_end) { goto ready; } *dst++ = (uint8_t)((value<<0)&0xff); if (dst >= dst_end) { goto ready; } break; } odd_dst = !odd_dst; } /* end col */ } /* end row */ ready:; } static void x3f_load_camf_decode_type4(x3f_camf_t *CAMF) { int i; uint8_t *p; x3f_true_huffman_element_t *element = NULL; for (i=0, p = (uint8_t*)CAMF->data; *p != 0; i++) { /* TODO: Is this too expensive ??*/ element = (x3f_true_huffman_element_t *)realloc(element, (i+1)*sizeof(*element)); element[i].code_size = *p++; element[i].code = *p++; } CAMF->table.size = i; CAMF->table.element = element; /* TODO: where does the values 28 and 32 come from? */ #define CAMF_T4_DATA_SIZE_OFFSET 28 #define CAMF_T4_DATA_OFFSET 32 CAMF->decoding_size = *(uint32_t *)((unsigned char*)CAMF->data + CAMF_T4_DATA_SIZE_OFFSET); CAMF->decoding_start = (uint8_t *)CAMF->data + CAMF_T4_DATA_OFFSET; /* TODO: can it be fewer than 8 bits? Maybe taken from TRU->table? */ new_huffman_tree(&CAMF->tree, 8); populate_true_huffman_tree(&CAMF->tree, &CAMF->table); #ifdef DBG_PRNT print_huffman_tree(CAMF->tree.nodes, 0, 0); #endif camf_decode_type4(CAMF); } static void camf_decode_type5(x3f_camf_t *CAMF) { int32_t acc = CAMF->t5.decode_bias; uint8_t *dst; x3f_hufftree_t *tree = &CAMF->tree; bit_state_t BS; int32_t i; CAMF->decoded_data_size = CAMF->t5.decoded_data_size; CAMF->decoded_data = malloc(CAMF->decoded_data_size); dst = (uint8_t *)CAMF->decoded_data; set_bit_state(&BS, CAMF->decoding_start); for (i = 0; i < CAMF->decoded_data_size; i++) { int32_t diff = get_true_diff(&BS, tree); acc = acc + diff; *dst++ = (uint8_t)(acc & 0xff); } } static void x3f_load_camf_decode_type5(x3f_camf_t *CAMF) { int i; uint8_t *p; x3f_true_huffman_element_t *element = NULL; for (i=0, p = (uint8_t*)CAMF->data; *p != 0; i++) { /* TODO: Is this too expensive ??*/ element = (x3f_true_huffman_element_t *)realloc(element, (i+1)*sizeof(*element)); element[i].code_size = *p++; element[i].code = *p++; } CAMF->table.size = i; CAMF->table.element = element; /* TODO: where does the values 28 and 32 come from? */ #define CAMF_T5_DATA_SIZE_OFFSET 28 #define CAMF_T5_DATA_OFFSET 32 CAMF->decoding_size = *(uint32_t *)((uint8_t*)CAMF->data + CAMF_T5_DATA_SIZE_OFFSET); CAMF->decoding_start = (uint8_t *)CAMF->data + CAMF_T5_DATA_OFFSET; /* TODO: can it be fewer than 8 bits? Maybe taken from TRU->table? */ new_huffman_tree(&CAMF->tree, 8); populate_true_huffman_tree(&CAMF->tree, &CAMF->table); #ifdef DBG_PRNT print_huffman_tree(CAMF->tree.nodes, 0, 0); #endif camf_decode_type5(CAMF); } static void x3f_setup_camf_text_entry(camf_entry_t *entry) { entry->text_size = *(uint32_t *)entry->value_address; entry->text = (char*)entry->value_address + 4; } static void x3f_setup_camf_property_entry(camf_entry_t *entry) { int i; uint8_t *e = (uint8_t*)entry->entry; uint8_t *v = (uint8_t*)entry->value_address; uint32_t num = entry->property_num = *(uint32_t *)v; uint32_t off = *(uint32_t *)(v + 4); entry->property_name = (char **)malloc(num*sizeof(uint8_t*)); entry->property_value = (uint8_t **)malloc(num*sizeof(uint8_t*)); for (i=0; iproperty_name[i] = (char *)(e + name_off); entry->property_value[i] = e + value_off; } } static void set_matrix_element_info(uint32_t type, uint32_t *size, matrix_type_t *decoded_type) { switch (type) { case 0: *size = 2; *decoded_type = M_INT; /* known to be true */ break; case 1: *size = 4; *decoded_type = M_UINT; /* TODO: unknown ???? */ break; case 2: *size = 4; *decoded_type = M_UINT; /* TODO: unknown ???? */ break; case 3: *size = 4; *decoded_type = M_FLOAT; /* known to be true */ break; case 5: *size = 1; *decoded_type = M_UINT; /* TODO: unknown ???? */ break; case 6: *size = 2; *decoded_type = M_UINT; /* TODO: unknown ???? */ break; default: throw LIBRAW_EXCEPTION_IO_CORRUPT; } } static void get_matrix_copy(camf_entry_t *entry) { uint32_t element_size = entry->matrix_element_size; uint32_t elements = entry->matrix_elements; int i, size = (entry->matrix_decoded_type==M_FLOAT ? sizeof(double) : sizeof(uint32_t)) * elements; entry->matrix_decoded = malloc(size); switch (element_size) { case 4: switch (entry->matrix_decoded_type) { case M_INT: case M_UINT: memcpy(entry->matrix_decoded, entry->matrix_data, size); break; case M_FLOAT: for (i=0; imatrix_decoded)[i] = (double)((float *)entry->matrix_data)[i]; break; default: throw LIBRAW_EXCEPTION_IO_CORRUPT; } break; case 2: switch (entry->matrix_decoded_type) { case M_INT: for (i=0; imatrix_decoded)[i] = (int32_t)((int16_t *)entry->matrix_data)[i]; break; case M_UINT: for (i=0; imatrix_decoded)[i] = (uint32_t)((uint16_t *)entry->matrix_data)[i]; break; default: throw LIBRAW_EXCEPTION_IO_CORRUPT; } break; case 1: switch (entry->matrix_decoded_type) { case M_INT: for (i=0; imatrix_decoded)[i] = (int32_t)((int8_t *)entry->matrix_data)[i]; break; case M_UINT: for (i=0; imatrix_decoded)[i] = (uint32_t)((uint8_t *)entry->matrix_data)[i]; break; default: throw LIBRAW_EXCEPTION_IO_CORRUPT; } break; default: throw LIBRAW_EXCEPTION_IO_CORRUPT; } } static void x3f_setup_camf_matrix_entry(camf_entry_t *entry) { int i; int totalsize = 1; uint8_t *e = (uint8_t *)entry->entry; uint8_t *v = (uint8_t *)entry->value_address; uint32_t type = entry->matrix_type = *(uint32_t *)(v + 0); uint32_t dim = entry->matrix_dim = *(uint32_t *)(v + 4); uint32_t off = entry->matrix_data_off = *(uint32_t *)(v + 8); camf_dim_entry_t *dentry = entry->matrix_dim_entry = (camf_dim_entry_t*)malloc(dim*sizeof(camf_dim_entry_t)); for (i=0; imatrix_element_size, &entry->matrix_decoded_type); entry->matrix_data = (void *)(e + off); entry->matrix_elements = totalsize; entry->matrix_used_space = entry->entry_size - off; /* This estimate only works for matrices above a certain size */ entry->matrix_estimated_element_size = entry->matrix_used_space / totalsize; get_matrix_copy(entry); } static void x3f_setup_camf_entries(x3f_camf_t *CAMF) { uint8_t *p = (uint8_t *)CAMF->decoded_data; uint8_t *end = p + CAMF->decoded_data_size; camf_entry_t *entry = NULL; int i; for (i=0; p < end; i++) { uint32_t *p4 = (uint32_t *)p; switch (*p4) { case X3F_CMbP: case X3F_CMbT: case X3F_CMbM: break; default: goto stop; } /* TODO: lots of realloc - may be inefficient */ entry = (camf_entry_t *)realloc(entry, (i+1)*sizeof(camf_entry_t)); /* Pointer */ entry[i].entry = p; /* Header */ entry[i].id = *p4++; entry[i].version = *p4++; entry[i].entry_size = *p4++; entry[i].name_offset = *p4++; entry[i].value_offset = *p4++; /* Compute adresses and sizes */ entry[i].name_address = (char *)(p + entry[i].name_offset); entry[i].value_address = p + entry[i].value_offset; entry[i].name_size = entry[i].value_offset - entry[i].name_offset; entry[i].value_size = entry[i].entry_size - entry[i].value_offset; entry[i].text_size = 0; entry[i].text = NULL; entry[i].property_num = 0; entry[i].property_name = NULL; entry[i].property_value = NULL; entry[i].matrix_type = 0; entry[i].matrix_dim = 0; entry[i].matrix_data_off = 0; entry[i].matrix_data = NULL; entry[i].matrix_dim_entry = NULL; entry[i].matrix_decoded = NULL; switch (entry[i].id) { case X3F_CMbP: x3f_setup_camf_property_entry(&entry[i]); break; case X3F_CMbT: x3f_setup_camf_text_entry(&entry[i]); break; case X3F_CMbM: x3f_setup_camf_matrix_entry(&entry[i]); break; } p += entry[i].entry_size; } stop: CAMF->entry_table.size = i; CAMF->entry_table.element = entry; } static void x3f_load_camf(x3f_info_t *I, x3f_directory_entry_t *DE) { x3f_directory_entry_header_t *DEH = &DE->header; x3f_camf_t *CAMF = &DEH->data_subsection.camf; read_data_set_offset(I, DE, X3F_CAMF_HEADER_SIZE); if (!CAMF->data_size) CAMF->data_size = read_data_block(&CAMF->data, I, DE, 0); switch (CAMF->type) { case 2: /* Older SD9-SD14 */ x3f_load_camf_decode_type2(CAMF); break; case 4: /* TRUE ... Merrill */ x3f_load_camf_decode_type4(CAMF); break; case 5: /* Quattro ... */ x3f_load_camf_decode_type5(CAMF); break; default: /* TODO: Shouldn't this be treated as a fatal error? */ throw LIBRAW_EXCEPTION_IO_CORRUPT; } if (CAMF->decoded_data != NULL) x3f_setup_camf_entries(CAMF); else throw LIBRAW_EXCEPTION_IO_CORRUPT; } /* extern */ x3f_return_t x3f_load_data(x3f_t *x3f, x3f_directory_entry_t *DE) { x3f_info_t *I = &x3f->info; if (DE == NULL) return X3F_ARGUMENT_ERROR; switch (DE->header.identifier) { case X3F_SECp: x3f_load_property_list(I, DE); break; case X3F_SECi: x3f_load_image(I, DE); break; case X3F_SECc: x3f_load_camf(I, DE); break; default: return X3F_INTERNAL_ERROR; } return X3F_OK; } /* extern */ int64_t x3f_load_data_size(x3f_t *x3f, x3f_directory_entry_t *DE) { x3f_info_t *I = &x3f->info; if (DE == NULL) return -1; switch (DE->header.identifier) { case X3F_SECi: return x3f_load_image_size(I, DE); default: return 0; } } /* extern */ x3f_return_t x3f_load_image_block(x3f_t *x3f, x3f_directory_entry_t *DE) { x3f_info_t *I = &x3f->info; if (DE == NULL) return X3F_ARGUMENT_ERROR; switch (DE->header.identifier) { case X3F_SECi: read_data_set_offset(I, DE, X3F_IMAGE_HEADER_SIZE); x3f_load_image_verbatim(I, DE); break; default: throw LIBRAW_EXCEPTION_IO_CORRUPT; return X3F_INTERNAL_ERROR; } return X3F_OK; } /* --------------------------------------------------------------------- */ /* The End */ /* --------------------------------------------------------------------- */ diff --git a/core/libs/rawengine/libraw/internal/var_defines.h b/core/libs/rawengine/libraw/internal/var_defines.h index 3ed033705a..73fbb8e6ad 100644 --- a/core/libs/rawengine/libraw/internal/var_defines.h +++ b/core/libs/rawengine/libraw/internal/var_defines.h @@ -1,214 +1,205 @@ /* -*- C++ -*- * File: var_defines.h - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) * Created: Sat Mar 8, 2008 * * LibRaw redefinitions of dcraw internal variables LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #ifndef VAR_DEFINES_H #define VAR_DEFINES_H // imgdata.idata #define make (imgdata.idata.make) #define model (imgdata.idata.model) #define software (imgdata.idata.software) #define is_raw (imgdata.idata.raw_count) #define dng_version (imgdata.idata.dng_version) #define is_foveon (imgdata.idata.is_foveon) #define colors (imgdata.idata.colors) #define cdesc (imgdata.idata.cdesc) #define filters (imgdata.idata.filters) #define xtrans (imgdata.idata.xtrans) #define xtrans_abs (imgdata.idata.xtrans_abs) #define xmpdata (imgdata.idata.xmpdata) #define xmplen (imgdata.idata.xmplen) //imgdata image #define image (imgdata.image) #define raw_image (imgdata.rawdata.raw_image) #define color_image (imgdata.rawdata.color_image) // imgdata.sizes #define raw_height (imgdata.sizes.raw_height) #define raw_width (imgdata.sizes.raw_width) #define raw_pitch (imgdata.sizes.raw_pitch) #define height (imgdata.sizes.height) #define width (imgdata.sizes.width) #define top_margin (imgdata.sizes.top_margin) #define left_margin (imgdata.sizes.left_margin) #define bottom_margin (imgdata.sizes.bottom_margin) #define right_margin (imgdata.sizes.right_margin) #define iheight (imgdata.sizes.iheight) #define iwidth (imgdata.sizes.iwidth) #define pixel_aspect (imgdata.sizes.pixel_aspect) #define flip (imgdata.sizes.flip) #define mask (imgdata.sizes.mask) //imgdata.color #define white (imgdata.color.white) #define cam_mul (imgdata.color.cam_mul) #define pre_mul (imgdata.color.pre_mul) #define cmatrix (imgdata.color.cmatrix) #define rgb_cam (imgdata.color.rgb_cam) #ifndef SRC_USES_CURVE #define curve (imgdata.color.curve) #endif #ifndef SRC_USES_BLACK #define black (imgdata.color.black) #define cblack (imgdata.color.cblack) #endif #define maximum (imgdata.color.maximum) #define channel_maximum (imgdata.color.channel_maximum) #define profile_length (imgdata.color.profile_length) #define color_flags (imgdata.color.color_flags) #define ph1 (imgdata.color.phase_one_data) #define flash_used (imgdata.color.flash_used) #define canon_ev (imgdata.color.canon_ev) #define model2 (imgdata.color.model2) #define baseline_exposure (imgdata.color.baseline_exposure) //imgdata.thumbnail #define thumb_width (imgdata.thumbnail.twidth) #define thumb_height (imgdata.thumbnail.theight) #define thumb_length (imgdata.thumbnail.tlength) //imgdata.others #define iso_speed (imgdata.other.iso_speed) #define shutter (imgdata.other.shutter) #define aperture (imgdata.other.aperture) #define focal_len (imgdata.other.focal_len) #define timestamp (imgdata.other.timestamp) #define shot_order (imgdata.other.shot_order) #define gpsdata (imgdata.other.gpsdata) #define desc (imgdata.other.desc) #define artist (imgdata.other.artist) //imgdata.output #define greybox (imgdata.params.greybox) #define cropbox (imgdata.params.cropbox) #define aber (imgdata.params.aber) #define gamm (imgdata.params.gamm) #define user_mul (imgdata.params.user_mul) #define shot_select (imgdata.params.shot_select) #define bright (imgdata.params.bright) #define threshold (imgdata.params.threshold) #define half_size (imgdata.params.half_size) #define four_color_rgb (imgdata.params.four_color_rgb) #define highlight (imgdata.params.highlight) //#define verbose (imgdata.params.verbose) #define use_auto_wb (imgdata.params.use_auto_wb) #define use_camera_wb (imgdata.params.use_camera_wb) #define use_camera_matrix (imgdata.params.use_camera_matrix) #define output_color (imgdata.params.output_color) #define output_bps (imgdata.params.output_bps) #define gamma_16bit (imgdata.params.gamma_16bit) #define output_tiff (imgdata.params.output_tiff) #define med_passes (imgdata.params.med_passes) #define no_auto_bright (imgdata.params.no_auto_bright) #define auto_bright_thr (imgdata.params.auto_bright_thr) #define use_fuji_rotate (imgdata.params.use_fuji_rotate) #define filtering_mode (imgdata.params.filtering_mode) -// Demosaic packs -//AFD -//#define afd_noise_att (imgdata.params.afd_noise_att) -//#define afd_noise_thres (imgdata.params.afd_noise_thres) -//#define afd_luminance_passes (imgdata.params.afd_luminance_passes) -//#define afd_chrominance_method (imgdata.params.afd_chrominance_method) -//#define afd_luminance_only (imgdata.params.afd_luminance_only) // DCB #define dcb_iterations (imgdata.params.iterations) #define dcb_enhance_fl (imgdata.params.dcb_enhance) #define fbdd_noiserd (imgdata.params.fbdd_noiserd) -// VCD -#define eeci_refine (imgdata.params.eeci_refine) -#define es_med_passes (imgdata.params.es_med_passes) - - //rgb_constants #define xyz_rgb (rgb_constants.xyz_rgb) #define d65_white (rgb_constants.d65_white) //libraw_internal_data.internal_data #define meta_data (libraw_internal_data.internal_data.meta_data) #define ifp libraw_internal_data.internal_data.input #define ifname ((char*)libraw_internal_data.internal_data.input->fname()) #define ofp libraw_internal_data.internal_data.output #define profile_offset (libraw_internal_data.internal_data.profile_offset) #define thumb_offset (libraw_internal_data.internal_data.toffset) #define pana_black (libraw_internal_data.internal_data.pana_black) //libraw_internal_data.internal_output_params #define mix_green (libraw_internal_data.internal_output_params.mix_green) #define raw_color (libraw_internal_data.internal_output_params.raw_color) #define use_gamma (libraw_internal_data.internal_output_params.use_gamma) #define zero_is_bad (libraw_internal_data.internal_output_params.zero_is_bad) #ifndef SRC_USES_SHRINK #define shrink (libraw_internal_data.internal_output_params.shrink) #endif #define fuji_width (libraw_internal_data.internal_output_params.fuji_width) //libraw_internal_data.output_data #define histogram (libraw_internal_data.output_data.histogram) #define oprof (libraw_internal_data.output_data.oprof) //libraw_internal_data.identify_data #define exif_cfa (libraw_internal_data.identify_data.olympus_exif_cfa) #define unique_id (libraw_internal_data.identify_data.unique_id) +#define OlyID (libraw_internal_data.identify_data.OlyID) #define tiff_nifds (libraw_internal_data.identify_data.tiff_nifds) #define tiff_flip (libraw_internal_data.identify_data.tiff_flip) //libraw_internal_data.unpacker_data #define order (libraw_internal_data.unpacker_data.order) #define data_error (libraw_internal_data.unpacker_data.data_error) #define cr2_slice (libraw_internal_data.unpacker_data.cr2_slice) #define sraw_mul (libraw_internal_data.unpacker_data.sraw_mul) #define kodak_cbpp (libraw_internal_data.unpacker_data.kodak_cbpp) #define strip_offset (libraw_internal_data.unpacker_data.strip_offset) #define data_offset (libraw_internal_data.unpacker_data.data_offset) #define data_size (libraw_internal_data.unpacker_data.data_size) #define meta_offset (libraw_internal_data.unpacker_data.meta_offset) #define meta_length (libraw_internal_data.unpacker_data.meta_length) #define thumb_misc (libraw_internal_data.unpacker_data.thumb_misc) #define fuji_layout (libraw_internal_data.unpacker_data.fuji_layout) #define tiff_samples (libraw_internal_data.unpacker_data.tiff_samples) #define tiff_bps (libraw_internal_data.unpacker_data.tiff_bps) #define tiff_compress (libraw_internal_data.unpacker_data.tiff_compress) #define zero_after_ff (libraw_internal_data.unpacker_data.zero_after_ff) #define tile_width (libraw_internal_data.unpacker_data.tile_width) #define tile_length (libraw_internal_data.unpacker_data.tile_length) #define load_flags (libraw_internal_data.unpacker_data.load_flags) +#define pana_encoding (libraw_internal_data.unpacker_data.pana_encoding) +#define pana_bpp (libraw_internal_data.unpacker_data.pana_bpp) #ifdef LIBRAW_IO_REDEFINED #define fread(ptr,size,n,stream) stream->read(ptr,size,n) #define fseek(stream,o,w) stream->seek(o,w) #define fseeko(stream,o,w) stream->seek(o,w) #define ftell(stream) stream->tell() #define ftello(stream) stream->tell() #define feof(stream) stream->eof() #ifdef getc #undef getc #endif #define getc(stream) stream->get_char() #define fgetc(stream) stream->get_char() #define fgetcb(stream) stream->get_char_buf() #define fgets(str,n,stream) stream->gets(str,n) #define fscanf(stream,fmt,ptr) stream->scanf_one(fmt,ptr) #endif #endif diff --git a/core/libs/rawengine/libraw/libraw/libraw.h b/core/libs/rawengine/libraw/libraw/libraw.h index 30b53c24fc..3c180fa152 100644 --- a/core/libs/rawengine/libraw/libraw/libraw.h +++ b/core/libs/rawengine/libraw/libraw/libraw.h @@ -1,384 +1,393 @@ /* -*- C++ -*- * File: libraw.h - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) * Created: Sat Mar 8, 2008 * * LibRaw C++ interface * LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #ifndef _LIBRAW_CLASS_H #define _LIBRAW_CLASS_H #ifdef __linux__ #define _FILE_OFFSET_BITS 64 #endif /* maximum file size to use LibRaw_file_datastream (fully buffered) I/O */ -#define LIBRAW_USE_STREAMS_DATASTREAM_MAXSIZE (250*1024L*1024L) - +#define LIBRAW_USE_STREAMS_DATASTREAM_MAXSIZE (250 * 1024L * 1024L) #include #include #include #include #include "libraw_datastream.h" #include "libraw_types.h" #include "libraw_const.h" #include "libraw_internal.h" #include "libraw_alloc.h" #ifdef __cplusplus extern "C" { #endif -DllDef const char *libraw_strerror(int errorcode); -DllDef const char *libraw_strprogress(enum LibRaw_progress); - /* LibRaw C API */ -DllDef libraw_data_t *libraw_init(unsigned int flags); -DllDef int libraw_open_file(libraw_data_t*, const char *); -DllDef int libraw_open_file_ex(libraw_data_t*, const char *, INT64 max_buff_sz); + DllDef const char *libraw_strerror(int errorcode); + DllDef const char *libraw_strprogress(enum LibRaw_progress); + /* LibRaw C API */ + DllDef libraw_data_t *libraw_init(unsigned int flags); + DllDef int libraw_open_file(libraw_data_t *, const char *); + DllDef int libraw_open_file_ex(libraw_data_t *, const char *, INT64 max_buff_sz); #if defined(_WIN32) && !defined(__MINGW32__) && defined(_MSC_VER) && (_MSC_VER > 1310) -DllDef int libraw_open_wfile(libraw_data_t*, const wchar_t *); -DllDef int libraw_open_wfile_ex(libraw_data_t*, const wchar_t *, INT64 max_buff_sz); + DllDef int libraw_open_wfile(libraw_data_t *, const wchar_t *); + DllDef int libraw_open_wfile_ex(libraw_data_t *, const wchar_t *, INT64 max_buff_sz); #endif -DllDef int libraw_open_buffer(libraw_data_t*, void * buffer, size_t size); -DllDef int libraw_unpack(libraw_data_t*); -DllDef int libraw_unpack_thumb(libraw_data_t*); -DllDef void libraw_recycle_datastream(libraw_data_t*); -DllDef void libraw_recycle(libraw_data_t*); -DllDef void libraw_close(libraw_data_t*); -DllDef void libraw_subtract_black(libraw_data_t*); -DllDef int libraw_raw2image(libraw_data_t*); -DllDef void libraw_free_image(libraw_data_t*); - /* version helpers */ -DllDef const char* libraw_version(); -DllDef int libraw_versionNumber(); - /* Camera list */ -DllDef const char** libraw_cameraList(); -DllDef int libraw_cameraCount(); + DllDef int libraw_open_buffer(libraw_data_t *, void *buffer, size_t size); + DllDef int libraw_unpack(libraw_data_t *); + DllDef int libraw_unpack_thumb(libraw_data_t *); + DllDef void libraw_recycle_datastream(libraw_data_t *); + DllDef void libraw_recycle(libraw_data_t *); + DllDef void libraw_close(libraw_data_t *); + DllDef void libraw_subtract_black(libraw_data_t *); + DllDef int libraw_raw2image(libraw_data_t *); + DllDef void libraw_free_image(libraw_data_t *); + /* version helpers */ + DllDef const char *libraw_version(); + DllDef int libraw_versionNumber(); + /* Camera list */ + DllDef const char **libraw_cameraList(); + DllDef int libraw_cameraCount(); /* helpers */ -DllDef void libraw_set_memerror_handler(libraw_data_t*, memory_callback cb, void *datap); -DllDef void libraw_set_exifparser_handler(libraw_data_t*, exif_parser_callback cb, void *datap); -DllDef void libraw_set_dataerror_handler(libraw_data_t*,data_callback func,void *datap); -DllDef void libraw_set_progress_handler(libraw_data_t*,progress_callback cb,void *datap); -DllDef const char * libraw_unpack_function_name(libraw_data_t* lr); -DllDef int libraw_get_decoder_info(libraw_data_t* lr,libraw_decoder_info_t* d); -DllDef int libraw_COLOR(libraw_data_t*,int row, int col); -DllDef unsigned libraw_capabilities(); - - /* DCRAW compatibility */ -DllDef int libraw_adjust_sizes_info_only(libraw_data_t*); -DllDef int libraw_dcraw_ppm_tiff_writer(libraw_data_t* lr,const char *filename); -DllDef int libraw_dcraw_thumb_writer(libraw_data_t* lr,const char *fname); -DllDef int libraw_dcraw_process(libraw_data_t* lr); -DllDef libraw_processed_image_t* libraw_dcraw_make_mem_image(libraw_data_t* lr, int *errc); -DllDef libraw_processed_image_t* libraw_dcraw_make_mem_thumb(libraw_data_t* lr, int *errc); -DllDef void libraw_dcraw_clear_mem(libraw_processed_image_t*); - /* getters/setters used by 3DLut Creator */ -DllDef void libraw_set_demosaic(libraw_data_t *lr,int value); -DllDef void libraw_set_output_color(libraw_data_t *lr,int value); -DllDef void libraw_set_user_mul(libraw_data_t *lr,int index, float val); -DllDef void libraw_set_output_bps(libraw_data_t *lr,int value); -DllDef void libraw_set_gamma(libraw_data_t *lr,int index, float value); -DllDef void libraw_set_no_auto_bright(libraw_data_t *lr,int value); -DllDef void libraw_set_bright(libraw_data_t *lr,float value); -DllDef void libraw_set_highlight(libraw_data_t *lr,int value); -DllDef void libraw_set_fbdd_noiserd(libraw_data_t *lr,int value); -DllDef int libraw_get_raw_height(libraw_data_t *lr); -DllDef int libraw_get_raw_width(libraw_data_t *lr); -DllDef int libraw_get_iheight(libraw_data_t *lr); -DllDef int libraw_get_iwidth(libraw_data_t *lr); -DllDef float libraw_get_cam_mul(libraw_data_t *lr,int index); -DllDef float libraw_get_pre_mul(libraw_data_t *lr,int index); -DllDef float libraw_get_rgb_cam(libraw_data_t *lr,int index1, int index2); -DllDef int libraw_get_color_maximum(libraw_data_t *lr); -DllDef void libraw_set_ca_correction(libraw_data_t *lr,int ca_correc, float ca_red, float ca_blue); -DllDef void libraw_set_cfalinenoise(libraw_data_t *lr,int cfaline, float linenoise); -DllDef void libraw_set_wf_debanding(libraw_data_t *lr, int wf_debanding, float wfd0, float wfd1, float wfd2, float wfd3); -DllDef void libraw_set_interpolation_passes(libraw_data_t *lr,int passes); + DllDef void libraw_set_memerror_handler(libraw_data_t *, memory_callback cb, void *datap); + DllDef void libraw_set_exifparser_handler(libraw_data_t *, exif_parser_callback cb, void *datap); + DllDef void libraw_set_dataerror_handler(libraw_data_t *, data_callback func, void *datap); + DllDef void libraw_set_progress_handler(libraw_data_t *, progress_callback cb, void *datap); + DllDef const char *libraw_unpack_function_name(libraw_data_t *lr); + DllDef int libraw_get_decoder_info(libraw_data_t *lr, libraw_decoder_info_t *d); + DllDef int libraw_COLOR(libraw_data_t *, int row, int col); + DllDef unsigned libraw_capabilities(); + + /* DCRAW compatibility */ + DllDef int libraw_adjust_sizes_info_only(libraw_data_t *); + DllDef int libraw_dcraw_ppm_tiff_writer(libraw_data_t *lr, const char *filename); + DllDef int libraw_dcraw_thumb_writer(libraw_data_t *lr, const char *fname); + DllDef int libraw_dcraw_process(libraw_data_t *lr); + DllDef libraw_processed_image_t *libraw_dcraw_make_mem_image(libraw_data_t *lr, int *errc); + DllDef libraw_processed_image_t *libraw_dcraw_make_mem_thumb(libraw_data_t *lr, int *errc); + DllDef void libraw_dcraw_clear_mem(libraw_processed_image_t *); + /* getters/setters used by 3DLut Creator */ + DllDef void libraw_set_demosaic(libraw_data_t *lr, int value); + DllDef void libraw_set_output_color(libraw_data_t *lr, int value); + DllDef void libraw_set_user_mul(libraw_data_t *lr, int index, float val); + DllDef void libraw_set_output_bps(libraw_data_t *lr, int value); + DllDef void libraw_set_gamma(libraw_data_t *lr, int index, float value); + DllDef void libraw_set_no_auto_bright(libraw_data_t *lr, int value); + DllDef void libraw_set_bright(libraw_data_t *lr, float value); + DllDef void libraw_set_highlight(libraw_data_t *lr, int value); + DllDef void libraw_set_fbdd_noiserd(libraw_data_t *lr, int value); + DllDef int libraw_get_raw_height(libraw_data_t *lr); + DllDef int libraw_get_raw_width(libraw_data_t *lr); + DllDef int libraw_get_iheight(libraw_data_t *lr); + DllDef int libraw_get_iwidth(libraw_data_t *lr); + DllDef float libraw_get_cam_mul(libraw_data_t *lr, int index); + DllDef float libraw_get_pre_mul(libraw_data_t *lr, int index); + DllDef float libraw_get_rgb_cam(libraw_data_t *lr, int index1, int index2); + DllDef int libraw_get_color_maximum(libraw_data_t *lr); + + DllDef libraw_iparams_t *libraw_get_iparams(libraw_data_t *lr); + DllDef libraw_lensinfo_t *libraw_get_lensinfo(libraw_data_t *lr); + DllDef libraw_imgother_t *libraw_get_imgother(libraw_data_t *lr); #ifdef __cplusplus } #endif - #ifdef __cplusplus class DllDef LibRaw { - public: - libraw_data_t imgdata; - int verbose; +public: + libraw_data_t imgdata; + int verbose; - LibRaw(unsigned int flags = LIBRAW_OPTIONS_NONE); - libraw_output_params_t* output_params_ptr() { return &imgdata.params;} - int open_file(const char *fname, INT64 max_buffered_sz=LIBRAW_USE_STREAMS_DATASTREAM_MAXSIZE); + LibRaw(unsigned int flags = LIBRAW_OPTIONS_NONE); + libraw_output_params_t *output_params_ptr() { return &imgdata.params; } + int open_file(const char *fname, INT64 max_buffered_sz = LIBRAW_USE_STREAMS_DATASTREAM_MAXSIZE); #if defined(_WIN32) && !defined(__MINGW32__) && defined(_MSC_VER) && (_MSC_VER > 1310) - int open_file(const wchar_t *fname, INT64 max_buffered_sz=LIBRAW_USE_STREAMS_DATASTREAM_MAXSIZE); + int open_file(const wchar_t *fname, INT64 max_buffered_sz = LIBRAW_USE_STREAMS_DATASTREAM_MAXSIZE); #endif - int open_buffer(void *buffer, size_t size); - virtual int open_datastream(LibRaw_abstract_datastream *); - int error_count(){return libraw_internal_data.unpacker_data.data_error;} - void recycle_datastream(); - int unpack(void); - int unpack_thumb(void); - int thumbOK(INT64 maxsz=-1); - int adjust_sizes_info_only(void); - int subtract_black(); - int subtract_black_internal(); - int raw2image(); - int raw2image_ex(int do_subtract_black); - void raw2image_start(); - void free_image(); - int adjust_maximum(); - void set_exifparser_handler( exif_parser_callback cb,void *data) {callbacks.exifparser_data = data; callbacks.exif_cb = cb; } - void set_memerror_handler( memory_callback cb,void *data) {callbacks.memcb_data = data; callbacks.mem_cb = cb; } - void set_dataerror_handler(data_callback func, void *data) { callbacks.datacb_data = data; callbacks.data_cb = func;} - void set_progress_handler(progress_callback pcb, void *data) { callbacks.progresscb_data = data; callbacks.progress_cb = pcb;} - - void convertFloatToInt(float dmin=4096.f, float dmax=32767.f, float dtarget = 16383.f); - /* helpers */ - static unsigned capabilities(); - static const char* version(); - static int versionNumber(); - static const char** cameraList(); - static int cameraCount(); - static const char* strprogress(enum LibRaw_progress); - static const char* strerror(int p); - /* dcraw emulation */ - int dcraw_ppm_tiff_writer(const char *filename); - int dcraw_thumb_writer(const char *fname); - int dcraw_process(void); - /* information calls */ - int is_fuji_rotated(){return libraw_internal_data.internal_output_params.fuji_width;} - int is_sraw(); - int sraw_midpoint(); - int is_nikon_sraw(); - int is_coolscan_nef(); - int is_floating_point(); - int have_fpdata(); - /* memory writers */ - virtual libraw_processed_image_t* dcraw_make_mem_image(int *errcode=NULL); - virtual libraw_processed_image_t* dcraw_make_mem_thumb(int *errcode=NULL); - static void dcraw_clear_mem(libraw_processed_image_t*); - - /* Additional calls for make_mem_image */ - void get_mem_image_format(int* width, int* height, int* colors, int* bps) const; - int copy_mem_image(void* scan0, int stride, int bgr); - - /* free all internal data structures */ - void recycle(); - virtual ~LibRaw(void); - - int COLOR(int row, int col) { return libraw_internal_data.internal_output_params.fuji_width? FCF(row,col):FC(row,col);} - - int FC(int row,int col) { return (imgdata.idata.filters >> (((row << 1 & 14) | (col & 1)) << 1) & 3);} - int fcol (int row, int col); - - const char *unpack_function_name(); - virtual int get_decoder_info(libraw_decoder_info_t* d_info); - libraw_internal_data_t * get_internal_data_pointer(){ return &libraw_internal_data; } - - /* Debanding filter */ - int wf_remove_banding(); + int open_buffer(void *buffer, size_t size); + virtual int open_datastream(LibRaw_abstract_datastream *); + virtual int open_bayer(unsigned char *data, unsigned datalen, ushort _raw_width, ushort _raw_height, + ushort _left_margin, ushort _top_margin, ushort _right_margin, ushort _bottom_margin, + unsigned char procflags, unsigned char bayer_pattern, unsigned unused_bits, + unsigned otherflags, unsigned black_level); + int error_count() { return libraw_internal_data.unpacker_data.data_error; } + void recycle_datastream(); + int unpack(void); + int unpack_thumb(void); + int thumbOK(INT64 maxsz = -1); + int adjust_sizes_info_only(void); + int subtract_black(); + int subtract_black_internal(); + int raw2image(); + int raw2image_ex(int do_subtract_black); + void raw2image_start(); + void free_image(); + int adjust_maximum(); + void set_exifparser_handler(exif_parser_callback cb, void *data) + { + callbacks.exifparser_data = data; + callbacks.exif_cb = cb; + } + void set_memerror_handler(memory_callback cb, void *data) + { + callbacks.memcb_data = data; + callbacks.mem_cb = cb; + } + void set_dataerror_handler(data_callback func, void *data) + { + callbacks.datacb_data = data; + callbacks.data_cb = func; + } + void set_progress_handler(progress_callback pcb, void *data) + { + callbacks.progresscb_data = data; + callbacks.progress_cb = pcb; + } + + void convertFloatToInt(float dmin = 4096.f, float dmax = 32767.f, float dtarget = 16383.f); + /* helpers */ + static unsigned capabilities(); + static const char *version(); + static int versionNumber(); + static const char **cameraList(); + static int cameraCount(); + static const char *strprogress(enum LibRaw_progress); + static const char *strerror(int p); + /* dcraw emulation */ + int dcraw_ppm_tiff_writer(const char *filename); + int dcraw_thumb_writer(const char *fname); + int dcraw_process(void); + /* information calls */ + int is_fuji_rotated() { return libraw_internal_data.internal_output_params.fuji_width; } + int is_sraw(); + int sraw_midpoint(); + int is_nikon_sraw(); + int is_coolscan_nef(); + int is_jpeg_thumb(); + int is_floating_point(); + int have_fpdata(); + /* memory writers */ + virtual libraw_processed_image_t *dcraw_make_mem_image(int *errcode = NULL); + virtual libraw_processed_image_t *dcraw_make_mem_thumb(int *errcode = NULL); + static void dcraw_clear_mem(libraw_processed_image_t *); + + /* Additional calls for make_mem_image */ + void get_mem_image_format(int *width, int *height, int *colors, int *bps) const; + int copy_mem_image(void *scan0, int stride, int bgr); + + /* free all internal data structures */ + void recycle(); + virtual ~LibRaw(void); + + int COLOR(int row, int col) + { + if (!imgdata.idata.filters) + return 6; /* Special value 0+1+2+3 */ + if (imgdata.idata.filters < 1000) + return fcol(row, col); + return libraw_internal_data.internal_output_params.fuji_width ? FCF(row, col) : FC(row, col); + } + + int FC(int row, int col) { return (imgdata.idata.filters >> (((row << 1 & 14) | (col & 1)) << 1) & 3); } + int fcol(int row, int col); + + const char *unpack_function_name(); + virtual int get_decoder_info(libraw_decoder_info_t *d_info); + libraw_internal_data_t *get_internal_data_pointer() { return &libraw_internal_data; } + + /* Debanding filter */ + int wf_remove_banding(); /* Phase one correction/subtractBL calls */ - /* Returns libraw error code */ + /* Returns libraw error code */ int phase_one_subtract_black(ushort *src, ushort *dest); int phase_one_correct(); - int set_rawspeed_camerafile(char *filename); + int set_rawspeed_camerafile(char *filename); virtual void setCancelFlag(); virtual void clearCancelFlag(); - virtual void adobe_coeff (const char *, const char *, int internal_only=0); + virtual void adobe_coeff(const char *, const char *, int internal_only = 0); - void set_dng_host(void *); + void set_dng_host(void *); protected: - int is_curve_linear(); - void checkCancel(); - void cam_xyz_coeff(float _rgb_cam[3][4], double cam_xyz[4][3]); - void phase_one_allocate_tempbuffer(); - void phase_one_free_tempbuffer(); - virtual int is_phaseone_compressed(); - virtual int is_canon_600(); - /* Hotspots */ - virtual void copy_fuji_uncropped(unsigned short cblack[4], unsigned short *dmaxp); - virtual void copy_bayer(unsigned short cblack[4], unsigned short *dmaxp); - virtual void fuji_rotate(); - virtual void convert_to_rgb_loop(float out_cam[3][4]); - virtual void lin_interpolate_loop(int code[16][16][32],int size); - virtual void scale_colors_loop(float scale_mul[4]); - - /* Fujifilm compressed decoder public interface (to make parallel decoder) */ - virtual void xtrans_decode_loop(const struct xtrans_params* common_info, int count, INT64* offsets, unsigned *sizes); - void xtrans_decode_strip(const struct xtrans_params* info_common, int cur_block, INT64 raw_offset, unsigned size); - - int FCF(int row,int col) { - int rr,cc; - if (libraw_internal_data.unpacker_data.fuji_layout) { - rr = libraw_internal_data.internal_output_params.fuji_width - 1 - col + (row >> 1); - cc = col + ((row+1) >> 1); - } else { - rr = libraw_internal_data.internal_output_params.fuji_width - 1 + row - (col >> 1); - cc = row + ((col+1) >> 1); - } - return FC(rr,cc); + int is_curve_linear(); + void checkCancel(); + void cam_xyz_coeff(float _rgb_cam[3][4], double cam_xyz[4][3]); + void phase_one_allocate_tempbuffer(); + void phase_one_free_tempbuffer(); + virtual int is_phaseone_compressed(); + virtual int is_canon_600(); + /* Hotspots */ + virtual void copy_fuji_uncropped(unsigned short cblack[4], unsigned short *dmaxp); + virtual void copy_bayer(unsigned short cblack[4], unsigned short *dmaxp); + virtual void fuji_rotate(); + virtual void convert_to_rgb_loop(float out_cam[3][4]); + virtual void lin_interpolate_loop(int code[16][16][32], int size); + virtual void scale_colors_loop(float scale_mul[4]); + + /* Fujifilm compressed decoder public interface (to make parallel decoder) */ + virtual void fuji_decode_loop(const struct fuji_compressed_params *common_info, int count, INT64 *offsets, + unsigned *sizes); + void fuji_decode_strip(const struct fuji_compressed_params *info_common, int cur_block, INT64 raw_offset, + unsigned size); + + int FCF(int row, int col) + { + int rr, cc; + if (libraw_internal_data.unpacker_data.fuji_layout) + { + rr = libraw_internal_data.internal_output_params.fuji_width - 1 - col + (row >> 1); + cc = col + ((row + 1) >> 1); } + else + { + rr = libraw_internal_data.internal_output_params.fuji_width - 1 + row - (col >> 1); + cc = row + ((col + 1) >> 1); + } + return FC(rr, cc); + } - void adjust_bl(); - void* malloc(size_t t); - void* calloc(size_t n,size_t t); - void* realloc(void *p, size_t s); - void free(void *p); - void merror (void *ptr, const char *where); - void derror(); - - LibRaw_TLS *tls; - libraw_internal_data_t libraw_internal_data; - decode first_decode[2048], *second_decode, *free_decode; - tiff_ifd_t tiff_ifd[10]; - libraw_memmgr memmgr; - libraw_callbacks_t callbacks; - - LibRaw_constants rgb_constants; - - void (LibRaw:: *write_thumb)(); - void (LibRaw:: *write_fun)(); - void (LibRaw:: *load_raw)(); - void (LibRaw:: *thumb_load_raw)(); - void (LibRaw:: *pentax_component_load_raw)(); - void (LibRaw:: *interpolate_bayer)(); - void (LibRaw:: *interpolate_xtrans)(); - - void kodak_thumb_loader(); - void write_thumb_ppm_tiff(FILE *); - void x3f_thumb_loader(); - INT64 x3f_thumb_size(); -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 - void foveon_thumb_loader (void); -#endif - - int own_filtering_supported(){ return 0;} - void identify(); - unsigned parse_custom_cameras(unsigned limit, libraw_custom_camera_t table[], char** list); - void write_ppm_tiff (); - void convert_to_rgb(); - void remove_zeroes(); - void crop_masked_pixels(); + void adjust_bl(); + void *malloc(size_t t); + void *calloc(size_t n, size_t t); + void *realloc(void *p, size_t s); + void free(void *p); + void merror(void *ptr, const char *where); + void derror(); + + LibRaw_TLS *tls; + libraw_internal_data_t libraw_internal_data; + decode first_decode[2048], *second_decode, *free_decode; + tiff_ifd_t tiff_ifd[LIBRAW_IFD_MAXCOUNT]; + libraw_memmgr memmgr; + libraw_callbacks_t callbacks; + + LibRaw_constants rgb_constants; + + void (LibRaw::*write_thumb)(); + void (LibRaw::*write_fun)(); + void (LibRaw::*load_raw)(); + void (LibRaw::*thumb_load_raw)(); + void (LibRaw::*pentax_component_load_raw)(); + + void kodak_thumb_loader(); + void write_thumb_ppm_tiff(FILE *); + void x3f_thumb_loader(); + INT64 x3f_thumb_size(); + + int own_filtering_supported() { return 0; } + void identify(); + void initdata(); + unsigned parse_custom_cameras(unsigned limit, libraw_custom_camera_t table[], char **list); + void write_ppm_tiff(); + void convert_to_rgb(); + void remove_zeroes(); + void crop_masked_pixels(); #ifndef NO_LCMS - void apply_profile(const char*,const char*); -#endif - void pre_interpolate(); - void border_interpolate (int border); - void lin_interpolate(); - void vng_interpolate(); - void ppg_interpolate(); - void cielab(ushort rgb[3], short lab[3]); - void xtrans_interpolate(int); - void ahd_interpolate(); - void dht_interpolate(); - void aahd_interpolate(); - - /* from demosaic pack */ - void ahd_interpolate_mod(); - void afd_interpolate_pl(int afd_passes, int clip_on); - void afd_noise_filter_pl(); - void lmmse_interpolate(int gamma_apply); - void dcb(int iterations, int dcb_enhance); - void fbdd(int noiserd); - void vcd_interpolate(int ahd_cutoff); - void amaze_demosaic_RT(); - void exp_bef(float expos, float preser); - void CA_correct_RT(float cared, float cablue); - void cfa_linedn(float linenoise); - void cfa_impulse_gauss(float lclean, float cclean); - void green_equilibrate(float thresh); - - /* demosaic pack end */ - - void bad_pixels(const char*); - void subtract(const char*); - void hat_transform (float *temp, float *base, int st, int size, int sc); - void wavelet_denoise(); - void scale_colors(); - void median_filter (); - void blend_highlights(); - void recover_highlights(); - void green_matching(); - - void stretch(); - -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 - void foveon_thumb (); + void apply_profile(const char *, const char *); #endif - void jpeg_thumb_writer (FILE *tfp,char *thumb,int thumb_length); - void jpeg_thumb (); - void ppm_thumb (); - void ppm16_thumb(); - void layer_thumb (); - void rollei_thumb (); - void kodak_thumb_load_raw(); - -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 - void foveon_decoder (unsigned size, unsigned code); -#endif - unsigned get4(); - - int flip_index (int row, int col); - void gamma_curve (double pwr, double ts, int mode, int imax); - void cubic_spline (const int *x_, const int *y_, const int len); + void pre_interpolate(); + void border_interpolate(int border); + void lin_interpolate(); + void vng_interpolate(); + void ppg_interpolate(); + void cielab(ushort rgb[3], short lab[3]); + void xtrans_interpolate(int); + void ahd_interpolate(); + void dht_interpolate(); + void aahd_interpolate(); + + void dcb(int iterations, int dcb_enhance); + void fbdd(int noiserd); + void exp_bef(float expos, float preser); + + void bad_pixels(const char *); + void subtract(const char *); + void hat_transform(float *temp, float *base, int st, int size, int sc); + void wavelet_denoise(); + void scale_colors(); + void median_filter(); + void blend_highlights(); + void recover_highlights(); + void green_matching(); + + void stretch(); + + void jpeg_thumb_writer(FILE *tfp, char *thumb, int thumb_length); + void jpeg_thumb(); + void ppm_thumb(); + void ppm16_thumb(); + void layer_thumb(); + void rollei_thumb(); + void kodak_thumb_load_raw(); + + unsigned get4(); + + int flip_index(int row, int col); + void gamma_curve(double pwr, double ts, int mode, int imax); + void cubic_spline(const int *x_, const int *y_, const int len); /* RawSpeed data */ - void *_rawspeed_camerameta; - void *_rawspeed_decoder; - void fix_after_rawspeed(int bl); - int try_rawspeed(); /* returns LIBRAW_SUCCESS on success */ + void *_rawspeed_camerameta; + void *_rawspeed_decoder; + void fix_after_rawspeed(int bl); + int try_rawspeed(); /* returns LIBRAW_SUCCESS on success */ /* Fast cancel flag */ - long _exitflag; + long _exitflag; /* DNG SDK data */ - void *dnghost; - int valid_for_dngsdk(); - int try_dngsdk(); + void *dnghost; + int valid_for_dngsdk(); + int try_dngsdk(); /* X3F data */ - void *_x3f_data; + void *_x3f_data; int raw_was_read() { - return imgdata.rawdata.raw_image || imgdata.rawdata.color4_image || imgdata.rawdata.color3_image - || imgdata.rawdata.float_image || imgdata.rawdata.float3_image || imgdata.rawdata.float4_image; + return imgdata.rawdata.raw_image || imgdata.rawdata.color4_image || imgdata.rawdata.color3_image || + imgdata.rawdata.float_image || imgdata.rawdata.float3_image || imgdata.rawdata.float4_image; } #ifdef LIBRAW_LIBRARY_BUILD #include "internal/libraw_internal_funcs.h" #endif - }; #ifdef LIBRAW_LIBRARY_BUILD -#define RUN_CALLBACK(stage,iter,expect) if(callbacks.progress_cb) { \ - int rr = (*callbacks.progress_cb)(callbacks.progresscb_data,stage,iter,expect); \ - if(rr!=0) throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK; \ - } +#define RUN_CALLBACK(stage, iter, expect) \ + if (callbacks.progress_cb) \ + { \ + int rr = (*callbacks.progress_cb)(callbacks.progresscb_data, stage, iter, expect); \ + if (rr != 0) \ + throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK; \ + } #endif - #endif /* __cplusplus */ - #endif /* _LIBRAW_CLASS_H */ diff --git a/core/libs/rawengine/libraw/libraw/libraw_alloc.h b/core/libs/rawengine/libraw/libraw/libraw_alloc.h index 16efeefa4a..6ff1ecc95c 100644 --- a/core/libs/rawengine/libraw/libraw/libraw_alloc.h +++ b/core/libs/rawengine/libraw/libraw/libraw_alloc.h @@ -1,96 +1,126 @@ /* -*- C++ -*- * File: libraw_alloc.h - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) - * Created: Sat Mar 22, 2008 + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) + * Created: Sat Mar 22, 2008 * * LibRaw C++ interface * LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #ifndef __LIBRAW_ALLOC_H #define __LIBRAW_ALLOC_H #include #include +#include "libraw_const.h" #ifdef __cplusplus -#define LIBRAW_MSIZE 64 +#define LIBRAW_MSIZE 512 class DllDef libraw_memmgr { - public: - libraw_memmgr() - { - memset(mems,0,sizeof(mems)); - calloc_cnt=0; - } - void *malloc(size_t sz) - { - void *ptr = ::malloc(sz); - mem_ptr(ptr); - return ptr; - } - void *calloc(size_t n, size_t sz) +public: + libraw_memmgr(unsigned ee) : extra_bytes(ee) + { + size_t alloc_sz = LIBRAW_MSIZE * sizeof(void *); + mems = (void **)::malloc(alloc_sz); + memset(mems, 0, alloc_sz); + alloc_cnt = 0; + } + ~libraw_memmgr() + { + cleanup(); + ::free(mems); + } + void *malloc(size_t sz) + { +#ifdef LIBRAW_MEMPOOL_CHECK + if(alloc_cnt >= LIBRAW_MSIZE) + throw LIBRAW_EXCEPTION_ALLOC; +#endif +#ifdef LIBRAW_USE_CALLOC_INSTEAD_OF_MALLOC + void *ptr = ::calloc(sz + extra_bytes,1); +#else + void *ptr = ::malloc(sz + extra_bytes); +#endif + mem_ptr(ptr); + return ptr; + } + void *calloc(size_t n, size_t sz) + { +#ifdef LIBRAW_MEMPOOL_CHECK + if(alloc_cnt >= LIBRAW_MSIZE) + throw LIBRAW_EXCEPTION_ALLOC; +#endif + void *ptr = ::calloc(n + (extra_bytes + sz - 1) / (sz ? sz : 1), sz); + mem_ptr(ptr); + return ptr; + } + void *realloc(void *ptr, size_t newsz) + { +#ifdef LIBRAW_MEMPOOL_CHECK + if(alloc_cnt >= LIBRAW_MSIZE) + throw LIBRAW_EXCEPTION_ALLOC; +#endif + void *ret = ::realloc(ptr, newsz + extra_bytes); + forget_ptr(ptr); + mem_ptr(ret); + return ret; + } + void free(void *ptr) + { + forget_ptr(ptr); + ::free(ptr); + } + void cleanup(void) + { + for (int i = 0; i < LIBRAW_MSIZE; i++) + if (mems[i]) + { + ::free(mems[i]); + alloc_cnt--; + mems[i] = NULL; + } + } + +private: + void **mems; + unsigned alloc_cnt; + unsigned extra_bytes; + void mem_ptr(void *ptr) + { + if (ptr) + for (int i = 0; i < LIBRAW_MSIZE; i++) + if (!mems[i]) { - void *ptr = ::calloc(n,sz); - mem_ptr(ptr); - return ptr; + mems[i] = ptr; + alloc_cnt++; + break; } - void *realloc(void *ptr,size_t newsz) + } + void forget_ptr(void *ptr) + { + if (ptr) + for (int i = 0; i < LIBRAW_MSIZE; i++) + if (mems[i] == ptr) { - void *ret = ::realloc(ptr,newsz); - forget_ptr(ptr); - mem_ptr(ret); - return ret; + mems[i] = NULL; + alloc_cnt--; + break; } - void free(void *ptr) - { - forget_ptr(ptr); - ::free(ptr); - } - void cleanup(void) - { - for(int i = 0; i< LIBRAW_MSIZE; i++) - if(mems[i]) - { - free(mems[i]); - mems[i] = NULL; - } - } - - private: - void *mems[LIBRAW_MSIZE]; - int calloc_cnt; - void mem_ptr(void *ptr) - { - if(ptr) - for(int i=0;i < LIBRAW_MSIZE; i++) - if(!mems[i]) - { - mems[i] = ptr; - break; - } - } - void forget_ptr(void *ptr) - { - if(ptr) - for(int i=0;i < LIBRAW_MSIZE; i++) - if(mems[i] == ptr) - mems[i] = NULL; - } - + } }; #endif /* C++ */ #endif diff --git a/core/libs/rawengine/libraw/libraw/libraw_const.h b/core/libs/rawengine/libraw/libraw/libraw_const.h index 4f03e2f129..5ead212341 100644 --- a/core/libs/rawengine/libraw/libraw/libraw_const.h +++ b/core/libs/rawengine/libraw/libraw/libraw_const.h @@ -1,281 +1,349 @@ /* -*- C++ -*- * File: libraw_const.h - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) * Created: Sat Mar 8 , 2008 * LibRaw error codes LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #ifndef _LIBRAW_ERRORS_H #define _LIBRAW_ERRORS_H #define LIBRAW_DEFAULT_ADJUST_MAXIMUM_THRESHOLD 0.75 #define LIBRAW_DEFAULT_AUTO_BRIGHTNESS_THRESHOLD 0.01 - /* limit allocation size, default is 2Gb */ #ifndef LIBRAW_MAX_ALLOC_MB #define LIBRAW_MAX_ALLOC_MB 2048L #endif +/* Check if enough file space exists before tag read */ +#ifndef LIBRAW_NO_IOSPACE_CHECK +#define LIBRAW_IOSPACE_CHECK +#endif +/* LibRaw uses own memory pool management, with LIBRAW_MSIZE (512) +entries. It is enough for parsing/decoding non-damaged files, but +may overflow on specially crafted files (eg. with many string values +like XMP blocks. +LIBRAW_MEMPOOL_CHECK define will result in error on pool overflow */ +#ifndef LIBRAW_NO_MEMPOOL_CHECK +#define LIBRAW_MEMPOOL_CHECK +#endif + +#define LIBRAW_IFD_MAXCOUNT 10 + +enum LibRaw_openbayer_patterns +{ + LIBRAW_OPENBAYER_RGGB = 0x94, + LIBRAW_OPENBAYER_BGGR = 0x16, + LIBRAW_OPENBAYER_GRBG = 0x61, + LIBRAW_OPENBAYER_GBRG = 0x49 +}; + +enum LibRaw_dngfields_marks +{ + LIBRAW_DNGFM_FORWARDMATRIX = 1, + LIBRAW_DNGFM_ILLUMINANT = 2, + LIBRAW_DNGFM_COLORMATRIX = 4, + LIBRAW_DNGFM_CALIBRATION = 8, + LIBRAW_DNGFM_ANALOGBALANCE = 16, + LIBRAW_DNGFM_BLACK = 32, + LIBRAW_DNGFM_WHITE = 64, + LIBRAW_DNGFM_OPCODE2 = 128, + LIBRAW_DNGFM_LINTABLE = 256, + LIBRAW_DNGFM_CROPORIGIN = 512, + LIBRAW_DNGFM_CROPSIZE = 1024, + LIBRAW_DNGFM_PREVIEWCS = 2048 +}; + enum LibRaw_whitebalance_code { -/* - EXIF light sources - 12 = FL-D; Daylight fluorescent (D 5700K – 7100K) (F1,F5) - 13 = FL-N; Day white fluorescent (N 4600K – 5400K) (F7,F8) - 14 = FL-W; Cool white fluorescent (W 3900K – 4500K) (F2,F6, office, store, warehouse) - 15 = FL-WW; White fluorescent (WW 3200K – 3700K) (F3, residential) - 16 = FL-L; Soft/Warm white fluorescent (L 2600K - 3250K) (F4, kitchen, bath) -*/ -LIBRAW_WBI_Unknown=0, -LIBRAW_WBI_Daylight=1, -LIBRAW_WBI_Fluorescent=2, -LIBRAW_WBI_Tungsten=3, -LIBRAW_WBI_Flash=4, -LIBRAW_WBI_FineWeather=9, -LIBRAW_WBI_Cloudy=10, -LIBRAW_WBI_Shade=11, -LIBRAW_WBI_FL_D=12, -LIBRAW_WBI_FL_N=13, -LIBRAW_WBI_FL_W=14, -LIBRAW_WBI_FL_WW=15, -LIBRAW_WBI_FL_L=16, -LIBRAW_WBI_Ill_A=17, -LIBRAW_WBI_Ill_B=18, -LIBRAW_WBI_Ill_C=19, -LIBRAW_WBI_D55=20, -LIBRAW_WBI_D65=21, -LIBRAW_WBI_D75=22, -LIBRAW_WBI_D50=23, -LIBRAW_WBI_StudioTungsten=24, -LIBRAW_WBI_Sunset=64, -LIBRAW_WBI_Other=255 + /* + EXIF light sources + 12 = FL-D; Daylight fluorescent (D 5700K – 7100K) (F1,F5) + 13 = FL-N; Day white fluorescent (N 4600K – 5400K) (F7,F8) + 14 = FL-W; Cool white fluorescent (W 3900K – 4500K) (F2,F6, office, store, warehouse) + 15 = FL-WW; White fluorescent (WW 3200K – 3700K) (F3, residential) + 16 = FL-L; Soft/Warm white fluorescent (L 2600K - 3250K) (F4, kitchen, bath) + */ + LIBRAW_WBI_Unknown = 0, + LIBRAW_WBI_Daylight = 1, + LIBRAW_WBI_Fluorescent = 2, + LIBRAW_WBI_Tungsten = 3, + LIBRAW_WBI_Flash = 4, + LIBRAW_WBI_FineWeather = 9, + LIBRAW_WBI_Cloudy = 10, + LIBRAW_WBI_Shade = 11, + LIBRAW_WBI_FL_D = 12, + LIBRAW_WBI_FL_N = 13, + LIBRAW_WBI_FL_W = 14, + LIBRAW_WBI_FL_WW = 15, + LIBRAW_WBI_FL_L = 16, + LIBRAW_WBI_Ill_A = 17, + LIBRAW_WBI_Ill_B = 18, + LIBRAW_WBI_Ill_C = 19, + LIBRAW_WBI_D55 = 20, + LIBRAW_WBI_D65 = 21, + LIBRAW_WBI_D75 = 22, + LIBRAW_WBI_D50 = 23, + LIBRAW_WBI_StudioTungsten = 24, + LIBRAW_WBI_Sunset = 64, + LIBRAW_WBI_Auto = 82, + LIBRAW_WBI_Custom = 83, + LIBRAW_WBI_Auto1 = 85, + LIBRAW_WBI_Auto2 = 86, + LIBRAW_WBI_Auto3 = 87, + LIBRAW_WBI_Auto4 = 88, + LIBRAW_WBI_Custom1 = 90, + LIBRAW_WBI_Custom2 = 91, + LIBRAW_WBI_Custom3 = 93, + LIBRAW_WBI_Custom4 = 93, + LIBRAW_WBI_Custom5 = 94, + LIBRAW_WBI_Custom6 = 95, + LIBRAW_WBI_Measured = 100, + LIBRAW_WBI_Underwater = 120, + LIBRAW_WBI_Other = 255 +}; + +enum LibRaw_MultiExposure_related +{ + LIBRAW_ME_NONE = 0, + LIBRAW_ME_SIMPLE = 1, + LIBRAW_ME_OVERLAY = 2, + LIBRAW_ME_HDR = 3 }; enum LibRaw_dng_processing { - LIBRAW_DNG_NONE=0, - LIBRAW_DNG_FLOAT=1, - LIBRAW_DNG_LINEAR=2, - LIBRAW_DNG_DEFLATE=4, - LIBRAW_DNG_XTRANS=8, - LIBRAW_DNG_OTHER=16, - LIBRAW_DNG_8BIT=32, - /*LIBRAW_DNG_LARGERANGE=64,*/ /* more than 16 bit integer */ - LIBRAW_DNG_ALL = LIBRAW_DNG_FLOAT|LIBRAW_DNG_LINEAR|LIBRAW_DNG_XTRANS|LIBRAW_DNG_8BIT|LIBRAW_DNG_OTHER /* |LIBRAW_DNG_LARGERANGE */, - LIBRAW_DNG_DEFAULT=LIBRAW_DNG_FLOAT|LIBRAW_DNG_LINEAR|LIBRAW_DNG_DEFLATE|LIBRAW_DNG_8BIT + LIBRAW_DNG_NONE = 0, + LIBRAW_DNG_FLOAT = 1, + LIBRAW_DNG_LINEAR = 2, + LIBRAW_DNG_DEFLATE = 4, + LIBRAW_DNG_XTRANS = 8, + LIBRAW_DNG_OTHER = 16, + LIBRAW_DNG_8BIT = 32, + /*LIBRAW_DNG_LARGERANGE=64,*/ /* more than 16 bit integer */ + LIBRAW_DNG_ALL = LIBRAW_DNG_FLOAT | LIBRAW_DNG_LINEAR | LIBRAW_DNG_XTRANS | LIBRAW_DNG_8BIT | + LIBRAW_DNG_OTHER /* |LIBRAW_DNG_LARGERANGE */, + LIBRAW_DNG_DEFAULT = LIBRAW_DNG_FLOAT | LIBRAW_DNG_LINEAR | LIBRAW_DNG_DEFLATE | LIBRAW_DNG_8BIT }; enum LibRaw_runtime_capabilities { - LIBRAW_CAPS_RAWSPEED=1, - LIBRAW_CAPS_DNGSDK=2, - LIBRAW_CAPS_DEMOSAICSGPL2=4, - LIBRAW_CAPS_DEMOSAICSGPL3=8 + LIBRAW_CAPS_RAWSPEED = 1, + LIBRAW_CAPS_DNGSDK = 2 }; enum LibRaw_camera_mounts - { - LIBRAW_MOUNT_Unknown=0, - LIBRAW_MOUNT_Minolta_A=1, - LIBRAW_MOUNT_Sony_E=2, - LIBRAW_MOUNT_Canon_EF=3, - LIBRAW_MOUNT_Canon_EF_S=4, - LIBRAW_MOUNT_Canon_EF_M=5, - LIBRAW_MOUNT_Nikon_F=6, - LIBRAW_MOUNT_Nikon_CX=7, /* used in Nikon 1 series */ - LIBRAW_MOUNT_FT=8, /* original 4/3 */ - LIBRAW_MOUNT_mFT=9, /* micro 4/3 */ - LIBRAW_MOUNT_Pentax_K=10, - LIBRAW_MOUNT_Pentax_Q=11, - LIBRAW_MOUNT_Pentax_645=12, - LIBRAW_MOUNT_Fuji_X=13, - LIBRAW_MOUNT_Leica_M=14, - LIBRAW_MOUNT_Leica_R=15, - LIBRAW_MOUNT_Leica_S=16, - LIBRAW_MOUNT_Samsung_NX=17, - LIBRAW_MOUNT_RicohModule=18, - LIBRAW_MOUNT_Samsung_NX_M=19, - LIBRAW_MOUNT_Leica_T=20, - LIBRAW_MOUNT_Contax_N=21, - LIBRAW_MOUNT_Sigma_X3F=22, - LIBRAW_MOUNT_Leica_SL=23, - LIBRAW_MOUNT_FixedLens=99 - }; +{ + LIBRAW_MOUNT_Unknown = 0, + LIBRAW_MOUNT_Minolta_A = 1, + LIBRAW_MOUNT_Sony_E = 2, + LIBRAW_MOUNT_Canon_EF = 3, + LIBRAW_MOUNT_Canon_EF_S = 4, + LIBRAW_MOUNT_Canon_EF_M = 5, + LIBRAW_MOUNT_Nikon_F = 6, + LIBRAW_MOUNT_Nikon_CX = 7, /* used in Nikon 1 series */ + LIBRAW_MOUNT_FT = 8, /* original 4/3 */ + LIBRAW_MOUNT_mFT = 9, /* micro 4/3 */ + LIBRAW_MOUNT_Pentax_K = 10, + LIBRAW_MOUNT_Pentax_Q = 11, + LIBRAW_MOUNT_Pentax_645 = 12, + LIBRAW_MOUNT_Fuji_X = 13, + LIBRAW_MOUNT_Leica_M = 14, + LIBRAW_MOUNT_Leica_R = 15, + LIBRAW_MOUNT_Leica_S = 16, + LIBRAW_MOUNT_Samsung_NX = 17, + LIBRAW_MOUNT_RicohModule = 18, + LIBRAW_MOUNT_Samsung_NX_M = 19, + LIBRAW_MOUNT_Leica_T = 20, + LIBRAW_MOUNT_Contax_N = 21, + LIBRAW_MOUNT_Sigma_X3F = 22, + LIBRAW_MOUNT_Leica_SL = 23, + LIBRAW_MOUNT_FixedLens = 99 +}; enum LibRaw_camera_formats - { - LIBRAW_FORMAT_APSC=1, - LIBRAW_FORMAT_FF=2, - LIBRAW_FORMAT_MF=3, - LIBRAW_FORMAT_APSH=4, - LIBRAW_FORMAT_1INCH=5, - LIBRAW_FORMAT_FT=8 - }; +{ + LIBRAW_FORMAT_APSC = 1, + LIBRAW_FORMAT_FF = 2, + LIBRAW_FORMAT_MF = 3, + LIBRAW_FORMAT_APSH = 4, + LIBRAW_FORMAT_1INCH = 5, + LIBRAW_FORMAT_FT = 8 +}; enum LibRaw_sony_cameratypes - { - LIBRAW_SONY_DSC=1, - LIBRAW_SONY_DSLR=2, - LIBRAW_SONY_NEX=3, - LIBRAW_SONY_SLT=4, - LIBRAW_SONY_ILCE=5, - LIBRAW_SONY_ILCA=6 - }; +{ + LIBRAW_SONY_DSC = 1, + LIBRAW_SONY_DSLR = 2, + LIBRAW_SONY_NEX = 3, + LIBRAW_SONY_SLT = 4, + LIBRAW_SONY_ILCE = 5, + LIBRAW_SONY_ILCA = 6 +}; enum LibRaw_processing_options - { - LIBRAW_PROCESSING_SONYARW2_NONE=0, - LIBRAW_PROCESSING_SONYARW2_BASEONLY=1, - LIBRAW_PROCESSING_SONYARW2_DELTAONLY=1<<1, - LIBRAW_PROCESSING_SONYARW2_DELTAZEROBASE=1<<2, - LIBRAW_PROCESSING_SONYARW2_DELTATOVALUE=1<<3, - LIBRAW_PROCESSING_SONYARW2_ALLFLAGS = LIBRAW_PROCESSING_SONYARW2_BASEONLY + LIBRAW_PROCESSING_SONYARW2_DELTAONLY + LIBRAW_PROCESSING_SONYARW2_DELTAZEROBASE + LIBRAW_PROCESSING_SONYARW2_DELTATOVALUE, - LIBRAW_PROCESSING_DP2Q_INTERPOLATERG=1<<4, - LIBRAW_PROCESSING_DP2Q_INTERPOLATEAF=1<<5, - LIBRAW_PROCESSING_PENTAX_PS_ALLFRAMES=1<<6, - LIBRAW_PROCESSING_CONVERTFLOAT_TO_INT=1<<7, - LIBRAW_PROCESSING_SRAW_NO_RGB=1<<8, - LIBRAW_PROCESSING_SRAW_NO_INTERPOLATE=1<<9, - LIBRAW_PROCESSING_FORCE_FOVEON_X3F=1<<10 - }; +{ + LIBRAW_PROCESSING_SONYARW2_NONE = 0, + LIBRAW_PROCESSING_SONYARW2_BASEONLY = 1, + LIBRAW_PROCESSING_SONYARW2_DELTAONLY = 1 << 1, + LIBRAW_PROCESSING_SONYARW2_DELTAZEROBASE = 1 << 2, + LIBRAW_PROCESSING_SONYARW2_DELTATOVALUE = 1 << 3, + LIBRAW_PROCESSING_SONYARW2_ALLFLAGS = LIBRAW_PROCESSING_SONYARW2_BASEONLY + LIBRAW_PROCESSING_SONYARW2_DELTAONLY + + LIBRAW_PROCESSING_SONYARW2_DELTAZEROBASE + + LIBRAW_PROCESSING_SONYARW2_DELTATOVALUE, + LIBRAW_PROCESSING_DP2Q_INTERPOLATERG = 1 << 4, + LIBRAW_PROCESSING_DP2Q_INTERPOLATEAF = 1 << 5, + LIBRAW_PROCESSING_PENTAX_PS_ALLFRAMES = 1 << 6, + LIBRAW_PROCESSING_CONVERTFLOAT_TO_INT = 1 << 7, + LIBRAW_PROCESSING_SRAW_NO_RGB = 1 << 8, + LIBRAW_PROCESSING_SRAW_NO_INTERPOLATE = 1 << 9, + LIBRAW_PROCESSING_NO_ROTATE_FOR_KODAK_THUMBNAILS = 1 << 11, + LIBRAW_PROCESSING_USE_DNG_DEFAULT_CROP = 1 << 12, + LIBRAW_PROCESSING_USE_PPM16_THUMBS = 1 << 13, + LIBRAW_PROCESSING_CHECK_DNG_ILLUMINANT = 1 << 15 +}; enum LibRaw_decoder_flags { - LIBRAW_DECODER_HASCURVE = 1<<4, - LIBRAW_DECODER_SONYARW2 = 1<<5, - LIBRAW_DECODER_TRYRAWSPEED = 1<<6, - LIBRAW_DECODER_OWNALLOC = 1<<7, - LIBRAW_DECODER_FIXEDMAXC = 1<<8, - LIBRAW_DECODER_ADOBECOPYPIXEL = 1<<9, - LIBRAW_DECODER_LEGACY_WITH_MARGINS = 1<<10, - LIBRAW_DECODER_NOTSET = 1<<15 + LIBRAW_DECODER_HASCURVE = 1 << 4, + LIBRAW_DECODER_SONYARW2 = 1 << 5, + LIBRAW_DECODER_TRYRAWSPEED = 1 << 6, + LIBRAW_DECODER_OWNALLOC = 1 << 7, + LIBRAW_DECODER_FIXEDMAXC = 1 << 8, + LIBRAW_DECODER_ADOBECOPYPIXEL = 1 << 9, + LIBRAW_DECODER_LEGACY_WITH_MARGINS = 1 << 10, + LIBRAW_DECODER_3CHANNEL = 1 << 11, + LIBRAW_DECODER_NOTSET = 1 << 15 }; #define LIBRAW_XTRANS 9 enum LibRaw_constructor_flags { - LIBRAW_OPTIONS_NONE =0, - LIBRAW_OPIONS_NO_MEMERR_CALLBACK=1, - LIBRAW_OPIONS_NO_DATAERR_CALLBACK=1<<1 + LIBRAW_OPTIONS_NONE = 0, + LIBRAW_OPIONS_NO_MEMERR_CALLBACK = 1, + LIBRAW_OPIONS_NO_DATAERR_CALLBACK = 1 << 1 }; enum LibRaw_warnings { LIBRAW_WARN_NONE = 0, LIBRAW_WARN_BAD_CAMERA_WB = 1 << 2, LIBRAW_WARN_NO_METADATA = 1 << 3, LIBRAW_WARN_NO_JPEGLIB = 1 << 4, LIBRAW_WARN_NO_EMBEDDED_PROFILE = 1 << 5, LIBRAW_WARN_NO_INPUT_PROFILE = 1 << 6, LIBRAW_WARN_BAD_OUTPUT_PROFILE = 1 << 7, LIBRAW_WARN_NO_BADPIXELMAP = 1 << 8, LIBRAW_WARN_BAD_DARKFRAME_FILE = 1 << 9, LIBRAW_WARN_BAD_DARKFRAME_DIM = 1 << 10, LIBRAW_WARN_NO_JASPER = 1 << 11, LIBRAW_WARN_RAWSPEED_PROBLEM = 1 << 12, LIBRAW_WARN_RAWSPEED_UNSUPPORTED = 1 << 13, LIBRAW_WARN_RAWSPEED_PROCESSED = 1 << 14, LIBRAW_WARN_FALLBACK_TO_AHD = 1 << 15, LIBRAW_WARN_PARSEFUJI_PROCESSED = 1 << 16 }; enum LibRaw_exceptions { - LIBRAW_EXCEPTION_NONE =0, - LIBRAW_EXCEPTION_ALLOC =1, - LIBRAW_EXCEPTION_DECODE_RAW =2, - LIBRAW_EXCEPTION_DECODE_JPEG=3, - LIBRAW_EXCEPTION_IO_EOF =4, - LIBRAW_EXCEPTION_IO_CORRUPT =5, - LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK=6, - LIBRAW_EXCEPTION_BAD_CROP =7, - LIBRAW_EXCEPTION_IO_BADFILE =8, - LIBRAW_EXCEPTION_DECODE_JPEG2000=9 + LIBRAW_EXCEPTION_NONE = 0, + LIBRAW_EXCEPTION_ALLOC = 1, + LIBRAW_EXCEPTION_DECODE_RAW = 2, + LIBRAW_EXCEPTION_DECODE_JPEG = 3, + LIBRAW_EXCEPTION_IO_EOF = 4, + LIBRAW_EXCEPTION_IO_CORRUPT = 5, + LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK = 6, + LIBRAW_EXCEPTION_BAD_CROP = 7, + LIBRAW_EXCEPTION_IO_BADFILE = 8, + LIBRAW_EXCEPTION_DECODE_JPEG2000 = 9, + LIBRAW_EXCEPTION_TOOBIG = 10 }; enum LibRaw_progress { - LIBRAW_PROGRESS_START = 0, - LIBRAW_PROGRESS_OPEN = 1, - LIBRAW_PROGRESS_IDENTIFY = 1<<1, - LIBRAW_PROGRESS_SIZE_ADJUST = 1<<2, - LIBRAW_PROGRESS_LOAD_RAW = 1<<3, - LIBRAW_PROGRESS_RAW2_IMAGE = 1<<4, - LIBRAW_PROGRESS_REMOVE_ZEROES = 1<<5, - LIBRAW_PROGRESS_BAD_PIXELS = 1<<6, - LIBRAW_PROGRESS_DARK_FRAME = 1<<7, - LIBRAW_PROGRESS_FOVEON_INTERPOLATE = 1<<8, - LIBRAW_PROGRESS_SCALE_COLORS = 1<<9, - LIBRAW_PROGRESS_PRE_INTERPOLATE = 1<<10, - LIBRAW_PROGRESS_INTERPOLATE = 1<<11, - LIBRAW_PROGRESS_MIX_GREEN = 1<<12, - LIBRAW_PROGRESS_MEDIAN_FILTER = 1<<13, - LIBRAW_PROGRESS_HIGHLIGHTS = 1<<14, - LIBRAW_PROGRESS_FUJI_ROTATE = 1<<15, - LIBRAW_PROGRESS_FLIP = 1<<16, - LIBRAW_PROGRESS_APPLY_PROFILE = 1<<17, - LIBRAW_PROGRESS_CONVERT_RGB = 1<<18, - LIBRAW_PROGRESS_STRETCH = 1<<19, -/* reserved */ - LIBRAW_PROGRESS_STAGE20 = 1<<20, - LIBRAW_PROGRESS_STAGE21 = 1<<21, - LIBRAW_PROGRESS_STAGE22 = 1<<22, - LIBRAW_PROGRESS_STAGE23 = 1<<23, - LIBRAW_PROGRESS_STAGE24 = 1<<24, - LIBRAW_PROGRESS_STAGE25 = 1<<25, - LIBRAW_PROGRESS_STAGE26 = 1<<26, - LIBRAW_PROGRESS_STAGE27 = 1<<27, + LIBRAW_PROGRESS_START = 0, + LIBRAW_PROGRESS_OPEN = 1, + LIBRAW_PROGRESS_IDENTIFY = 1 << 1, + LIBRAW_PROGRESS_SIZE_ADJUST = 1 << 2, + LIBRAW_PROGRESS_LOAD_RAW = 1 << 3, + LIBRAW_PROGRESS_RAW2_IMAGE = 1 << 4, + LIBRAW_PROGRESS_REMOVE_ZEROES = 1 << 5, + LIBRAW_PROGRESS_BAD_PIXELS = 1 << 6, + LIBRAW_PROGRESS_DARK_FRAME = 1 << 7, + LIBRAW_PROGRESS_FOVEON_INTERPOLATE = 1 << 8, + LIBRAW_PROGRESS_SCALE_COLORS = 1 << 9, + LIBRAW_PROGRESS_PRE_INTERPOLATE = 1 << 10, + LIBRAW_PROGRESS_INTERPOLATE = 1 << 11, + LIBRAW_PROGRESS_MIX_GREEN = 1 << 12, + LIBRAW_PROGRESS_MEDIAN_FILTER = 1 << 13, + LIBRAW_PROGRESS_HIGHLIGHTS = 1 << 14, + LIBRAW_PROGRESS_FUJI_ROTATE = 1 << 15, + LIBRAW_PROGRESS_FLIP = 1 << 16, + LIBRAW_PROGRESS_APPLY_PROFILE = 1 << 17, + LIBRAW_PROGRESS_CONVERT_RGB = 1 << 18, + LIBRAW_PROGRESS_STRETCH = 1 << 19, + /* reserved */ + LIBRAW_PROGRESS_STAGE20 = 1 << 20, + LIBRAW_PROGRESS_STAGE21 = 1 << 21, + LIBRAW_PROGRESS_STAGE22 = 1 << 22, + LIBRAW_PROGRESS_STAGE23 = 1 << 23, + LIBRAW_PROGRESS_STAGE24 = 1 << 24, + LIBRAW_PROGRESS_STAGE25 = 1 << 25, + LIBRAW_PROGRESS_STAGE26 = 1 << 26, + LIBRAW_PROGRESS_STAGE27 = 1 << 27, - LIBRAW_PROGRESS_THUMB_LOAD = 1<<28, - LIBRAW_PROGRESS_TRESERVED1 = 1<<29, - LIBRAW_PROGRESS_TRESERVED2 = 1<<30, - LIBRAW_PROGRESS_TRESERVED3 = 1<<31 + LIBRAW_PROGRESS_THUMB_LOAD = 1 << 28, + LIBRAW_PROGRESS_TRESERVED1 = 1 << 29, + LIBRAW_PROGRESS_TRESERVED2 = 1 << 30, + LIBRAW_PROGRESS_TRESERVED3 = 1 << 31 }; #define LIBRAW_PROGRESS_THUMB_MASK 0x0fffffff enum LibRaw_errors { - LIBRAW_SUCCESS = 0, - LIBRAW_UNSPECIFIED_ERROR=-1, - LIBRAW_FILE_UNSUPPORTED = -2, - LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE=-3, - LIBRAW_OUT_OF_ORDER_CALL=-4, - LIBRAW_NO_THUMBNAIL=-5, - LIBRAW_UNSUPPORTED_THUMBNAIL=-6, - LIBRAW_INPUT_CLOSED=-7, - LIBRAW_NOT_IMPLEMENTED=-8, - LIBRAW_UNSUFFICIENT_MEMORY=-100007, - LIBRAW_DATA_ERROR=-100008, - LIBRAW_IO_ERROR=-100009, - LIBRAW_CANCELLED_BY_CALLBACK=-100010, - LIBRAW_BAD_CROP=-100011 + LIBRAW_SUCCESS = 0, + LIBRAW_UNSPECIFIED_ERROR = -1, + LIBRAW_FILE_UNSUPPORTED = -2, + LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE = -3, + LIBRAW_OUT_OF_ORDER_CALL = -4, + LIBRAW_NO_THUMBNAIL = -5, + LIBRAW_UNSUPPORTED_THUMBNAIL = -6, + LIBRAW_INPUT_CLOSED = -7, + LIBRAW_NOT_IMPLEMENTED = -8, + LIBRAW_UNSUFFICIENT_MEMORY = -100007, + LIBRAW_DATA_ERROR = -100008, + LIBRAW_IO_ERROR = -100009, + LIBRAW_CANCELLED_BY_CALLBACK = -100010, + LIBRAW_BAD_CROP = -100011, + LIBRAW_TOO_BIG = -100012 }; -#define LIBRAW_FATAL_ERROR(ec) ((ec)<-100000) +#define LIBRAW_FATAL_ERROR(ec) ((ec) < -100000) enum LibRaw_thumbnail_formats { - LIBRAW_THUMBNAIL_UNKNOWN=0, - LIBRAW_THUMBNAIL_JPEG=1, - LIBRAW_THUMBNAIL_BITMAP=2, - LIBRAW_THUMBNAIL_LAYER=4, - LIBRAW_THUMBNAIL_ROLLEI=5 + LIBRAW_THUMBNAIL_UNKNOWN = 0, + LIBRAW_THUMBNAIL_JPEG = 1, + LIBRAW_THUMBNAIL_BITMAP = 2, + LIBRAW_THUMBNAIL_BITMAP16 = 3, + LIBRAW_THUMBNAIL_LAYER = 4, + LIBRAW_THUMBNAIL_ROLLEI = 5 }; enum LibRaw_image_formats { - LIBRAW_IMAGE_JPEG=1, - LIBRAW_IMAGE_BITMAP=2 + LIBRAW_IMAGE_JPEG = 1, + LIBRAW_IMAGE_BITMAP = 2 }; #endif diff --git a/core/libs/rawengine/libraw/libraw/libraw_datastream.h b/core/libs/rawengine/libraw/libraw/libraw_datastream.h index d7da139df4..1840adb2a6 100644 --- a/core/libs/rawengine/libraw/libraw/libraw_datastream.h +++ b/core/libs/rawengine/libraw/libraw/libraw_datastream.h @@ -1,294 +1,306 @@ /* -*- C -*- * File: libraw_datastream.h - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) * Created: Sun Jan 18 13:07:35 2009 * * LibRaw Data stream interface LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #ifndef __LIBRAW_DATASTREAM_H #define __LIBRAW_DATASTREAM_H #include #include #include #include #ifndef __cplusplus - #else /* __cplusplus */ +#if defined WIN32 || defined(__MINGW32__) +#include +#endif #include "libraw_const.h" #include "libraw_types.h" #include #include -#if defined WIN32 || defined (__MINGW32__) -#include +#if defined WIN32 || defined(__MINGW32__) /* MSVS 2008 and above... */ #if _MSC_VER >= 1500 #define WIN32SECURECALLS #endif #endif #ifdef USE_DNGSDK -#if defined WIN32 || defined (__MINGW32__) +#if defined WIN32 || defined(__MINGW32__) #define qWinOS 1 #define qMacOS 0 #elif defined(__APPLE__) #define qWinOS 0 #define qMacOS 1 #else /* define OS types for DNG here */ #endif -#define qDNGXMPDocOps 0 +#define qDNGXMPDocOps 0 #define qDNGUseLibJPEG 1 -#define qDNGXMPFiles 0 +#define qDNGXMPFiles 0 #define qDNGExperimental 1 #define qDNGThreadSafe 1 #include "dng_stream.h" #endif /* DNGSDK */ - -#define IOERROR() do { throw LIBRAW_EXCEPTION_IO_EOF; } while(0) +#define IOERROR() \ + do \ + { \ + throw LIBRAW_EXCEPTION_IO_EOF; \ + } while (0) class LibRaw_buffer_datastream; class LibRaw_bit_buffer; class DllDef LibRaw_abstract_datastream { - public: - LibRaw_abstract_datastream(){ substream=0;}; - virtual ~LibRaw_abstract_datastream(void){if(substream) delete substream;} - virtual int valid() = 0; - virtual int read(void *,size_t, size_t ) = 0; - virtual int seek(INT64 , int ) = 0; - virtual INT64 tell() = 0; - virtual INT64 size() = 0; - virtual int get_char() = 0; - virtual char* gets(char *, int) = 0; - virtual int scanf_one(const char *, void *) = 0; - virtual int eof() = 0; - virtual void * make_jas_stream() = 0; - virtual int jpeg_src(void *) { return -1; } - /* reimplement in subclass to use parallel access in xtrans_load_raw() if OpenMP is not used */ - virtual int lock() { return 1;} /* success */ - virtual void unlock(){} - /* subfile parsing not implemented in base class */ - virtual const char* fname(){ return NULL;}; +public: + LibRaw_abstract_datastream() { substream = 0; }; + virtual ~LibRaw_abstract_datastream(void) + { + if (substream) + delete substream; + } + virtual int valid() = 0; + virtual int read(void *, size_t, size_t) = 0; + virtual int seek(INT64, int) = 0; + virtual INT64 tell() = 0; + virtual INT64 size() = 0; + virtual int get_char() = 0; + virtual char *gets(char *, int) = 0; + virtual int scanf_one(const char *, void *) = 0; + virtual int eof() = 0; + virtual void *make_jas_stream() = 0; + virtual int jpeg_src(void *) { return -1; } + /* reimplement in subclass to use parallel access in xtrans_load_raw() if OpenMP is not used */ + virtual int lock() { return 1; } /* success */ + virtual void unlock() {} + /* subfile parsing not implemented in base class */ + virtual const char *fname() { return NULL; }; #if defined(_WIN32) && !defined(__MINGW32__) && defined(_MSC_VER) && (_MSC_VER > 1310) - virtual const wchar_t* wfname(){ return NULL;}; - virtual int subfile_open(const wchar_t*) { return -1;} + virtual const wchar_t *wfname() { return NULL; }; + virtual int subfile_open(const wchar_t *) { return -1; } #endif - virtual int subfile_open(const char*) { return -1;} - virtual void subfile_close() { } + virtual int subfile_open(const char *) { return -1; } + virtual void subfile_close() {} - virtual int tempbuffer_open(void*, size_t); - virtual void tempbuffer_close(); + virtual int tempbuffer_open(void *, size_t); + virtual void tempbuffer_close(); - protected: - LibRaw_abstract_datastream *substream; +protected: + LibRaw_abstract_datastream *substream; }; #ifdef WIN32 template class DllDef std::auto_ptr; #endif -class DllDef LibRaw_file_datastream: public LibRaw_abstract_datastream +class DllDef LibRaw_file_datastream : public LibRaw_abstract_datastream { - protected: - std::auto_ptr f; /* will close() automatically through dtor */ - std::auto_ptr saved_f; /* when *f is a subfile, *saved_f is the master file */ - std::string filename; - INT64 _fsize; +protected: + std::auto_ptr f; /* will close() automatically through dtor */ + std::auto_ptr saved_f; /* when *f is a subfile, *saved_f is the master file */ + std::string filename; + INT64 _fsize; #ifdef WIN32 - std::wstring wfilename; + std::wstring wfilename; #endif - FILE *jas_file; - public: - virtual ~LibRaw_file_datastream(); - LibRaw_file_datastream(const char *fname); + FILE *jas_file; + +public: + virtual ~LibRaw_file_datastream(); + LibRaw_file_datastream(const char *fname); #if defined(_WIN32) && !defined(__MINGW32__) && defined(_MSC_VER) && (_MSC_VER > 1310) - LibRaw_file_datastream(const wchar_t *fname); + LibRaw_file_datastream(const wchar_t *fname); #endif - virtual void *make_jas_stream(); - virtual int jpeg_src(void *jpegdata); - virtual int valid(); - virtual int read(void * ptr,size_t size, size_t nmemb); - virtual int eof(); - virtual int seek(INT64 o, int whence); - virtual INT64 tell(); - virtual INT64 size() { return _fsize;} - virtual int get_char() - { - if(substream) return substream->get_char(); - return f->sbumpc(); - } - virtual char* gets(char *str, int sz); - virtual int scanf_one(const char *fmt, void*val); - virtual const char* fname(); + virtual void *make_jas_stream(); + virtual int jpeg_src(void *jpegdata); + virtual int valid(); + virtual int read(void *ptr, size_t size, size_t nmemb); + virtual int eof(); + virtual int seek(INT64 o, int whence); + virtual INT64 tell(); + virtual INT64 size() { return _fsize; } + virtual int get_char() + { + if (substream) + return substream->get_char(); + return f->sbumpc(); + } + virtual char *gets(char *str, int sz); + virtual int scanf_one(const char *fmt, void *val); + virtual const char *fname(); #if defined(_WIN32) && !defined(__MINGW32__) && defined(_MSC_VER) && (_MSC_VER > 1310) - virtual const wchar_t* wfname(); - virtual int subfile_open(const wchar_t *fn); + virtual const wchar_t *wfname(); + virtual int subfile_open(const wchar_t *fn); #endif - virtual int subfile_open(const char *fn); - virtual void subfile_close(); + virtual int subfile_open(const char *fn); + virtual void subfile_close(); }; - -class DllDef LibRaw_buffer_datastream : public LibRaw_abstract_datastream +class DllDef LibRaw_buffer_datastream : public LibRaw_abstract_datastream { - public: - LibRaw_buffer_datastream(void *buffer, size_t bsize); - virtual ~LibRaw_buffer_datastream(); - virtual int valid(); - virtual void *make_jas_stream(); - virtual int jpeg_src(void *jpegdata); - virtual int read(void * ptr,size_t sz, size_t nmemb); - virtual int eof(); - virtual int seek(INT64 o, int whence); - virtual INT64 tell(); - virtual INT64 size() { return streamsize;} - virtual char* gets(char *s, int sz); - virtual int scanf_one(const char *fmt, void* val); - virtual int get_char() - { - if(substream) return substream->get_char(); - if(streampos>=streamsize) - return -1; - return buf[streampos++]; - } +public: + LibRaw_buffer_datastream(void *buffer, size_t bsize); + virtual ~LibRaw_buffer_datastream(); + virtual int valid(); + virtual void *make_jas_stream(); + virtual int jpeg_src(void *jpegdata); + virtual int read(void *ptr, size_t sz, size_t nmemb); + virtual int eof(); + virtual int seek(INT64 o, int whence); + virtual INT64 tell(); + virtual INT64 size() { return streamsize; } + virtual char *gets(char *s, int sz); + virtual int scanf_one(const char *fmt, void *val); + virtual int get_char() + { + if (substream) + return substream->get_char(); + if (streampos >= streamsize) + return -1; + return buf[streampos++]; + } - private: - unsigned char *buf; - size_t streampos,streamsize; +private: + unsigned char *buf; + size_t streampos, streamsize; }; class DllDef LibRaw_bigfile_datastream : public LibRaw_abstract_datastream { - public: - LibRaw_bigfile_datastream(const char *fname); +public: + LibRaw_bigfile_datastream(const char *fname); #if defined(_WIN32) && !defined(__MINGW32__) && defined(_MSC_VER) && (_MSC_VER > 1310) - LibRaw_bigfile_datastream(const wchar_t *fname); + LibRaw_bigfile_datastream(const wchar_t *fname); #endif - virtual ~LibRaw_bigfile_datastream(); - virtual int valid(); - virtual int jpeg_src(void *jpegdata); - virtual void *make_jas_stream(); - - virtual int read(void * ptr,size_t size, size_t nmemb); - virtual int eof(); - virtual int seek(INT64 o, int whence); - virtual INT64 tell(); - virtual INT64 size() { return _fsize;} - virtual char* gets(char *str, int sz); - virtual int scanf_one(const char *fmt, void*val); - virtual const char *fname(); + virtual ~LibRaw_bigfile_datastream(); + virtual int valid(); + virtual int jpeg_src(void *jpegdata); + virtual void *make_jas_stream(); + + virtual int read(void *ptr, size_t size, size_t nmemb); + virtual int eof(); + virtual int seek(INT64 o, int whence); + virtual INT64 tell(); + virtual INT64 size() { return _fsize; } + virtual char *gets(char *str, int sz); + virtual int scanf_one(const char *fmt, void *val); + virtual const char *fname(); #if defined(_WIN32) && !defined(__MINGW32__) && defined(_MSC_VER) && (_MSC_VER > 1310) - virtual const wchar_t* wfname(); - virtual int subfile_open(const wchar_t *fn); + virtual const wchar_t *wfname(); + virtual int subfile_open(const wchar_t *fn); #endif - virtual int subfile_open(const char *fn); - virtual void subfile_close(); - virtual int get_char() - { + virtual int subfile_open(const char *fn); + virtual void subfile_close(); + virtual int get_char() + { #if !defined(_WIN32) && !defined(__MINGW32__) - return substream?substream->get_char():getc_unlocked(f); + return substream ? substream->get_char() : getc_unlocked(f); #else - return substream?substream->get_char():fgetc(f); + return substream ? substream->get_char() : fgetc(f); #endif - } + } protected: - FILE *f,*sav; - std::string filename; - INT64 _fsize; + FILE *f, *sav; + std::string filename; + INT64 _fsize; #ifdef WIN32 - std::wstring wfilename; + std::wstring wfilename; #endif }; #ifdef WIN32 -class DllDef LibRaw_windows_datastream : public LibRaw_buffer_datastream +class DllDef LibRaw_windows_datastream : public LibRaw_buffer_datastream { public: - /* ctor: high level constructor opens a file by name */ - LibRaw_windows_datastream(const TCHAR* sFile); - /* ctor: construct with a file handle - caller is responsible for closing the file handle */ - LibRaw_windows_datastream(HANDLE hFile); - /* dtor: unmap and close the mapping handle */ - virtual ~LibRaw_windows_datastream(); - virtual INT64 size() { return cbView_;} + /* ctor: high level constructor opens a file by name */ + LibRaw_windows_datastream(const TCHAR *sFile); + /* ctor: construct with a file handle - caller is responsible for closing the file handle */ + LibRaw_windows_datastream(HANDLE hFile); + /* dtor: unmap and close the mapping handle */ + virtual ~LibRaw_windows_datastream(); + virtual INT64 size() { return cbView_; } protected: - void Open(HANDLE hFile); - inline void reconstruct_base() - { - /* this subterfuge is to overcome the private-ness of LibRaw_buffer_datastream */ - (LibRaw_buffer_datastream&)*this = LibRaw_buffer_datastream(pView_, (size_t)cbView_); - } - - HANDLE hMap_; /* handle of the file mapping */ - void* pView_; /* pointer to the mapped memory */ - __int64 cbView_; /* size of the mapping in bytes */ + void Open(HANDLE hFile); + inline void reconstruct_base() + { + /* this subterfuge is to overcome the private-ness of LibRaw_buffer_datastream */ + (LibRaw_buffer_datastream &)*this = LibRaw_buffer_datastream(pView_, (size_t)cbView_); + } + + HANDLE hMap_; /* handle of the file mapping */ + void *pView_; /* pointer to the mapped memory */ + __int64 cbView_; /* size of the mapping in bytes */ }; #endif #ifdef USE_DNGSDK -class libraw_dng_stream: public dng_stream +class libraw_dng_stream : public dng_stream { public: - libraw_dng_stream(LibRaw_abstract_datastream* p): dng_stream((dng_abort_sniffer*)NULL,kBigBufferSize,0),parent_stream(p) - { - if(parent_stream) - { - off = parent_stream->tell(); - parent_stream->seek(0UL,SEEK_SET); /* seek to start */ - } - } - ~libraw_dng_stream(){ - if(parent_stream) - parent_stream->seek(off,SEEK_SET); - } - virtual uint64 DoGetLength (){ - if(parent_stream) - return parent_stream->size(); - return 0; - } - virtual void DoRead (void *data, uint32 count, uint64 offset) - { - if(parent_stream) - { - parent_stream->seek(offset,SEEK_SET); - parent_stream->read(data,1,count); - } - } + libraw_dng_stream(LibRaw_abstract_datastream *p) + : dng_stream((dng_abort_sniffer *)NULL, kBigBufferSize, 0), parent_stream(p) + { + if (parent_stream) + { + off = parent_stream->tell(); + parent_stream->seek(0UL, SEEK_SET); /* seek to start */ + } + } + ~libraw_dng_stream() + { + if (parent_stream) + parent_stream->seek(off, SEEK_SET); + } + virtual uint64 DoGetLength() + { + if (parent_stream) + return parent_stream->size(); + return 0; + } + virtual void DoRead(void *data, uint32 count, uint64 offset) + { + if (parent_stream) + { + parent_stream->seek(offset, SEEK_SET); + parent_stream->read(data, 1, count); + } + } private: - libraw_dng_stream (const libraw_dng_stream &stream); - libraw_dng_stream & operator= (const libraw_dng_stream &stream); - LibRaw_abstract_datastream *parent_stream; - INT64 off; + libraw_dng_stream(const libraw_dng_stream &stream); + libraw_dng_stream &operator=(const libraw_dng_stream &stream); + LibRaw_abstract_datastream *parent_stream; + INT64 off; }; #endif #endif /* cplusplus */ #endif - diff --git a/core/libs/rawengine/libraw/libraw/libraw_internal.h b/core/libs/rawengine/libraw/libraw/libraw_internal.h index 2f6fc71f18..bae5c73989 100644 --- a/core/libs/rawengine/libraw/libraw/libraw_internal.h +++ b/core/libs/rawengine/libraw/libraw/libraw_internal.h @@ -1,226 +1,279 @@ /* -*- C++ -*- * File: libraw_internal.h - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) * Created: Sat Mar 8 , 2008 * * LibRaw internal data structures (not visible outside) LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #ifndef _LIBRAW_INTERNAL_TYPES_H #define _LIBRAW_INTERNAL_TYPES_H #include #ifdef __cplusplus #ifdef LIBRAW_LIBRARY_BUILD #ifndef CLASS #define CLASS LibRaw:: #endif #endif #else #ifndef CLASS #define CLASS #endif #endif - #ifdef __cplusplus #include "libraw_datastream.h" #include "libraw_types.h" class LibRaw_TLS { public: - struct - { - unsigned bitbuf; - int vbits, reset; - }getbits; - struct - { - UINT64 bitbuf; - int vbits; - - }ph1_bits; - struct - { - unsigned pad[128], p; - }sony_decrypt; - struct - { - uchar buf[0x4000]; - int vbits, padding; - }pana_bits; - uchar jpeg_buffer[4096]; - struct - { - float cbrt[0x10000], xyz_cam[3][4]; - }ahd_data; - void init() - { - getbits.bitbuf = 0; getbits.vbits = getbits.reset = 0; - ph1_bits.bitbuf = 0; ph1_bits.vbits = 0; - pana_bits.vbits = 0; - ahd_data.cbrt[0]=-2.0f; - } + struct + { + unsigned bitbuf; + int vbits, reset; + } getbits; + struct + { + UINT64 bitbuf; + int vbits; + + } ph1_bits; + struct + { + unsigned pad[128], p; + } sony_decrypt; + struct + { + uchar buf[0x4002]; + int vpos, padding; + } pana_data; + uchar jpeg_buffer[4096]; + struct + { + float cbrt[0x10000], xyz_cam[3][4]; + } ahd_data; + void init() + { + getbits.bitbuf = 0; + getbits.vbits = getbits.reset = 0; + ph1_bits.bitbuf = 0; + ph1_bits.vbits = 0; + pana_data.vpos = 0; + ahd_data.cbrt[0] = -2.0f; + } }; - class LibRaw_constants { - public: - static const float d65_white[3]; - static const double xyz_rgb[3][3]; +public: + static const float d65_white[3]; + static const double xyz_rgb[3][3]; }; #endif /* __cplusplus */ - typedef struct { #ifndef __cplusplus - struct + struct #endif - LibRaw_abstract_datastream *input; - FILE *output; - int input_internal; - char *meta_data; - INT64 profile_offset; - INT64 toffset; - unsigned pana_black[4]; + LibRaw_abstract_datastream *input; + FILE *output; + int input_internal; + char *meta_data; + INT64 profile_offset; + INT64 toffset; + unsigned pana_black[4]; } internal_data_t; - #define LIBRAW_HISTOGRAM_SIZE 0x2000 typedef struct { - int (*histogram)[LIBRAW_HISTOGRAM_SIZE]; - unsigned *oprof; + int (*histogram)[LIBRAW_HISTOGRAM_SIZE]; + unsigned *oprof; } output_data_t; typedef struct { - unsigned olympus_exif_cfa; - unsigned unique_id; - unsigned tiff_nifds; - int tiff_flip; -}identify_data_t; + unsigned olympus_exif_cfa; + unsigned unique_id; + unsigned long long OlyID; + unsigned tiff_nifds; + int tiff_flip; +} identify_data_t; typedef struct { - short order; - ushort sraw_mul[4],cr2_slice[3]; - unsigned kodak_cbpp; - INT64 strip_offset, data_offset; - INT64 meta_offset; - unsigned data_size; - unsigned meta_length; - unsigned thumb_misc; - unsigned fuji_layout; - unsigned tiff_samples; - unsigned tiff_bps; - unsigned tiff_compress; - unsigned zero_after_ff; - unsigned tile_width, tile_length,load_flags; - unsigned data_error; - int hasselblad_parser_flag; + short order; + ushort sraw_mul[4], cr2_slice[3]; + unsigned kodak_cbpp; + INT64 strip_offset, data_offset; + INT64 meta_offset; + unsigned data_size; + unsigned meta_length; + unsigned thumb_misc; + unsigned fuji_layout; + unsigned tiff_samples; + unsigned tiff_bps; + unsigned tiff_compress; + unsigned zero_after_ff; + unsigned tile_width, tile_length, load_flags; + unsigned data_error; + int hasselblad_parser_flag; long long posRAFData; unsigned lenRAFData; - int fuji_total_lines, fuji_total_blocks, fuji_block_width, fuji_bits; -}unpacker_data_t; + int fuji_total_lines, fuji_total_blocks, fuji_block_width, fuji_bits, fuji_raw_type; + int pana_encoding, pana_bpp; +} unpacker_data_t; typedef struct { - internal_data_t internal_data; - libraw_internal_output_params_t internal_output_params; - output_data_t output_data; - identify_data_t identify_data; - unpacker_data_t unpacker_data; + internal_data_t internal_data; + libraw_internal_output_params_t internal_output_params; + output_data_t output_data; + identify_data_t identify_data; + unpacker_data_t unpacker_data; } libraw_internal_data_t; - struct decode { - struct decode *branch[2]; - int leaf; + struct decode *branch[2]; + int leaf; }; -struct tiff_ifd_t { +struct tiff_ifd_t +{ int t_width, t_height, bps, comp, phint, offset, t_flip, samples, bytes; - int t_tile_width, t_tile_length,sample_format,predictor; + int t_tile_width, t_tile_length, sample_format, predictor; int rows_per_strip; - int *strip_offsets,strip_offsets_count; - int *strip_byte_counts,strip_byte_counts_count; + int *strip_offsets, strip_offsets_count; + int *strip_byte_counts, strip_byte_counts_count; float t_shutter; + /* Per-IFD DNG fields */ + INT64 opcode2_offset; + INT64 lineartable_offset; + int lineartable_len; + libraw_dng_color_t dng_color[2]; + libraw_dng_levels_t dng_levels; }; -struct jhead { +struct jhead +{ int algo, bits, high, wide, clrs, sraw, psv, restart, vpred[6]; ushort quant[64], idct[64], *huff[20], *free[20], *row; }; -struct tiff_tag { +struct libraw_tiff_tag +{ ushort tag, type; int count; - union { char c[4]; short s[2]; int i; } val; + union { + char c[4]; + short s[2]; + int i; + } val; }; -struct tiff_hdr { +struct tiff_hdr +{ ushort t_order, magic; int ifd; ushort pad, ntag; - struct tiff_tag tag[23]; + struct libraw_tiff_tag tag[23]; int nextifd; ushort pad2, nexif; - struct tiff_tag exif[4]; + struct libraw_tiff_tag exif[4]; ushort pad3, ngps; - struct tiff_tag gpst[10]; + struct libraw_tiff_tag gpst[10]; short bps[4]; int rat[10]; unsigned gps[26]; char t_desc[512], t_make[64], t_model[64], soft[32], date[20], t_artist[64]; }; - - #ifdef DEBUG_STAGE_CHECKS -#define CHECK_ORDER_HIGH(expected_stage) \ - do { if((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) >= expected_stage) {fprintf(stderr,"CHECK_HIGH: check %d >= %d\n",imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK,expected_stage);return LIBRAW_OUT_OF_ORDER_CALL;} } while(0) - -#define CHECK_ORDER_LOW(expected_stage) \ - do { printf("Checking LOW %d/%d : %d\n",imgdata.progress_flags,expected_stage,imgdata.progress_flags= expected_stage) \ + { \ + fprintf(stderr, "CHECK_HIGH: check %d >= %d\n", imgdata.progress_flags &LIBRAW_PROGRESS_THUMB_MASK, \ + expected_stage); \ + return LIBRAW_OUT_OF_ORDER_CALL; \ + } \ + } while (0) + +#define CHECK_ORDER_LOW(expected_stage) \ + do \ + { \ + printf("Checking LOW %d/%d : %d\n", imgdata.progress_flags, expected_stage, \ + imgdata.progress_flags < expected_stage); \ + if ((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) < expected_stage) \ + { \ + printf("failed!\n"); \ + return LIBRAW_OUT_OF_ORDER_CALL; \ + } \ + } while (0) +#define CHECK_ORDER_BIT(expected_stage) \ + do \ + { \ + if (imgdata.progress_flags & expected_stage) \ + return LIBRAW_OUT_OF_ORDER_CALL; \ + } while (0) + +#define SET_PROC_FLAG(stage) \ + do \ + { \ + imgdata.progress_flags |= stage; \ + fprintf(stderr, "SET_FLAG: %d\n", stage); \ + } while (0) #else -#define CHECK_ORDER_HIGH(expected_stage) \ - do { if((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) >= expected_stage) \ - {return LIBRAW_OUT_OF_ORDER_CALL;} } while(0) - -#define CHECK_ORDER_LOW(expected_stage) \ - do { if((imgdata.progress_flags&LIBRAW_PROGRESS_THUMB_MASK) < expected_stage) \ - return LIBRAW_OUT_OF_ORDER_CALL; } while(0) - -#define CHECK_ORDER_BIT(expected_stage) \ - do { if(imgdata.progress_flags & expected_stage) return LIBRAW_OUT_OF_ORDER_CALL; } while(0) - -#define SET_PROC_FLAG(stage) do {imgdata.progress_flags |= stage;} while (0) +#define CHECK_ORDER_HIGH(expected_stage) \ + do \ + { \ + if ((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) >= expected_stage) \ + { \ + return LIBRAW_OUT_OF_ORDER_CALL; \ + } \ + } while (0) + +#define CHECK_ORDER_LOW(expected_stage) \ + do \ + { \ + if ((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) < expected_stage) \ + return LIBRAW_OUT_OF_ORDER_CALL; \ + } while (0) + +#define CHECK_ORDER_BIT(expected_stage) \ + do \ + { \ + if (imgdata.progress_flags & expected_stage) \ + return LIBRAW_OUT_OF_ORDER_CALL; \ + } while (0) + +#define SET_PROC_FLAG(stage) \ + do \ + { \ + imgdata.progress_flags |= stage; \ + } while (0) #endif #endif diff --git a/core/libs/rawengine/libraw/libraw/libraw_types.h b/core/libs/rawengine/libraw/libraw/libraw_types.h index 0a5989cf7c..230c877866 100644 --- a/core/libs/rawengine/libraw/libraw/libraw_types.h +++ b/core/libs/rawengine/libraw/libraw/libraw_types.h @@ -1,716 +1,790 @@ /* -*- C++ -*- * File: libraw_types.h - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) * Created: Sat Mar 8 , 2008 * * LibRaw C data structures * LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #ifndef _LIBRAW_TYPES_H #define _LIBRAW_TYPES_H #include #ifndef WIN32 #include #endif #include #if defined(_WIN32) -#if defined (_MSC_VER) && (_MSC_VER <=1500) -typedef signed __int8 int8_t; -typedef unsigned __int8 uint8_t; -typedef signed __int16 int16_t; -typedef unsigned __int16 uint16_t; -typedef signed __int32 int32_t; -typedef unsigned __int32 uint32_t; -typedef signed __int64 int64_t; -typedef unsigned __int64 uint64_t; +#if defined(_MSC_VER) && (_MSC_VER <= 1500) +typedef signed __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef signed __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef signed __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; #else #include -#endif // _WIN32 +#endif /* _WIN32 */ #include #else #include #endif -#if defined (_OPENMP) +#if defined(_OPENMP) #if defined(WIN32) -# if defined (_MSC_VER) && (_MSC_VER >= 1600 || (_MSC_VER == 1500 && _MSC_FULL_VER >= 150030729) ) +#if defined(_MSC_VER) && (_MSC_VER >= 1600 || (_MSC_VER == 1500 && _MSC_FULL_VER >= 150030729)) /* VS2010+ : OpenMP works OK, VS2008: have tested by cgilles */ -# define LIBRAW_USE_OPENMP -#elif defined (__INTEL_COMPILER) && (__INTEL_COMPILER >=910) +#define LIBRAW_USE_OPENMP +#elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 910) /* Have not tested on 9.x and 10.x, but Intel documentation claims OpenMP 2.5 support in 9.1 */ -# define LIBRAW_USE_OPENMP +#define LIBRAW_USE_OPENMP #else -# undef LIBRAW_USE_OPENMP +#undef LIBRAW_USE_OPENMP #endif /* Not Win32 */ -# elif (defined(__APPLE__) || defined(__MACOSX__)) && defined(_REENTRANT) -# undef LIBRAW_USE_OPENMP -# else -# define LIBRAW_USE_OPENMP -# endif +#elif (defined(__APPLE__) || defined(__MACOSX__)) && defined(_REENTRANT) +#undef LIBRAW_USE_OPENMP +#else +#define LIBRAW_USE_OPENMP +#endif #endif #ifdef LIBRAW_USE_OPENMP #include #endif - #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif #if defined(USE_LCMS) #include #elif defined(USE_LCMS2) #include #else #define NO_LCMS #endif #include "libraw_const.h" #include "libraw_version.h" #ifdef WIN32 -typedef __int64 INT64; -typedef unsigned __int64 UINT64; + typedef __int64 INT64; + typedef unsigned __int64 UINT64; #else typedef long long INT64; typedef unsigned long long UINT64; #endif -typedef unsigned char uchar; -typedef unsigned short ushort; + typedef unsigned char uchar; + typedef unsigned short ushort; #ifdef WIN32 #ifdef LIBRAW_NODLL -# define DllDef +#define DllDef #else -# ifdef LIBRAW_BUILDLIB -# define DllDef __declspec( dllexport ) -# else -# define DllDef __declspec( dllimport ) -# endif +#ifdef LIBRAW_BUILDLIB +#define DllDef __declspec(dllexport) +#else +#define DllDef __declspec(dllimport) +#endif #endif #else -# define DllDef +#define DllDef #endif -typedef struct -{ - const char *decoder_name; - unsigned decoder_flags; -}libraw_decoder_info_t; - -typedef struct -{ - unsigned mix_green; - unsigned raw_color; - unsigned zero_is_bad; - ushort shrink; - ushort fuji_width; -} libraw_internal_output_params_t; + typedef struct + { + const char *decoder_name; + unsigned decoder_flags; + } libraw_decoder_info_t; + typedef struct + { + unsigned mix_green; + unsigned raw_color; + unsigned zero_is_bad; + ushort shrink; + ushort fuji_width; + } libraw_internal_output_params_t; -typedef void (* memory_callback)(void * data, const char *file, const char *where); -typedef void (*exif_parser_callback) (void *context, int tag, int type, int len,unsigned int ord, void *ifp); + typedef void (*memory_callback)(void *data, const char *file, const char *where); + typedef void (*exif_parser_callback)(void *context, int tag, int type, int len, unsigned int ord, void *ifp); -DllDef void default_memory_callback(void *data,const char *file, const char *where); + DllDef void default_memory_callback(void *data, const char *file, const char *where); -typedef void (*data_callback)(void *data,const char *file, const int offset); + typedef void (*data_callback)(void *data, const char *file, const int offset); -DllDef void default_data_callback(void *data,const char *file, const int offset); + DllDef void default_data_callback(void *data, const char *file, const int offset); -typedef int (* progress_callback) (void *data,enum LibRaw_progress stage, int iteration,int expected); + typedef int (*progress_callback)(void *data, enum LibRaw_progress stage, int iteration, int expected); + typedef int (*pre_identify_callback)(void *ctx); + typedef void (*post_identify_callback)(void *ctx); + typedef void (*process_step_callback)(void *ctx); -typedef struct -{ + typedef struct + { memory_callback mem_cb; - void* memcb_data; + void *memcb_data; data_callback data_cb; - void* datacb_data; + void *datacb_data; progress_callback progress_cb; void *progresscb_data; - exif_parser_callback exif_cb; - void *exifparser_data; -} libraw_callbacks_t; - - -typedef struct -{ + exif_parser_callback exif_cb; + void *exifparser_data; + pre_identify_callback pre_identify_cb; + post_identify_callback post_identify_cb; + process_step_callback pre_subtractblack_cb, pre_scalecolors_cb, pre_preinterpolate_cb, pre_interpolate_cb, + interpolate_bayer_cb, interpolate_xtrans_cb, + post_interpolate_cb, pre_converttorgb_cb, post_converttorgb_cb; + } libraw_callbacks_t; + + typedef struct + { enum LibRaw_image_formats type; - ushort height, - width, - colors, - bits; - unsigned int data_size; + ushort height, width, colors, bits; + unsigned int data_size; unsigned char data[1]; -}libraw_processed_image_t; - - -typedef struct -{ - char guard[4]; - char make[64]; - char model[64]; - char software[64]; - unsigned raw_count; - unsigned dng_version; - unsigned is_foveon; - int colors; - unsigned filters; - char xtrans[6][6]; - char xtrans_abs[6][6]; - char cdesc[5]; - unsigned xmplen; - char *xmpdata; - -}libraw_iparams_t; - -typedef struct -{ - ushort raw_height, - raw_width, - height, - width, - top_margin, - left_margin; - ushort iheight, - iwidth; - unsigned raw_pitch; - double pixel_aspect; - int flip; - int mask[8][4]; -} libraw_image_sizes_t; - -struct ph1_t -{ - int format, key_off, tag_21a; - int t_black, split_col, black_col, split_row, black_row; - float tag_210; -}; - -typedef struct -{ - ushort illuminant; - float calibration[4][4]; - float colormatrix[4][3]; - float forwardmatrix[3][4]; -} libraw_dng_color_t; - -typedef struct -{ - - unsigned dng_cblack[4102]; - unsigned dng_black; - unsigned dng_whitelevel[4]; - float dng_blacklevel[4]; - float analogbalance[4]; -} libraw_dng_levels_t; - -typedef struct -{ - float romm_cam[9]; -} libraw_P1_color_t; - -typedef struct -{ - int CanonColorDataVer; - int CanonColorDataSubVer; - int SpecularWhiteLevel; - int ChannelBlackLevel[4]; - int AverageBlackLevel; -/* metering */ - short MeteringMode; - short SpotMeteringMode; - uchar FlashMeteringMode; - short FlashExposureLock; - short ExposureMode; - short AESetting; - uchar HighlightTonePriority; -/* stabilization */ - short ImageStabilization; -/* focus */ - short FocusMode; - short AFPoint; - short FocusContinuous; - short AFPointsInFocus30D; - uchar AFPointsInFocus1D[8]; - ushort AFPointsInFocus5D; /* bytes in reverse*/ -/* AFInfo */ - ushort AFAreaMode; - ushort NumAFPoints; - ushort ValidAFPoints; - ushort AFImageWidth; - ushort AFImageHeight; - short AFAreaWidths[61]; /* cycle to NumAFPoints */ - short AFAreaHeights[61]; /* --''-- */ - short AFAreaXPositions[61]; /* --''-- */ - short AFAreaYPositions[61]; /* --''-- */ - short AFPointsInFocus[4]; /* cycle to floor((NumAFPoints+15)/16) */ - short AFPointsSelected[4]; /* --''-- */ - ushort PrimaryAFPoint; -/* flash */ - short FlashMode; - short FlashActivity; - short FlashBits; - short ManualFlashOutput; - short FlashOutput; - short FlashGuideNumber; -/* drive */ - short ContinuousDrive; -/* sensor */ - short SensorWidth; - short SensorHeight; - short SensorLeftBorder; - short SensorTopBorder; - short SensorRightBorder; - short SensorBottomBorder; - short BlackMaskLeftBorder; - short BlackMaskTopBorder; - short BlackMaskRightBorder; - short BlackMaskBottomBorder; - -} libraw_canon_makernotes_t; - -typedef struct -{ - float FujiExpoMidPointShift; - ushort FujiDynamicRange; - ushort FujiFilmMode; - ushort FujiDynamicRangeSetting; - ushort FujiDevelopmentDynamicRange; - ushort FujiAutoDynamicRange; - ushort FocusMode; - ushort AFMode; - ushort FocusPixel[2]; - ushort ImageStabilization[3]; - ushort FlashMode; - ushort WB_Preset; - ushort ShutterType; - ushort ExrMode; - ushort Macro; - unsigned Rating; - ushort FrameRate; - ushort FrameWidth; - ushort FrameHeight; -} libraw_fuji_info_t; - -typedef struct -{ - - double ExposureBracketValue; - ushort ActiveDLighting; - ushort ShootingMode; -/* stabilization */ - uchar ImageStabilization[7]; - uchar VibrationReduction; - uchar VRMode; -/* focus */ - char FocusMode[7]; - uchar AFPoint; - ushort AFPointsInFocus; - uchar ContrastDetectAF; - uchar AFAreaMode; - uchar PhaseDetectAF; - uchar PrimaryAFPoint; - uchar AFPointsUsed[29]; - ushort AFImageWidth; - ushort AFImageHeight; - ushort AFAreaXPposition; - ushort AFAreaYPosition; - ushort AFAreaWidth; - ushort AFAreaHeight; - uchar ContrastDetectAFInFocus; -/* flash */ - char FlashSetting[13]; - char FlashType[20]; - uchar FlashExposureCompensation[4]; - uchar ExternalFlashExposureComp[4]; - uchar FlashExposureBracketValue[4]; - uchar FlashMode; - signed char FlashExposureCompensation2; - signed char FlashExposureCompensation3; - signed char FlashExposureCompensation4; - uchar FlashSource; - uchar FlashFirmware[2]; - uchar ExternalFlashFlags; - uchar FlashControlCommanderMode; - uchar FlashOutputAndCompensation; - uchar FlashFocalLength; - uchar FlashGNDistance; - uchar FlashGroupControlMode[4]; - uchar FlashGroupOutputAndCompensation[4]; - uchar FlashColorFilter; -} libraw_nikon_makernotes_t; - -typedef struct -{ - int OlympusCropID; - ushort OlympusFrame[4]; /* upper left XY, lower right XY */ - int OlympusSensorCalibration[2]; - ushort FocusMode[2]; - ushort AutoFocus; - ushort AFPoint; - unsigned AFAreas[64]; - double AFPointSelected[5]; - ushort AFResult; - unsigned ImageStabilization; - ushort ColorSpace; -} libraw_olympus_makernotes_t; - -typedef struct -{ - ushort FocusMode; - uchar AFPointMode; - ushort AFPointSelected[2]; - unsigned AFPointsInFocus; - uchar DriveMode[4]; - uchar SRResult; - uchar ShakeReduction; -} libraw_pentax_makernotes_t; - -typedef struct -{ - ushort SonyCameraType; -} libraw_sony_info_t; - -typedef struct -{ - ushort curve[0x10000]; - unsigned cblack[4102]; - unsigned black; - unsigned data_maximum; - unsigned maximum; - long linear_max[4]; - float fmaximum; - float fnorm; - ushort white[8][8]; - float cam_mul[4]; - float pre_mul[4]; - float cmatrix[3][4]; - float ccm[3][4]; - float rgb_cam[3][4]; - float cam_xyz[4][3]; - struct ph1_t phase_one_data; - float flash_used; - float canon_ev; - char model2[64]; - char UniqueCameraModel[64]; - char LocalizedCameraModel[64]; - void *profile; - unsigned profile_length; - unsigned black_stat[8]; - libraw_dng_color_t dng_color[2]; - libraw_dng_levels_t dng_levels; - float baseline_exposure; - int WB_Coeffs[256][4]; /* R, G1, B, G2 coeffs */ - float WBCT_Coeffs[64][5]; /* CCT, than R, G1, B, G2 coeffs */ - libraw_P1_color_t P1_color[2]; -} libraw_colordata_t; - -typedef struct -{ - enum LibRaw_thumbnail_formats tformat; - ushort twidth, - theight; - unsigned tlength; - int tcolors; - char *thumb; -}libraw_thumbnail_t; - -typedef struct -{ - float latitude[3]; /* Deg,min,sec */ - float longtitude[3]; /* Deg,min,sec */ - float gpstimestamp[3]; /* Deg,min,sec */ - float altitude; - char altref, latref, longref, gpsstatus; - char gpsparsed; -} libraw_gps_info_t; - -typedef struct -{ - float iso_speed; - float shutter; - float aperture; - float focal_len; - time_t timestamp; - unsigned shot_order; - unsigned gpsdata[32]; - libraw_gps_info_t parsed_gps; - char desc[512], - artist[64]; - float FlashEC; -} libraw_imgother_t; - -typedef struct -{ - unsigned greybox[4]; /* -A x1 y1 x2 y2 */ - unsigned cropbox[4]; /* -B x1 y1 x2 y2 */ - double aber[4]; /* -C */ - double gamm[6]; /* -g */ - float user_mul[4]; /* -r mul0 mul1 mul2 mul3 */ - unsigned shot_select; /* -s */ - float bright; /* -b */ - float threshold; /* -n */ - int half_size; /* -h */ - int four_color_rgb; /* -f */ - int highlight; /* -H */ - int use_auto_wb; /* -a */ - int use_camera_wb; /* -w */ - int use_camera_matrix; /* +M/-M */ - int output_color; /* -o */ - char *output_profile; /* -o */ - char *camera_profile; /* -p */ - char *bad_pixels; /* -P */ - char *dark_frame; /* -K */ - int output_bps; /* -4 */ - int output_tiff; /* -T */ - int user_flip; /* -t */ - int user_qual; /* -q */ - int user_black; /* -k */ - int user_cblack[4]; - int user_sat; /* -S */ - - int med_passes; /* -m */ - float auto_bright_thr; - float adjust_maximum_thr; - int no_auto_bright; /* -W */ - int use_fuji_rotate;/* -j */ - int green_matching; - /* DCB parameters */ - int dcb_iterations; - int dcb_enhance_fl; - int fbdd_noiserd; - /* VCD parameters */ - int eeci_refine; - int es_med_passes; - /* AMaZE*/ - int ca_correc; - float cared; - float cablue; - int cfaline; - float linenoise; - int cfa_clean; - float lclean; - float cclean; - int cfa_green; - float green_thresh; - int exp_correc; - float exp_shift; - float exp_preser; - /* WF debanding */ - int wf_debanding; - float wf_deband_treshold[4]; - /* Raw speed */ - int use_rawspeed; - /* DNG SDK */ - int use_dngsdk; - /* Disable Auto-scale */ - int no_auto_scale; - /* Disable intepolation */ - int no_interpolation; - /* int x3f_flags; */ - /* Sony ARW2 digging mode */ - /* int sony_arw2_options; */ - unsigned raw_processing_options; - int sony_arw2_posterization_thr; - /* Nikon Coolscan */ - float coolscan_nef_gamma; - char p4shot_order[5]; - /* Custom camera list */ - char **custom_camera_strings; -}libraw_output_params_t; - -typedef struct -{ + } libraw_processed_image_t; + + typedef struct + { + char guard[4]; + char make[64]; + char model[64]; + char software[64]; + unsigned raw_count; + unsigned dng_version; + unsigned is_foveon; + int colors; + unsigned filters; + char xtrans[6][6]; + char xtrans_abs[6][6]; + char cdesc[5]; + unsigned xmplen; + char *xmpdata; + + } libraw_iparams_t; + + typedef struct + { + ushort cleft, ctop, cwidth, cheight; + } libraw_raw_crop_t; + + typedef struct + { + ushort raw_height, raw_width, height, width, top_margin, left_margin; + ushort iheight, iwidth; + unsigned raw_pitch; + double pixel_aspect; + int flip; + int mask[8][4]; + libraw_raw_crop_t raw_crop; + } libraw_image_sizes_t; + + struct ph1_t + { + int format, key_off, tag_21a; + int t_black, split_col, black_col, split_row, black_row; + float tag_210; + }; + + typedef struct + { + unsigned parsedfields; + ushort illuminant; + float calibration[4][4]; + float colormatrix[4][3]; + float forwardmatrix[3][4]; + } libraw_dng_color_t; + + typedef struct + { + unsigned parsedfields; + unsigned dng_cblack[4102]; + unsigned dng_black; + unsigned dng_whitelevel[4]; + unsigned default_crop[4]; /* Origin and size */ + unsigned preview_colorspace; + float analogbalance[4]; + } libraw_dng_levels_t; + + typedef struct + { + float romm_cam[9]; + } libraw_P1_color_t; + + typedef struct + { + int CanonColorDataVer; + int CanonColorDataSubVer; + int SpecularWhiteLevel; + int NormalWhiteLevel; + int ChannelBlackLevel[4]; + int AverageBlackLevel; + /* multishot */ + unsigned int multishot[4]; + /* metering */ + short MeteringMode; + short SpotMeteringMode; + uchar FlashMeteringMode; + short FlashExposureLock; + short ExposureMode; + short AESetting; + uchar HighlightTonePriority; + /* stabilization */ + short ImageStabilization; + /* focus */ + short FocusMode; + short AFPoint; + short FocusContinuous; + short AFPointsInFocus30D; + uchar AFPointsInFocus1D[8]; + ushort AFPointsInFocus5D; /* bytes in reverse*/ + /* AFInfo */ + ushort AFAreaMode; + ushort NumAFPoints; + ushort ValidAFPoints; + ushort AFImageWidth; + ushort AFImageHeight; + short AFAreaWidths[61]; /* cycle to NumAFPoints */ + short AFAreaHeights[61]; /* --''-- */ + short AFAreaXPositions[61]; /* --''-- */ + short AFAreaYPositions[61]; /* --''-- */ + short AFPointsInFocus[4]; /* cycle to floor((NumAFPoints+15)/16) */ + short AFPointsSelected[4]; /* --''-- */ + ushort PrimaryAFPoint; + /* flash */ + short FlashMode; + short FlashActivity; + short FlashBits; + short ManualFlashOutput; + short FlashOutput; + short FlashGuideNumber; + /* drive */ + short ContinuousDrive; + /* sensor */ + short SensorWidth; + short SensorHeight; + short SensorLeftBorder; + short SensorTopBorder; + short SensorRightBorder; + short SensorBottomBorder; + short BlackMaskLeftBorder; + short BlackMaskTopBorder; + short BlackMaskRightBorder; + short BlackMaskBottomBorder; + int AFMicroAdjMode; + float AFMicroAdjValue; + + } libraw_canon_makernotes_t; + + typedef struct + { + int BaseISO; + double Gain; + } libraw_hasselblad_makernotes_t; + + typedef struct + { + float FujiExpoMidPointShift; + ushort FujiDynamicRange; + ushort FujiFilmMode; + ushort FujiDynamicRangeSetting; + ushort FujiDevelopmentDynamicRange; + ushort FujiAutoDynamicRange; + ushort FocusMode; + ushort AFMode; + ushort FocusPixel[2]; + ushort ImageStabilization[3]; + ushort FlashMode; + ushort WB_Preset; + ushort ShutterType; + ushort ExrMode; + ushort Macro; + unsigned Rating; + ushort FrameRate; + ushort FrameWidth; + ushort FrameHeight; + } libraw_fuji_info_t; + + typedef struct + { + + double ExposureBracketValue; + ushort ActiveDLighting; + ushort ShootingMode; + /* stabilization */ + uchar ImageStabilization[7]; + uchar VibrationReduction; + uchar VRMode; + /* focus */ + char FocusMode[7]; + uchar AFPoint; + ushort AFPointsInFocus; + uchar ContrastDetectAF; + uchar AFAreaMode; + uchar PhaseDetectAF; + uchar PrimaryAFPoint; + uchar AFPointsUsed[29]; + ushort AFImageWidth; + ushort AFImageHeight; + ushort AFAreaXPposition; + ushort AFAreaYPosition; + ushort AFAreaWidth; + ushort AFAreaHeight; + uchar ContrastDetectAFInFocus; + /* flash */ + char FlashSetting[13]; + char FlashType[20]; + uchar FlashExposureCompensation[4]; + uchar ExternalFlashExposureComp[4]; + uchar FlashExposureBracketValue[4]; + uchar FlashMode; + signed char FlashExposureCompensation2; + signed char FlashExposureCompensation3; + signed char FlashExposureCompensation4; + uchar FlashSource; + uchar FlashFirmware[2]; + uchar ExternalFlashFlags; + uchar FlashControlCommanderMode; + uchar FlashOutputAndCompensation; + uchar FlashFocalLength; + uchar FlashGNDistance; + uchar FlashGroupControlMode[4]; + uchar FlashGroupOutputAndCompensation[4]; + uchar FlashColorFilter; + ushort NEFCompression; + int ExposureMode; + int nMEshots; + int MEgainOn; + double ME_WB[4]; + uchar AFFineTune; + uchar AFFineTuneIndex; + int8_t AFFineTuneAdj; + } libraw_nikon_makernotes_t; + + typedef struct + { + int OlympusCropID; + ushort OlympusFrame[4]; /* upper left XY, lower right XY */ + int OlympusSensorCalibration[2]; + ushort FocusMode[2]; + ushort AutoFocus; + ushort AFPoint; + unsigned AFAreas[64]; + double AFPointSelected[5]; + ushort AFResult; + unsigned ImageStabilization; + ushort ColorSpace; + uchar AFFineTune; + short AFFineTuneAdj[3]; + } libraw_olympus_makernotes_t; + + typedef struct + { +/* Compression: + 34826 (Panasonic RAW 2): LEICA DIGILUX 2; + 34828 (Panasonic RAW 3): LEICA D-LUX 3; LEICA V-LUX 1; Panasonic DMC-LX1; Panasonic DMC-LX2; Panasonic DMC-FZ30; Panasonic DMC-FZ50; + 34830 (not in exiftool): LEICA DIGILUX 3; Panasonic DMC-L1; + 34316 (Panasonic RAW 1): others (LEICA, Panasonic, YUNEEC); +*/ + ushort Compression; + ushort BlackLevelDim; + float BlackLevel[8]; + } libraw_panasonic_makernotes_t; + + typedef struct + { + ushort FocusMode; + ushort AFPointSelected; + unsigned AFPointsInFocus; + ushort FocusPosition; + uchar DriveMode[4]; + short AFAdjustment; + /* uchar AFPointMode; */ + /* uchar SRResult; */ + /* uchar ShakeReduction; */ + } libraw_pentax_makernotes_t; + + typedef struct + { + ushort BlackLevelTop; + ushort BlackLevelBottom; + short offset_left, offset_top; /* KDC files, negative values or zeros */ + ushort clipBlack, clipWhite; /* valid for P712, P850, P880 */ + float romm_camDaylight[3][3]; + float romm_camTungsten[3][3]; + float romm_camFluorescent[3][3]; + float romm_camFlash[3][3]; + float romm_camCustom[3][3]; + float romm_camAuto[3][3]; + } libraw_kodak_makernotes_t; + + typedef struct + { + ushort SonyCameraType; + uchar Sony0x9400_version; /* 0 if not found/deciphered, 0xa, 0xb, 0xc following exiftool convention */ + uchar Sony0x9400_ReleaseMode2; + unsigned Sony0x9400_SequenceImageNumber; + uchar Sony0x9400_SequenceLength1; + unsigned Sony0x9400_SequenceFileNumber; + uchar Sony0x9400_SequenceLength2; + libraw_raw_crop_t raw_crop; + int8_t AFMicroAdjValue; + int8_t AFMicroAdjOn; + uchar AFMicroAdjRegisteredLenses; + ushort group2010; + ushort real_iso_offset; + float firmware; + ushort ImageCount3_offset; + unsigned ImageCount3; + unsigned ElectronicFrontCurtainShutter; + ushort MeteringMode2; + char SonyDateTime[20]; + uchar TimeStamp[6]; + unsigned ShotNumberSincePowerUp; + } libraw_sony_info_t; + + typedef struct + { + ushort curve[0x10000]; + unsigned cblack[4102]; + unsigned black; + unsigned data_maximum; + unsigned maximum; + long linear_max[4]; + float fmaximum; + float fnorm; + ushort white[8][8]; + float cam_mul[4]; + float pre_mul[4]; + float cmatrix[3][4]; + float ccm[3][4]; + float rgb_cam[3][4]; + float cam_xyz[4][3]; + struct ph1_t phase_one_data; + float flash_used; + float canon_ev; + char model2[64]; + char UniqueCameraModel[64]; + char LocalizedCameraModel[64]; + void *profile; + unsigned profile_length; + unsigned black_stat[8]; + libraw_dng_color_t dng_color[2]; + libraw_dng_levels_t dng_levels; + float baseline_exposure; + int WB_Coeffs[256][4]; /* R, G1, B, G2 coeffs */ + float WBCT_Coeffs[64][5]; /* CCT, than R, G1, B, G2 coeffs */ + libraw_P1_color_t P1_color[2]; + } libraw_colordata_t; + + typedef struct + { + enum LibRaw_thumbnail_formats tformat; + ushort twidth, theight; + unsigned tlength; + int tcolors; + char *thumb; + } libraw_thumbnail_t; + + typedef struct + { + float latitude[3]; /* Deg,min,sec */ + float longtitude[3]; /* Deg,min,sec */ + float gpstimestamp[3]; /* Deg,min,sec */ + float altitude; + char altref, latref, longref, gpsstatus; + char gpsparsed; + } libraw_gps_info_t; + + typedef struct + { + float iso_speed; + float shutter; + float aperture; + float focal_len; + time_t timestamp; + unsigned shot_order; + unsigned gpsdata[32]; + libraw_gps_info_t parsed_gps; + char desc[512], artist[64]; + float FlashEC; + float FlashGN; + float CameraTemperature; + float SensorTemperature; + float SensorTemperature2; + float LensTemperature; + float AmbientTemperature; + float BatteryTemperature; + float exifAmbientTemperature; + float exifHumidity; + float exifPressure; + float exifWaterDepth; + float exifAcceleration; + float exifCameraElevationAngle; + float real_ISO; + } libraw_imgother_t; + + typedef struct + { + unsigned greybox[4]; /* -A x1 y1 x2 y2 */ + unsigned cropbox[4]; /* -B x1 y1 x2 y2 */ + double aber[4]; /* -C */ + double gamm[6]; /* -g */ + float user_mul[4]; /* -r mul0 mul1 mul2 mul3 */ + unsigned shot_select; /* -s */ + float bright; /* -b */ + float threshold; /* -n */ + int half_size; /* -h */ + int four_color_rgb; /* -f */ + int highlight; /* -H */ + int use_auto_wb; /* -a */ + int use_camera_wb; /* -w */ + int use_camera_matrix; /* +M/-M */ + int output_color; /* -o */ + char *output_profile; /* -o */ + char *camera_profile; /* -p */ + char *bad_pixels; /* -P */ + char *dark_frame; /* -K */ + int output_bps; /* -4 */ + int output_tiff; /* -T */ + int user_flip; /* -t */ + int user_qual; /* -q */ + int user_black; /* -k */ + int user_cblack[4]; + int user_sat; /* -S */ + + int med_passes; /* -m */ + float auto_bright_thr; + float adjust_maximum_thr; + int no_auto_bright; /* -W */ + int use_fuji_rotate; /* -j */ + int green_matching; + /* DCB parameters */ + int dcb_iterations; + int dcb_enhance_fl; + int fbdd_noiserd; + int exp_correc; + float exp_shift; + float exp_preser; + /* Raw speed */ + int use_rawspeed; + /* DNG SDK */ + int use_dngsdk; + /* Disable Auto-scale */ + int no_auto_scale; + /* Disable intepolation */ + int no_interpolation; + /* int x3f_flags; */ + /* Sony ARW2 digging mode */ + /* int sony_arw2_options; */ + unsigned raw_processing_options; + int sony_arw2_posterization_thr; + /* Nikon Coolscan */ + float coolscan_nef_gamma; + char p4shot_order[5]; + /* Custom camera list */ + char **custom_camera_strings; + } libraw_output_params_t; + + typedef struct + { /* really allocated bitmap */ - void *raw_alloc; - /* alias to single_channel variant */ - ushort *raw_image; - /* alias to 4-channel variant */ - ushort (*color4_image)[4] ; - /* alias to 3-color variand decoded by RawSpeed */ - ushort (*color3_image)[3]; - /* float bayer */ - float *float_image; - /* float 3-component */ - float (*float3_image)[3]; - /* float 4-component */ - float (*float4_image)[4]; - - /* Phase One black level data; */ - short (*ph1_cblack)[2]; - short (*ph1_rblack)[2]; - /* save color and sizes here, too.... */ - libraw_iparams_t iparams; - libraw_image_sizes_t sizes; - libraw_internal_output_params_t ioparams; - libraw_colordata_t color; -} libraw_rawdata_t; - -typedef struct -{ - unsigned long long LensID; - char Lens[128]; - ushort LensFormat; /* to characterize the image circle the lens covers */ - ushort LensMount; /* 'male', lens itself */ - unsigned long long CamID; - ushort CameraFormat; /* some of the sensor formats */ - ushort CameraMount; /* 'female', body throat */ - char body[64]; - short FocalType; /* -1/0 is unknown; 1 is fixed focal; 2 is zoom */ - char LensFeatures_pre[16], LensFeatures_suf[16]; - float MinFocal, MaxFocal; - float MaxAp4MinFocal, MaxAp4MaxFocal, MinAp4MinFocal, MinAp4MaxFocal; - float MaxAp, MinAp; - float CurFocal, CurAp; - float MaxAp4CurFocal, MinAp4CurFocal; - float MinFocusDistance; - float FocusRangeIndex; - float LensFStops; - unsigned long long TeleconverterID; - char Teleconverter[128]; - unsigned long long AdapterID; - char Adapter[128]; - unsigned long long AttachmentID; - char Attachment[128]; - ushort CanonFocalUnits; - float FocalLengthIn35mmFormat; -} libraw_makernotes_lens_t; - -typedef struct -{ - float NikonEffectiveMaxAp; - uchar NikonLensIDNumber, NikonLensFStops, NikonMCUVersion, NikonLensType; -} libraw_nikonlens_t; - -typedef struct -{ - float MinFocal, MaxFocal, MaxAp4MinFocal, MaxAp4MaxFocal; -} libraw_dnglens_t; - -typedef struct -{ - float MinFocal, MaxFocal, MaxAp4MinFocal, MaxAp4MaxFocal, EXIF_MaxAp; - char LensMake[128], Lens[128], LensSerial[128], InternalLensSerial[128]; - ushort FocalLengthIn35mmFormat; - libraw_nikonlens_t nikon; - libraw_dnglens_t dng; - libraw_makernotes_lens_t makernotes; -} libraw_lensinfo_t; - -typedef struct -{ - libraw_canon_makernotes_t canon; - libraw_fuji_info_t fuji; - libraw_olympus_makernotes_t olympus; - libraw_sony_info_t sony; -} libraw_makernotes_t; - -typedef struct -{ - short DriveMode; - short FocusMode; - short MeteringMode; - short AFPoint; - short ExposureMode; - short ImageStabilization; - char BodySerial[64]; - char InternalBodySerial[64]; /* this may be PCB or sensor serial, depends on make/model*/ -} libraw_shootinginfo_t; - -typedef struct { + void *raw_alloc; + /* alias to single_channel variant */ + ushort *raw_image; + /* alias to 4-channel variant */ + ushort (*color4_image)[4]; + /* alias to 3-color variand decoded by RawSpeed */ + ushort (*color3_image)[3]; + /* float bayer */ + float *float_image; + /* float 3-component */ + float (*float3_image)[3]; + /* float 4-component */ + float (*float4_image)[4]; + + /* Phase One black level data; */ + short (*ph1_cblack)[2]; + short (*ph1_rblack)[2]; + /* save color and sizes here, too.... */ + libraw_iparams_t iparams; + libraw_image_sizes_t sizes; + libraw_internal_output_params_t ioparams; + libraw_colordata_t color; + } libraw_rawdata_t; + + typedef struct + { + unsigned long long LensID; + char Lens[128]; + ushort LensFormat; /* to characterize the image circle the lens covers */ + ushort LensMount; /* 'male', lens itself */ + unsigned long long CamID; + ushort CameraFormat; /* some of the sensor formats */ + ushort CameraMount; /* 'female', body throat */ + char body[64]; + short FocalType; /* -1/0 is unknown; 1 is fixed focal; 2 is zoom */ + char LensFeatures_pre[16], LensFeatures_suf[16]; + float MinFocal, MaxFocal; + float MaxAp4MinFocal, MaxAp4MaxFocal, MinAp4MinFocal, MinAp4MaxFocal; + float MaxAp, MinAp; + float CurFocal, CurAp; + float MaxAp4CurFocal, MinAp4CurFocal; + float MinFocusDistance; + float FocusRangeIndex; + float LensFStops; + unsigned long long TeleconverterID; + char Teleconverter[128]; + unsigned long long AdapterID; + char Adapter[128]; + unsigned long long AttachmentID; + char Attachment[128]; + ushort CanonFocalUnits; + float FocalLengthIn35mmFormat; + } libraw_makernotes_lens_t; + + typedef struct + { + float NikonEffectiveMaxAp; + uchar NikonLensIDNumber, NikonLensFStops, NikonMCUVersion, NikonLensType; + } libraw_nikonlens_t; + + typedef struct + { + float MinFocal, MaxFocal, MaxAp4MinFocal, MaxAp4MaxFocal; + } libraw_dnglens_t; + + typedef struct + { + float MinFocal, MaxFocal, MaxAp4MinFocal, MaxAp4MaxFocal, EXIF_MaxAp; + char LensMake[128], Lens[128], LensSerial[128], InternalLensSerial[128]; + ushort FocalLengthIn35mmFormat; + libraw_nikonlens_t nikon; + libraw_dnglens_t dng; + libraw_makernotes_lens_t makernotes; + } libraw_lensinfo_t; + + typedef struct + { + libraw_canon_makernotes_t canon; + libraw_nikon_makernotes_t nikon; + libraw_hasselblad_makernotes_t hasselblad; + libraw_fuji_info_t fuji; + libraw_olympus_makernotes_t olympus; + libraw_sony_info_t sony; + libraw_kodak_makernotes_t kodak; + libraw_panasonic_makernotes_t panasonic; + libraw_pentax_makernotes_t pentax; + } libraw_makernotes_t; + + typedef struct + { + short DriveMode; + short FocusMode; + short MeteringMode; + short AFPoint; + short ExposureMode; + short ImageStabilization; + char BodySerial[64]; + char InternalBodySerial[64]; /* this may be PCB or sensor serial, depends on make/model*/ + } libraw_shootinginfo_t; + + typedef struct + { unsigned fsize; ushort rw, rh; uchar lm, tm, rm, bm, lf, cf, max, flags; char t_make[10], t_model[20]; ushort offset; -} libraw_custom_camera_t; - -typedef struct -{ - ushort (*image)[4] ; - libraw_image_sizes_t sizes; - libraw_iparams_t idata; - libraw_lensinfo_t lens; - libraw_makernotes_t makernotes; - libraw_shootinginfo_t shootinginfo; - libraw_output_params_t params; - unsigned int progress_flags; - unsigned int process_warnings; - libraw_colordata_t color; - libraw_imgother_t other; - libraw_thumbnail_t thumbnail; - libraw_rawdata_t rawdata; - void *parent_class; -} libraw_data_t; - - -struct xtrans_params -{ - char *q_table; /* quantization table */ - int q_point[5]; /* quantization points */ - int max_bits; - int min_value; - int raw_bits; - int total_values; - int maxDiff; - ushort line_width; -}; + } libraw_custom_camera_t; + + typedef struct + { + ushort (*image)[4]; + libraw_image_sizes_t sizes; + libraw_iparams_t idata; + libraw_lensinfo_t lens; + libraw_makernotes_t makernotes; + libraw_shootinginfo_t shootinginfo; + libraw_output_params_t params; + unsigned int progress_flags; + unsigned int process_warnings; + libraw_colordata_t color; + libraw_imgother_t other; + libraw_thumbnail_t thumbnail; + libraw_rawdata_t rawdata; + void *parent_class; + } libraw_data_t; + + struct fuji_compressed_params + { + int8_t *q_table; /* quantization table */ + int q_point[5]; /* quantization points */ + int max_bits; + int min_value; + int raw_bits; + int total_values; + int maxDiff; + ushort line_width; + }; #ifdef __cplusplus } #endif /* Byte order */ #if defined(__POWERPC__) #define LibRawBigEndian 1 #elif defined(__INTEL__) #define LibRawBigEndian 0 #elif defined(_M_IX86) || defined(__i386__) #define LibRawBigEndian 0 #elif defined(_M_X64) || defined(__amd64__) || defined(__x86_64__) #define LibRawBigEndian 0 #elif defined(__LITTLE_ENDIAN__) #define LibRawBigEndian 0 #elif defined(__BIG_ENDIAN__) #define LibRawBigEndian 1 #elif defined(_ARM_) #define LibRawBigEndian 0 #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define LibRawBigEndian 0 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ #define LibRawBigEndian 1 #else #ifndef qXCodeRez #error Unable to figure out byte order. #endif #endif #endif diff --git a/core/libs/rawengine/libraw/libraw/libraw_version.h b/core/libs/rawengine/libraw/libraw/libraw_version.h index a114ba6c2d..9dfed7c910 100644 --- a/core/libs/rawengine/libraw/libraw/libraw_version.h +++ b/core/libs/rawengine/libraw/libraw/libraw_version.h @@ -1,59 +1,55 @@ /* -*- C++ -*- * File: libraw_version.h - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) - * Created: Mon Sept 8, 2008 + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) + * Created: Mon Sept 8, 2008 * * LibRaw C++ interface * LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See the file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See the file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #ifndef __VERSION_H #define __VERSION_H -#define LIBRAW_MAJOR_VERSION 0 -#define LIBRAW_MINOR_VERSION 18 -#define LIBRAW_PATCH_VERSION 13 -#define LIBRAW_VERSION_TAIL Release +#define LIBRAW_MAJOR_VERSION 0 +#define LIBRAW_MINOR_VERSION 19 +#define LIBRAW_PATCH_VERSION 0 +#define LIBRAW_VERSION_TAIL Release -#define LIBRAW_SHLIB_CURRENT 16 -#define LIBRAW_SHLIB_REVISION 0 -#define LIBRAW_SHLIB_AGE 0 +#define LIBRAW_SHLIB_CURRENT 19 +#define LIBRAW_SHLIB_REVISION 0 +#define LIBRAW_SHLIB_AGE 0 -#define _LIBRAW_VERSION_MAKE(a,b,c,d) #a"."#b"."#c"-"#d -#define LIBRAW_VERSION_MAKE(a,b,c,d) _LIBRAW_VERSION_MAKE(a,b,c,d) +#define _LIBRAW_VERSION_MAKE(a, b, c, d) #a "." #b "." #c "-" #d +#define LIBRAW_VERSION_MAKE(a, b, c, d) _LIBRAW_VERSION_MAKE(a, b, c, d) -#define LIBRAW_VERSION_STR LIBRAW_VERSION_MAKE(LIBRAW_MAJOR_VERSION,LIBRAW_MINOR_VERSION,LIBRAW_PATCH_VERSION,LIBRAW_VERSION_TAIL) +#define LIBRAW_VERSION_STR \ + LIBRAW_VERSION_MAKE(LIBRAW_MAJOR_VERSION, LIBRAW_MINOR_VERSION, LIBRAW_PATCH_VERSION, LIBRAW_VERSION_TAIL) -#define LIBRAW_MAKE_VERSION(major,minor,patch) \ - (((major) << 16) | ((minor) << 8) | (patch)) +#define LIBRAW_MAKE_VERSION(major, minor, patch) (((major) << 16) | ((minor) << 8) | (patch)) -#define LIBRAW_VERSION \ - LIBRAW_MAKE_VERSION(LIBRAW_MAJOR_VERSION,LIBRAW_MINOR_VERSION,LIBRAW_PATCH_VERSION) +#define LIBRAW_VERSION LIBRAW_MAKE_VERSION(LIBRAW_MAJOR_VERSION, LIBRAW_MINOR_VERSION, LIBRAW_PATCH_VERSION) -#define LIBRAW_CHECK_VERSION(major,minor,patch) \ - ( LibRaw::versionNumber() >= LIBRAW_MAKE_VERSION(major,minor,patch) ) +#define LIBRAW_CHECK_VERSION(major, minor, patch) (LibRaw::versionNumber() >= LIBRAW_MAKE_VERSION(major, minor, patch)) -#define LIBRAW_RUNTIME_CHECK_VERSION_EXACT() \ - ( (LibRaw::versionNumber() & 0xffff00) == LIBRAW_MAKE_VERSION(LIBRAW_MAJOR_VERSION,LIBRAW_MINOR_VERSION,0) ) +#define LIBRAW_RUNTIME_CHECK_VERSION_EXACT() \ + ((LibRaw::versionNumber() & 0xffff00) == LIBRAW_MAKE_VERSION(LIBRAW_MAJOR_VERSION, LIBRAW_MINOR_VERSION, 0)) -#define LIBRAW_RUNTIME_CHECK_VERSION_NOTLESS() \ - ( (LibRaw::versionNumber() & 0xffff00) >= LIBRAW_MAKE_VERSION(LIBRAW_MAJOR_VERSION,LIBRAW_MINOR_VERSION,0) ) +#define LIBRAW_RUNTIME_CHECK_VERSION_NOTLESS() \ + ((LibRaw::versionNumber() & 0xffff00) >= LIBRAW_MAKE_VERSION(LIBRAW_MAJOR_VERSION, LIBRAW_MINOR_VERSION, 0)) -#define LIBRAW_COMPILE_CHECK_VERSION(major,minor) \ - (LIBRAW_MAKE_VERSION(major,minor,0) == (LIBRAW_VERSION & 0xffff00)) - -#define LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(major,minor) \ - (LIBRAW_MAKE_VERSION(major,minor,0) <= (LIBRAW_VERSION & 0xffff00)) +#define LIBRAW_COMPILE_CHECK_VERSION(major, minor) (LIBRAW_MAKE_VERSION(major, minor, 0) == (LIBRAW_VERSION & 0xffff00)) +#define LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(major, minor) \ + (LIBRAW_MAKE_VERSION(major, minor, 0) <= (LIBRAW_VERSION & 0xffff00)) #endif diff --git a/core/libs/rawengine/libraw/samples/4channels.cpp b/core/libs/rawengine/libraw/samples/4channels.cpp index a0d7aae553..05acd9b828 100644 --- a/core/libs/rawengine/libraw/samples/4channels.cpp +++ b/core/libs/rawengine/libraw/samples/4channels.cpp @@ -1,175 +1,170 @@ /* -*- C++ -*- * File: 4channels.cpp - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) * Created: Mon Feb 09, 2009 * * LibRaw sample * Generates 4 TIFF file from RAW data, one file per channel * LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #include #include #include #ifndef WIN32 #include #else #include #endif #include "libraw/libraw.h" #ifdef WIN32 #define snprintf _snprintf #endif int main(int ac, char *av[]) { - int i, ret; - int autoscale=0,black_subtraction=1, use_gamma=0; - char outfn[1024]; - - LibRaw RawProcessor; - if(ac<2) - { - usage: - printf( - "4channels - LibRaw %s sample. %d cameras supported\n" - "Usage: %s [-s N] [-g] [-A] [-B] [-N] raw-files....\n" - "\t-s N - select Nth image in file (default=0)\n" - "\t-g - use gamma correction with gamma 2.2 (not precise,use for visual inspection only)\n" - "\t-A - autoscaling (by integer factor)\n" - "\t-B - no black subtraction\n" - ,LibRaw::version(), - LibRaw::cameraCount(), - av[0]); - return 0; - } - + int i, ret; + int autoscale = 0, black_subtraction = 1, use_gamma = 0; + char outfn[1024]; + + LibRaw RawProcessor; + if (ac < 2) + { + usage: + printf("4channels - LibRaw %s sample. %d cameras supported\n" + "Usage: %s [-s N] [-g] [-A] [-B] [-N] raw-files....\n" + "\t-s N - select Nth image in file (default=0)\n" + "\t-g - use gamma correction with gamma 2.2 (not precise,use for visual inspection only)\n" + "\t-A - autoscaling (by integer factor)\n" + "\t-B - no black subtraction\n", + LibRaw::version(), LibRaw::cameraCount(), av[0]); + return 0; + } + #define P1 RawProcessor.imgdata.idata #define S RawProcessor.imgdata.sizes #define C RawProcessor.imgdata.color #define T RawProcessor.imgdata.thumbnail #define P2 RawProcessor.imgdata.other #define OUT RawProcessor.imgdata.params - OUT.output_bps=16; - OUT.output_tiff=1; - OUT.user_flip=0; - OUT.no_auto_bright = 1; - OUT.half_size=1; - - for (i=1;i0 && max< 1<<15) - { - scale = (1<<16)/max; - printf("Scaling with multiplier=%d (max=%d)\n",scale,max); - for(int j=0; j0) - { - for (int rc = 0; rc < S.iheight*S.iwidth; rc++) - RawProcessor.imgdata.image[rc][0] = RawProcessor.imgdata.image[rc][layer]; - } - char lname[8]; - if(isrgb) - { - snprintf(lname,7,"%c",((char*)("RGBG"))[layer]); - if(layer==3) - strcat(lname,"2"); - } - else - snprintf(lname,7,"%c",((char*)("GCMY"))[layer]); - - if(OUT.shot_select) - snprintf(outfn,sizeof(outfn),"%s-%d.%s.tiff",av[i],OUT.shot_select,lname); - else - snprintf(outfn,sizeof(outfn),"%s.%s.tiff",av[i],lname); - - printf("Writing file %s\n",outfn); - if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn))) - fprintf(stderr,"Cannot write %s: %s\n",outfn,libraw_strerror(ret)); - } - - } - return 0; + OUT.output_bps = 16; + OUT.output_tiff = 1; + OUT.user_flip = 0; + OUT.no_auto_bright = 1; + OUT.half_size = 1; + + for (i = 1; i < ac; i++) + { + if (av[i][0] == '-') + { + if (av[i][1] == 's' && av[i][2] == 0) + { + i++; + OUT.shot_select = av[i] ? atoi(av[i]) : 0; + } + else if (av[i][1] == 'g' && av[i][2] == 0) + use_gamma = 1; + else if (av[i][1] == 'A' && av[i][2] == 0) + autoscale = 1; + else if (av[i][1] == 'B' && av[i][2] == 0) + { + black_subtraction = 0; + } + else + goto usage; + continue; + } + if (!use_gamma) + OUT.gamm[0] = OUT.gamm[1] = 1; + + int c; + printf("Processing file %s\n", av[i]); + if ((ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS) + { + fprintf(stderr, "Cannot open %s: %s\n", av[i], libraw_strerror(ret)); + continue; // no recycle b/c open file will recycle itself + } + if (P1.is_foveon) + { + printf("Cannot process Foveon image %s\n", av[i]); + continue; + } + if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS) + { + fprintf(stderr, "Cannot unpack %s: %s\n", av[i], libraw_strerror(ret)); + continue; + } + RawProcessor.raw2image(); + if (black_subtraction) + { + RawProcessor.subtract_black(); + } + + if (autoscale) + { + unsigned max = 0, scale = 1; + for (int j = 0; j < S.iheight * S.iwidth; j++) + for (int c = 0; c < 4; c++) + if (max < RawProcessor.imgdata.image[j][c]) + max = RawProcessor.imgdata.image[j][c]; + if (max > 0 && max < 1 << 15) + { + scale = (1 << 16) / max; + printf("Scaling with multiplier=%d (max=%d)\n", scale, max); + for (int j = 0; j < S.iheight * S.iwidth; j++) + for (c = 0; c < 4; c++) + RawProcessor.imgdata.image[j][c] *= scale; + } + printf("Black level (scaled)=%d\n", C.black * scale); + } + else + printf("Black level (unscaled)=%d\n", C.black); + + // hack to make dcraw tiff writer happy + int isrgb = (P1.colors == 4 ? 0 : 1); + P1.colors = 1; + S.width = S.iwidth; + S.height = S.iheight; + + for (int layer = 0; layer < 4; layer++) + { + if (layer > 0) + { + for (int rc = 0; rc < S.iheight * S.iwidth; rc++) + RawProcessor.imgdata.image[rc][0] = RawProcessor.imgdata.image[rc][layer]; + } + char lname[8]; + if (isrgb) + { + snprintf(lname, 7, "%c", ((char *)("RGBG"))[layer]); + if (layer == 3) + strcat(lname, "2"); + } + else + snprintf(lname, 7, "%c", ((char *)("GCMY"))[layer]); + + if (OUT.shot_select) + snprintf(outfn, sizeof(outfn), "%s-%d.%s.tiff", av[i], OUT.shot_select, lname); + else + snprintf(outfn, sizeof(outfn), "%s.%s.tiff", av[i], lname); + + printf("Writing file %s\n", outfn); + if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn))) + fprintf(stderr, "Cannot write %s: %s\n", outfn, libraw_strerror(ret)); + } + } + return 0; } diff --git a/core/libs/rawengine/libraw/samples/dcraw_emu.cpp b/core/libs/rawengine/libraw/samples/dcraw_emu.cpp index d55a9223af..f9efb24147 100644 --- a/core/libs/rawengine/libraw/samples/dcraw_emu.cpp +++ b/core/libs/rawengine/libraw/samples/dcraw_emu.cpp @@ -1,585 +1,562 @@ /* -*- C++ -*- * File: dcraw_emu.cpp - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) * Created: Sun Mar 23, 2008 * * LibRaw simple C++ API sample: almost complete dcraw emulator * LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #ifdef WIN32 // suppress sprintf-related warning. sprintf() is permitted in sample code #define _CRT_SECURE_NO_WARNINGS #endif #include #include #include #include #include #ifndef WIN32 #include #include #include #else #include #endif #include #include #include "libraw/libraw.h" #ifdef WIN32 #define snprintf _snprintf #include #else #define O_BINARY 0 #endif #ifdef USE_DNGSDK #include "dng_host.h" #include "dng_negative.h" #include "dng_simple_image.h" #include "dng_info.h" #endif - void usage(const char *prog) { - printf("dcraw_emu: almost complete dcraw emulator\n"); - printf("Usage: %s [OPTION]... [FILE]...\n", prog); - printf( -"-c float-num Set adjust maximum threshold (default 0.75)\n" -"-v Verbose: print progress messages (repeated -v will add verbosity)\n" -"-w Use camera white balance, if possible\n" -"-a Average the whole image for white balance\n" -"-A Average a grey box for white balance\n" -"-r Set custom white balance\n" -"+M/-M Use/don't use an embedded color matrix\n" -"-C Correct chromatic aberration\n" -"-P Fix the dead pixels listed in this file\n" -"-K Subtract dark frame (16-bit raw PGM)\n" -"-k Set the darkness level\n" -"-S Set the saturation level\n" -"-R Set raw processing options to num\n" -"-n Set threshold for wavelet denoising\n" -"-H [0-9] Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)\n" -"-t [0-7] Flip image (0=none, 3=180, 5=90CCW, 6=90CW)\n" -"-o [0-6] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ,ACES)\n" + printf("dcraw_emu: almost complete dcraw emulator\n"); + printf("Usage: %s [OPTION]... [FILE]...\n", prog); + printf("-c float-num Set adjust maximum threshold (default 0.75)\n" + "-v Verbose: print progress messages (repeated -v will add verbosity)\n" + "-w Use camera white balance, if possible\n" + "-a Average the whole image for white balance\n" + "-A Average a grey box for white balance\n" + "-r Set custom white balance\n" + "+M/-M Use/don't use an embedded color matrix\n" + "-C Correct chromatic aberration\n" + "-P Fix the dead pixels listed in this file\n" + "-K Subtract dark frame (16-bit raw PGM)\n" + "-k Set the darkness level\n" + "-S Set the saturation level\n" + "-R Set raw processing options to num\n" + "-n Set threshold for wavelet denoising\n" + "-H [0-9] Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)\n" + "-t [0-7] Flip image (0=none, 3=180, 5=90CCW, 6=90CW)\n" + "-o [0-6] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ,ACES)\n" #ifndef NO_LCMS -"-o file Output ICC profile\n" -"-p file Camera input profile (use \'embed\' for embedded profile)\n" -#endif -"-j Don't stretch or rotate raw pixels\n" -"-W Don't automatically brighten the image\n" -"-b Adjust brightness (default = 1.0)\n" -"-q N Set the interpolation quality:\n" -" 0 - linear, 1 - VNG, 2 - PPG, 3 - AHD, 4 - DCB\n" -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 -" 5 - modified AHD,6 - AFD (5pass), 7 - VCD, 8 - VCD+AHD, 9 - LMMSE\n" -#endif -#ifdef LIBRAW_DEMOSAIC_PACK_GPL3 -" 10-AMaZE\n" -#endif -"-h Half-size color image (twice as fast as \"-q 0\")\n" -"-f Interpolate RGGB as four colors\n" -"-m Apply a 3x3 median filter to R-G and B-G\n" -"-s [0..N-1] Select one raw image from input file\n" -"-4 Linear 16-bit, same as \"-6 -W -g 1 1\n" -"-6 Write 16-bit linear instead of 8-bit with gamma\n" -"-g pow ts Set gamma curve to gamma pow and toe slope ts (default = 2.222 4.5)\n" -"-T Write TIFF instead of PPM\n" -"-G Use green_matching() filter\n" -"-B use cropbox\n" -"-F Use FILE I/O instead of streambuf API\n" -"-timing Detailed timing report\n" -"-fbdd N 0 - disable FBDD noise reduction (default), 1 - light FBDD, 2 - full\n" -"-dcbi N Number of extra DCD iterations (default - 0)\n" -"-dcbe DCB color enhance\n" -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 -"-eeci EECI refine for mixed VCD/AHD (q=8)\n" -"-esmed N Number of edge-sensitive median filter passes (only if q=8)\n" -#endif -#ifdef LIBRAW_DEMOSAIC_PACK_GPL3 -//"-amazeca Use AMaZE chromatic aberrations refine (only if q=10)\n" -"-acae Use chromatic aberrations correction\n" //modifJD -"-aline reduction of line noise\n" -"-aclean clean CFA\n" -"-agreen equilibrate green\n" + "-o file Output ICC profile\n" + "-p file Camera input profile (use \'embed\' for embedded profile)\n" #endif -"-aexpo exposure correction\n" -"-apentax4shot enables merge of 4-shot pentax files\n" -"-apentax4shotorder 3102 sets pentax 4-shot alignment order\n" -// WF -"-dbnd debanding\n" + "-j Don't stretch or rotate raw pixels\n" + "-W Don't automatically brighten the image\n" + "-b Adjust brightness (default = 1.0)\n" + "-q N Set the interpolation quality:\n" + " 0 - linear, 1 - VNG, 2 - PPG, 3 - AHD, 4 - DCB\n" + " 11 - DHT, 12 - AAHD\n" + "-h Half-size color image (twice as fast as \"-q 0\")\n" + "-f Interpolate RGGB as four colors\n" + "-m Apply a 3x3 median filter to R-G and B-G\n" + "-s [0..N-1] Select one raw image from input file\n" + "-4 Linear 16-bit, same as \"-6 -W -g 1 1\n" + "-6 Write 16-bit linear instead of 8-bit with gamma\n" + "-g pow ts Set gamma curve to gamma pow and toe slope ts (default = 2.222 4.5)\n" + "-T Write TIFF instead of PPM\n" + "-G Use green_matching() filter\n" + "-B use cropbox\n" + "-F Use FILE I/O instead of streambuf API\n" + "-timing Detailed timing report\n" + "-fbdd N 0 - disable FBDD noise reduction (default), 1 - light FBDD, 2 - full\n" + "-dcbi N Number of extra DCD iterations (default - 0)\n" + "-dcbe DCB color enhance\n" + "-aexpo exposure correction\n" + "-apentax4shot enables merge of 4-shot pentax files\n" + "-apentax4shotorder 3102 sets pentax 4-shot alignment order\n" #ifndef WIN32 -"-mmap Use mmap()-ed buffer instead of plain FILE I/O\n" + "-mmap Use mmap()-ed buffer instead of plain FILE I/O\n" #endif -"-mem Use memory buffer instead of FILE I/O\n" -"-disars Do not use RawSpeed library\n" -"-disinterp Do not run interpolation step\n" -"-dsrawrgb1 Disable YCbCr to RGB conversion for sRAW (Cb/Cr interpolation enabled)\n" -"-dsrawrgb2 Disable YCbCr to RGB conversion for sRAW (Cb/Cr interpolation disabled)\n" -"-disadcf Do not use dcraw Foveon code even if compiled with demosaic-pack-GPL2\n" + "-mem Use memory buffer instead of FILE I/O\n" + "-disars Do not use RawSpeed library\n" + "-disinterp Do not run interpolation step\n" + "-dsrawrgb1 Disable YCbCr to RGB conversion for sRAW (Cb/Cr interpolation enabled)\n" + "-dsrawrgb2 Disable YCbCr to RGB conversion for sRAW (Cb/Cr interpolation disabled)\n" #ifdef USE_DNGSDK -"-dngsdk Use Adobe DNG SDK for DNG decode\n" -"-dngflags N set DNG decoding options to value N\n" + "-dngsdk Use Adobe DNG SDK for DNG decode\n" + "-dngflags N set DNG decoding options to value N\n" #endif -); - exit(1); + ); + exit(1); } -static int verbosity=0; -int cnt=0; -int my_progress_callback(void *d,enum LibRaw_progress p,int iteration, int expected) +static int verbosity = 0; +int cnt = 0; +int my_progress_callback(void *d, enum LibRaw_progress p, int iteration, int expected) { - char *passed = (char*)(d?d:"default string"); // data passed to callback at set_callback stage + char *passed = (char *)(d ? d : "default string"); // data passed to callback at set_callback stage - if(verbosity>2) // verbosity set by repeat -v switches - { - printf("CB: %s pass %d of %d (data passed=%s)\n",libraw_strprogress(p),iteration,expected,passed); - } + if (verbosity > 2) // verbosity set by repeat -v switches + { + printf("CB: %s pass %d of %d (data passed=%s)\n", libraw_strprogress(p), iteration, expected, passed); + } else if (iteration == 0) // 1st iteration of each step - printf("Starting %s (expecting %d iterations)\n", libraw_strprogress(p),expected); - else if (iteration == expected-1) - printf("%s finished\n",libraw_strprogress(p)); - + printf("Starting %s (expecting %d iterations)\n", libraw_strprogress(p), expected); + else if (iteration == expected - 1) + printf("%s finished\n", libraw_strprogress(p)); + /// if(++cnt>10) return 1; // emulate user termination on 10-th callback call - - return 0; // always return 0 to continue processing + + return 0; // always return 0 to continue processing } // timer #ifndef WIN32 -static struct timeval start,end; -void timerstart(void) -{ - gettimeofday(&start,NULL); -} -void timerprint(const char *msg,const char *filename) +static struct timeval start, end; +void timerstart(void) { gettimeofday(&start, NULL); } +void timerprint(const char *msg, const char *filename) { - gettimeofday(&end,NULL); - float msec = (end.tv_sec - start.tv_sec)*1000.0f + (end.tv_usec - start.tv_usec)/1000.0f; - printf("Timing: %s/%s: %6.3f msec\n",filename,msg,msec); + gettimeofday(&end, NULL); + float msec = (end.tv_sec - start.tv_sec) * 1000.0f + (end.tv_usec - start.tv_usec) / 1000.0f; + printf("Timing: %s/%s: %6.3f msec\n", filename, msg, msec); } #else LARGE_INTEGER start; -void timerstart(void) -{ - QueryPerformanceCounter(&start); -} +void timerstart(void) { QueryPerformanceCounter(&start); } void timerprint(const char *msg, const char *filename) { - LARGE_INTEGER unit,end; + LARGE_INTEGER unit, end; QueryPerformanceCounter(&end); QueryPerformanceFrequency(&unit); float msec = (float)(end.QuadPart - start.QuadPart); - msec /= (float)unit.QuadPart/1000.0f; - printf("Timing: %s/%s: %6.3f msec\n",filename,msg,msec); + msec /= (float)unit.QuadPart / 1000.0f; + printf("Timing: %s/%s: %6.3f msec\n", filename, msg, msec); } #endif int main(int argc, char *argv[]) { - if(argc==1) usage(argv[0]); + if (argc == 1) + usage(argv[0]); - LibRaw RawProcessor; - int i,arg,c,ret; - char opm,opt,*cp,*sp; - int use_bigfile=0, use_timing=0,use_mem=0; + LibRaw RawProcessor; + int i, arg, c, ret; + char opm, opt, *cp, *sp; + int use_bigfile = 0, use_timing = 0, use_mem = 0; #ifdef USE_DNGSDK - dng_host *dnghost = NULL; + dng_host *dnghost = NULL; #endif #ifndef WIN32 - int msize = 0,use_mmap=0; - + int msize = 0, use_mmap = 0; + #endif - void *iobuffer=0; + void *iobuffer = 0; #ifdef OUT #undef OUT #endif #define OUT RawProcessor.imgdata.params - - argv[argc] = (char*)""; - for (arg=1; (((opm = argv[arg][0]) - 2) | 2) == '+'; ) - { - char *optstr = argv[arg]; - opt = argv[arg++][1]; - if ((cp = strchr (sp=(char*)"cnbrkStqmHABCgU", opt))!=0) - for (i=0; i < "111411111144221"[cp-sp]-'0'; i++) - if (!isdigit(argv[arg+i][0]) && !optstr[2]) - { - fprintf (stderr,"Non-numeric argument to \"-%c\"\n", opt); - return 1; - } - if(!strchr("ftdeam",opt) && argv[arg-1][2]) - fprintf (stderr,"Unknown option \"%s\".\n",argv[arg-1]); - switch (opt) - { - case 'v': verbosity++; break; - case 'G': OUT.green_matching = 1; break; - case 'c': OUT.adjust_maximum_thr = (float)atof(argv[arg++]); break; - case 'U': OUT.auto_bright_thr = (float)atof(argv[arg++]); break; - case 'n': OUT.threshold = (float)atof(argv[arg++]); break; - case 'b': OUT.bright = (float)atof(argv[arg++]); break; - case 'P': OUT.bad_pixels = argv[arg++]; break; - case 'K': OUT.dark_frame = argv[arg++]; break; - case 'r': - for(c=0;c<4;c++) - OUT.user_mul[c] = (float)atof(argv[arg++]); - break; - case 'C': - OUT.aber[0] = 1 / atof(argv[arg++]); - OUT.aber[2] = 1 / atof(argv[arg++]); - break; - case 'g': - OUT.gamm[0] = 1 / atof(argv[arg++]); - OUT.gamm[1] = atof(argv[arg++]); - break; - case 'k': OUT.user_black = atoi(argv[arg++]); break; - case 'S': OUT.user_sat = atoi(argv[arg++]); break; - case 'R': OUT.raw_processing_options = atoi(argv[arg++]); break; - case 't': - if(!strcmp(optstr,"-timing")) - use_timing=1; - else if(!argv[arg-1][2]) - OUT.user_flip = atoi(argv[arg++]); - else - fprintf (stderr,"Unknown option \"%s\".\n",argv[arg-1]); - break; - case 'q': OUT.user_qual = atoi(argv[arg++]); break; - case 'm': + + argv[argc] = (char *)""; + for (arg = 1; (((opm = argv[arg][0]) - 2) | 2) == '+';) + { + char *optstr = argv[arg]; + opt = argv[arg++][1]; + if ((cp = strchr(sp = (char *)"cnbrkStqmHABCgU", opt)) != 0) + for (i = 0; i < "111411111144221"[cp - sp] - '0'; i++) + if (!isdigit(argv[arg + i][0]) && !optstr[2]) + { + fprintf(stderr, "Non-numeric argument to \"-%c\"\n", opt); + return 1; + } + if (!strchr("ftdeam", opt) && argv[arg - 1][2]) + fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]); + switch (opt) + { + case 'v': + verbosity++; + break; + case 'G': + OUT.green_matching = 1; + break; + case 'c': + OUT.adjust_maximum_thr = (float)atof(argv[arg++]); + break; + case 'U': + OUT.auto_bright_thr = (float)atof(argv[arg++]); + break; + case 'n': + OUT.threshold = (float)atof(argv[arg++]); + break; + case 'b': + OUT.bright = (float)atof(argv[arg++]); + break; + case 'P': + OUT.bad_pixels = argv[arg++]; + break; + case 'K': + OUT.dark_frame = argv[arg++]; + break; + case 'r': + for (c = 0; c < 4; c++) + OUT.user_mul[c] = (float)atof(argv[arg++]); + break; + case 'C': + OUT.aber[0] = 1 / atof(argv[arg++]); + OUT.aber[2] = 1 / atof(argv[arg++]); + break; + case 'g': + OUT.gamm[0] = 1 / atof(argv[arg++]); + OUT.gamm[1] = atof(argv[arg++]); + break; + case 'k': + OUT.user_black = atoi(argv[arg++]); + break; + case 'S': + OUT.user_sat = atoi(argv[arg++]); + break; + case 'R': + OUT.raw_processing_options = atoi(argv[arg++]); + break; + case 't': + if (!strcmp(optstr, "-timing")) + use_timing = 1; + else if (!argv[arg - 1][2]) + OUT.user_flip = atoi(argv[arg++]); + else + fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]); + break; + case 'q': + OUT.user_qual = atoi(argv[arg++]); + break; + case 'm': #ifndef WIN32 - if(!strcmp(optstr,"-mmap")) - use_mmap = 1; - else + if (!strcmp(optstr, "-mmap")) + use_mmap = 1; + else #endif - if(!strcmp(optstr,"-mem")) - use_mem = 1; - else - { - if(!argv[arg-1][2]) - OUT.med_passes = atoi(argv[arg++]); - else - fprintf (stderr,"Unknown option \"%s\".\n",argv[arg-1]); - } - break; - case 'H': OUT.highlight = atoi(argv[arg++]); break; - case 's': OUT.shot_select = abs(atoi(argv[arg++])); break; - case 'o': - if(isdigit(argv[arg][0]) && !isdigit(argv[arg][1])) - OUT.output_color = atoi(argv[arg++]); + if (!strcmp(optstr, "-mem")) + use_mem = 1; + else + { + if (!argv[arg - 1][2]) + OUT.med_passes = atoi(argv[arg++]); + else + fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]); + } + break; + case 'H': + OUT.highlight = atoi(argv[arg++]); + break; + case 's': + OUT.shot_select = abs(atoi(argv[arg++])); + break; + case 'o': + if (isdigit(argv[arg][0]) && !isdigit(argv[arg][1])) + OUT.output_color = atoi(argv[arg++]); #ifndef NO_LCMS - else - OUT.output_profile = argv[arg++]; - break; - case 'p': OUT.camera_profile = argv[arg++]; -#endif - break; - case 'h': - OUT.half_size = 1; - break; - case 'f': - if(!strcmp(optstr,"-fbdd")) - OUT.fbdd_noiserd = atoi(argv[arg++]); - else - { - if(!argv[arg-1][2]) - OUT.four_color_rgb = 1; - else - fprintf (stderr,"Unknown option \"%s\".\n",argv[arg-1]); - } - break; - case 'A': for(c=0; c<4;c++) OUT.greybox[c] = atoi(argv[arg++]); break; - case 'B': for(c=0; c<4;c++) OUT.cropbox[c] = atoi(argv[arg++]); break; - case 'a': - if(!strcmp(optstr,"-aexpo")) - { - OUT.exp_correc = 1; - OUT.exp_shift = (float)atof(argv[arg++]); - OUT.exp_preser = (float)atof(argv[arg++]); - } - else if(!strcmp(optstr,"-apentax4shot")) - { - OUT.raw_processing_options |= LIBRAW_PROCESSING_PENTAX_PS_ALLFRAMES; - } - else if(!strcmp(optstr,"-apentax4shotorder")) - { - strncpy(OUT.p4shot_order,argv[arg++],5); - } - else -#ifdef LIBRAW_DEMOSAIC_PACK_GPL3 - if(!strcmp(optstr,"-acae")) - { - OUT.ca_correc = 1; - OUT.cared = (float)atof(argv[arg++]); - OUT.cablue = (float)atof(argv[arg++]); - } - else if(!strcmp(optstr,"-aline")) - { - OUT.cfaline = 1; - OUT.linenoise = (float)atof(argv[arg++]); - } - else if(!strcmp(optstr,"-aclean")) - { - OUT.cfa_clean = 1; - OUT.lclean = (float)atof(argv[arg++]); - OUT.cclean = (float)atof(argv[arg++]); - } - else if(!strcmp(optstr,"-agreen")) - { - OUT.cfa_green = 1; - OUT.green_thresh =(float)atof(argv[arg++]); - } - else + else + OUT.output_profile = argv[arg++]; + break; + case 'p': + OUT.camera_profile = argv[arg++]; #endif - if(!argv[arg-1][2]) - OUT.use_auto_wb = 1; - else - fprintf (stderr,"Unknown option \"%s\".\n",argv[arg-1]); - break; - case 'w': OUT.use_camera_wb = 1; break; - case 'M': OUT.use_camera_matrix = (opm == '+'); break; - case 'j': OUT.use_fuji_rotate = 0; break; - case 'W': OUT.no_auto_bright = 1; break; - case 'T': OUT.output_tiff = 1; break; - case '4': OUT.gamm[0] = OUT.gamm[1] = OUT.no_auto_bright = 1; /* no break here! */ - case '6': OUT.output_bps = 16; break; - case 'F': use_bigfile=1; break; - case 'd': - if(!strcmp(optstr,"-dcbi")) - OUT.dcb_iterations = atoi(argv[arg++]); - else if(!strcmp(optstr,"-disars")) - OUT.use_rawspeed=0; - else if(!strcmp(optstr,"-disadcf")) - OUT.raw_processing_options |=LIBRAW_PROCESSING_FORCE_FOVEON_X3F; - else if(!strcmp(optstr,"-disinterp")) - OUT.no_interpolation=1; - else if(!strcmp(optstr,"-dcbe")) - OUT.dcb_enhance_fl = 1; - else if(!strcmp(optstr,"-dsrawrgb1")) - { - OUT.raw_processing_options |= LIBRAW_PROCESSING_SRAW_NO_RGB; - OUT.raw_processing_options &= ~LIBRAW_PROCESSING_SRAW_NO_INTERPOLATE; - } - else if(!strcmp(optstr,"-dsrawrgb2")) - { - OUT.raw_processing_options &= ~LIBRAW_PROCESSING_SRAW_NO_RGB; - OUT.raw_processing_options |= LIBRAW_PROCESSING_SRAW_NO_INTERPOLATE; - } - else if(!strcmp(optstr,"-dbnd")) - { - for(c=0; c<4; c++) - OUT.wf_deband_treshold[c] = (float)atof(argv[arg++]); - OUT.wf_debanding = 1; - } + break; + case 'h': + OUT.half_size = 1; + break; + case 'f': + if (!strcmp(optstr, "-fbdd")) + OUT.fbdd_noiserd = atoi(argv[arg++]); + else + { + if (!argv[arg - 1][2]) + OUT.four_color_rgb = 1; + else + fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]); + } + break; + case 'A': + for (c = 0; c < 4; c++) + OUT.greybox[c] = atoi(argv[arg++]); + break; + case 'B': + for (c = 0; c < 4; c++) + OUT.cropbox[c] = atoi(argv[arg++]); + break; + case 'a': + if (!strcmp(optstr, "-aexpo")) + { + OUT.exp_correc = 1; + OUT.exp_shift = (float)atof(argv[arg++]); + OUT.exp_preser = (float)atof(argv[arg++]); + } + else if (!strcmp(optstr, "-apentax4shot")) + { + OUT.raw_processing_options |= LIBRAW_PROCESSING_PENTAX_PS_ALLFRAMES; + } + else if (!strcmp(optstr, "-apentax4shotorder")) + { + strncpy(OUT.p4shot_order, argv[arg++], 5); + } + else if (!argv[arg - 1][2]) + OUT.use_auto_wb = 1; + else + fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]); + break; + case 'w': + OUT.use_camera_wb = 1; + break; + case 'M': + OUT.use_camera_matrix = (opm == '+'); + break; + case 'j': + OUT.use_fuji_rotate = 0; + break; + case 'W': + OUT.no_auto_bright = 1; + break; + case 'T': + OUT.output_tiff = 1; + break; + case '4': + OUT.gamm[0] = OUT.gamm[1] = OUT.no_auto_bright = 1; /* no break here! */ + case '6': + OUT.output_bps = 16; + break; + case 'F': + use_bigfile = 1; + break; + case 'd': + if (!strcmp(optstr, "-dcbi")) + OUT.dcb_iterations = atoi(argv[arg++]); + else if (!strcmp(optstr, "-disars")) + OUT.use_rawspeed = 0; + else if (!strcmp(optstr, "-disinterp")) + OUT.no_interpolation = 1; + else if (!strcmp(optstr, "-dcbe")) + OUT.dcb_enhance_fl = 1; + else if (!strcmp(optstr, "-dsrawrgb1")) + { + OUT.raw_processing_options |= LIBRAW_PROCESSING_SRAW_NO_RGB; + OUT.raw_processing_options &= ~LIBRAW_PROCESSING_SRAW_NO_INTERPOLATE; + } + else if (!strcmp(optstr, "-dsrawrgb2")) + { + OUT.raw_processing_options &= ~LIBRAW_PROCESSING_SRAW_NO_RGB; + OUT.raw_processing_options |= LIBRAW_PROCESSING_SRAW_NO_INTERPOLATE; + } #ifdef USE_DNGSDK - else if(!strcmp(optstr,"-dngsdk")) - { - dnghost = new dng_host; - RawProcessor.set_dng_host(dnghost); - } - else if(!strcmp(optstr,"-dngflags")) - { - OUT.use_dngsdk = atoi(argv[arg++]); - } -#endif - else - fprintf (stderr,"Unknown option \"%s\".\n",argv[arg-1]); - break; -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 - case 'e': - if(!strcmp(optstr,"-eeci")) - OUT.eeci_refine = 1; - else if(!strcmp(optstr,"-esmed")) - OUT.es_med_passes = atoi(argv[arg++]); - else - fprintf (stderr,"Unknown option \"%s\".\n",argv[arg-1]); - break; + else if (!strcmp(optstr, "-dngsdk")) + { + dnghost = new dng_host; + RawProcessor.set_dng_host(dnghost); + } + else if (!strcmp(optstr, "-dngflags")) + { + OUT.use_dngsdk = atoi(argv[arg++]); + } #endif - default: - fprintf (stderr,"Unknown option \"-%c\".\n", opt); - return 1; - } - } + else + fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]); + break; + default: + fprintf(stderr, "Unknown option \"-%c\".\n", opt); + return 1; + } + } #ifndef WIN32 - putenv ((char*)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field + putenv((char *)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field #else - _putenv ((char*)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field + _putenv((char *)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field #endif #define P1 RawProcessor.imgdata.idata #define S RawProcessor.imgdata.sizes #define C RawProcessor.imgdata.color #define T RawProcessor.imgdata.thumbnail #define P2 RawProcessor.imgdata.other - if(verbosity>1) - RawProcessor.set_progress_handler(my_progress_callback,(void*)"Sample data passed"); + if (verbosity > 1) + RawProcessor.set_progress_handler(my_progress_callback, (void *)"Sample data passed"); #ifdef LIBRAW_USE_OPENMP - if(verbosity) - printf ("Using %d threads\n", omp_get_max_threads()); + if (verbosity) + printf("Using %d threads\n", omp_get_max_threads()); #endif - - for ( ; arg < argc; arg++) - { - char outfn[1024]; - if(verbosity) printf("Processing file %s\n",argv[arg]); - - timerstart(); - -#ifndef WIN32 - if(use_mmap) - { - int file = open(argv[arg],O_RDONLY); - struct stat st; - if(file<0) - { - fprintf(stderr,"Cannot open %s: %s\n",argv[arg],strerror(errno)); - continue; - } - if(fstat(file,&st)) - { - fprintf(stderr,"Cannot stat %s: %s\n",argv[arg],strerror(errno)); - close(file); - continue; - } - int pgsz = getpagesize(); - msize = ((st.st_size+pgsz-1)/pgsz)*pgsz; - iobuffer = mmap(NULL,msize,PROT_READ,MAP_PRIVATE,file,0); - if(!iobuffer) - { - fprintf(stderr,"Cannot mmap %s: %s\n",argv[arg],strerror(errno)); - close(file); - continue; - } - close(file); - if( (ret = RawProcessor.open_buffer(iobuffer,st.st_size) != LIBRAW_SUCCESS)) - { - fprintf(stderr,"Cannot open_buffer %s: %s\n",argv[arg],libraw_strerror(ret)); - continue; // no recycle b/c open file will recycle itself - } + for (; arg < argc; arg++) + { + char outfn[1024]; - } - else + if (verbosity) + printf("Processing file %s\n", argv[arg]); + + timerstart(); + +#ifndef WIN32 + if (use_mmap) + { + int file = open(argv[arg], O_RDONLY); + struct stat st; + if (file < 0) + { + fprintf(stderr, "Cannot open %s: %s\n", argv[arg], strerror(errno)); + continue; + } + if (fstat(file, &st)) + { + fprintf(stderr, "Cannot stat %s: %s\n", argv[arg], strerror(errno)); + close(file); + continue; + } + int pgsz = getpagesize(); + msize = ((st.st_size + pgsz - 1) / pgsz) * pgsz; + iobuffer = mmap(NULL, msize, PROT_READ, MAP_PRIVATE, file, 0); + if (!iobuffer) + { + fprintf(stderr, "Cannot mmap %s: %s\n", argv[arg], strerror(errno)); + close(file); + continue; + } + close(file); + if ((ret = RawProcessor.open_buffer(iobuffer, st.st_size) != LIBRAW_SUCCESS)) + { + fprintf(stderr, "Cannot open_buffer %s: %s\n", argv[arg], libraw_strerror(ret)); + continue; // no recycle b/c open file will recycle itself + } + } + else #endif if (use_mem) - { - int file = open(argv[arg],O_RDONLY|O_BINARY); - struct stat st; - if(file<0) - { - fprintf(stderr,"Cannot open %s: %s\n",argv[arg],strerror(errno)); - continue; - } - if(fstat(file,&st)) - { - fprintf(stderr,"Cannot stat %s: %s\n",argv[arg],strerror(errno)); - close(file); - continue; - } - if(!(iobuffer = malloc(st.st_size))) - { - fprintf(stderr,"Cannot allocate %d kbytes for memory buffer\n",(int)(st.st_size/1024)); - close(file); - continue; - } - int rd; - if(st.st_size!=(rd=read(file,iobuffer,st.st_size))) - { - fprintf(stderr,"Cannot read %d bytes instead of %d to memory buffer\n",(int)rd,(int)st.st_size); - close(file); - free(iobuffer); - continue; - } - close(file); - if( (ret = RawProcessor.open_buffer(iobuffer,st.st_size)) != LIBRAW_SUCCESS) - { - fprintf(stderr,"Cannot open_buffer %s: %s\n",argv[arg],libraw_strerror(ret)); - free(iobuffer); - continue; // no recycle b/c open file will recycle itself - } - } - else - { - if(use_bigfile) - // force open_file switch to bigfile processing - ret = RawProcessor.open_file(argv[arg],1); - else - ret = RawProcessor.open_file(argv[arg]); - - if( ret != LIBRAW_SUCCESS) - { - fprintf(stderr,"Cannot open %s: %s\n",argv[arg],libraw_strerror(ret)); - continue; // no recycle b/c open_file will recycle itself - } - } - - if(use_timing) - timerprint("LibRaw::open_file()",argv[arg]); - - - timerstart(); - if( (ret = RawProcessor.unpack() ) != LIBRAW_SUCCESS) - { - fprintf(stderr,"Cannot unpack %s: %s\n",argv[arg],libraw_strerror(ret)); - continue; - } + { + int file = open(argv[arg], O_RDONLY | O_BINARY); + struct stat st; + if (file < 0) + { + fprintf(stderr, "Cannot open %s: %s\n", argv[arg], strerror(errno)); + continue; + } + if (fstat(file, &st)) + { + fprintf(stderr, "Cannot stat %s: %s\n", argv[arg], strerror(errno)); + close(file); + continue; + } + if (!(iobuffer = malloc(st.st_size))) + { + fprintf(stderr, "Cannot allocate %d kbytes for memory buffer\n", (int)(st.st_size / 1024)); + close(file); + continue; + } + int rd; + if (st.st_size != (rd = read(file, iobuffer, st.st_size))) + { + fprintf(stderr, "Cannot read %d bytes instead of %d to memory buffer\n", (int)rd, (int)st.st_size); + close(file); + free(iobuffer); + continue; + } + close(file); + if ((ret = RawProcessor.open_buffer(iobuffer, st.st_size)) != LIBRAW_SUCCESS) + { + fprintf(stderr, "Cannot open_buffer %s: %s\n", argv[arg], libraw_strerror(ret)); + free(iobuffer); + continue; // no recycle b/c open file will recycle itself + } + } + else + { + if (use_bigfile) + // force open_file switch to bigfile processing + ret = RawProcessor.open_file(argv[arg], 1); + else + ret = RawProcessor.open_file(argv[arg]); - if(use_timing) - timerprint("LibRaw::unpack()",argv[arg]); + if (ret != LIBRAW_SUCCESS) + { + fprintf(stderr, "Cannot open %s: %s\n", argv[arg], libraw_strerror(ret)); + continue; // no recycle b/c open_file will recycle itself + } + } - timerstart(); - if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_process())) - { - fprintf(stderr,"Cannot do postpocessing on %s: %s\n",argv[arg],libraw_strerror(ret)); - if(LIBRAW_FATAL_ERROR(ret)) - continue; - } - if(use_timing) - timerprint("LibRaw::dcraw_process()",argv[arg]); + if (use_timing) + timerprint("LibRaw::open_file()", argv[arg]); - snprintf(outfn,sizeof(outfn), - "%s.%s", - argv[arg], OUT.output_tiff ? "tiff" : (P1.colors>1?"ppm":"pgm")); + timerstart(); + if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS) + { + fprintf(stderr, "Cannot unpack %s: %s\n", argv[arg], libraw_strerror(ret)); + continue; + } - if(verbosity) - { - printf("Writing file %s\n",outfn); - } + if (use_timing) + timerprint("LibRaw::unpack()", argv[arg]); + + timerstart(); + if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_process())) + { + fprintf(stderr, "Cannot do postpocessing on %s: %s\n", argv[arg], libraw_strerror(ret)); + if (LIBRAW_FATAL_ERROR(ret)) + continue; + } + if (use_timing) + timerprint("LibRaw::dcraw_process()", argv[arg]); + + snprintf(outfn, sizeof(outfn), "%s.%s", argv[arg], OUT.output_tiff ? "tiff" : (P1.colors > 1 ? "ppm" : "pgm")); + + if (verbosity) + { + printf("Writing file %s\n", outfn); + } - if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn))) - fprintf(stderr,"Cannot write %s: %s\n",outfn,libraw_strerror(ret)); + if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn))) + fprintf(stderr, "Cannot write %s: %s\n", outfn, libraw_strerror(ret)); #ifndef WIN32 - if(use_mmap && iobuffer) - { - munmap(iobuffer,msize); - iobuffer=0; - } + if (use_mmap && iobuffer) + { + munmap(iobuffer, msize); + iobuffer = 0; + } #endif - else if(use_mem && iobuffer) - { - free(iobuffer); - iobuffer = 0; - } - - RawProcessor.recycle(); // just for show this call + else if (use_mem && iobuffer) + { + free(iobuffer); + iobuffer = 0; } + + RawProcessor.recycle(); // just for show this call + } #ifdef USE_DNGSDK - if(dnghost) - delete dnghost; + if (dnghost) + delete dnghost; #endif return 0; } diff --git a/core/libs/rawengine/libraw/samples/dcraw_half.c b/core/libs/rawengine/libraw/samples/dcraw_half.c index 6ef570dea1..7cc3db1e96 100644 --- a/core/libs/rawengine/libraw/samples/dcraw_half.c +++ b/core/libs/rawengine/libraw/samples/dcraw_half.c @@ -1,79 +1,77 @@ /* -*- C++ -*- * File: dcraw_half.c - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) * Created: Sat Mar 8 , 2008 * * LibRaw C API sample: emulates "dcraw -h" * LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #include #include #include #include #include "libraw/libraw.h" +#define HANDLE_FATAL_ERROR(ret) \ + if (ret) \ + { \ + fprintf(stderr, "%s: libraw %s\n", av[i], libraw_strerror(ret)); \ + if (LIBRAW_FATAL_ERROR(ret)) \ + exit(1); \ + } -#define HANDLE_FATAL_ERROR(ret)\ - if(ret)\ - {\ - fprintf(stderr,"%s: libraw %s\n",av[i],libraw_strerror(ret));\ - if(LIBRAW_FATAL_ERROR(ret))\ - exit(1); \ - }\ - -#define HANDLE_ALL_ERRORS(ret)\ - if(ret)\ - {\ - fprintf(stderr,"%s: libraw %s\n",av[i],libraw_strerror(ret));\ - continue; \ - }\ - +#define HANDLE_ALL_ERRORS(ret) \ + if (ret) \ + { \ + fprintf(stderr, "%s: libraw %s\n", av[i], libraw_strerror(ret)); \ + continue; \ + } int main(int ac, char *av[]) { - int i; - libraw_data_t *iprc = libraw_init(0); - - if(!iprc) - { - fprintf(stderr,"Cannot create libraw handle\n"); - exit(1); - } - - iprc->params.half_size = 1; /* dcraw -h */ - - for (i=1;iidata.make,iprc->idata.model); - - ret = libraw_unpack(iprc); - HANDLE_ALL_ERRORS(ret); - - ret = libraw_dcraw_process(iprc); - HANDLE_ALL_ERRORS(ret); - - strcpy(outfn,av[i]); - strcat(outfn,".ppm"); - printf("Writing to %s\n",outfn); - - ret = libraw_dcraw_ppm_tiff_writer(iprc,outfn); - HANDLE_FATAL_ERROR(ret); - } - libraw_close(iprc); - return 0; + int i; + libraw_data_t *iprc = libraw_init(0); + + if (!iprc) + { + fprintf(stderr, "Cannot create libraw handle\n"); + exit(1); + } + + iprc->params.half_size = 1; /* dcraw -h */ + + for (i = 1; i < ac; i++) + { + char outfn[1024]; + int ret = libraw_open_file(iprc, av[i]); + HANDLE_ALL_ERRORS(ret); + + printf("Processing %s (%s %s)\n", av[i], iprc->idata.make, iprc->idata.model); + + ret = libraw_unpack(iprc); + HANDLE_ALL_ERRORS(ret); + + ret = libraw_dcraw_process(iprc); + HANDLE_ALL_ERRORS(ret); + + strcpy(outfn, av[i]); + strcat(outfn, ".ppm"); + printf("Writing to %s\n", outfn); + + ret = libraw_dcraw_ppm_tiff_writer(iprc, outfn); + HANDLE_FATAL_ERROR(ret); + } + libraw_close(iprc); + return 0; } diff --git a/core/libs/rawengine/libraw/samples/half_mt.c b/core/libs/rawengine/libraw/samples/half_mt.c index 3acfb60b53..ca9c2d8e80 100644 --- a/core/libs/rawengine/libraw/samples/half_mt.c +++ b/core/libs/rawengine/libraw/samples/half_mt.c @@ -1,170 +1,176 @@ /* -*- C++ -*- * File: halt_mt.c - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) * Created: Sat Mar 8, 2008 * * LibRaw C API mutithreaded sample: emulates call to "dcraw -h [-w] [-a] [-v]" * LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #include #include #include #include #include #include "libraw/libraw.h" -#define HANDLE_ERRORS(ret) do { \ - if(ret) \ - { \ - fprintf(stderr,"%s: %s\n",fn,libraw_strerror(ret)); \ - if(LIBRAW_FATAL_ERROR(ret)) \ - { \ - libraw_close(iprc); \ - return NULL ; \ - } \ - } \ - }while(0) - - -int verbose=0,use_camera_wb=0,use_auto_wb=0,tiff_mode=0; +#define HANDLE_ERRORS(ret) \ + do \ + { \ + if (ret) \ + { \ + fprintf(stderr, "%s: %s\n", fn, libraw_strerror(ret)); \ + if (LIBRAW_FATAL_ERROR(ret)) \ + { \ + libraw_close(iprc); \ + return NULL; \ + } \ + } \ + } while (0) + +int verbose = 0, use_camera_wb = 0, use_auto_wb = 0, tiff_mode = 0; pthread_mutex_t qm; -char **queue=NULL; -size_t qsize=0,qptr=0; +char **queue = NULL; +size_t qsize = 0, qptr = 0; char *get_next_file() { - char *ret; - if(!queue) return NULL; - if(qptr>=qsize) return NULL; - pthread_mutex_lock(&qm); - ret = queue[qptr++]; - pthread_mutex_unlock(&qm); - return ret; + char *ret; + if (!queue) + return NULL; + if (qptr >= qsize) + return NULL; + pthread_mutex_lock(&qm); + ret = queue[qptr++]; + pthread_mutex_unlock(&qm); + return ret; } - -void * process_files(void *q) +void *process_files(void *q) { - int ret; - int count=0; - char outfn[1024], *fn; - libraw_data_t *iprc = libraw_init(0); + int ret; + int count = 0; + char outfn[1024], *fn; + libraw_data_t *iprc = libraw_init(0); + + if (!iprc) + { + fprintf(stderr, "Cannot create libraw handle\n"); + return NULL; + } - if(!iprc) - { - fprintf(stderr,"Cannot create libraw handle\n"); - return NULL ; - } + while ((fn = get_next_file())) + { - while((fn = get_next_file())) - { + iprc->params.half_size = 1; /* dcraw -h */ + iprc->params.use_camera_wb = use_camera_wb; + iprc->params.use_auto_wb = use_auto_wb; + iprc->params.output_tiff = tiff_mode; - iprc->params.half_size = 1; /* dcraw -h */ - iprc->params.use_camera_wb = use_camera_wb; - iprc->params.use_auto_wb = use_auto_wb; - iprc->params.output_tiff = tiff_mode; - - ret = libraw_open_file(iprc,fn); - if(verbose) fprintf(stderr,"%s: %s/%s\n",fn,iprc->idata.make,iprc->idata.model); - HANDLE_ERRORS(ret); - - ret = libraw_unpack(iprc); - HANDLE_ERRORS(ret); - - ret = libraw_dcraw_process(iprc); - HANDLE_ERRORS(ret); - - snprintf(outfn,1023,"%s.%s",fn,tiff_mode?"tiff":"ppm"); - - if(verbose) fprintf(stderr,"Writing file %s\n",outfn); - ret = libraw_dcraw_ppm_tiff_writer(iprc,outfn); - HANDLE_ERRORS(ret); - count++; - } - libraw_close(iprc); - return NULL; + ret = libraw_open_file(iprc, fn); + if (verbose) + fprintf(stderr, "%s: %s/%s\n", fn, iprc->idata.make, iprc->idata.model); + HANDLE_ERRORS(ret); + + ret = libraw_unpack(iprc); + HANDLE_ERRORS(ret); + + ret = libraw_dcraw_process(iprc); + HANDLE_ERRORS(ret); + + snprintf(outfn, 1023, "%s.%s", fn, tiff_mode ? "tiff" : "ppm"); + + if (verbose) + fprintf(stderr, "Writing file %s\n", outfn); + ret = libraw_dcraw_ppm_tiff_writer(iprc, outfn); + HANDLE_ERRORS(ret); + count++; + } + libraw_close(iprc); + return NULL; } -void usage(const char*p) +void usage(const char *p) { - printf("%s: Multi-threaded LibRaw sample app. Emulates dcraw -h [-w] [-a]\n",p); - printf( - "Options:\n" - "-J n - set parrallel job coun (default 2)\n" - "-v - verbose\n" - "-w - use camera white balance\n" - "-a - average image for white balance\n"); - exit(1); + printf("%s: Multi-threaded LibRaw sample app. Emulates dcraw -h [-w] [-a]\n", p); + printf("Options:\n" + "-J n - set parallel job count (default 2)\n" + "-v - verbose\n" + "-w - use camera white balance\n" + "-a - average image for white balance\n"); + exit(1); } int show_files(void *q) { - char *p; - int cnt = 0; - while((p = get_next_file())) - { - printf("%s\n",p); - cnt++; - } - return cnt; - + char *p; + int cnt = 0; + while ((p = get_next_file())) + { + printf("%s\n", p); + cnt++; + } + return cnt; } int main(int ac, char *av[]) { - int i, max_threads = 2; - pthread_t *threads; - if(ac<2) - usage(av[0]); - - queue = calloc(ac-1,sizeof(queue[0])); - - for (i=1;i #include #include #include #include #include "libraw/libraw.h" #ifdef WIN32 #define snprintf _snprintf #endif - -#define HANDLE_ERRORS(ret) do { \ - if(ret) \ - { \ - fprintf(stderr,"%s: %s\n",fn,libraw_strerror(ret)); \ - if(LIBRAW_FATAL_ERROR(ret)) \ - { \ - libraw_close(iprc); \ - return -1; \ - } \ - } \ - }while(0) - +#define HANDLE_ERRORS(ret) \ + do \ + { \ + if (ret) \ + { \ + fprintf(stderr, "%s: %s\n", fn, libraw_strerror(ret)); \ + if (LIBRAW_FATAL_ERROR(ret)) \ + { \ + libraw_close(iprc); \ + return -1; \ + } \ + } \ + } while (0) // global settings -int verbose=0,use_camera_wb=0,use_auto_wb=0,tiff_mode=0; +int verbose = 0, use_camera_wb = 0, use_auto_wb = 0, tiff_mode = 0; // global file queue HANDLE qmutex; -char **queue=NULL; -size_t qsize=0,qptr=0; +char **queue = NULL; +size_t qsize = 0, qptr = 0; char *get_next_file() { - char *ret; - DWORD dwWaitResult; - if(!queue) return NULL; - if(qptr>=qsize) return NULL; - - dwWaitResult = WaitForSingleObject( - qmutex, // handle to mutex - INFINITE); // no time-out interval - switch (dwWaitResult) - { - // The thread got ownership of the mutex - case WAIT_OBJECT_0: - ret = queue[qptr++]; - ReleaseMutex(qmutex); - break; - case WAIT_ABANDONED: - return NULL; // cannot obtain the lock - }; - return ret; + char *ret; + DWORD dwWaitResult; + if (!queue) + return NULL; + if (qptr >= qsize) + return NULL; + + dwWaitResult = WaitForSingleObject(qmutex, // handle to mutex + INFINITE); // no time-out interval + switch (dwWaitResult) + { + // The thread got ownership of the mutex + case WAIT_OBJECT_0: + ret = queue[qptr++]; + ReleaseMutex(qmutex); + break; + case WAIT_ABANDONED: + return NULL; // cannot obtain the lock + }; + return ret; } - // thread routine int process_files(void *q) { - int ret; - int count=0; - char outfn[1024], *fn; - libraw_data_t *iprc = libraw_init(0); - - if(!iprc) - { - fprintf(stderr,"Cannot create libraw handle\n"); - return -1; - } - - while((fn = get_next_file())) - { - - iprc->params.half_size = 1; /* dcraw -h */ - iprc->params.use_camera_wb = use_camera_wb; - iprc->params.use_auto_wb = use_auto_wb; - iprc->params.output_tiff = tiff_mode; - - ret = libraw_open_file(iprc,fn); - if(verbose) fprintf(stderr,"%s: %s/%s\n",fn,iprc->idata.make,iprc->idata.model); - HANDLE_ERRORS(ret); - - ret = libraw_unpack(iprc); - HANDLE_ERRORS(ret); - - ret = libraw_dcraw_process(iprc); - HANDLE_ERRORS(ret); - - snprintf(outfn,1023,"%s.%s",fn,tiff_mode?"tif":"ppm"); - - if(verbose) fprintf(stderr,"Writing file %s\n",outfn); - ret = libraw_dcraw_ppm_tiff_writer(iprc,outfn); - HANDLE_ERRORS(ret); - count++; - } - libraw_close(iprc); - printf("Processed %d files\n",count); - return 0; + int ret; + int count = 0; + char outfn[1024], *fn; + libraw_data_t *iprc = libraw_init(0); + + if (!iprc) + { + fprintf(stderr, "Cannot create libraw handle\n"); + return -1; + } + + while ((fn = get_next_file())) + { + + iprc->params.half_size = 1; /* dcraw -h */ + iprc->params.use_camera_wb = use_camera_wb; + iprc->params.use_auto_wb = use_auto_wb; + iprc->params.output_tiff = tiff_mode; + + ret = libraw_open_file(iprc, fn); + if (verbose) + fprintf(stderr, "%s: %s/%s\n", fn, iprc->idata.make, iprc->idata.model); + HANDLE_ERRORS(ret); + + ret = libraw_unpack(iprc); + HANDLE_ERRORS(ret); + + ret = libraw_dcraw_process(iprc); + HANDLE_ERRORS(ret); + + snprintf(outfn, 1023, "%s.%s", fn, tiff_mode ? "tif" : "ppm"); + + if (verbose) + fprintf(stderr, "Writing file %s\n", outfn); + ret = libraw_dcraw_ppm_tiff_writer(iprc, outfn); + HANDLE_ERRORS(ret); + count++; + } + libraw_close(iprc); + printf("Processed %d files\n", count); + return 0; } -void usage(const char*p) +void usage(const char *p) { - printf( - "Options:\n" - "-J n - set parrallel job coun (default 2)\n" - "-v - verbose\n" - "-w - use camera white balance\n" - "-T - output TIFF instead of PPM\n" - "-a - average image for white balance\n"); - exit(1); + printf("Options:\n" + "-J n - set parallel job count (default 2)\n" + "-v - verbose\n" + "-w - use camera white balance\n" + "-T - output TIFF instead of PPM\n" + "-a - average image for white balance\n"); + exit(1); } int show_files(void *q) { - char *p; - int cnt = 0; - while(p = get_next_file()) - { - printf("%s\n",p); - cnt++; - } - return cnt; - + char *p; + int cnt = 0; + while (p = get_next_file()) + { + printf("%s\n", p); + cnt++; + } + return cnt; } int main(int ac, char *av[]) { - int i,max_threads = 2; - HANDLE *threads; - DWORD ThreadID; - - if(ac<2) - usage(av[0]); - - queue = calloc(ac-1,sizeof(queue[0])); - - for (i=1;i #include #include #include "libraw/libraw.h" #ifdef WIN32 #define snprintf _snprintf #include #pragma comment(lib, "ws2_32.lib") #else #include #endif - // no error reporting, only params check void write_ppm(libraw_processed_image_t *img, const char *basename) { - if(!img) return; - // type SHOULD be LIBRAW_IMAGE_BITMAP, but we'll check - if(img->type != LIBRAW_IMAGE_BITMAP) return; - // only 3-color images supported... - if(img->colors != 3) return; - - char fn[1024]; - snprintf(fn,1024,"%s.ppm",basename); - FILE *f = fopen(fn,"wb"); - if(!f) return; - fprintf (f, "P6\n%d %d\n%d\n", img->width, img->height, (1 << img->bits)-1); + if (!img) + return; + // type SHOULD be LIBRAW_IMAGE_BITMAP, but we'll check + if (img->type != LIBRAW_IMAGE_BITMAP) + return; + // only 3-color images supported... + if (img->colors != 3) + return; + + char fn[1024]; + snprintf(fn, 1024, "%s.ppm", basename); + FILE *f = fopen(fn, "wb"); + if (!f) + return; + fprintf(f, "P6\n%d %d\n%d\n", img->width, img->height, (1 << img->bits) - 1); /* NOTE: data in img->data is not converted to network byte order. So, we should swap values on some architectures for dcraw compatibility (unfortunately, xv cannot display 16-bit PPMs with network byte order data */ -#define SWAP(a,b) { a ^= b; a ^= (b ^= a); } - if (img->bits == 16 && htons(0x55aa) != 0x55aa) - for(unsigned i=0; i< img->data_size; i+=2) - SWAP(img->data[i],img->data[i+1]); +#define SWAP(a, b) \ + { \ + a ^= b; \ + a ^= (b ^= a); \ + } + if (img->bits == 16 && htons(0x55aa) != 0x55aa) + for (unsigned i = 0; i < img->data_size; i += 2) + SWAP(img->data[i], img->data[i + 1]); #undef SWAP - fwrite(img->data,img->data_size,1,f); - fclose(f); + fwrite(img->data, img->data_size, 1, f); + fclose(f); } void write_thumb(libraw_processed_image_t *img, const char *basename) { - if(!img) return; - - if(img->type == LIBRAW_IMAGE_BITMAP) - { - char fnt[1024]; - snprintf(fnt,1024,"%s.thumb",basename); - write_ppm(img,fnt); - } - else if (img->type == LIBRAW_IMAGE_JPEG) - { - char fn[1024]; - snprintf(fn,1024,"%s.thumb.jpg",basename); - FILE *f = fopen(fn,"wb"); - if(!f) return; - fwrite(img->data,img->data_size,1,f); - fclose(f); - } + if (!img) + return; + + if (img->type == LIBRAW_IMAGE_BITMAP) + { + char fnt[1024]; + snprintf(fnt, 1024, "%s.thumb", basename); + write_ppm(img, fnt); + } + else if (img->type == LIBRAW_IMAGE_JPEG) + { + char fn[1024]; + snprintf(fn, 1024, "%s.thumb.jpg", basename); + FILE *f = fopen(fn, "wb"); + if (!f) + return; + fwrite(img->data, img->data_size, 1, f); + fclose(f); + } } - - int main(int ac, char *av[]) { - int i, ret, output_thumbs=0; + int i, ret, output_thumbs = 0; - // don't use fixed size buffers in real apps! + // don't use fixed size buffers in real apps! - LibRaw RawProcessor; - - if(ac<2) - { - printf( - "mem_image - LibRaw sample, to illustrate work for memory buffers. Emulates dcraw [-4] [-1] [-e] [-h]\n" - "Usage: %s [-D] [-T] [-v] [-e] raw-files....\n" - "\t-6 - output 16-bit PPM\n" - "\t-4 - linear 16-bit data\n" - "\t-e - extract thumbnails (same as dcraw -e in separate run)\n", - "\t-h - use half_size\n"); - return 0; - } + LibRaw RawProcessor; + + if (ac < 2) + { + printf("mem_image - LibRaw sample, to illustrate work for memory buffers. Emulates dcraw [-4] [-1] [-e] [-h]\n" + "Usage: %s [-D] [-T] [-v] [-e] raw-files....\n" + "\t-6 - output 16-bit PPM\n" + "\t-4 - linear 16-bit data\n" + "\t-e - extract thumbnails (same as dcraw -e in separate run)\n", + "\t-h - use half_size\n"); + return 0; + } + + putenv((char *)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field - putenv ((char*)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field - #define P1 RawProcessor.imgdata.idata #define S RawProcessor.imgdata.sizes #define C RawProcessor.imgdata.color #define T RawProcessor.imgdata.thumbnail #define P2 RawProcessor.imgdata.other #define OUT RawProcessor.imgdata.params - - for (i=1;i #include #include #ifndef WIN32 #include #include #include #include #endif #include "libraw/libraw.h" #ifdef WIN32 #define snprintf _snprintf #endif -int process_once(LibRaw& RawProcessor, int half_mode, int camera_wb, int auto_wb, int suffix, int user_flip,char *fname) +int process_once(LibRaw &RawProcessor, int half_mode, int camera_wb, int auto_wb, int suffix, int user_flip, + char *fname) { - char outfn[1024]; - RawProcessor.imgdata.params.half_size = half_mode; - RawProcessor.imgdata.params.use_camera_wb = camera_wb; - RawProcessor.imgdata.params.use_auto_wb = auto_wb; - RawProcessor.imgdata.params.user_flip = user_flip; - - int ret = RawProcessor.dcraw_process(); - - if(LIBRAW_SUCCESS !=ret) - { - fprintf(stderr,"Cannot do postpocessing on %s: %s\n", - fname,libraw_strerror(ret)); - return ret; - } - snprintf(outfn,sizeof(outfn),"%s.%d.%s", fname, suffix, (RawProcessor.imgdata.idata.colors>1?"ppm":"pgm")); - - printf("Writing file %s\n",outfn); - - if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn))) - fprintf(stderr,"Cannot write %s: %s\n",outfn,libraw_strerror(ret)); + char outfn[1024]; + RawProcessor.imgdata.params.half_size = half_mode; + RawProcessor.imgdata.params.use_camera_wb = camera_wb; + RawProcessor.imgdata.params.use_auto_wb = auto_wb; + RawProcessor.imgdata.params.user_flip = user_flip; + + int ret = RawProcessor.dcraw_process(); + + if (LIBRAW_SUCCESS != ret) + { + fprintf(stderr, "Cannot do postpocessing on %s: %s\n", fname, libraw_strerror(ret)); return ret; -} + } + snprintf(outfn, sizeof(outfn), "%s.%d.%s", fname, suffix, (RawProcessor.imgdata.idata.colors > 1 ? "ppm" : "pgm")); + printf("Writing file %s\n", outfn); + if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn))) + fprintf(stderr, "Cannot write %s: %s\n", outfn, libraw_strerror(ret)); + return ret; +} int main(int ac, char *av[]) { - int i, ret; - - LibRaw RawProcessor; - if(ac<2) - { - printf( - "multirender_test - LibRaw %s sample. Performs 4 different renderings of one file\n" - " %d cameras supported\n" - "Usage: %s raw-files....\n" - ,LibRaw::version(), LibRaw::cameraCount(), - av[0]); - return 0; - } - - for (i=1;i +#include +#include + +#ifndef WIN32 +#include +#include +#include +#include +#endif + +#include "libraw/libraw.h" + +int main(int ac, char *av[]) +{ + if (ac != 2) + return 1; + FILE *in = fopen(av[1], "rb"); + fseek(in, 0, SEEK_END); + unsigned fsz = ftell(in); + unsigned char *buffer = (unsigned char *)malloc(fsz); + if (!buffer) + return 2; + fseek(in, 0, SEEK_SET); + unsigned readb = fread(buffer, 1, fsz, in); + if (readb != fsz) + return 3; + LibRaw rp; + rp.imgdata.params.output_tiff = 1; + int ret = rp.open_bayer(buffer, fsz, 640, 480, 0, 0, 0, 0, 0, LIBRAW_OPENBAYER_RGGB, 0, 0, 1400); + if (ret != LIBRAW_SUCCESS) + return 4; + if ((ret = rp.unpack()) != LIBRAW_SUCCESS) + printf("Unpack error: %d\n", ret); + + if ((ret = rp.dcraw_process()) != LIBRAW_SUCCESS) + printf("Processing error: %d\n", ret); + + char outfn[256]; + sprintf(outfn, "%s.tif", av[1]); + if (LIBRAW_SUCCESS != (ret = rp.dcraw_ppm_tiff_writer(outfn))) + printf("Cannot write %s: %s\n", outfn, libraw_strerror(ret)); + else + printf("Created %s\n", outfn); +} \ No newline at end of file diff --git a/core/libs/rawengine/libraw/samples/postprocessing_benchmark.cpp b/core/libs/rawengine/libraw/samples/postprocessing_benchmark.cpp index 78a2b13c13..a4fa33903b 100644 --- a/core/libs/rawengine/libraw/samples/postprocessing_benchmark.cpp +++ b/core/libs/rawengine/libraw/samples/postprocessing_benchmark.cpp @@ -1,217 +1,209 @@ /* -*- C++ -*- * File: postprocessing_benchmark.cpp - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) * Created: Jul 13, 2011 * * LibRaw simple C++ API: creates 8 different renderings from 1 source file. The 1st and 4th one should be identical LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #include #include #include #ifndef WIN32 #include #include #include #else #include #endif #include "libraw/libraw.h" void timerstart(void); float timerend(void); - int main(int argc, char *argv[]) { - int i, ret,rep=1; - LibRaw RawProcessor; + int i, ret, rep = 1; + LibRaw RawProcessor; #ifdef OUT #undef OUT #endif #define OUT RawProcessor.imgdata.params #define S RawProcessor.imgdata.sizes - if(argc<2) - { - printf( - "postprocessing benchmark: LibRaw %s sample, %d cameras supported\n" - "Measures postprocessing speed with different options\n" - "Usage: %s [-a] [-H N] [-q N] [-h] [-m N] [-n N] [-s N] [-B x y w h] [-R N]\n" - "-a average image for white balance\n" - "-H Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)\n" - "-q Set the interpolation quality\n" - "-h Half-size color image\n" - "-m Apply a num-passes 3x3 median filter to R-G and B-G\n" - "-n Set threshold for wavelet denoising\n" - "-s Select one raw image from input file\n" - "-B Crop output image\n" - "-R Number of repetitions\n" - "-c Do not use rawspeed\n" - ,LibRaw::version(), LibRaw::cameraCount(), - argv[0]); - return 0; - } - char opm,opt,*cp,*sp; - int arg,c; - int shrink = 0; - - argv[argc] = (char*)""; - for (arg=1; (((opm = argv[arg][0]) - 2) | 2) == '+'; ) - { - char *optstr = argv[arg]; - opt = argv[arg++][1]; - if ((cp = strchr (sp=(char*)"HqmnsBR", opt))!=0) - for (i=0; i < "1111141"[cp-sp]-'0'; i++) - if (!isdigit(argv[arg+i][0]) && !optstr[2]) - { - fprintf (stderr,"Non-numeric argument to \"-%c\"\n", opt); - return 1; - } - switch (opt) - { - case 'a': - OUT.use_auto_wb = 1; - break; - case 'H': - OUT.highlight = atoi(argv[arg++]); - break; - case 'q': - OUT.user_qual = atoi(argv[arg++]); - break; - case 'h': - OUT.half_size = 1; - OUT.four_color_rgb = 1; - shrink = 1; - break; - case 'm': - OUT.med_passes = atoi(argv[arg++]); - break; - case 'n': - OUT.threshold = (float)atof(argv[arg++]); - break; - case 's': - OUT.shot_select = abs(atoi(argv[arg++])); - break; - case 'B': - for(c=0; c<4;c++) OUT.cropbox[c] = atoi(argv[arg++]); - break; - case 'R': - rep = abs(atoi(argv[arg++])); - if(rep<1) rep = 1; - break; - case 'c': - OUT.use_rawspeed = 0; - break; - default: - fprintf (stderr,"Unknown option \"-%c\".\n", opt); - return 1; - } - } - for ( ; arg < argc; arg++) + if (argc < 2) + { + printf("postprocessing benchmark: LibRaw %s sample, %d cameras supported\n" + "Measures postprocessing speed with different options\n" + "Usage: %s [-a] [-H N] [-q N] [-h] [-m N] [-n N] [-s N] [-B x y w h] [-R N]\n" + "-a average image for white balance\n" + "-H Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)\n" + "-q Set the interpolation quality\n" + "-h Half-size color image\n" + "-m Apply a num-passes 3x3 median filter to R-G and B-G\n" + "-n Set threshold for wavelet denoising\n" + "-s Select one raw image from input file\n" + "-B Crop output image\n" + "-R Number of repetitions\n" + "-c Do not use rawspeed\n", + LibRaw::version(), LibRaw::cameraCount(), argv[0]); + return 0; + } + char opm, opt, *cp, *sp; + int arg, c; + int shrink = 0; + + argv[argc] = (char *)""; + for (arg = 1; (((opm = argv[arg][0]) - 2) | 2) == '+';) + { + char *optstr = argv[arg]; + opt = argv[arg++][1]; + if ((cp = strchr(sp = (char *)"HqmnsBR", opt)) != 0) + for (i = 0; i < "1111141"[cp - sp] - '0'; i++) + if (!isdigit(argv[arg + i][0]) && !optstr[2]) { - printf("Processing file %s\n",argv[arg]); - timerstart(); - if( (ret = RawProcessor.open_file(argv[arg])) != LIBRAW_SUCCESS) - { - fprintf(stderr,"Cannot open_file %s: %s\n",argv[arg],libraw_strerror(ret)); - continue; // no recycle b/c open file will recycle itself - } - - if( (ret = RawProcessor.unpack() ) != LIBRAW_SUCCESS) - { - fprintf(stderr,"Cannot unpack %s: %s\n",argv[arg],libraw_strerror(ret)); - continue; - } - float qsec = timerend(); - printf("\n%.1f msec for unpack\n",qsec); - float mpix,rmpix; - timerstart(); - for(c=0; c < rep; c++) - { - if( (ret = RawProcessor.dcraw_process() ) != LIBRAW_SUCCESS) - { - fprintf(stderr,"Cannot postprocess %s: %s\n",argv[arg],libraw_strerror(ret)); - break; - } - libraw_processed_image_t *p = RawProcessor.dcraw_make_mem_image(); - if(p) - RawProcessor.dcraw_clear_mem(p); - RawProcessor.free_image(); - } - float msec = timerend()/(float)rep; - - if( (ret = RawProcessor.adjust_sizes_info_only() ) != LIBRAW_SUCCESS) - { - fprintf(stderr,"Cannot adjust sizes for %s: %s\n",argv[arg],libraw_strerror(ret)); - break; - } - rmpix = (S.iwidth*S.iheight)/1000000.0f; - - if(c==rep) // no failure - { - unsigned int crop[4]; - for(int i=0;i<4;i++) crop[i] = (OUT.cropbox[i])>>shrink; - if(crop[0]+crop[2]>S.iwidth) crop[2] = S.iwidth-crop[0]; - if(crop[1]+crop[3]>S.iheight) crop[3] = S.iheight-crop[1]; - - mpix = float(crop[2]*crop[3])/1000000.0f; - float mpixsec = mpix*1000.0f/msec; - - printf( - "Performance: %.2f Mpix/sec\n" - "File: %s, Frame: %d %.1f total Mpix, %.1f msec\n" - "Params: WB=%s Highlight=%d Qual=%d HalfSize=%s Median=%d Wavelet=%.0f\n" - "Crop: %u-%u:%ux%u, active Mpix: %.2f, %.1f frames/sec\n", - mpixsec - ,argv[arg],OUT.shot_select,rmpix,msec, - OUT.use_auto_wb?"auto":"default",OUT.highlight,OUT.user_qual,OUT.half_size?"YES":"No", - OUT.med_passes,OUT.threshold, - crop[0],crop[1],crop[2],crop[3],mpix,1000.0f/msec); - } + fprintf(stderr, "Non-numeric argument to \"-%c\"\n", opt); + return 1; } - - return 0; + switch (opt) + { + case 'a': + OUT.use_auto_wb = 1; + break; + case 'H': + OUT.highlight = atoi(argv[arg++]); + break; + case 'q': + OUT.user_qual = atoi(argv[arg++]); + break; + case 'h': + OUT.half_size = 1; + OUT.four_color_rgb = 1; + shrink = 1; + break; + case 'm': + OUT.med_passes = atoi(argv[arg++]); + break; + case 'n': + OUT.threshold = (float)atof(argv[arg++]); + break; + case 's': + OUT.shot_select = abs(atoi(argv[arg++])); + break; + case 'B': + for (c = 0; c < 4; c++) + OUT.cropbox[c] = atoi(argv[arg++]); + break; + case 'R': + rep = abs(atoi(argv[arg++])); + if (rep < 1) + rep = 1; + break; + case 'c': + OUT.use_rawspeed = 0; + break; + default: + fprintf(stderr, "Unknown option \"-%c\".\n", opt); + return 1; + } + } + for (; arg < argc; arg++) + { + printf("Processing file %s\n", argv[arg]); + timerstart(); + if ((ret = RawProcessor.open_file(argv[arg])) != LIBRAW_SUCCESS) + { + fprintf(stderr, "Cannot open_file %s: %s\n", argv[arg], libraw_strerror(ret)); + continue; // no recycle b/c open file will recycle itself + } + + if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS) + { + fprintf(stderr, "Cannot unpack %s: %s\n", argv[arg], libraw_strerror(ret)); + continue; + } + float qsec = timerend(); + printf("\n%.1f msec for unpack\n", qsec); + float mpix, rmpix; + timerstart(); + for (c = 0; c < rep; c++) + { + if ((ret = RawProcessor.dcraw_process()) != LIBRAW_SUCCESS) + { + fprintf(stderr, "Cannot postprocess %s: %s\n", argv[arg], libraw_strerror(ret)); + break; + } + libraw_processed_image_t *p = RawProcessor.dcraw_make_mem_image(); + if (p) + RawProcessor.dcraw_clear_mem(p); + RawProcessor.free_image(); + } + float msec = timerend() / (float)rep; + + if ((ret = RawProcessor.adjust_sizes_info_only()) != LIBRAW_SUCCESS) + { + fprintf(stderr, "Cannot adjust sizes for %s: %s\n", argv[arg], libraw_strerror(ret)); + break; + } + rmpix = (S.iwidth * S.iheight) / 1000000.0f; + + if (c == rep) // no failure + { + unsigned int crop[4]; + for (int i = 0; i < 4; i++) + crop[i] = (OUT.cropbox[i]) >> shrink; + if (crop[0] + crop[2] > S.iwidth) + crop[2] = S.iwidth - crop[0]; + if (crop[1] + crop[3] > S.iheight) + crop[3] = S.iheight - crop[1]; + + mpix = float(crop[2] * crop[3]) / 1000000.0f; + float mpixsec = mpix * 1000.0f / msec; + + printf("Performance: %.2f Mpix/sec\n" + "File: %s, Frame: %d %.1f total Mpix, %.1f msec\n" + "Params: WB=%s Highlight=%d Qual=%d HalfSize=%s Median=%d Wavelet=%.0f\n" + "Crop: %u-%u:%ux%u, active Mpix: %.2f, %.1f frames/sec\n", + mpixsec, argv[arg], OUT.shot_select, rmpix, msec, OUT.use_auto_wb ? "auto" : "default", OUT.highlight, + OUT.user_qual, OUT.half_size ? "YES" : "No", OUT.med_passes, OUT.threshold, crop[0], crop[1], crop[2], + crop[3], mpix, 1000.0f / msec); + } + } + + return 0; } - #ifndef WIN32 -static struct timeval start,end; -void timerstart(void) -{ - gettimeofday(&start,NULL); -} +static struct timeval start, end; +void timerstart(void) { gettimeofday(&start, NULL); } float timerend(void) { - gettimeofday(&end,NULL); - float msec = (end.tv_sec - start.tv_sec)*1000.0f + (end.tv_usec - start.tv_usec)/1000.0f; - return msec; + gettimeofday(&end, NULL); + float msec = (end.tv_sec - start.tv_sec) * 1000.0f + (end.tv_usec - start.tv_usec) / 1000.0f; + return msec; } #else LARGE_INTEGER start; -void timerstart(void) -{ - QueryPerformanceCounter(&start); -} +void timerstart(void) { QueryPerformanceCounter(&start); } float timerend() { - LARGE_INTEGER unit,end; - QueryPerformanceCounter(&end); - QueryPerformanceFrequency(&unit); - float msec = (float)(end.QuadPart - start.QuadPart); - msec /= (float)unit.QuadPart/1000.0f; - return msec; + LARGE_INTEGER unit, end; + QueryPerformanceCounter(&end); + QueryPerformanceFrequency(&unit); + float msec = (float)(end.QuadPart - start.QuadPart); + msec /= (float)unit.QuadPart / 1000.0f; + return msec; } #endif diff --git a/core/libs/rawengine/libraw/samples/raw-identify.cpp b/core/libs/rawengine/libraw/samples/raw-identify.cpp index bc3b38628d..d8eadc7afb 100644 --- a/core/libs/rawengine/libraw/samples/raw-identify.cpp +++ b/core/libs/rawengine/libraw/samples/raw-identify.cpp @@ -1,569 +1,843 @@ /* -*- C++ -*- * File: identify.cpp - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) * Created: Sat Mar 8, 2008 * * LibRaw C++ demo: emulates dcraw -i [-v] * LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #include #include #include #include #include "libraw/libraw.h" #ifdef WIN32 #define snprintf _snprintf #define strcasecmp stricmp #define strncasecmp strnicmp #endif #define P1 MyCoolRawProcessor.imgdata.idata #define P2 MyCoolRawProcessor.imgdata.other #define mnLens MyCoolRawProcessor.imgdata.lens.makernotes #define exifLens MyCoolRawProcessor.imgdata.lens #define ShootingInfo MyCoolRawProcessor.imgdata.shootinginfo -#define S MyCoolRawProcessor.imgdata.sizes -#define O MyCoolRawProcessor.imgdata.params -#define C MyCoolRawProcessor.imgdata.color -#define T MyCoolRawProcessor.imgdata.thumbnail +#define S MyCoolRawProcessor.imgdata.sizes +#define O MyCoolRawProcessor.imgdata.params +#define C MyCoolRawProcessor.imgdata.color +#define T MyCoolRawProcessor.imgdata.thumbnail #define Canon MyCoolRawProcessor.imgdata.makernotes.canon -#define Fuji MyCoolRawProcessor.imgdata.makernotes.fuji -#define Oly MyCoolRawProcessor.imgdata.makernotes.olympus +#define Hasselblad MyCoolRawProcessor.imgdata.makernotes.hasselblad +#define Fuji MyCoolRawProcessor.imgdata.makernotes.fuji +#define Nikon MyCoolRawProcessor.imgdata.makernotes.nikon +#define Oly MyCoolRawProcessor.imgdata.makernotes.olympus +#define Sony MyCoolRawProcessor.imgdata.makernotes.sony const char *EXIF_LightSources[] = { - "Unknown", - "Daylight", - "Fluorescent", - "Tungsten", - "Flash", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Fine Weather", - "Cloudy", - "Shade", - "Daylight Fluorescent D", - "Day White Fluorescent N", - "Cool White Fluorescent W", - "White Fluorescent WW", - "Warm White Fluorescent L", - "Illuminant A", - "Illuminant B", - "Illuminant C", - "D55", - "D65", - "D75", - "D50", - "ISO Studio Tungsten", + "Unknown", + "Daylight", + "Fluorescent", + "Tungsten", + "Flash", + "Reserved", + "Reserved", + "Reserved", + "Reserved", + "Fine Weather", + "Cloudy", + "Shade", + "Daylight Fluorescent D", + "Day White Fluorescent N", + "Cool White Fluorescent W", + "White Fluorescent WW", + "Warm White Fluorescent L", + "Illuminant A", + "Illuminant B", + "Illuminant C", + "D55", + "D65", + "D75", + "D50", + "ISO Studio Tungsten", }; /* table of fluorescents: 12 = FL-D; Daylight fluorescent (D 5700K – 7100K) (F1,F5) 13 = FL-N; Day white fluorescent (N 4600K – 5400K) (F7,F8) 14 = FL-W; Cool white fluorescent (W 3900K – 4500K) (F2,F6, office, store, warehouse) 15 = FL-WW; White fluorescent (WW 3200K – 3700K) (F3, residential) 16 = FL-L; Soft/Warm white fluorescent (L 2600K - 3250K) (F4, kitchen, bath) */ const char *WB_LightSources[] = { - "Unknown", - "Daylight", - "Fluorescent", - "Tungsten", - "Flash", - "Reserved", - "Reserved", - "Reserved", - "Reserved", - "Fine Weather", - "Cloudy", - "Shade", - "FL-D", - "FL-N", - "FL-W", - "FL-WW", - "FL-L", - "Ill. A", - "Ill. B", - "Ill. C", - "D55", - "D65", - "D75", - "D50", - "Studio Tungsten", + "Unknown", "Daylight", "Fluorescent", "Tungsten", "Flash", "Reserved", "Reserved", + "Reserved", "Reserved", "Fine Weather", "Cloudy", "Shade", "FL-D", "FL-N", + "FL-W", "FL-WW", "FL-L", "Ill. A", "Ill. B", "Ill. C", "D55", + "D65", "D75", "D50", "Studio Tungsten", }; void trimSpaces(char *s) { char *p = s; - if (!strncasecmp(p, "NO=", 3)) p = p+3; /* fix for Nikon D70, D70s */ + if (!strncasecmp(p, "NO=", 3)) + p = p + 3; /* fix for Nikon D70, D70s */ int l = strlen(p); - if(!l) return; - while(isspace(p[l - 1])) p[--l] = 0; /* trim trailing spaces */ - while(*p && isspace(*p)) ++p, --l; /* trim leading spaces */ + if (!l) + return; + while (isspace(p[l - 1])) + p[--l] = 0; /* trim trailing spaces */ + while (*p && isspace(*p)) + ++p, --l; /* trim leading spaces */ memmove(s, p, l + 1); } int main(int ac, char *av[]) { - int verbose = 0, ret,print_unpack=0,print_frame=0,print_wb=0; - int compact = 0; - LibRaw MyCoolRawProcessor; - - for (int i=1;i= 0; i -= 8) + printf("%d%c", P1.dng_version >> i & 255, i ? '.' : '\n'); + } + printf("\nEXIF:\n"); + printf("\tMinFocal: %0.1f mm\n", exifLens.MinFocal); + printf("\tMaxFocal: %0.1f mm\n", exifLens.MaxFocal); + printf("\tMaxAp @MinFocal: f/%0.1f\n", exifLens.MaxAp4MinFocal); + printf("\tMaxAp @MaxFocal: f/%0.1f\n", exifLens.MaxAp4MaxFocal); + printf("\tMaxAperture @CurFocal: f/%0.1f\n", exifLens.EXIF_MaxAp); + printf("\tFocalLengthIn35mmFormat: %d mm\n", exifLens.FocalLengthIn35mmFormat); + printf("\tLensMake: %s\n", exifLens.LensMake); + printf("\tLens: %s\n", exifLens.Lens); + printf("\n"); + + printf("\nMakernotes:\n"); + printf("\tDriveMode: %d\n", ShootingInfo.DriveMode); + printf("\tFocusMode: %d\n", ShootingInfo.FocusMode); + printf("\tMeteringMode: %d\n", ShootingInfo.MeteringMode); + printf("\tAFPoint: %d\n", ShootingInfo.AFPoint); + printf("\tExposureMode: %d\n", ShootingInfo.ExposureMode); + printf("\tImageStabilization: %d\n", ShootingInfo.ImageStabilization); + if (mnLens.body[0]) + { + printf("\tMF Camera Body: %s\n", mnLens.body); + } + printf("\tCameraFormat: %d, ", mnLens.CameraFormat); + switch (mnLens.CameraFormat) + { + case 0: + printf("Undefined\n"); + break; + case 1: + printf("APS-C\n"); + break; + case 2: + printf("FF\n"); + break; + case 3: + printf("MF\n"); + break; + case 4: + printf("APS-H\n"); + break; + case 5: + printf("1\"\n"); + break; + case 8: + printf("4/3\n"); + break; + default: + printf("Unknown\n"); + break; + } + printf("\tCameraMount: %d, ", mnLens.CameraMount); + switch (mnLens.CameraMount) + { + case 0: + printf("Undefined or Fixed Lens\n"); + break; + case 1: + printf("Sony/Minolta A\n"); + break; + case 2: + printf("Sony E\n"); + break; + case 3: + printf("Canon EF\n"); + break; + case 4: + printf("Canon EF-S\n"); + break; + case 5: + printf("Canon EF-M\n"); + break; + case 6: + printf("Nikon F\n"); + break; + case 7: + printf("Nikon CX\n"); + break; + case 8: + printf("4/3\n"); + break; + case 9: + printf("m4/3\n"); + break; + case 10: + printf("Pentax K\n"); + break; + case 11: + printf("Pentax Q\n"); + break; + case 12: + printf("Pentax 645\n"); + break; + case 13: + printf("Fuji X\n"); + break; + case 14: + printf("Leica M\n"); + break; + case 15: + printf("Leica R\n"); + break; + case 16: + printf("Leica S\n"); + break; + case 17: + printf("Samsung NX\n"); + break; + case 19: + printf("Samsung NX-M\n"); + break; + case 99: + printf("Fixed Lens\n"); + break; + default: + printf("Unknown\n"); + break; + } + + if (mnLens.LensID == -1) + { + printf("\tLensID: n/a\n"); + } + else + { + printf("\tLensID: %llu 0x%0llx\n", mnLens.LensID, mnLens.LensID); + } + printf("\tLens: %s\n", mnLens.Lens); + printf("\tLensFormat: %d, ", mnLens.LensFormat); + switch (mnLens.LensFormat) + { + case 0: + printf("Undefined\n"); + break; + case 1: + printf("APS-C\n"); + break; + case 2: + printf("FF\n"); + break; + case 3: + printf("MF\n"); + break; + case 8: + printf("4/3\n"); + break; + default: + printf("Unknown\n"); + break; + } + printf("\tLensMount: %d, ", mnLens.LensMount); + switch (mnLens.LensMount) + { + case 0: + printf("Undefined or Fixed Lens\n"); + break; + case 1: + printf("Sony/Minolta A\n"); + break; + case 2: + printf("Sony E\n"); + break; + case 3: + printf("Canon EF\n"); + break; + case 4: + printf("Canon EF-S\n"); + break; + case 5: + printf("Canon EF-M\n"); + break; + case 6: + printf("Nikon F\n"); + break; + case 7: + printf("Nikon CX\n"); + break; + case 8: + printf("4/3\n"); + break; + case 9: + printf("m4/3\n"); + break; + case 10: + printf("Pentax K\n"); + break; + case 11: + printf("Pentax Q\n"); + break; + case 12: + printf("Pentax 645\n"); + break; + case 13: + printf("Fuji X\n"); + break; + case 14: + printf("Leica M\n"); + break; + case 15: + printf("Leica R\n"); + break; + case 16: + printf("Leica S\n"); + break; + case 17: + printf("Samsung NX\n"); + break; + case 18: + printf("Ricoh module\n"); + break; + case 99: + printf("Fixed Lens\n"); + break; + default: + printf("Unknown\n"); + break; + } + printf("\tFocalType: %d, ", mnLens.FocalType); + switch (mnLens.FocalType) + { + case 0: + printf("Undefined\n"); + break; + case 1: + printf("Fixed Focal\n"); + break; + case 2: + printf("Zoom\n"); + break; + default: + printf("Unknown\n"); + break; + } + printf("\tLensFeatures_pre: %s\n", mnLens.LensFeatures_pre); + printf("\tLensFeatures_suf: %s\n", mnLens.LensFeatures_suf); + printf("\tMinFocal: %0.1f mm\n", mnLens.MinFocal); + printf("\tMaxFocal: %0.1f mm\n", mnLens.MaxFocal); + printf("\tMaxAp @MinFocal: f/%0.1f\n", mnLens.MaxAp4MinFocal); + printf("\tMaxAp @MaxFocal: f/%0.1f\n", mnLens.MaxAp4MaxFocal); + printf("\tMinAp @MinFocal: f/%0.1f\n", mnLens.MinAp4MinFocal); + printf("\tMinAp @MaxFocal: f/%0.1f\n", mnLens.MinAp4MaxFocal); + printf("\tMaxAp: f/%0.1f\n", mnLens.MaxAp); + printf("\tMinAp: f/%0.1f\n", mnLens.MinAp); + printf("\tCurFocal: %0.1f mm\n", mnLens.CurFocal); + printf("\tCurAp: f/%0.1f\n", mnLens.CurAp); + printf("\tMaxAp @CurFocal: f/%0.1f\n", mnLens.MaxAp4CurFocal); + printf("\tMinAp @CurFocal: f/%0.1f\n", mnLens.MinAp4CurFocal); + + if (exifLens.makernotes.FocalLengthIn35mmFormat > 1.0f) + printf("\tFocalLengthIn35mmFormat: %0.1f mm\n", exifLens.makernotes.FocalLengthIn35mmFormat); + + if (exifLens.nikon.NikonEffectiveMaxAp > 0.1f) + printf("\tNikonEffectiveMaxAp: f/%0.1f\n", exifLens.nikon.NikonEffectiveMaxAp); + + if (exifLens.makernotes.LensFStops > 0.1f) + printf("\tLensFStops @CurFocal: %0.2f\n", exifLens.makernotes.LensFStops); + + printf("\tTeleconverterID: %lld\n", mnLens.TeleconverterID); + printf("\tTeleconverter: %s\n", mnLens.Teleconverter); + printf("\tAdapterID: %lld\n", mnLens.AdapterID); + printf("\tAdapter: %s\n", mnLens.Adapter); + printf("\tAttachmentID: %lld\n", mnLens.AttachmentID); + printf("\tAttachment: %s\n", mnLens.Attachment); + printf("\n"); + + printf("ISO speed: %d\n", (int)P2.iso_speed); + if (P2.real_ISO > 0.1f) + printf("real ISO speed: %d\n", (int)P2.real_ISO); + printf("Shutter: "); + if (P2.shutter > 0 && P2.shutter < 1) + P2.shutter = (printf("1/"), 1 / P2.shutter); + printf("%0.1f sec\n", P2.shutter); + printf("Aperture: f/%0.1f\n", P2.aperture); + printf("Focal length: %0.1f mm\n", P2.focal_len); + if (P2.exifAmbientTemperature > -273.15f) + printf("Ambient temperature (exif data): %6.2f° C\n", P2.exifAmbientTemperature); + if (P2.CameraTemperature > -273.15f) + printf("Camera temperature: %6.2f° C\n", P2.CameraTemperature); + if (P2.SensorTemperature > -273.15f) + printf("Sensor temperature: %6.2f° C\n", P2.SensorTemperature); + if (P2.SensorTemperature2 > -273.15f) + printf("Sensor temperature2: %6.2f° C\n", P2.SensorTemperature2); + if (P2.LensTemperature > -273.15f) + printf("Lens temperature: %6.2f° C\n", P2.LensTemperature); + if (P2.AmbientTemperature > -273.15f) + printf("Ambient temperature: %6.2f° C\n", P2.AmbientTemperature); + if (P2.BatteryTemperature > -273.15f) + printf("Battery temperature: %6.2f° C\n", P2.BatteryTemperature); + if (P2.FlashGN > 1.0f) + printf("Flash Guide Number: %6.2f\n", P2.FlashGN); + printf("Flash exposure compensation: %0.2f EV\n", P2.FlashEC); + if (C.profile) + printf("Embedded ICC profile: yes, %d bytes\n", C.profile_length); + else + printf("Embedded ICC profile: no\n"); + + if (C.baseline_exposure > -999.f) + printf("Baseline exposure: %04.3f\n", C.baseline_exposure); + + printf("Number of raw images: %d\n", P1.raw_count); + if (Fuji.FujiExpoMidPointShift > -999.f) + printf("Fuji Exposure shift: %04.3f\n", Fuji.FujiExpoMidPointShift); + + if (Fuji.FujiDynamicRange != 0xffff) + printf("Fuji Dynamic Range: %d\n", Fuji.FujiDynamicRange); + if (Fuji.FujiFilmMode != 0xffff) + printf("Fuji Film Mode: %d\n", Fuji.FujiFilmMode); + if (Fuji.FujiDynamicRangeSetting != 0xffff) + printf("Fuji Dynamic Range Setting: %d\n", Fuji.FujiDynamicRangeSetting); + if (Fuji.FujiDevelopmentDynamicRange != 0xffff) + printf("Fuji Development Dynamic Range: %d\n", Fuji.FujiDevelopmentDynamicRange); + if (Fuji.FujiAutoDynamicRange != 0xffff) + printf("Fuji Auto Dynamic Range: %d\n", Fuji.FujiAutoDynamicRange); + + if (S.pixel_aspect != 1) + printf("Pixel Aspect Ratio: %0.6f\n", S.pixel_aspect); + if (T.tlength) + printf("Thumb size: %4d x %d\n", T.twidth, T.theight); + printf("Full size: %4d x %d\n", S.raw_width, S.raw_height); + + if (S.raw_crop.cwidth) + { + printf("Raw crop, width x height: %4d x %d ", S.raw_crop.cwidth, S.raw_crop.cheight); + if (S.raw_crop.cleft != 0xffff) + printf("left: %d ", S.raw_crop.cleft); + if (S.raw_crop.ctop != 0xffff) + printf("top: %d", S.raw_crop.ctop); + printf("\n"); + } + + printf("Image size: %4d x %d\n", S.width, S.height); + printf("Output size: %4d x %d\n", S.iwidth, S.iheight); + + if (Canon.SensorWidth) + printf("SensorWidth = %d\n", Canon.SensorWidth); + if (Canon.SensorHeight) + printf("SensorHeight = %d\n", Canon.SensorHeight); + if (Canon.SensorLeftBorder) + printf("SensorLeftBorder = %d\n", Canon.SensorLeftBorder); + if (Canon.SensorTopBorder) + printf("SensorTopBorder = %d\n", Canon.SensorTopBorder); + if (Canon.SensorRightBorder) + printf("SensorRightBorder = %d\n", Canon.SensorRightBorder); + if (Canon.SensorBottomBorder) + printf("SensorBottomBorder = %d\n", Canon.SensorBottomBorder); + if (Canon.BlackMaskLeftBorder) + printf("BlackMaskLeftBorder = %d\n", Canon.BlackMaskLeftBorder); + if (Canon.BlackMaskTopBorder) + printf("BlackMaskTopBorder = %d\n", Canon.BlackMaskTopBorder); + if (Canon.BlackMaskRightBorder) + printf("BlackMaskRightBorder = %d\n", Canon.BlackMaskRightBorder); + if (Canon.BlackMaskBottomBorder) + printf("BlackMaskBottomBorder= %d\n", Canon.BlackMaskBottomBorder); + if (Canon.ChannelBlackLevel[0]) + printf("ChannelBlackLevel (from makernotes): %d %d %d %d\n", Canon.ChannelBlackLevel[0], + Canon.ChannelBlackLevel[1], Canon.ChannelBlackLevel[2], Canon.ChannelBlackLevel[3]); + + if (Hasselblad.BaseISO) + printf("Hasselblad base ISO: %d\n", Hasselblad.BaseISO); + if (Hasselblad.Gain) + printf("Hasselblad gain: %g\n", Hasselblad.Gain); + + if (Oly.OlympusCropID != -1) + { + printf("Olympus aspect ID: %d\nOlympus crop", Oly.OlympusCropID); + for (int c = 0; c < 4; c++) + printf(" %d", Oly.OlympusFrame[c]); + printf("\n"); + } + + printf("Raw colors: %d", P1.colors); + if (P1.filters) + { + printf("\nFilter pattern: "); + if (!P1.cdesc[3]) + P1.cdesc[3] = 'G'; + for (int i = 0; i < 16; i++) + putchar(P1.cdesc[MyCoolRawProcessor.fcol(i >> 1, i & 1)]); + } + if (C.linear_max[0] != 0) + { + printf("\nHighlight linearity limits:"); + for (int c = 0; c < 4; c++) + printf(" %ld", C.linear_max[c]); + } + if (C.cam_mul[0] > 0) + { + printf("\nMakernotes 'As shot' WB multipliers:"); + for (int c = 0; c < 4; c++) + printf(" %f", C.cam_mul[c]); + } + + for (int cnt = 0; cnt < 25; cnt++) + { + if (C.WB_Coeffs[cnt][0] > 0) + { + printf("\nMakernotes '%s' WB multipliers:", EXIF_LightSources[cnt]); + for (int c = 0; c < 4; c++) + printf(" %d", C.WB_Coeffs[cnt][c]); + } + } + if (C.WB_Coeffs[LIBRAW_WBI_Sunset][0] > 0) + { + printf("\nMakernotes 'Sunset' multipliers:"); + for (int c = 0; c < 4; c++) + printf(" %d", C.WB_Coeffs[LIBRAW_WBI_Sunset][c]); + } + + if (C.WB_Coeffs[LIBRAW_WBI_Other][0] > 0) + { + printf("\nMakernotes 'Other' multipliers:"); + for (int c = 0; c < 4; c++) + printf(" %d", C.WB_Coeffs[LIBRAW_WBI_Other][c]); + } + + if (C.WB_Coeffs[LIBRAW_WBI_Auto][0] > 0) + { + printf("\nMakernotes 'Camera Auto' WB multipliers:"); + for (int c = 0; c < 4; c++) + printf(" %d", C.WB_Coeffs[LIBRAW_WBI_Auto][c]); + } + if (C.WB_Coeffs[LIBRAW_WBI_Measured][0] > 0) + { + printf("\nMakernotes 'Camera Measured' WB multipliers:"); + for (int c = 0; c < 4; c++) + printf(" %d", C.WB_Coeffs[LIBRAW_WBI_Measured][c]); + } + + if (C.WB_Coeffs[LIBRAW_WBI_Custom][0] > 0) + { + printf("\nMakernotes 'Custom' WB multipliers:"); + for (int c = 0; c < 4; c++) + printf(" %d", C.WB_Coeffs[LIBRAW_WBI_Custom][c]); + } + if (C.WB_Coeffs[LIBRAW_WBI_Custom1][0] > 0) + { + printf("\nMakernotes 'Custom1' WB multipliers:"); + for (int c = 0; c < 4; c++) + printf(" %d", C.WB_Coeffs[LIBRAW_WBI_Custom1][c]); + } + if (C.WB_Coeffs[LIBRAW_WBI_Custom2][0] > 0) + { + printf("\nMakernotes 'Custom2' WB multipliers:"); + for (int c = 0; c < 4; c++) + printf(" %d", C.WB_Coeffs[LIBRAW_WBI_Custom2][c]); + } + if (C.WB_Coeffs[LIBRAW_WBI_Custom3][0] > 0) + { + printf("\nMakernotes 'Custom3' WB multipliers:"); + for (int c = 0; c < 4; c++) + printf(" %d", C.WB_Coeffs[LIBRAW_WBI_Custom3][c]); + } + if (C.WB_Coeffs[LIBRAW_WBI_Custom4][0] > 0) + { + printf("\nMakernotes 'Custom4' WB multipliers:"); + for (int c = 0; c < 4; c++) + printf(" %d", C.WB_Coeffs[LIBRAW_WBI_Custom4][c]); + } + if (C.WB_Coeffs[LIBRAW_WBI_Custom5][0] > 0) + { + printf("\nMakernotes 'Custom5' WB multipliers:"); + for (int c = 0; c < 4; c++) + printf(" %d", C.WB_Coeffs[LIBRAW_WBI_Custom5][c]); + } + if (C.WB_Coeffs[LIBRAW_WBI_Custom6][0] > 0) + { + printf("\nMakernotes 'Custom6' WB multipliers:"); + for (int c = 0; c < 4; c++) + printf(" %d", C.WB_Coeffs[LIBRAW_WBI_Custom6][c]); + } + + if ((Nikon.ME_WB[0] != 0.0f) && (Nikon.ME_WB[0] != 1.0f)) + { + printf("\nNikon multi-exposure WB multipliers:"); + for (int c = 0; c < 4; c++) + printf(" %f", Nikon.ME_WB[c]); + } + + if (C.rgb_cam[0][0] > 0.0001 && P1.colors > 1) + { + printf("\nCamera2RGB matrix:\n"); + for (int i = 0; i < P1.colors; i++) + printf("%6.4f\t%6.4f\t%6.4f\n", C.rgb_cam[i][0], C.rgb_cam[i][1], C.rgb_cam[i][2]); + } + printf("\nXYZ->CamRGB matrix:\n"); + for (int i = 0; i < P1.colors; i++) + printf("%6.4f\t%6.4f\t%6.4f\n", C.cam_xyz[i][0], C.cam_xyz[i][1], C.cam_xyz[i][2]); + + if (C.dng_color[0].illuminant < 0xffff) + printf("\nDNG Illuminant 1: %s", EXIF_LightSources[C.dng_color[0].illuminant]); + if (C.dng_color[1].illuminant < 0xffff) + printf("\nDNG Illuminant 2: %s", EXIF_LightSources[C.dng_color[1].illuminant]); + + if (fabsf(C.P1_color[0].romm_cam[0]) > 0) + { + printf("\nPhaseOne Matrix1:\n"); + for (int i = 0; i < 3; i++) + printf("%6.4f\t%6.4f\t%6.4f\n", C.P1_color[0].romm_cam[i * 3], C.P1_color[0].romm_cam[i * 3 + 1], + C.P1_color[0].romm_cam[i * 3 + 2]); + } + + if (fabsf(C.P1_color[1].romm_cam[0]) > 0) + { + printf("\nPhaseOne Matrix2:\n"); + for (int i = 0; i < 3; i++) + printf("%6.4f\t%6.4f\t%6.4f\n", C.P1_color[1].romm_cam[i * 3], C.P1_color[1].romm_cam[i * 3 + 1], + C.P1_color[1].romm_cam[i * 3 + 2]); + } + + if (fabsf(C.cmatrix[0][0]) > 0) + { + printf("\ncamRGB -> sRGB Matrix:\n"); + for (int i = 0; i < P1.colors; i++) + { + for (int j = 0; j < P1.colors; j++) + printf("%6.4f\t", C.cmatrix[j][i]); + printf("\n"); + } + } + + if (fabsf(C.ccm[0][0]) > 0) + { + printf("\nColor Correction Matrix:\n"); + for (int i = 0; i < P1.colors; i++) + { + for (int j = 0; j < P1.colors; j++) + printf("%6.4f\t", C.ccm[j][i]); + printf("\n"); + } + } + if (fabsf(C.dng_color[0].colormatrix[0][0]) > 0) + { + printf("\nDNG color matrix 1:\n"); + for (int i = 0; i < P1.colors; i++) + printf("%6.4f\t%6.4f\t%6.4f\n", C.dng_color[0].colormatrix[i][0], C.dng_color[0].colormatrix[i][1], + C.dng_color[0].colormatrix[i][2]); + } + if (fabsf(C.dng_color[1].colormatrix[0][0]) > 0) + { + printf("\nDNG color matrix 2:\n"); + for (int i = 0; i < P1.colors; i++) + printf("%6.4f\t%6.4f\t%6.4f\n", C.dng_color[1].colormatrix[i][0], C.dng_color[1].colormatrix[i][1], + C.dng_color[1].colormatrix[i][2]); + } + + if (fabsf(C.dng_color[0].calibration[0][0]) > 0) + { + printf("\nDNG calibration matrix 1:\n"); + for (int i = 0; i < P1.colors; i++) + { + for (int j = 0; j < P1.colors; j++) + printf("%6.4f\t", C.dng_color[0].calibration[j][i]); + printf("\n"); + } + } + if (fabsf(C.dng_color[1].calibration[0][0]) > 0) + { + printf("\nDNG calibration matrix 2:\n"); + for (int i = 0; i < P1.colors; i++) + { + for (int j = 0; j < P1.colors; j++) + printf("%6.4f\t", C.dng_color[1].calibration[j][i]); + printf("\n"); + } + } + + if (fabsf(C.dng_color[0].forwardmatrix[0][0]) > 0) + { + printf("\nDNG forward matrix 1:\n"); + for (int i = 0; i < P1.colors; i++) + printf("%6.4f\t%6.4f\t%6.4f\n", C.dng_color[0].forwardmatrix[0][i], C.dng_color[0].forwardmatrix[1][i], + C.dng_color[0].forwardmatrix[2][i]); + } + if (fabsf(C.dng_color[1].forwardmatrix[0][0]) > 0) + { + printf("\nDNG forward matrix 2:\n"); + for (int i = 0; i < P1.colors; i++) + printf("%6.4f\t%6.4f\t%6.4f\n", C.dng_color[1].forwardmatrix[0][i], C.dng_color[1].forwardmatrix[1][i], + C.dng_color[1].forwardmatrix[2][i]); + } + + printf("\nDerived D65 multipliers:"); + for (int c = 0; c < P1.colors; c++) + printf(" %f", C.pre_mul[c]); + printf("\n"); + + if (Sony.Sony0x9400_version) + printf("\nSONY Sequence data, tag 0x9400 version %x\n\ +\tReleaseMode2: %d\n\ +\tSequenceImageNumber: %d (starts at zero)\n\ +\tSequenceLength1: %d shot(s)\n\ +\tSequenceFileNumber: %d (starts at zero, exiftool starts at 1)\n\ +\tSequenceLength2: %d file(s)\n", + Sony.Sony0x9400_version, Sony.Sony0x9400_ReleaseMode2, Sony.Sony0x9400_SequenceImageNumber, + Sony.Sony0x9400_SequenceLength1, Sony.Sony0x9400_SequenceFileNumber, Sony.Sony0x9400_SequenceLength2); + } + else + { + if (print_unpack) + { + char frame[48] = ""; + if (print_frame) + { + ushort right_margin = S.raw_width - S.width - S.left_margin; + ushort bottom_margin = S.raw_height - S.height - S.top_margin; + snprintf(frame, 48, "F=%dx%dx%dx%d RS=%dx%d", S.left_margin, S.top_margin, right_margin, bottom_margin, + S.raw_width, S.raw_height); + printf("%s\t%s\t%s\t%s/%s\n", av[i], MyCoolRawProcessor.unpack_function_name(), frame, P1.make, P1.model); + } + } + else if (print_wb) + { + printf("// %s %s\n", P1.make, P1.model); + for (int cnt = 0; cnt < 25; cnt++) + if (C.WB_Coeffs[cnt][0]) { - printf("Cannot decode %s: %s\n",av[i],libraw_strerror(ret)); - continue; // no recycle, open_file will recycle - } - if(verbose) { - if( (ret = MyCoolRawProcessor.adjust_sizes_info_only())) - { - printf("Cannot decode %s: %s\n",av[i],libraw_strerror(ret)); - continue; // no recycle, open_file will recycle - } - - printf ("\nFilename: %s\n", av[i]); - printf ("Timestamp: %s", ctime(&(P2.timestamp))); - printf ("Camera: %s %s\n", P1.make, P1.model); - if (ShootingInfo.BodySerial[0]) { - trimSpaces(ShootingInfo.BodySerial); - printf ("Body serial: %s\n", ShootingInfo.BodySerial); - } - if (P2.artist[0]) - printf ("Owner: %s\n", P2.artist); - if (P1.dng_version) { - printf ("DNG Version: "); - for (int i=24; i >= 0; i -= 8) - printf ("%d%c", P1.dng_version >> i & 255, i ? '.':'\n'); - } - printf ("\nEXIF:\n"); - printf ("\tMinFocal: %0.1f mm\n", exifLens.MinFocal); - printf ("\tMaxFocal: %0.1f mm\n", exifLens.MaxFocal); - printf ("\tMaxAp @MinFocal: f/%0.1f\n", exifLens.MaxAp4MinFocal); - printf ("\tMaxAp @MaxFocal: f/%0.1f\n", exifLens.MaxAp4MaxFocal); - printf ("\tMaxAperture @CurFocal: f/%0.1f\n", exifLens.EXIF_MaxAp); - printf ("\tFocalLengthIn35mmFormat: %d mm\n", exifLens.FocalLengthIn35mmFormat); - printf ("\tLensMake: %s\n", exifLens.LensMake); - printf ("\tLens: %s\n", exifLens.Lens); - printf ("\n"); - - printf ("\nMakernotes:\n"); - printf ("\tDriveMode: %d\n", ShootingInfo.DriveMode); - printf ("\tFocusMode: %d\n", ShootingInfo.FocusMode); - printf ("\tMeteringMode: %d\n", ShootingInfo.MeteringMode); - printf ("\tAFPoint: %d\n", ShootingInfo.AFPoint); - printf ("\tExposureMode: %d\n", ShootingInfo.ExposureMode); - printf ("\tImageStabilization: %d\n", ShootingInfo.ImageStabilization); - if (mnLens.body[0]) - { - printf("\tMF Camera Body: %s\n", mnLens.body); - } - printf("\tCameraFormat: %d, ", mnLens.CameraFormat); - switch (mnLens.CameraFormat) - { - case 0: printf("Undefined\n"); break; - case 1: printf("APS-C\n"); break; - case 2: printf("FF\n"); break; - case 3: printf("MF\n"); break; - case 4: printf("APS-H\n"); break; - case 5: printf("1\"\n"); break; - case 8: printf("4/3\n"); break; - default: printf("Unknown\n"); break; - } - printf("\tCameraMount: %d, ", mnLens.CameraMount); - switch (mnLens.CameraMount) - { - case 0: printf("Undefined or Fixed Lens\n"); break; - case 1: printf("Sony/Minolta A\n"); break; - case 2: printf("Sony E\n"); break; - case 3: printf("Canon EF\n"); break; - case 4: printf("Canon EF-S\n"); break; - case 5: printf("Canon EF-M\n"); break; - case 6: printf("Nikon F\n"); break; - case 7: printf("Nikon CX\n"); break; - case 8: printf("4/3\n"); break; - case 9: printf("m4/3\n"); break; - case 10: printf("Pentax K\n"); break; - case 11: printf("Pentax Q\n"); break; - case 12: printf("Pentax 645\n"); break; - case 13: printf("Fuji X\n"); break; - case 14: printf("Leica M\n"); break; - case 15: printf("Leica R\n"); break; - case 16: printf("Leica S\n"); break; - case 17: printf("Samsung NX\n"); break; - case 19: printf("Samsung NX-M\n"); break; - case 99: printf("Fixed Lens\n"); break; - default: printf("Unknown\n"); break; - } - - if (mnLens.LensID == -1) - { - printf("\tLensID: n/a\n"); - } - else - { - printf("\tLensID: %llu 0x%0llx\n", mnLens.LensID, mnLens.LensID); - } - printf("\tLens: %s\n", mnLens.Lens); - printf("\tLensFormat: %d, ", mnLens.LensFormat); - switch (mnLens.LensFormat) - { - case 0: printf("Undefined\n"); break; - case 1: printf("APS-C\n"); break; - case 2: printf("FF\n"); break; - case 3: printf("MF\n"); break; - case 8: printf("4/3\n"); break; - default: printf("Unknown\n"); break; - } - printf("\tLensMount: %d, ", mnLens.LensMount); - switch (mnLens.LensMount) - { - case 0: printf("Undefined or Fixed Lens\n"); break; - case 1: printf("Sony/Minolta A\n"); break; - case 2: printf("Sony E\n"); break; - case 3: printf("Canon EF\n"); break; - case 4: printf("Canon EF-S\n"); break; - case 5: printf("Canon EF-M\n"); break; - case 6: printf("Nikon F\n"); break; - case 7: printf("Nikon CX\n"); break; - case 8: printf("4/3\n"); break; - case 9: printf("m4/3\n"); break; - case 10: printf("Pentax K\n"); break; - case 11: printf("Pentax Q\n"); break; - case 12: printf("Pentax 645\n"); break; - case 13: printf("Fuji X\n"); break; - case 14: printf("Leica M\n"); break; - case 15: printf("Leica R\n"); break; - case 16: printf("Leica S\n"); break; - case 17: printf("Samsung NX\n"); break; - case 18: printf("Ricoh module\n"); break; - case 99: printf("Fixed Lens\n"); break; - default: printf("Unknown\n"); break; - } - printf("\tFocalType: %d, ", mnLens.FocalType); - switch (mnLens.FocalType) - { - case 0: printf("Undefined\n"); break; - case 1: printf("Fixed Focal\n"); break; - case 2: printf("Zoom\n"); break; - default: printf("Unknown\n"); break; - } - printf("\tLensFeatures_pre: %s\n", mnLens.LensFeatures_pre); - printf("\tLensFeatures_suf: %s\n", mnLens.LensFeatures_suf); - printf("\tMinFocal: %0.1f mm\n", mnLens.MinFocal); - printf("\tMaxFocal: %0.1f mm\n", mnLens.MaxFocal); - printf("\tMaxAp @MinFocal: f/%0.1f\n", mnLens.MaxAp4MinFocal); - printf("\tMaxAp @MaxFocal: f/%0.1f\n", mnLens.MaxAp4MaxFocal); - printf("\tMinAp @MinFocal: f/%0.1f\n", mnLens.MinAp4MinFocal); - printf("\tMinAp @MaxFocal: f/%0.1f\n", mnLens.MinAp4MaxFocal); - printf("\tMaxAp: f/%0.1f\n", mnLens.MaxAp); - printf("\tMinAp: f/%0.1f\n", mnLens.MinAp); - printf("\tCurFocal: %0.1f mm\n", mnLens.CurFocal); - printf("\tCurAp: f/%0.1f\n", mnLens.CurAp); - printf("\tMaxAp @CurFocal: f/%0.1f\n", mnLens.MaxAp4CurFocal); - printf("\tMinAp @CurFocal: f/%0.1f\n", mnLens.MinAp4CurFocal); - - if (exifLens.makernotes.FocalLengthIn35mmFormat > 1.0f) - printf("\tFocalLengthIn35mmFormat: %0.1f mm\n", exifLens.makernotes.FocalLengthIn35mmFormat); - - if (exifLens.nikon.NikonEffectiveMaxAp > 0.1f) - printf("\tNikonEffectiveMaxAp: f/%0.1f\n", exifLens.nikon.NikonEffectiveMaxAp); - - if (exifLens.makernotes.LensFStops > 0.1f) - printf("\tLensFStops @CurFocal: %0.2f\n", exifLens.makernotes.LensFStops); - - printf("\tTeleconverterID: %lld\n", mnLens.TeleconverterID); - printf("\tTeleconverter: %s\n", mnLens.Teleconverter); - printf("\tAdapterID: %lld\n", mnLens.AdapterID); - printf("\tAdapter: %s\n", mnLens.Adapter); - printf("\tAttachmentID: %lld\n", mnLens.AttachmentID); - printf("\tAttachment: %s\n", mnLens.Attachment); - printf ("\n"); - - printf ("ISO speed: %d\n", (int) P2.iso_speed); - printf ("Shutter: "); - if (P2.shutter > 0 && P2.shutter < 1) - P2.shutter = (printf ("1/"), 1 / P2.shutter); - printf ("%0.1f sec\n", P2.shutter); - printf ("Aperture: f/%0.1f\n", P2.aperture); - printf ("Focal length: %0.1f mm\n", P2.focal_len); - printf ("Flash exposure compensation: %0.2f EV\n", P2.FlashEC); - if(C.profile) - printf ("Embedded ICC profile: yes, %d bytes\n", C.profile_length); + printf("{\"%s\", \"%s\", %d, {%6.5ff, 1.0f, %6.5ff, ", P1.make, P1.model, cnt, + C.WB_Coeffs[cnt][0] / (float)C.WB_Coeffs[cnt][1], C.WB_Coeffs[cnt][2] / (float)C.WB_Coeffs[cnt][1]); + if (C.WB_Coeffs[cnt][1] == C.WB_Coeffs[cnt][3]) + printf("1.0f}},\n"); else - printf ("Embedded ICC profile: no\n"); - - if (C.baseline_exposure > -999.f) printf ("Baseline exposure: %04.3f\n", C.baseline_exposure); - - printf ("Number of raw images: %d\n", P1.raw_count); - if (Fuji.FujiExpoMidPointShift > -999.f) printf ("Fuji Exposure shift: %04.3f\n", Fuji.FujiExpoMidPointShift); - - if (Fuji.FujiDynamicRange != 0xffff) printf ("Fuji Dynamic Range: %d\n", Fuji.FujiDynamicRange); - if (Fuji.FujiFilmMode != 0xffff) printf ("Fuji Film Mode: %d\n", Fuji.FujiFilmMode); - if (Fuji.FujiDynamicRangeSetting != 0xffff) printf ("Fuji Dynamic Range Setting: %d\n", Fuji.FujiDynamicRangeSetting); - if (Fuji.FujiDevelopmentDynamicRange != 0xffff) printf ("Fuji Development Dynamic Range: %d\n", Fuji.FujiDevelopmentDynamicRange); - if (Fuji.FujiAutoDynamicRange != 0xffff) printf ("Fuji Auto Dynamic Range: %d\n", Fuji.FujiAutoDynamicRange); - - - if (S.pixel_aspect != 1) - printf ("Pixel Aspect Ratio: %0.6f\n", S.pixel_aspect); - if (T.tlength) - printf ("Thumb size: %4d x %d\n", T.twidth, T.theight); - printf ("Full size: %4d x %d\n", S.raw_width, S.raw_height); - - printf ("Image size: %4d x %d\n", S.width, S.height); - printf ("Output size: %4d x %d\n", S.iwidth, S.iheight); - - if (Canon.SensorWidth) printf("SensorWidth = %d\n", Canon.SensorWidth); - if (Canon.SensorHeight) printf("SensorHeight = %d\n", Canon.SensorHeight); - if (Canon.SensorLeftBorder) printf("SensorLeftBorder = %d\n", Canon.SensorLeftBorder); - if (Canon.SensorTopBorder) printf("SensorTopBorder = %d\n", Canon.SensorTopBorder); - if (Canon.SensorRightBorder) printf("SensorRightBorder = %d\n", Canon.SensorRightBorder); - if (Canon.SensorBottomBorder) printf("SensorBottomBorder = %d\n", Canon.SensorBottomBorder); - if (Canon.BlackMaskLeftBorder) printf("BlackMaskLeftBorder = %d\n", Canon.BlackMaskLeftBorder); - if (Canon.BlackMaskTopBorder) printf("BlackMaskTopBorder = %d\n", Canon.BlackMaskTopBorder); - if (Canon.BlackMaskRightBorder) printf("BlackMaskRightBorder = %d\n", Canon.BlackMaskRightBorder); - if (Canon.BlackMaskBottomBorder) printf("BlackMaskBottomBorder= %d\n", Canon.BlackMaskBottomBorder); - - if (Oly.OlympusCropID != -1) - { - printf ("Olympus aspect ID: %d\nOlympus crop", Oly.OlympusCropID); - for (int c=0;c<4;c++) printf (" %d", Oly.OlympusFrame[c]); - printf ("\n"); - } - - printf ("Raw colors: %d", P1.colors); - if (P1.filters) - { - printf ("\nFilter pattern: "); - if (!P1.cdesc[3]) P1.cdesc[3] = 'G'; - for (int i=0; i < 16; i++) - putchar (P1.cdesc[MyCoolRawProcessor.fcol(i >> 1,i & 1)]); - } - if (C.linear_max[0] != 0) - { - printf ("\nHighlight linearity limits:"); - for(int c=0;c<4;c++) printf (" %ld", C.linear_max[c]); - } - if (C.cam_mul[0] > 0) - { - printf ("\nMakernotes 'As shot' multipliers:"); - for(int c=0;c<4;c++) printf (" %f", C.cam_mul[c]); - } - - for (int cnt=0; cnt<25; cnt++) - { - if (C.WB_Coeffs[cnt][0] > 0) - { - printf ("\nMakernotes '%s' multipliers:", EXIF_LightSources[cnt]); - for(int c=0;c<4;c++) printf (" %d", C.WB_Coeffs[cnt][c]); - } - } - if (C.WB_Coeffs[LIBRAW_WBI_Other][0] > 0) - { - printf ("\nMakernotes 'Other' multipliers:"); - for(int c=0;c<4;c++) printf (" %d", C.WB_Coeffs[LIBRAW_WBI_Other][c]); - } - if(C.rgb_cam[0][0] > 0.0001 && P1.colors>1) - { - printf("\nCamera2RGB matrix:\n"); - for(int i=0; i< P1.colors; i++) - printf("%6.4f\t%6.4f\t%6.4f\n",C.rgb_cam[i][0],C.rgb_cam[i][1],C.rgb_cam[i][2]); - } - printf("\nXYZ->CamRGB matrix:\n"); - for(int i=0; i< P1.colors; i++) - printf("%6.4f\t%6.4f\t%6.4f\n",C.cam_xyz[i][0],C.cam_xyz[i][1],C.cam_xyz[i][2]); - - if (C.dng_color[0].illuminant < 0xffff) - printf ("\nDNG Illuminant 1: %s", EXIF_LightSources[C.dng_color[0].illuminant]); - if (C.dng_color[1].illuminant < 0xffff) - printf ("\nDNG Illuminant 2: %s", EXIF_LightSources[C.dng_color[1].illuminant]); - - if (fabsf(C.P1_color[0].romm_cam[0]) > 0) - { - printf("\nPhaseOne Matrix1:\n"); - for(int i=0; i< 3; i++) - printf("%6.4f\t%6.4f\t%6.4f\n",C.P1_color[0].romm_cam[i*3],C.P1_color[0].romm_cam[i*3+1],C.P1_color[0].romm_cam[i*3+2]); - } - - if (fabsf(C.P1_color[1].romm_cam[0]) > 0) - { - printf("\nPhaseOne Matrix2:\n"); - for(int i=0; i< 3; i++) - printf("%6.4f\t%6.4f\t%6.4f\n",C.P1_color[1].romm_cam[i*3],C.P1_color[1].romm_cam[i*3+1],C.P1_color[1].romm_cam[i*3+2]); - } - - if (fabsf(C.cmatrix[0][0]) > 0) - { - printf("\ncamRGB -> sRGB Matrix:\n"); - for(int i=0; i< P1.colors; i++) - { - for(int j=0; j< P1.colors; j++) - printf("%6.4f\t",C.cmatrix[j][i]); - printf ("\n"); - } - } - - if (fabsf(C.ccm[0][0]) > 0) - { - printf("\nColor Correction Matrix:\n"); - for(int i=0; i< P1.colors; i++) - { - for(int j=0; j< P1.colors; j++) - printf("%6.4f\t",C.ccm[j][i]); - printf ("\n"); - } - } - if (fabsf(C.dng_color[0].colormatrix[0][0]) > 0) - { - printf("\nDNG color matrix 1:\n"); - for(int i=0; i< P1.colors; i++) - printf("%6.4f\t%6.4f\t%6.4f\n",C.dng_color[0].colormatrix[i][0],C.dng_color[0].colormatrix[i][1],C.dng_color[0].colormatrix[i][2]); - } - if (fabsf(C.dng_color[1].colormatrix[0][0]) > 0) - { - printf("\nDNG color matrix 2:\n"); - for(int i=0; i< P1.colors; i++) - printf("%6.4f\t%6.4f\t%6.4f\n",C.dng_color[1].colormatrix[i][0],C.dng_color[1].colormatrix[i][1],C.dng_color[1].colormatrix[i][2]); - } - - if (fabsf(C.dng_color[0].calibration[0][0]) > 0) - { - printf("\nDNG calibration matrix 1:\n"); - for(int i=0; i< P1.colors; i++) - { - for(int j=0; j< P1.colors; j++) - printf("%6.4f\t",C.dng_color[0].calibration[j][i]); - printf ("\n"); - } - } - if (fabsf(C.dng_color[1].calibration[0][0]) > 0) - { - printf("\nDNG calibration matrix 2:\n"); - for(int i=0; i< P1.colors; i++) - { - for(int j=0; j< P1.colors; j++) - printf("%6.4f\t",C.dng_color[1].calibration[j][i]); - printf ("\n"); - } - } - - if (fabsf(C.dng_color[0].forwardmatrix[0][0]) > 0) - { - printf("\nDNG forward matrix 1:\n"); - for(int i=0; i< P1.colors; i++) - printf("%6.4f\t%6.4f\t%6.4f\n",C.dng_color[0].forwardmatrix[0][i],C.dng_color[0].forwardmatrix[1][i],C.dng_color[0].forwardmatrix[2][i]); - } - if (fabsf(C.dng_color[1].forwardmatrix[0][0]) > 0) - { - printf("\nDNG forward matrix 2:\n"); - for(int i=0; i< P1.colors; i++) - printf("%6.4f\t%6.4f\t%6.4f\n",C.dng_color[1].forwardmatrix[0][i],C.dng_color[1].forwardmatrix[1][i],C.dng_color[1].forwardmatrix[2][i]); - } - - printf ("\nDerived D65 multipliers:"); - for(int c=0;c #include #include #ifndef WIN32 #include #include #include #include #endif #include "libraw/libraw.h" #ifdef WIN32 #define snprintf _snprintf #endif -int my_progress_callback(void *unused_data,enum LibRaw_progress state,int iter, int expected) +int my_progress_callback(void *unused_data, enum LibRaw_progress state, int iter, int expected) { - if(iter==0) - printf("CB: state=%x, expected %d iterations\n",state,expected); - return 0; + if (iter == 0) + printf("CB: state=%x, expected %d iterations\n", state, expected); + return 0; } -char * customCameras[]= - { - (char*)"43704960,4080,5356, 0, 0, 0, 0,0,148,0,0, Dalsa, FTF4052C Full,0", - (char*)"42837504,4008,5344, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF4052C 3:4", - (char*)"32128128,4008,4008, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF4052C 1:1", - (char*)"24096096,4008,3006, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF4052C 4:3", - (char*)"18068064,4008,2254, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF4052C 16:9", - (char*)"67686894,5049,6703, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C Full", - (char*)"66573312,4992,6668, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C 3:4", - (char*)"49840128,4992,4992, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C 1:1", - (char*)"37400064,4992,3746, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C 4:3", - (char*)"28035072,4992,2808, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C 16:9", - NULL -}; +char *customCameras[] = {(char *)"43704960,4080,5356, 0, 0, 0, 0,0,148,0,0, Dalsa, FTF4052C Full,0", + (char *)"42837504,4008,5344, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF4052C 3:4", + (char *)"32128128,4008,4008, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF4052C 1:1", + (char *)"24096096,4008,3006, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF4052C 4:3", + (char *)"18068064,4008,2254, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF4052C 16:9", + (char *)"67686894,5049,6703, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C Full", + (char *)"66573312,4992,6668, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C 3:4", + (char *)"49840128,4992,4992, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C 1:1", + (char *)"37400064,4992,3746, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C 4:3", + (char *)"28035072,4992,2808, 0, 0, 0, 0,0,148,0,0,Dalsa, FTF5066C 16:9", + NULL}; int main(int ac, char *av[]) { - int i, ret, verbose=0, output_thumbs=0; + int i, ret, verbose = 0, output_thumbs = 0; - // don't use fixed size buffers in real apps! - char outfn[1024],thumbfn[1024]; + // don't use fixed size buffers in real apps! + char outfn[1024], thumbfn[1024]; - LibRaw RawProcessor; - RawProcessor.imgdata.params.custom_camera_strings = customCameras; - if(ac<2) - { - printf( - "simple_dcraw - LibRaw %s sample. Emulates dcraw [-D] [-T] [-v] [-e] [-E]\n" - " %d cameras supported\n" - "Usage: %s [-D] [-T] [-v] [-e] raw-files....\n" - "\t-4 - 16-bit mode\n" - "\t-L - list supported cameras and exit\n" - "\t-v - verbose output\n" - "\t-T - output TIFF files instead of .pgm/ppm\n" - "\t-e - extract thumbnails (same as dcraw -e in separate run)\n",LibRaw::version(), - LibRaw::cameraCount(), - av[0]); - return 0; - } - - putenv ((char*)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field + LibRaw RawProcessor; + RawProcessor.imgdata.params.custom_camera_strings = customCameras; + if (ac < 2) + { + printf("simple_dcraw - LibRaw %s sample. Emulates dcraw [-D] [-T] [-v] [-e] [-E]\n" + " %d cameras supported\n" + "Usage: %s [-D] [-T] [-v] [-e] raw-files....\n" + "\t-4 - 16-bit mode\n" + "\t-L - list supported cameras and exit\n" + "\t-v - verbose output\n" + "\t-T - output TIFF files instead of .pgm/ppm\n" + "\t-e - extract thumbnails (same as dcraw -e in separate run)\n", + LibRaw::version(), LibRaw::cameraCount(), av[0]); + return 0; + } + + putenv((char *)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field #define P1 RawProcessor.imgdata.idata #define S RawProcessor.imgdata.sizes #define C RawProcessor.imgdata.color #define T RawProcessor.imgdata.thumbnail #define P2 RawProcessor.imgdata.other #define OUT RawProcessor.imgdata.params + for (i = 1; i < ac; i++) + { + if (av[i][0] == '-') + { + if (av[i][1] == 'T' && av[i][2] == 0) + OUT.output_tiff = 1; + if (av[i][1] == 'v' && av[i][2] == 0) + verbose++; + if (av[i][1] == 'e' && av[i][2] == 0) + output_thumbs++; + if (av[i][1] == '4' && av[i][2] == 0) + OUT.output_bps = 16; + if (av[i][1] == 'C' && av[i][2] == 0) + RawProcessor.set_progress_handler(my_progress_callback, NULL); + if (av[i][1] == 'L' && av[i][2] == 0) + { + const char **clist = LibRaw::cameraList(); + const char **cc = clist; + while (*cc) + { + printf("%s\n", *cc); + cc++; + } - for (i=1;i1?"ppm":"pgm")); - - if(verbose) printf("Writing file %s\n",outfn); - - if( LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn))) - fprintf(stderr,"Cannot write %s: %s\n",outfn,libraw_strerror(ret)); - - RawProcessor.recycle(); // just for show this call + fprintf(stderr, "Cannot write %s: %s\n", thumbfn, libraw_strerror(ret)); + if (LIBRAW_FATAL_ERROR(ret)) + continue; } - return 0; + } + continue; + } + + ret = RawProcessor.dcraw_process(); + + if (LIBRAW_SUCCESS != ret) + { + fprintf(stderr, "Cannot do postpocessing on %s: %s\n", av[i], libraw_strerror(ret)); + if (LIBRAW_FATAL_ERROR(ret)) + continue; + } + snprintf(outfn, sizeof(outfn), "%s.%s", av[i], OUT.output_tiff ? "tiff" : (P1.colors > 1 ? "ppm" : "pgm")); + + if (verbose) + printf("Writing file %s\n", outfn); + + if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn))) + fprintf(stderr, "Cannot write %s: %s\n", outfn, libraw_strerror(ret)); + + RawProcessor.recycle(); // just for show this call + } + return 0; } diff --git a/core/libs/rawengine/libraw/samples/unprocessed_raw.cpp b/core/libs/rawengine/libraw/samples/unprocessed_raw.cpp index abdb20527f..822d6a873c 100644 --- a/core/libs/rawengine/libraw/samples/unprocessed_raw.cpp +++ b/core/libs/rawengine/libraw/samples/unprocessed_raw.cpp @@ -1,287 +1,297 @@ /* -*- C++ -*- * File: unprocessed_raw.cpp * Copyright 2009-2016 LibRaw LLC (info@libraw.org) * Created: Fri Jan 02, 2009 * * LibRaw sample * Generates unprocessed raw image: with masked pixels and without black subtraction * LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #include #include #include #include #ifndef WIN32 #include #else #include #include #endif #include "libraw/libraw.h" #ifdef WIN32 #define snprintf _snprintf #endif -#if !(LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0,14)) +#if !(LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0, 14)) #error This code is for LibRaw 0.14+ only #endif -void gamma_curve (unsigned short curve[]); +void gamma_curve(unsigned short curve[]); void write_ppm(unsigned width, unsigned height, unsigned short *bitmap, const char *basename); void write_tiff(int width, int height, unsigned short *bitmap, const char *basename); int main(int ac, char *av[]) { - int i, ret; - int verbose=1,autoscale=0,use_gamma=0,out_tiff=0; - char outfn[1024]; - - LibRaw RawProcessor; - if(ac<2) - { - usage: - printf( - "unprocessed_raw - LibRaw %s sample. %d cameras supported\n" - "Usage: %s [-q] [-A] [-g] [-s N] raw-files....\n" - "\t-q - be quiet\n" - "\t-s N - select Nth image in file (default=0)\n" - "\t-g - use gamma correction with gamma 2.2 (not precise,use for visual inspection only)\n" - "\t-A - autoscaling (by integer factor)\n" - "\t-T - write tiff instead of pgm\n" - ,LibRaw::version(), - LibRaw::cameraCount(), - av[0]); - return 0; - } - + int i, ret; + int verbose = 1, autoscale = 0, use_gamma = 0, out_tiff = 0; + char outfn[1024]; + + LibRaw RawProcessor; + if (ac < 2) + { + usage: + printf("unprocessed_raw - LibRaw %s sample. %d cameras supported\n" + "Usage: %s [-q] [-A] [-g] [-s N] raw-files....\n" + "\t-q - be quiet\n" + "\t-s N - select Nth image in file (default=0)\n" + "\t-g - use gamma correction with gamma 2.2 (not precise,use for visual inspection only)\n" + "\t-A - autoscaling (by integer factor)\n" + "\t-T - write tiff instead of pgm\n", + LibRaw::version(), LibRaw::cameraCount(), av[0]); + return 0; + } + #define S RawProcessor.imgdata.sizes #define OUT RawProcessor.imgdata.params - for (i=1;i0 && max< 1<<15) - { - scale = (1<<16)/max; - if(verbose) - printf("Scaling with multiplier=%d (max=%d)\n",scale,max); - - for(int j=0; j 0 && max < 1 << 15) + { + scale = (1 << 16) / max; + if (verbose) + printf("Scaling with multiplier=%d (max=%d)\n", scale, max); + + for (int j = 0; j < S.raw_height * S.raw_width; j++) + RawProcessor.imgdata.rawdata.raw_image[j] *= scale; + } + } + if (use_gamma) + { + unsigned short curve[0x10000]; + gamma_curve(curve); + for (int j = 0; j < S.raw_height * S.raw_width; j++) + RawProcessor.imgdata.rawdata.raw_image[j] = curve[RawProcessor.imgdata.rawdata.raw_image[j]]; + if (verbose) + printf("Gamma-corrected....\n"); + } + + if (OUT.shot_select) + snprintf(outfn, sizeof(outfn), "%s-%d.%s", av[i], OUT.shot_select, out_tiff ? "tiff" : "pgm"); + else + snprintf(outfn, sizeof(outfn), "%s.%s", av[i], out_tiff ? "tiff" : "pgm"); + + if (out_tiff) + write_tiff(S.raw_width, S.raw_height, RawProcessor.imgdata.rawdata.raw_image, outfn); + else + write_ppm(S.raw_width, S.raw_height, RawProcessor.imgdata.rawdata.raw_image, outfn); + + if (verbose) + printf("Stored to file %s\n", outfn); + } + return 0; } void write_ppm(unsigned width, unsigned height, unsigned short *bitmap, const char *fname) { - if(!bitmap) return; - - FILE *f = fopen(fname,"wb"); - if(!f) return; - int bits = 16; - fprintf (f, "P5\n%d %d\n%d\n", width, height, (1 << bits)-1); - unsigned char *data = (unsigned char *)bitmap; - unsigned data_size = width*height*2; -#define SWAP(a,b) { a ^= b; a ^= (b ^= a); } - for(unsigned i=0; i< data_size; i+=2) - SWAP(data[i],data[i+1]); + if (!bitmap) + return; + + FILE *f = fopen(fname, "wb"); + if (!f) + return; + int bits = 16; + fprintf(f, "P5\n%d %d\n%d\n", width, height, (1 << bits) - 1); + unsigned char *data = (unsigned char *)bitmap; + unsigned data_size = width * height * 2; +#define SWAP(a, b) \ + { \ + a ^= b; \ + a ^= (b ^= a); \ + } + for (unsigned i = 0; i < data_size; i += 2) + SWAP(data[i], data[i + 1]); #undef SWAP - fwrite(data,data_size,1,f); - fclose(f); + fwrite(data, data_size, 1, f); + fclose(f); } /* == gamma curve and tiff writer - simplified cut'n'paste from dcraw.c */ -#define SQR(x) ((x)*(x)) +#define SQR(x) ((x) * (x)) -void gamma_curve (unsigned short *curve) +void gamma_curve(unsigned short *curve) { - double pwr = 1.0/2.2; - double ts = 0.0; - int imax = 0xffff; - int mode = 2; + double pwr = 1.0 / 2.2; + double ts = 0.0; + int imax = 0xffff; + int mode = 2; int i; - double g[6], bnd[2]={0,0}, r; + 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]; + 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[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; - for (i=0; i < 0x10000; i++) { + 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; + 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])))); + 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 tiff_set (ushort *ntag, - ushort tag, ushort type, int count, int val) +void tiff_set(ushort *ntag, ushort tag, ushort type, int count, int val) { - struct tiff_tag *tt; + struct libraw_tiff_tag *tt; int c; - tt = (struct tiff_tag *)(ntag+1) + (*ntag)++; + tt = (struct libraw_tiff_tag *)(ntag + 1) + (*ntag)++; tt->tag = tag; tt->type = type; tt->count = count; if (type < 3 && count <= 4) - for(c=0;c<4;c++) tt->val.c[c] = val >> (c << 3); + for (c = 0; c < 4; c++) + tt->val.c[c] = val >> (c << 3); else if (type == 3 && count <= 2) - for(c=0;c<2;c++) tt->val.s[c] = val >> (c << 4); - else tt->val.i = val; + for (c = 0; c < 2; c++) + tt->val.s[c] = val >> (c << 4); + else + tt->val.i = val; } #define TOFF(ptr) ((char *)(&(ptr)) - (char *)th) - -void tiff_head (int width, int height, struct tiff_hdr *th) +void tiff_head(int width, int height, struct tiff_hdr *th) { int c; time_t timestamp = time(NULL); struct tm *t; - memset (th, 0, sizeof *th); + memset(th, 0, sizeof *th); th->t_order = htonl(0x4d4d4949) >> 16; th->magic = 42; th->ifd = 10; - tiff_set (&th->ntag, 254, 4, 1, 0); - tiff_set (&th->ntag, 256, 4, 1, width); - tiff_set (&th->ntag, 257, 4, 1, height); - tiff_set (&th->ntag, 258, 3, 1, 16); - for(c=0;c<4;c++) th->bps[c] = 16; - tiff_set (&th->ntag, 259, 3, 1, 1); - tiff_set (&th->ntag, 262, 3, 1, 1); - tiff_set (&th->ntag, 273, 4, 1, sizeof *th); - tiff_set (&th->ntag, 277, 3, 1, 1); - tiff_set (&th->ntag, 278, 4, 1, height); - tiff_set (&th->ntag, 279, 4, 1, height*width*2); - tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[0])); - tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[2])); - tiff_set (&th->ntag, 284, 3, 1, 1); - tiff_set (&th->ntag, 296, 3, 1, 2); - tiff_set (&th->ntag, 306, 2, 20, TOFF(th->date)); + tiff_set(&th->ntag, 254, 4, 1, 0); + tiff_set(&th->ntag, 256, 4, 1, width); + tiff_set(&th->ntag, 257, 4, 1, height); + tiff_set(&th->ntag, 258, 3, 1, 16); + for (c = 0; c < 4; c++) + th->bps[c] = 16; + tiff_set(&th->ntag, 259, 3, 1, 1); + tiff_set(&th->ntag, 262, 3, 1, 1); + tiff_set(&th->ntag, 273, 4, 1, sizeof *th); + tiff_set(&th->ntag, 277, 3, 1, 1); + tiff_set(&th->ntag, 278, 4, 1, height); + tiff_set(&th->ntag, 279, 4, 1, height * width * 2); + tiff_set(&th->ntag, 282, 5, 1, TOFF(th->rat[0])); + tiff_set(&th->ntag, 283, 5, 1, TOFF(th->rat[2])); + tiff_set(&th->ntag, 284, 3, 1, 1); + tiff_set(&th->ntag, 296, 3, 1, 2); + tiff_set(&th->ntag, 306, 2, 20, TOFF(th->date)); th->rat[0] = th->rat[2] = 300; th->rat[1] = th->rat[3] = 1; - t = localtime (×tamp); - if(t) - sprintf (th->date, "%04d:%02d:%02d %02d:%02d:%02d", - t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec); + t = localtime(×tamp); + if (t) + sprintf(th->date, "%04d:%02d:%02d %02d:%02d:%02d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, + t->tm_min, t->tm_sec); } void write_tiff(int width, int height, unsigned short *bitmap, const char *fn) { struct tiff_hdr th; - FILE *ofp = fopen(fn,"wb"); - if(!ofp) return; - tiff_head (width,height,&th); - fwrite (&th, sizeof th, 1, ofp); - fwrite (bitmap, 2, width*height, ofp); + FILE *ofp = fopen(fn, "wb"); + if (!ofp) + return; + tiff_head(width, height, &th); + fwrite(&th, sizeof th, 1, ofp); + fwrite(bitmap, 2, width * height, ofp); fclose(ofp); } diff --git a/core/libs/rawengine/libraw/src/libraw_c_api.cpp b/core/libs/rawengine/libraw/src/libraw_c_api.cpp index ef29e6aed5..62319028d5 100644 --- a/core/libs/rawengine/libraw/src/libraw_c_api.cpp +++ b/core/libs/rawengine/libraw/src/libraw_c_api.cpp @@ -1,384 +1,410 @@ /* -*- C++ -*- * File: libraw_c_api.cpp - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) * Created: Sat Mar 8 , 2008 * - * LibRaw C interface + * LibRaw C interface LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #include #include #include "libraw/libraw.h" #ifdef __cplusplus #include -extern "C" +extern "C" { #endif - libraw_data_t *libraw_init(unsigned int flags) + libraw_data_t *libraw_init(unsigned int flags) + { + LibRaw *ret; + try { - LibRaw *ret; - try { - ret = new LibRaw(flags); - } - catch (std::bad_alloc) - { - return NULL; - } - return &(ret->imgdata); + ret = new LibRaw(flags); } - - unsigned libraw_capabilities() { return LibRaw::capabilities();} - const char* libraw_version() { return LibRaw::version();} - const char* libraw_strprogress(enum LibRaw_progress p) { return LibRaw::strprogress(p);} - int libraw_versionNumber() { return LibRaw::versionNumber();} - const char** libraw_cameraList() { return LibRaw::cameraList();} - int libraw_cameraCount() { return LibRaw::cameraCount(); } - const char* libraw_unpack_function_name(libraw_data_t* lr) - { - if(!lr) return "NULL parameter passed"; - LibRaw *ip = (LibRaw*) lr->parent_class; - return ip->unpack_function_name(); - } - - void libraw_subtract_black(libraw_data_t* lr) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->subtract_black(); - } - - - int libraw_open_file(libraw_data_t* lr, const char *file) - { - if(!lr) return EINVAL; - LibRaw *ip = (LibRaw*) lr->parent_class; - return ip->open_file(file); - } - - int libraw_open_file_ex(libraw_data_t* lr, const char *file,INT64 sz) + catch (std::bad_alloc) { - if(!lr) return EINVAL; - LibRaw *ip = (LibRaw*) lr->parent_class; - return ip->open_file(file,sz); + return NULL; } + return &(ret->imgdata); + } + + unsigned libraw_capabilities() { return LibRaw::capabilities(); } + const char *libraw_version() { return LibRaw::version(); } + const char *libraw_strprogress(enum LibRaw_progress p) { return LibRaw::strprogress(p); } + int libraw_versionNumber() { return LibRaw::versionNumber(); } + const char **libraw_cameraList() { return LibRaw::cameraList(); } + int libraw_cameraCount() { return LibRaw::cameraCount(); } + const char *libraw_unpack_function_name(libraw_data_t *lr) + { + if (!lr) + return "NULL parameter passed"; + LibRaw *ip = (LibRaw *)lr->parent_class; + return ip->unpack_function_name(); + } + + void libraw_subtract_black(libraw_data_t *lr) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + ip->subtract_black(); + } + + int libraw_open_file(libraw_data_t *lr, const char *file) + { + if (!lr) + return EINVAL; + LibRaw *ip = (LibRaw *)lr->parent_class; + return ip->open_file(file); + } + + libraw_iparams_t *libraw_get_iparams(libraw_data_t *lr) + { + if (!lr) + return NULL; + return &(lr->idata); + } + + libraw_lensinfo_t *libraw_get_lensinfo(libraw_data_t *lr) + { + if (!lr) + return NULL; + return &(lr->lens); + } + + libraw_imgother_t *libraw_get_imgother(libraw_data_t *lr) + { + if (!lr) + return NULL; + return &(lr->other); + } + + int libraw_open_file_ex(libraw_data_t *lr, const char *file, INT64 sz) + { + if (!lr) + return EINVAL; + LibRaw *ip = (LibRaw *)lr->parent_class; + return ip->open_file(file, sz); + } #if defined(_WIN32) && !defined(__MINGW32__) && defined(_MSC_VER) && (_MSC_VER > 1310) - int libraw_open_wfile(libraw_data_t* lr, const wchar_t *file) - { - if(!lr) return EINVAL; - LibRaw *ip = (LibRaw*) lr->parent_class; - return ip->open_file(file); - } - - int libraw_open_wfile_ex(libraw_data_t* lr, const wchar_t *file,INT64 sz) - { - if(!lr) return EINVAL; - LibRaw *ip = (LibRaw*) lr->parent_class; - return ip->open_file(file,sz); - } + int libraw_open_wfile(libraw_data_t *lr, const wchar_t *file) + { + if (!lr) + return EINVAL; + LibRaw *ip = (LibRaw *)lr->parent_class; + return ip->open_file(file); + } + + int libraw_open_wfile_ex(libraw_data_t *lr, const wchar_t *file, INT64 sz) + { + if (!lr) + return EINVAL; + LibRaw *ip = (LibRaw *)lr->parent_class; + return ip->open_file(file, sz); + } #endif - int libraw_open_buffer(libraw_data_t* lr, void *buffer, size_t size) - { - if(!lr) return EINVAL; - LibRaw *ip = (LibRaw*) lr->parent_class; - return ip->open_buffer(buffer,size); - } - int libraw_unpack(libraw_data_t* lr) - { - if(!lr) return EINVAL; - LibRaw *ip = (LibRaw*) lr->parent_class; - return ip->unpack(); - } - int libraw_unpack_thumb(libraw_data_t* lr) - { - if(!lr) return EINVAL; - LibRaw *ip = (LibRaw*) lr->parent_class; - return ip->unpack_thumb(); - } - void libraw_recycle_datastream(libraw_data_t* lr) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->recycle_datastream(); - } - void libraw_recycle(libraw_data_t* lr) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->recycle(); - } - void libraw_close(libraw_data_t* lr) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - delete ip; - } - - void libraw_set_exifparser_handler(libraw_data_t* lr, exif_parser_callback cb,void *data) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->set_exifparser_handler(cb,data); - - } - - void libraw_set_memerror_handler(libraw_data_t* lr, memory_callback cb,void *data) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->set_memerror_handler(cb,data); - - } - void libraw_set_dataerror_handler(libraw_data_t* lr,data_callback func,void *data) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->set_dataerror_handler(func,data); - - } - void libraw_set_progress_handler(libraw_data_t* lr, progress_callback cb,void *data) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->set_progress_handler(cb,data); - - } - - // DCRAW - int libraw_adjust_sizes_info_only(libraw_data_t* lr) - { - if(!lr) return EINVAL; - LibRaw *ip = (LibRaw*) lr->parent_class; - return ip->adjust_sizes_info_only(); - } - int libraw_dcraw_ppm_tiff_writer(libraw_data_t* lr,const char *filename) - { - if(!lr) return EINVAL; - LibRaw *ip = (LibRaw*) lr->parent_class; - return ip->dcraw_ppm_tiff_writer(filename); - } - int libraw_dcraw_thumb_writer(libraw_data_t* lr,const char *fname) - { - if(!lr) return EINVAL; - LibRaw *ip = (LibRaw*) lr->parent_class; - return ip->dcraw_thumb_writer(fname); - - } - int libraw_dcraw_process(libraw_data_t* lr) - { - if(!lr) return EINVAL; - LibRaw *ip = (LibRaw*) lr->parent_class; - return ip->dcraw_process(); - } - libraw_processed_image_t *libraw_dcraw_make_mem_image(libraw_data_t* lr,int *errc) - { - if(!lr) { if(errc) *errc=EINVAL; return NULL;} - LibRaw *ip = (LibRaw*) lr->parent_class; - return ip->dcraw_make_mem_image(errc); - } - libraw_processed_image_t *libraw_dcraw_make_mem_thumb(libraw_data_t* lr,int *errc) - { - if(!lr) { if(errc) *errc=EINVAL; return NULL;} - LibRaw *ip = (LibRaw*) lr->parent_class; - return ip->dcraw_make_mem_thumb(errc); - } - - void libraw_dcraw_clear_mem(libraw_processed_image_t* p) - { - LibRaw::dcraw_clear_mem(p); - } - - int libraw_raw2image(libraw_data_t* lr) - { - if(!lr) return EINVAL; - LibRaw *ip = (LibRaw*) lr->parent_class; - return ip->raw2image(); - } - void libraw_free_image(libraw_data_t* lr) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->free_image(); - } - int libraw_get_decoder_info(libraw_data_t* lr,libraw_decoder_info_t *d) + int libraw_open_buffer(libraw_data_t *lr, void *buffer, size_t size) + { + if (!lr) + return EINVAL; + LibRaw *ip = (LibRaw *)lr->parent_class; + return ip->open_buffer(buffer, size); + } + int libraw_unpack(libraw_data_t *lr) + { + if (!lr) + return EINVAL; + LibRaw *ip = (LibRaw *)lr->parent_class; + return ip->unpack(); + } + int libraw_unpack_thumb(libraw_data_t *lr) + { + if (!lr) + return EINVAL; + LibRaw *ip = (LibRaw *)lr->parent_class; + return ip->unpack_thumb(); + } + void libraw_recycle_datastream(libraw_data_t *lr) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + ip->recycle_datastream(); + } + void libraw_recycle(libraw_data_t *lr) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + ip->recycle(); + } + void libraw_close(libraw_data_t *lr) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + delete ip; + } + + void libraw_set_exifparser_handler(libraw_data_t *lr, exif_parser_callback cb, void *data) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + ip->set_exifparser_handler(cb, data); + } + + void libraw_set_memerror_handler(libraw_data_t *lr, memory_callback cb, void *data) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + ip->set_memerror_handler(cb, data); + } + void libraw_set_dataerror_handler(libraw_data_t *lr, data_callback func, void *data) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + ip->set_dataerror_handler(func, data); + } + void libraw_set_progress_handler(libraw_data_t *lr, progress_callback cb, void *data) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + ip->set_progress_handler(cb, data); + } + + // DCRAW + int libraw_adjust_sizes_info_only(libraw_data_t *lr) + { + if (!lr) + return EINVAL; + LibRaw *ip = (LibRaw *)lr->parent_class; + return ip->adjust_sizes_info_only(); + } + int libraw_dcraw_ppm_tiff_writer(libraw_data_t *lr, const char *filename) + { + if (!lr) + return EINVAL; + LibRaw *ip = (LibRaw *)lr->parent_class; + return ip->dcraw_ppm_tiff_writer(filename); + } + int libraw_dcraw_thumb_writer(libraw_data_t *lr, const char *fname) + { + if (!lr) + return EINVAL; + LibRaw *ip = (LibRaw *)lr->parent_class; + return ip->dcraw_thumb_writer(fname); + } + int libraw_dcraw_process(libraw_data_t *lr) + { + if (!lr) + return EINVAL; + LibRaw *ip = (LibRaw *)lr->parent_class; + return ip->dcraw_process(); + } + libraw_processed_image_t *libraw_dcraw_make_mem_image(libraw_data_t *lr, int *errc) + { + if (!lr) { - if(!lr || !d) return EINVAL; - LibRaw *ip = (LibRaw*) lr->parent_class; - return ip->get_decoder_info(d); + if (errc) + *errc = EINVAL; + return NULL; } - int libraw_COLOR(libraw_data_t *lr, int row, int col) + LibRaw *ip = (LibRaw *)lr->parent_class; + return ip->dcraw_make_mem_image(errc); + } + libraw_processed_image_t *libraw_dcraw_make_mem_thumb(libraw_data_t *lr, int *errc) + { + if (!lr) { - if(!lr) return EINVAL; - LibRaw *ip = (LibRaw*) lr->parent_class; - return ip->COLOR(row,col); + if (errc) + *errc = EINVAL; + return NULL; } - - /* getters/setters used by 3DLut Creator */ -DllDef void libraw_set_demosaic(libraw_data_t *lr,int value) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->imgdata.params.user_qual = value; - } - -DllDef void libraw_set_output_color(libraw_data_t *lr,int value) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->imgdata.params.output_color = value; - } - -DllDef void libraw_set_output_bps(libraw_data_t *lr,int value) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->imgdata.params.output_bps = value; - } - -#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)) - -DllDef void libraw_set_user_mul(libraw_data_t *lr,int index, float val) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->imgdata.params.user_mul[LIM(index,0,3)]=val; - } - -DllDef void libraw_set_gamma(libraw_data_t *lr,int index, float value) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->imgdata.params.gamm[LIM(index,0,5)] = value; - } - -DllDef void libraw_set_no_auto_bright(libraw_data_t *lr,int value) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->imgdata.params.no_auto_bright = value; - } - -DllDef void libraw_set_bright(libraw_data_t *lr,float value) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->imgdata.params.bright = value; - } - -DllDef void libraw_set_highlight(libraw_data_t *lr,int value) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->imgdata.params.highlight = value; - } - -DllDef void libraw_set_fbdd_noiserd(libraw_data_t *lr,int value) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->imgdata.params.fbdd_noiserd = value; - } - -DllDef int libraw_get_raw_height(libraw_data_t *lr) - { - if(!lr) return EINVAL; - return lr->sizes.raw_height; - } - -DllDef int libraw_get_raw_width(libraw_data_t *lr) - { - if(!lr) return EINVAL; - return lr->sizes.raw_width; - } - -DllDef int libraw_get_iheight(libraw_data_t *lr) - { - if(!lr) return EINVAL; - return lr->sizes.iheight; - } - -DllDef int libraw_get_iwidth(libraw_data_t *lr) - { - if(!lr) return EINVAL; - return lr->sizes.iwidth; - } - - -DllDef float libraw_get_cam_mul(libraw_data_t *lr,int index) - { - if(!lr) return EINVAL; - return lr->color.cam_mul[LIM(index,0,3)]; - } - -DllDef float libraw_get_pre_mul(libraw_data_t *lr,int index) - { - if(!lr) return EINVAL; - return lr->color.pre_mul[LIM(index,0,3)]; - } - -DllDef float libraw_get_rgb_cam(libraw_data_t *lr,int index1, int index2) - { - if(!lr) return EINVAL; - return lr->color.rgb_cam[LIM(index1,0,2)][LIM(index2,0,3)]; - } - -DllDef int libraw_get_color_maximum(libraw_data_t *lr) - { - if(!lr) return EINVAL; - return lr->color.maximum; - } - -DllDef void libraw_set_ca_correction(libraw_data_t *lr,int ca_correc, float ca_red, float ca_blue) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->imgdata.params.ca_correc = ca_correc; - ip->imgdata.params.cared = ca_red; - ip->imgdata.params.cablue = ca_blue; - } - -DllDef void libraw_set_cfalinenoise(libraw_data_t *lr,int cfaline, float linenoise) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->imgdata.params.cfaline = cfaline; - ip->imgdata.params.linenoise = linenoise; - } - -DllDef void libraw_set_wf_debanding(libraw_data_t *lr, int wf_debanding, float wfd0, float wfd1, float wfd2, float wfd3) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->imgdata.params.wf_debanding = wf_debanding; - ip->imgdata.params.wf_deband_treshold[0] = wfd0; - ip->imgdata.params.wf_deband_treshold[1] = wfd1; - ip->imgdata.params.wf_deband_treshold[2] = wfd2; - ip->imgdata.params.wf_deband_treshold[3] = wfd3; - } - -DllDef void libraw_set_interpolation_passes(libraw_data_t *lr,int passes) - { - if(!lr) return; - LibRaw *ip = (LibRaw*) lr->parent_class; - ip->imgdata.params.med_passes = passes; - ip->imgdata.params.es_med_passes = passes; - ip->imgdata.params.dcb_iterations = passes; - } + LibRaw *ip = (LibRaw *)lr->parent_class; + return ip->dcraw_make_mem_thumb(errc); + } + + void libraw_dcraw_clear_mem(libraw_processed_image_t *p) { LibRaw::dcraw_clear_mem(p); } + + int libraw_raw2image(libraw_data_t *lr) + { + if (!lr) + return EINVAL; + LibRaw *ip = (LibRaw *)lr->parent_class; + return ip->raw2image(); + } + void libraw_free_image(libraw_data_t *lr) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + ip->free_image(); + } + int libraw_get_decoder_info(libraw_data_t *lr, libraw_decoder_info_t *d) + { + if (!lr || !d) + return EINVAL; + LibRaw *ip = (LibRaw *)lr->parent_class; + return ip->get_decoder_info(d); + } + int libraw_COLOR(libraw_data_t *lr, int row, int col) + { + if (!lr) + return EINVAL; + LibRaw *ip = (LibRaw *)lr->parent_class; + return ip->COLOR(row, col); + } + + /* getters/setters used by 3DLut Creator */ + DllDef void libraw_set_demosaic(libraw_data_t *lr, int value) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + ip->imgdata.params.user_qual = value; + } + + DllDef void libraw_set_output_color(libraw_data_t *lr, int value) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + ip->imgdata.params.output_color = value; + } + + DllDef void libraw_set_output_bps(libraw_data_t *lr, int value) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + ip->imgdata.params.output_bps = value; + } + +#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)) + + DllDef void libraw_set_user_mul(libraw_data_t *lr, int index, float val) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + ip->imgdata.params.user_mul[LIM(index, 0, 3)] = val; + } + + DllDef void libraw_set_gamma(libraw_data_t *lr, int index, float value) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + ip->imgdata.params.gamm[LIM(index, 0, 5)] = value; + } + + DllDef void libraw_set_no_auto_bright(libraw_data_t *lr, int value) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + ip->imgdata.params.no_auto_bright = value; + } + + DllDef void libraw_set_bright(libraw_data_t *lr, float value) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + ip->imgdata.params.bright = value; + } + + DllDef void libraw_set_highlight(libraw_data_t *lr, int value) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + ip->imgdata.params.highlight = value; + } + + DllDef void libraw_set_fbdd_noiserd(libraw_data_t *lr, int value) + { + if (!lr) + return; + LibRaw *ip = (LibRaw *)lr->parent_class; + ip->imgdata.params.fbdd_noiserd = value; + } + + DllDef int libraw_get_raw_height(libraw_data_t *lr) + { + if (!lr) + return EINVAL; + return lr->sizes.raw_height; + } + + DllDef int libraw_get_raw_width(libraw_data_t *lr) + { + if (!lr) + return EINVAL; + return lr->sizes.raw_width; + } + + DllDef int libraw_get_iheight(libraw_data_t *lr) + { + if (!lr) + return EINVAL; + return lr->sizes.iheight; + } + + DllDef int libraw_get_iwidth(libraw_data_t *lr) + { + if (!lr) + return EINVAL; + return lr->sizes.iwidth; + } + + DllDef float libraw_get_cam_mul(libraw_data_t *lr, int index) + { + if (!lr) + return EINVAL; + return lr->color.cam_mul[LIM(index, 0, 3)]; + } + + DllDef float libraw_get_pre_mul(libraw_data_t *lr, int index) + { + if (!lr) + return EINVAL; + return lr->color.pre_mul[LIM(index, 0, 3)]; + } + + DllDef float libraw_get_rgb_cam(libraw_data_t *lr, int index1, int index2) + { + if (!lr) + return EINVAL; + return lr->color.rgb_cam[LIM(index1, 0, 2)][LIM(index2, 0, 3)]; + } + + DllDef int libraw_get_color_maximum(libraw_data_t *lr) + { + if (!lr) + return EINVAL; + return lr->color.maximum; + } #ifdef __cplusplus } #endif diff --git a/core/libs/rawengine/libraw/src/libraw_cxx.cpp b/core/libs/rawengine/libraw/src/libraw_cxx.cpp index 659b93ef8b..d79d34bf03 100644 --- a/core/libs/rawengine/libraw/src/libraw_cxx.cpp +++ b/core/libs/rawengine/libraw/src/libraw_cxx.cpp @@ -1,6033 +1,6674 @@ /* -*- C++ -*- * File: libraw_cxx.cpp - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) * Created: Sat Mar 8 , 2008 * * LibRaw C++ interface (implementation) LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #include #include #include #include #include #include #include #if !defined(_WIN32) && !defined(__MINGW32__) #include #else #include #endif #define LIBRAW_LIBRARY_BUILD #include "libraw/libraw.h" #include "internal/defines.h" #ifdef USE_ZLIB #include #endif - - #ifdef USE_RAWSPEED #include "../RawSpeed/rawspeed_xmldata.cpp" #include #include #include #include #include #include #endif #ifdef USE_DNGSDK #include "dng_host.h" #include "dng_negative.h" #include "dng_simple_image.h" #include "dng_info.h" #endif -#include "libraw_xtrans_compressed.cpp" +#include "libraw_fuji_compressed.cpp" #ifdef __cplusplus extern "C" { #endif - void default_memory_callback(void *,const char *file,const char *where) + void default_memory_callback(void *, const char *file, const char *where) { - fprintf (stderr,"%s: Out of memory in %s\n", file?file:"unknown file", where); + fprintf(stderr, "%s: Out of memory in %s\n", file ? file : "unknown file", where); } - void default_data_callback(void*,const char *file, const int offset) + void default_data_callback(void *, const char *file, const int offset) { - if(offset < 0) - fprintf (stderr,"%s: Unexpected end of file\n", file?file:"unknown file"); + if (offset < 0) + fprintf(stderr, "%s: Unexpected end of file\n", file ? file : "unknown file"); else - fprintf (stderr,"%s: data corrupted at %d\n",file?file:"unknown file",offset); + fprintf(stderr, "%s: data corrupted at %d\n", file ? file : "unknown file", offset); } const char *libraw_strerror(int e) { enum LibRaw_errors errorcode = (LibRaw_errors)e; - switch(errorcode) - { - case LIBRAW_SUCCESS: - return "No error"; - case LIBRAW_UNSPECIFIED_ERROR: - return "Unspecified error"; - case LIBRAW_FILE_UNSUPPORTED: - return "Unsupported file format or not RAW file"; - case LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE: - return "Request for nonexisting image number"; - case LIBRAW_OUT_OF_ORDER_CALL: - return "Out of order call of libraw function"; - case LIBRAW_NO_THUMBNAIL: - return "No thumbnail in file"; - case LIBRAW_UNSUPPORTED_THUMBNAIL: - return "Unsupported thumbnail format"; - case LIBRAW_INPUT_CLOSED: - return "No input stream, or input stream closed"; - case LIBRAW_UNSUFFICIENT_MEMORY: - return "Unsufficient memory"; - case LIBRAW_DATA_ERROR: - return "Corrupted data or unexpected EOF"; - case LIBRAW_IO_ERROR: - return "Input/output error"; - case LIBRAW_CANCELLED_BY_CALLBACK: - return "Cancelled by user callback"; - case LIBRAW_BAD_CROP: - return "Bad crop box"; - default: - return "Unknown error code"; - } + switch (errorcode) + { + case LIBRAW_SUCCESS: + return "No error"; + case LIBRAW_UNSPECIFIED_ERROR: + return "Unspecified error"; + case LIBRAW_FILE_UNSUPPORTED: + return "Unsupported file format or not RAW file"; + case LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE: + return "Request for nonexisting image number"; + case LIBRAW_OUT_OF_ORDER_CALL: + return "Out of order call of libraw function"; + case LIBRAW_NO_THUMBNAIL: + return "No thumbnail in file"; + case LIBRAW_UNSUPPORTED_THUMBNAIL: + return "Unsupported thumbnail format"; + case LIBRAW_INPUT_CLOSED: + return "No input stream, or input stream closed"; + case LIBRAW_UNSUFFICIENT_MEMORY: + return "Unsufficient memory"; + case LIBRAW_DATA_ERROR: + return "Corrupted data or unexpected EOF"; + case LIBRAW_IO_ERROR: + return "Input/output error"; + case LIBRAW_CANCELLED_BY_CALLBACK: + return "Cancelled by user callback"; + case LIBRAW_BAD_CROP: + return "Bad crop box"; + case LIBRAW_TOO_BIG: + return "Image too big for processing"; + default: + return "Unknown error code"; + } } #ifdef __cplusplus } #endif -#define Sigma_X3F 22 +#define Sigma_X3F 22 -const double LibRaw_constants::xyz_rgb[3][3] = -{ - { 0.412453, 0.357580, 0.180423 }, - { 0.212671, 0.715160, 0.072169 }, - { 0.019334, 0.119193, 0.950227 } -}; +const double LibRaw_constants::xyz_rgb[3][3] = { + {0.4124564, 0.3575761, 0.1804375}, {0.2126729, 0.7151522, 0.0721750}, {0.0193339, 0.1191920, 0.9503041}}; -const float LibRaw_constants::d65_white[3] = { 0.950456f, 1.0f, 1.088754f }; +const float LibRaw_constants::d65_white[3] = {0.95047f, 1.0f, 1.08883f}; #define P1 imgdata.idata #define S imgdata.sizes #define O imgdata.params #define C imgdata.color #define T imgdata.thumbnail #define IO libraw_internal_data.internal_output_params #define ID libraw_internal_data.internal_data -#define EXCEPTION_HANDLER(e) do{ \ - /* fprintf(stderr,"Exception %d caught\n",e);*/ \ - switch(e) \ - { \ - case LIBRAW_EXCEPTION_ALLOC: \ - recycle(); \ - return LIBRAW_UNSUFFICIENT_MEMORY; \ - case LIBRAW_EXCEPTION_DECODE_RAW: \ - case LIBRAW_EXCEPTION_DECODE_JPEG: \ - recycle(); \ - return LIBRAW_DATA_ERROR; \ - case LIBRAW_EXCEPTION_DECODE_JPEG2000: \ - recycle(); \ - return LIBRAW_DATA_ERROR; \ - case LIBRAW_EXCEPTION_IO_EOF: \ - case LIBRAW_EXCEPTION_IO_CORRUPT: \ - recycle(); \ - return LIBRAW_IO_ERROR; \ - case LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK: \ - recycle(); \ - return LIBRAW_CANCELLED_BY_CALLBACK; \ - case LIBRAW_EXCEPTION_BAD_CROP: \ - recycle(); \ - return LIBRAW_BAD_CROP; \ - default: \ - return LIBRAW_UNSPECIFIED_ERROR; \ - } \ - }while(0) - -const char* LibRaw::version() { return LIBRAW_VERSION_STR;} +#define EXCEPTION_HANDLER(e) \ + do \ + { \ + /* fprintf(stderr,"Exception %d caught\n",e);*/ \ + switch (e) \ + { \ + case LIBRAW_EXCEPTION_ALLOC: \ + recycle(); \ + return LIBRAW_UNSUFFICIENT_MEMORY; \ + case LIBRAW_EXCEPTION_TOOBIG: \ + recycle(); \ + return LIBRAW_TOO_BIG; \ + case LIBRAW_EXCEPTION_DECODE_RAW: \ + case LIBRAW_EXCEPTION_DECODE_JPEG: \ + recycle(); \ + return LIBRAW_DATA_ERROR; \ + case LIBRAW_EXCEPTION_DECODE_JPEG2000: \ + recycle(); \ + return LIBRAW_DATA_ERROR; \ + case LIBRAW_EXCEPTION_IO_EOF: \ + case LIBRAW_EXCEPTION_IO_CORRUPT: \ + recycle(); \ + return LIBRAW_IO_ERROR; \ + case LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK: \ + recycle(); \ + return LIBRAW_CANCELLED_BY_CALLBACK; \ + case LIBRAW_EXCEPTION_BAD_CROP: \ + recycle(); \ + return LIBRAW_BAD_CROP; \ + default: \ + return LIBRAW_UNSPECIFIED_ERROR; \ + } \ + } while (0) + +const char *LibRaw::version() { return LIBRAW_VERSION_STR; } int LibRaw::versionNumber() { return LIBRAW_VERSION; } -const char* LibRaw::strerror(int p) { return libraw_strerror(p);} +const char *LibRaw::strerror(int p) { return libraw_strerror(p); } unsigned LibRaw::capabilities() { - unsigned ret = 0; + unsigned ret = 0; #ifdef USE_RAWSPEED - ret |= LIBRAW_CAPS_RAWSPEED; + ret |= LIBRAW_CAPS_RAWSPEED; #endif #ifdef USE_DNGSDK - ret |= LIBRAW_CAPS_DNGSDK; -#endif -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 - ret |= LIBRAW_CAPS_DEMOSAICSGPL2; -#endif -#ifdef LIBRAW_DEMOSAIC_PACK_GPL3 - ret |= LIBRAW_CAPS_DEMOSAICSGPL3; + ret |= LIBRAW_CAPS_DNGSDK; #endif - return ret; + return ret; } -unsigned LibRaw:: parse_custom_cameras(unsigned limit, libraw_custom_camera_t table[], char** list) +unsigned LibRaw::parse_custom_cameras(unsigned limit, libraw_custom_camera_t table[], char **list) { - if(!list) return 0; + if (!list) + return 0; unsigned index = 0; - for(int i=0; i< limit; i++) - { - if(!list[i]) break; - if(strlen(list[i])<10) continue; - char *string = (char*)malloc(strlen(list[i])+1); - strcpy(string,list[i]); - char *start = string; - memset(&table[index],0,sizeof(table[0])); - for(int j = 0; start && j < 14; j++) - { - char *end = strchr(start,','); - if(end) { *end = 0; end++; } // move to next char - while(isspace(*start) && *start) start++; // skip leading spaces? - unsigned val = strtol(start,0,10); - switch(j) - { - case 0: table[index].fsize = val; break; - case 1: table[index].rw = val; break; - case 2: table[index].rh = val; break; - case 3: table[index].lm = val; break; - case 4: table[index].tm = val; break; - case 5: table[index].rm = val; break; - case 6: table[index].bm = val; break; - case 7: table[index].lf = val; break; - case 8: table[index].cf = val; break; - case 9: table[index].max = val; break; - case 10: table[index].flags = val; break; - case 11: strncpy(table[index].t_make,start,sizeof(table[index].t_make)-1); break; - case 12: strncpy(table[index].t_model,start,sizeof(table[index].t_model)-1); break; - case 13: table[index].offset = val; break; - default: break; - } - start = end; - } - free(string); - if(table[index].t_make[0]) - index++; + for (int i = 0; i < limit; i++) + { + if (!list[i]) + break; + if (strlen(list[i]) < 10) + continue; + char *string = (char *)malloc(strlen(list[i]) + 1); + strcpy(string, list[i]); + char *start = string; + memset(&table[index], 0, sizeof(table[0])); + for (int j = 0; start && j < 14; j++) + { + char *end = strchr(start, ','); + if (end) + { + *end = 0; + end++; + } // move to next char + while (isspace(*start) && *start) + start++; // skip leading spaces? + unsigned val = strtol(start, 0, 10); + switch (j) + { + case 0: + table[index].fsize = val; + break; + case 1: + table[index].rw = val; + break; + case 2: + table[index].rh = val; + break; + case 3: + table[index].lm = val; + break; + case 4: + table[index].tm = val; + break; + case 5: + table[index].rm = val; + break; + case 6: + table[index].bm = val; + break; + case 7: + table[index].lf = val; + break; + case 8: + table[index].cf = val; + break; + case 9: + table[index].max = val; + break; + case 10: + table[index].flags = val; + break; + case 11: + strncpy(table[index].t_make, start, sizeof(table[index].t_make) - 1); + break; + case 12: + strncpy(table[index].t_model, start, sizeof(table[index].t_model) - 1); + break; + case 13: + table[index].offset = val; + break; + default: + break; + } + start = end; } + free(string); + if (table[index].t_make[0]) + index++; + } return index; } void LibRaw::derror() { if (!libraw_internal_data.unpacker_data.data_error && libraw_internal_data.internal_data.input) + { + if (libraw_internal_data.internal_data.input->eof()) { - if (libraw_internal_data.internal_data.input->eof()) - { - if(callbacks.data_cb)(*callbacks.data_cb)(callbacks.datacb_data, - libraw_internal_data.internal_data.input->fname(),-1); - throw LIBRAW_EXCEPTION_IO_EOF; - } - else - { - if(callbacks.data_cb)(*callbacks.data_cb)(callbacks.datacb_data, - libraw_internal_data.internal_data.input->fname(), - libraw_internal_data.internal_data.input->tell()); - //throw LIBRAW_EXCEPTION_IO_CORRUPT; - } + if (callbacks.data_cb) + (*callbacks.data_cb)(callbacks.datacb_data, libraw_internal_data.internal_data.input->fname(), -1); + throw LIBRAW_EXCEPTION_IO_EOF; + } + else + { + if (callbacks.data_cb) + (*callbacks.data_cb)(callbacks.datacb_data, libraw_internal_data.internal_data.input->fname(), + libraw_internal_data.internal_data.input->tell()); + // throw LIBRAW_EXCEPTION_IO_CORRUPT; } + } libraw_internal_data.unpacker_data.data_error++; } -void LibRaw::dcraw_clear_mem(libraw_processed_image_t* p) +void LibRaw::dcraw_clear_mem(libraw_processed_image_t *p) { - if(p) ::free(p); + if (p) + ::free(p); } -int LibRaw::is_sraw() { return load_raw == &LibRaw::canon_sraw_load_raw || load_raw == &LibRaw::nikon_load_sraw ; } -int LibRaw::is_coolscan_nef() { return load_raw == &LibRaw::nikon_coolscan_load_raw;} +int LibRaw::is_sraw() { return load_raw == &LibRaw::canon_sraw_load_raw || load_raw == &LibRaw::nikon_load_sraw; } +int LibRaw::is_coolscan_nef() { return load_raw == &LibRaw::nikon_coolscan_load_raw; } +int LibRaw::is_jpeg_thumb() { return thumb_load_raw == 0 && write_thumb == &LibRaw::jpeg_thumb; } -int LibRaw::is_nikon_sraw(){ - return load_raw == &LibRaw::nikon_load_sraw; -} -int LibRaw::sraw_midpoint() { - if (load_raw == &LibRaw::canon_sraw_load_raw) return 8192; - else if (load_raw == &LibRaw::nikon_load_sraw) return 2048; - else return 0; +int LibRaw::is_nikon_sraw() { return load_raw == &LibRaw::nikon_load_sraw; } +int LibRaw::sraw_midpoint() +{ + if (load_raw == &LibRaw::canon_sraw_load_raw) + return 8192; + else if (load_raw == &LibRaw::nikon_load_sraw) + return 2048; + else + return 0; } - #ifdef USE_RAWSPEED using namespace RawSpeed; class CameraMetaDataLR : public CameraMetaData { public: CameraMetaDataLR() : CameraMetaData() {} - CameraMetaDataLR(char *filename) : CameraMetaData(filename){} + CameraMetaDataLR(char *filename) : CameraMetaData(filename) {} CameraMetaDataLR(char *data, int sz); }; -CameraMetaDataLR::CameraMetaDataLR(char *data, int sz) : CameraMetaData() { +CameraMetaDataLR::CameraMetaDataLR(char *data, int sz) : CameraMetaData() +{ ctxt = xmlNewParserCtxt(); - if (ctxt == NULL) { + if (ctxt == NULL) + { ThrowCME("CameraMetaData:Could not initialize context."); } xmlResetLastError(); - doc = xmlCtxtReadMemory(ctxt, data,sz, "", NULL, XML_PARSE_DTDVALID); + doc = xmlCtxtReadMemory(ctxt, data, sz, "", NULL, XML_PARSE_DTDVALID); - if (doc == NULL) { + if (doc == NULL) + { ThrowCME("CameraMetaData: XML Document could not be parsed successfully. Error was: %s", ctxt->lastError.message); } - if (ctxt->valid == 0) { - if (ctxt->lastError.code == 0x5e) { + if (ctxt->valid == 0) + { + if (ctxt->lastError.code == 0x5e) + { // printf("CameraMetaData: Unable to locate DTD, attempting to ignore."); - } else { + } + else + { ThrowCME("CameraMetaData: XML file does not validate. DTD Error was: %s", ctxt->lastError.message); } } xmlNodePtr cur; cur = xmlDocGetRootElement(doc); - if (xmlStrcmp(cur->name, (const xmlChar *) "Cameras")) { + if (xmlStrcmp(cur->name, (const xmlChar *)"Cameras")) + { ThrowCME("CameraMetaData: XML document of the wrong type, root node is not cameras."); return; } cur = cur->xmlChildrenNode; - while (cur != NULL) { - if ((!xmlStrcmp(cur->name, (const xmlChar *)"Camera"))) { + while (cur != NULL) + { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"Camera"))) + { Camera *camera = new Camera(doc, cur); addCamera(camera); // Create cameras for aliases. - for (unsigned int i = 0; i < camera->aliases.size(); i++) { + for (unsigned int i = 0; i < camera->aliases.size(); i++) + { addCamera(new Camera(camera, i)); } } cur = cur->next; } if (doc) xmlFreeDoc(doc); doc = 0; if (ctxt) xmlFreeParserCtxt(ctxt); ctxt = 0; } -#define RAWSPEED_DATA_COUNT (sizeof(_rawspeed_data_xml)/sizeof(_rawspeed_data_xml[0])) -static CameraMetaDataLR* make_camera_metadata() +#define RAWSPEED_DATA_COUNT (sizeof(_rawspeed_data_xml) / sizeof(_rawspeed_data_xml[0])) +static CameraMetaDataLR *make_camera_metadata() { - int len = 0,i; - for(i=0;ilen) break; - memmove(rawspeed_xml+offt,_rawspeed_data_xml[i],ll); - offt+=ll; - } - rawspeed_xml[offt]=0; - CameraMetaDataLR *ret=NULL; - try { - ret = new CameraMetaDataLR(rawspeed_xml,offt); - } catch (...) { + for (i = 0; i < RAWSPEED_DATA_COUNT; i++) + if (_rawspeed_data_xml[i]) + { + int ll = strlen(_rawspeed_data_xml[i]); + if (offt + ll > len) + break; + memmove(rawspeed_xml + offt, _rawspeed_data_xml[i], ll); + offt += ll; + } + rawspeed_xml[offt] = 0; + CameraMetaDataLR *ret = NULL; + try + { + ret = new CameraMetaDataLR(rawspeed_xml, offt); + } + catch (...) + { // Mask all exceptions } free(rawspeed_xml); return ret; } #endif -#define ZERO(a) memset(&a,0,sizeof(a)) +#define ZERO(a) memset(&a, 0, sizeof(a)) -static void cleargps(libraw_gps_info_t*q) +static void cleargps(libraw_gps_info_t *q) { - for (int i = 0; i < 3; i++) - q->latitude[i] = q->longtitude[i] = q->gpstimestamp[i] = 0.f; - q->altitude = 0.f; - q->altref = q->latref = q->longref = q->gpsstatus = q->gpsparsed = 0; + for (int i = 0; i < 3; i++) + q->latitude[i] = q->longtitude[i] = q->gpstimestamp[i] = 0.f; + q->altitude = 0.f; + q->altref = q->latref = q->longref = q->gpsstatus = q->gpsparsed = 0; } -LibRaw:: LibRaw(unsigned int flags) +LibRaw::LibRaw(unsigned int flags) : memmgr(1024) { - double aber[4] = {1,1,1,1}; - double gamm[6] = { 0.45,4.5,0,0,0,0 }; - unsigned greybox[4] = { 0, 0, UINT_MAX, UINT_MAX }; - unsigned cropbox[4] = { 0, 0, UINT_MAX, UINT_MAX }; + double aber[4] = {1, 1, 1, 1}; + double gamm[6] = {0.45, 4.5, 0, 0, 0, 0}; + unsigned greybox[4] = {0, 0, UINT_MAX, UINT_MAX}; + unsigned cropbox[4] = {0, 0, UINT_MAX, UINT_MAX}; #ifdef DCRAW_VERBOSE verbose = 1; #else verbose = 0; #endif ZERO(imgdata); cleargps(&imgdata.other.parsed_gps); ZERO(libraw_internal_data); ZERO(callbacks); _rawspeed_camerameta = _rawspeed_decoder = NULL; - dnghost = NULL; + dnghost = NULL; _x3f_data = NULL; #ifdef USE_RAWSPEED CameraMetaDataLR *camerameta = make_camera_metadata(); // May be NULL in case of exception in make_camera_metadata() - _rawspeed_camerameta = static_cast(camerameta); + _rawspeed_camerameta = static_cast(camerameta); #endif - callbacks.mem_cb = (flags & LIBRAW_OPIONS_NO_MEMERR_CALLBACK) ? NULL: &default_memory_callback; - callbacks.data_cb = (flags & LIBRAW_OPIONS_NO_DATAERR_CALLBACK)? NULL : &default_data_callback; + callbacks.mem_cb = (flags & LIBRAW_OPIONS_NO_MEMERR_CALLBACK) ? NULL : &default_memory_callback; + callbacks.data_cb = (flags & LIBRAW_OPIONS_NO_DATAERR_CALLBACK) ? NULL : &default_data_callback; callbacks.exif_cb = NULL; // no default callback - memmove(&imgdata.params.aber,&aber,sizeof(aber)); - memmove(&imgdata.params.gamm,&gamm,sizeof(gamm)); - memmove(&imgdata.params.greybox,&greybox,sizeof(greybox)); - memmove(&imgdata.params.cropbox,&cropbox,sizeof(cropbox)); - - imgdata.params.bright=1; - imgdata.params.use_camera_matrix=1; - imgdata.params.user_flip=-1; - imgdata.params.user_black=-1; - imgdata.params.user_cblack[0]=imgdata.params.user_cblack[1]=imgdata.params.user_cblack[2]=imgdata.params.user_cblack[3]=-1000001; - imgdata.params.user_sat=-1; - imgdata.params.user_qual=-1; - imgdata.params.output_color=1; - imgdata.params.output_bps=8; - imgdata.params.use_fuji_rotate=1; + callbacks.pre_identify_cb = NULL; + callbacks.post_identify_cb = NULL; + callbacks.pre_subtractblack_cb = callbacks.pre_scalecolors_cb = callbacks.pre_preinterpolate_cb + = callbacks.pre_interpolate_cb = callbacks.interpolate_bayer_cb = callbacks.interpolate_xtrans_cb + = callbacks.post_interpolate_cb = callbacks.pre_converttorgb_cb = callbacks.post_converttorgb_cb + = NULL; + + memmove(&imgdata.params.aber, &aber, sizeof(aber)); + memmove(&imgdata.params.gamm, &gamm, sizeof(gamm)); + memmove(&imgdata.params.greybox, &greybox, sizeof(greybox)); + memmove(&imgdata.params.cropbox, &cropbox, sizeof(cropbox)); + + imgdata.params.bright = 1; + imgdata.params.use_camera_matrix = 1; + imgdata.params.user_flip = -1; + imgdata.params.user_black = -1; + imgdata.params.user_cblack[0] = imgdata.params.user_cblack[1] = imgdata.params.user_cblack[2] = + imgdata.params.user_cblack[3] = -1000001; + imgdata.params.user_sat = -1; + imgdata.params.user_qual = -1; + imgdata.params.output_color = 1; + imgdata.params.output_bps = 8; + imgdata.params.use_fuji_rotate = 1; imgdata.params.exp_shift = 1.0; imgdata.params.auto_bright_thr = LIBRAW_DEFAULT_AUTO_BRIGHTNESS_THRESHOLD; - imgdata.params.adjust_maximum_thr= LIBRAW_DEFAULT_ADJUST_MAXIMUM_THRESHOLD; + imgdata.params.adjust_maximum_thr = LIBRAW_DEFAULT_ADJUST_MAXIMUM_THRESHOLD; imgdata.params.use_rawspeed = 1; imgdata.params.use_dngsdk = LIBRAW_DNG_DEFAULT; imgdata.params.no_auto_scale = 0; imgdata.params.no_interpolation = 0; - imgdata.params.raw_processing_options = LIBRAW_PROCESSING_DP2Q_INTERPOLATERG|LIBRAW_PROCESSING_DP2Q_INTERPOLATEAF | LIBRAW_PROCESSING_CONVERTFLOAT_TO_INT; + imgdata.params.raw_processing_options = LIBRAW_PROCESSING_DP2Q_INTERPOLATERG | LIBRAW_PROCESSING_DP2Q_INTERPOLATEAF | + LIBRAW_PROCESSING_CONVERTFLOAT_TO_INT; imgdata.params.sony_arw2_posterization_thr = 0; imgdata.params.green_matching = 0; - imgdata.params.custom_camera_strings=0; + imgdata.params.custom_camera_strings = 0; imgdata.params.coolscan_nef_gamma = 1.0f; imgdata.parent_class = this; imgdata.progress_flags = 0; imgdata.color.baseline_exposure = -999.f; _exitflag = 0; tls = new LibRaw_TLS; tls->init(); - interpolate_bayer = 0; - interpolate_xtrans = 0; } int LibRaw::set_rawspeed_camerafile(char *filename) { #ifdef USE_RAWSPEED try + { + CameraMetaDataLR *camerameta = new CameraMetaDataLR(filename); + if (_rawspeed_camerameta) { - CameraMetaDataLR *camerameta = new CameraMetaDataLR(filename); - if(_rawspeed_camerameta) - { - CameraMetaDataLR *d = static_cast(_rawspeed_camerameta); - delete d; - } - _rawspeed_camerameta = static_cast(camerameta); + CameraMetaDataLR *d = static_cast(_rawspeed_camerameta); + delete d; } + _rawspeed_camerameta = static_cast(camerameta); + } catch (...) - { - //just return error code - return -1; - } + { + // just return error code + return -1; + } #endif return 0; } LibRaw::~LibRaw() { recycle(); delete tls; #ifdef USE_RAWSPEED - if(_rawspeed_camerameta) - { - CameraMetaDataLR *cmeta = static_cast(_rawspeed_camerameta); - delete cmeta; - _rawspeed_camerameta = NULL; - } + if (_rawspeed_camerameta) + { + CameraMetaDataLR *cmeta = static_cast(_rawspeed_camerameta); + delete cmeta; + _rawspeed_camerameta = NULL; + } #endif } -void* LibRaw:: malloc(size_t t) +void *LibRaw::malloc(size_t t) { - void *p = memmgr.malloc(t); - if(!p) - throw LIBRAW_EXCEPTION_ALLOC; - return p; + void *p = memmgr.malloc(t); + if (!p) + throw LIBRAW_EXCEPTION_ALLOC; + return p; } -void* LibRaw:: realloc(void *q,size_t t) +void *LibRaw::realloc(void *q, size_t t) { - void *p = memmgr.realloc(q,t); - if(!p) - throw LIBRAW_EXCEPTION_ALLOC; - return p; + void *p = memmgr.realloc(q, t); + if (!p) + throw LIBRAW_EXCEPTION_ALLOC; + return p; } - -void* LibRaw:: calloc(size_t n,size_t t) -{ - void *p = memmgr.calloc(n,t); - if(!p) - throw LIBRAW_EXCEPTION_ALLOC; - return p; -} -void LibRaw:: free(void *p) +void *LibRaw::calloc(size_t n, size_t t) { - memmgr.free(p); + void *p = memmgr.calloc(n, t); + if (!p) + throw LIBRAW_EXCEPTION_ALLOC; + return p; } +void LibRaw::free(void *p) { memmgr.free(p); } -void LibRaw:: recycle_datastream() +void LibRaw::recycle_datastream() { - if(libraw_internal_data.internal_data.input && libraw_internal_data.internal_data.input_internal) - { - delete libraw_internal_data.internal_data.input; - libraw_internal_data.internal_data.input = NULL; - } + if (libraw_internal_data.internal_data.input && libraw_internal_data.internal_data.input_internal) + { + delete libraw_internal_data.internal_data.input; + libraw_internal_data.internal_data.input = NULL; + } libraw_internal_data.internal_data.input_internal = 0; } -void x3f_clear(void*); - +void x3f_clear(void *); -void LibRaw:: recycle() +void LibRaw::recycle() { recycle_datastream(); -#define FREE(a) do { if(a) { free(a); a = NULL;} }while(0) +#define FREE(a) \ + do \ + { \ + if (a) \ + { \ + free(a); \ + a = NULL; \ + } \ + } while (0) FREE(imgdata.image); + FREE(imgdata.thumbnail.thumb); FREE(libraw_internal_data.internal_data.meta_data); FREE(libraw_internal_data.output_data.histogram); FREE(libraw_internal_data.output_data.oprof); FREE(imgdata.color.profile); FREE(imgdata.rawdata.ph1_cblack); FREE(imgdata.rawdata.ph1_rblack); FREE(imgdata.rawdata.raw_alloc); FREE(imgdata.idata.xmpdata); + #undef FREE + ZERO(imgdata.sizes); + imgdata.sizes.raw_crop.cleft = 0xffff; + imgdata.sizes.raw_crop.ctop = 0xffff; + ZERO(imgdata.idata); ZERO(imgdata.makernotes); ZERO(imgdata.color); ZERO(imgdata.other); ZERO(imgdata.thumbnail); ZERO(imgdata.rawdata); imgdata.makernotes.olympus.OlympusCropID = -1; + imgdata.makernotes.sony.raw_crop.cleft = 0xffff; + imgdata.makernotes.sony.raw_crop.ctop = 0xffff; cleargps(&imgdata.other.parsed_gps); imgdata.color.baseline_exposure = -999.f; imgdata.makernotes.fuji.FujiExpoMidPointShift = -999.f; imgdata.makernotes.fuji.FujiDynamicRange = 0xffff; imgdata.makernotes.fuji.FujiFilmMode = 0xffff; imgdata.makernotes.fuji.FujiDynamicRangeSetting = 0xffff; imgdata.makernotes.fuji.FujiDevelopmentDynamicRange = 0xffff; imgdata.makernotes.fuji.FujiAutoDynamicRange = 0xffff; imgdata.makernotes.fuji.FocusMode = 0xffff; imgdata.makernotes.fuji.AFMode = 0xffff; imgdata.makernotes.fuji.FocusPixel[0] = imgdata.makernotes.fuji.FocusPixel[1] = 0xffff; - imgdata.makernotes.fuji.ImageStabilization[0] = imgdata.makernotes.fuji.ImageStabilization[1] = imgdata.makernotes.fuji.ImageStabilization[2] = 0xffff; + imgdata.makernotes.fuji.ImageStabilization[0] = imgdata.makernotes.fuji.ImageStabilization[1] = + imgdata.makernotes.fuji.ImageStabilization[2] = 0xffff; imgdata.makernotes.sony.SonyCameraType = 0xffff; + imgdata.makernotes.sony.real_iso_offset = 0xffff; + imgdata.makernotes.sony.ImageCount3_offset = 0xffff; + imgdata.makernotes.sony.ElectronicFrontCurtainShutter = 0xffff; + + imgdata.makernotes.kodak.BlackLevelTop = 0xffff; + imgdata.makernotes.kodak.BlackLevelBottom = 0xffff; + imgdata.color.dng_color[0].illuminant = imgdata.color.dng_color[1].illuminant = 0xffff; - for(int i = 0; i < 4; i++) - imgdata.color.dng_levels.analogbalance[i]= - imgdata.color.dng_levels.analogbalance[i]=1.0f; + for (int i = 0; i < 4; i++) + imgdata.color.dng_levels.analogbalance[i] = 1.0f; ZERO(libraw_internal_data); ZERO(imgdata.lens); imgdata.lens.makernotes.CanonFocalUnits = 1; imgdata.lens.makernotes.LensID = 0xffffffffffffffffULL; ZERO(imgdata.shootinginfo); imgdata.shootinginfo.DriveMode = -1; imgdata.shootinginfo.FocusMode = -1; imgdata.shootinginfo.MeteringMode = -1; imgdata.shootinginfo.AFPoint = -1; imgdata.shootinginfo.ExposureMode = -1; imgdata.shootinginfo.ImageStabilization = -1; _exitflag = 0; #ifdef USE_RAWSPEED - if(_rawspeed_decoder) - { - RawDecoder *d = static_cast(_rawspeed_decoder); - delete d; - } + if (_rawspeed_decoder) + { + RawDecoder *d = static_cast(_rawspeed_decoder); + delete d; + } _rawspeed_decoder = 0; #endif - if(_x3f_data) - { - x3f_clear(_x3f_data); - _x3f_data = 0; - } + if (_x3f_data) + { + x3f_clear(_x3f_data); + _x3f_data = 0; + } memmgr.cleanup(); + imgdata.thumbnail.tformat = LIBRAW_THUMBNAIL_UNKNOWN; imgdata.progress_flags = 0; load_raw = thumb_load_raw = 0; tls->init(); } -const char * LibRaw::unpack_function_name() +const char *LibRaw::unpack_function_name() { libraw_decoder_info_t decoder_info; get_decoder_info(&decoder_info); return decoder_info.decoder_name; } -int LibRaw::get_decoder_info(libraw_decoder_info_t* d_info) +int LibRaw::get_decoder_info(libraw_decoder_info_t *d_info) { - if(!d_info) return LIBRAW_UNSPECIFIED_ERROR; + if (!d_info) + return LIBRAW_UNSPECIFIED_ERROR; d_info->decoder_name = 0; d_info->decoder_flags = 0; - if (!load_raw) return LIBRAW_OUT_OF_ORDER_CALL; + if (!load_raw) + return LIBRAW_OUT_OF_ORDER_CALL; int rawdata = (imgdata.idata.filters || P1.colors == 1); // dcraw.c names order if (load_raw == &LibRaw::android_tight_load_raw) { - d_info->decoder_name = "android_tight_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; + d_info->decoder_name = "android_tight_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; } else if (load_raw == &LibRaw::android_loose_load_raw) { - d_info->decoder_name = "android_loose_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; + d_info->decoder_name = "android_loose_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; } else if (load_raw == &LibRaw::canon_600_load_raw) - { - d_info->decoder_name = "canon_600_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; - } - else if (load_raw == &LibRaw::xtrans_compressed_load_raw) { - d_info->decoder_name = "xtrans_compressed_load_raw()"; + d_info->decoder_name = "canon_600_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; + } + else if (load_raw == &LibRaw::fuji_compressed_load_raw) + { + d_info->decoder_name = "fuji_compressed_load_raw()"; + } + else if (load_raw == &LibRaw::fuji_14bit_load_raw) + { + d_info->decoder_name = "fuji_14bit_load_raw()"; } else if (load_raw == &LibRaw::canon_load_raw) - { - d_info->decoder_name = "canon_load_raw()"; - } + { + d_info->decoder_name = "canon_load_raw()"; + } else if (load_raw == &LibRaw::lossless_jpeg_load_raw) - { - d_info->decoder_name = "lossless_jpeg_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_TRYRAWSPEED; - } + { + d_info->decoder_name = "lossless_jpeg_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_TRYRAWSPEED; + } else if (load_raw == &LibRaw::canon_sraw_load_raw) - { - d_info->decoder_name = "canon_sraw_load_raw()"; - //d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED; - } + { + d_info->decoder_name = "canon_sraw_load_raw()"; + // d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED; + } else if (load_raw == &LibRaw::lossless_dng_load_raw) - { - d_info->decoder_name = "lossless_dng_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_ADOBECOPYPIXEL; - } + { + d_info->decoder_name = "lossless_dng_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_ADOBECOPYPIXEL; + } else if (load_raw == &LibRaw::packed_dng_load_raw) - { - d_info->decoder_name = "packed_dng_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_ADOBECOPYPIXEL; - } - else if (load_raw == &LibRaw::pentax_load_raw ) - { - d_info->decoder_name = "pentax_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED; - } + { + d_info->decoder_name = "packed_dng_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_ADOBECOPYPIXEL; + } + else if (load_raw == &LibRaw::pentax_load_raw) + { + d_info->decoder_name = "pentax_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED; + } else if (load_raw == &LibRaw::nikon_load_raw) - { - d_info->decoder_name = "nikon_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED; - } - else if (load_raw == &LibRaw::nikon_coolscan_load_raw ) { - d_info->decoder_name = "nikon_coolscan_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; + d_info->decoder_name = "nikon_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED; } - else if (load_raw == &LibRaw::nikon_load_sraw ) - { - d_info->decoder_name = "nikon_load_sraw()"; - d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_FIXEDMAXC; - } - else if (load_raw == &LibRaw::nikon_yuv_load_raw ) - { - d_info->decoder_name = "nikon_load_yuv_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_FIXEDMAXC; - } - else if (load_raw == &LibRaw::rollei_load_raw ) - { - // UNTESTED - d_info->decoder_name = "rollei_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; - } - else if (load_raw == &LibRaw::phase_one_load_raw ) - { - d_info->decoder_name = "phase_one_load_raw()"; - } - else if (load_raw == &LibRaw::phase_one_load_raw_c ) - { - d_info->decoder_name = "phase_one_load_raw_c()"; - } - else if (load_raw == &LibRaw::hasselblad_load_raw ) - { - d_info->decoder_name = "hasselblad_load_raw()"; - } - else if (load_raw == &LibRaw::leaf_hdr_load_raw ) - { - d_info->decoder_name = "leaf_hdr_load_raw()"; - } - else if (load_raw == &LibRaw::unpacked_load_raw ) - { - d_info->decoder_name = "unpacked_load_raw()"; - } - else if (load_raw == &LibRaw::unpacked_load_raw_reversed ) + else if (load_raw == &LibRaw::nikon_coolscan_load_raw) { - d_info->decoder_name = "unpacked_load_raw_reversed()"; - d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; + d_info->decoder_name = "nikon_coolscan_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; } - else if (load_raw == &LibRaw::sinar_4shot_load_raw ) - { - // UNTESTED - d_info->decoder_name = "sinar_4shot_load_raw()"; - } - else if (load_raw == &LibRaw::imacon_full_load_raw ) - { - d_info->decoder_name = "imacon_full_load_raw()"; - } - else if (load_raw == &LibRaw::hasselblad_full_load_raw ) - { - d_info->decoder_name = "hasselblad_full_load_raw()"; - } - else if (load_raw == &LibRaw::packed_load_raw ) - { - d_info->decoder_name = "packed_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED; - } - else if (load_raw == &LibRaw::broadcom_load_raw ) - { - // UNTESTED - d_info->decoder_name = "broadcom_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; - } - else if (load_raw == &LibRaw::nokia_load_raw ) - { - // UNTESTED - d_info->decoder_name = "nokia_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; - } - else if (load_raw == &LibRaw::canon_rmf_load_raw ) - { - // UNTESTED - d_info->decoder_name = "canon_rmf_load_raw()"; - } - else if (load_raw == &LibRaw::panasonic_load_raw ) - { - d_info->decoder_name = "panasonic_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED; - } - else if (load_raw == &LibRaw::olympus_load_raw ) - { - d_info->decoder_name = "olympus_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED; - } - else if (load_raw == &LibRaw::minolta_rd175_load_raw ) - { - // UNTESTED - d_info->decoder_name = "minolta_rd175_load_raw()"; - } - else if (load_raw == &LibRaw::quicktake_100_load_raw ) - { - // UNTESTED - d_info->decoder_name = "quicktake_100_load_raw()"; - } - else if (load_raw == &LibRaw::kodak_radc_load_raw ) - { - d_info->decoder_name = "kodak_radc_load_raw()"; - } - else if (load_raw == &LibRaw::kodak_jpeg_load_raw ) - { - // UNTESTED + RBAYER - d_info->decoder_name = "kodak_jpeg_load_raw()"; - } - else if (load_raw == &LibRaw::lossy_dng_load_raw) - { - // Check rbayer - d_info->decoder_name = "lossy_dng_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_HASCURVE; - } - else if (load_raw == &LibRaw::kodak_dc120_load_raw ) - { - d_info->decoder_name = "kodak_dc120_load_raw()"; - } - else if (load_raw == &LibRaw::eight_bit_load_raw ) - { - d_info->decoder_name = "eight_bit_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_HASCURVE|LIBRAW_DECODER_FIXEDMAXC; - } - else if (load_raw == &LibRaw::kodak_c330_load_raw ) - { - d_info->decoder_name = "kodak_yrgb_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_HASCURVE|LIBRAW_DECODER_FIXEDMAXC; - } - else if (load_raw == &LibRaw::kodak_c603_load_raw ) - { - d_info->decoder_name = "kodak_yrgb_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_HASCURVE|LIBRAW_DECODER_FIXEDMAXC; - } - else if (load_raw == &LibRaw::kodak_262_load_raw ) - { - d_info->decoder_name = "kodak_262_load_raw()"; // UNTESTED! - d_info->decoder_flags = LIBRAW_DECODER_HASCURVE|LIBRAW_DECODER_FIXEDMAXC; - } - else if (load_raw == &LibRaw::kodak_65000_load_raw ) - { - d_info->decoder_name = "kodak_65000_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_HASCURVE; - } - else if (load_raw == &LibRaw::kodak_ycbcr_load_raw ) - { - // UNTESTED - d_info->decoder_name = "kodak_ycbcr_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_HASCURVE|LIBRAW_DECODER_FIXEDMAXC; - } - else if (load_raw == &LibRaw::kodak_rgb_load_raw ) - { - // UNTESTED - d_info->decoder_name = "kodak_rgb_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; - } - else if (load_raw == &LibRaw::sony_load_raw ) - { - d_info->decoder_name = "sony_load_raw()"; - } - else if (load_raw == &LibRaw::sony_arw_load_raw ) - { - d_info->decoder_name = "sony_arw_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED; - - } - else if (load_raw == &LibRaw::sony_arw2_load_raw ) - { - d_info->decoder_name = "sony_arw2_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_SONYARW2; - } - else if (load_raw == &LibRaw::samsung_load_raw ) - { - d_info->decoder_name = "samsung_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED; - } - else if (load_raw == &LibRaw::samsung2_load_raw ) - { - d_info->decoder_name = "samsung2_load_raw()"; - } - else if (load_raw == &LibRaw::samsung3_load_raw ) - { - d_info->decoder_name = "samsung3_load_raw()"; - } - else if (load_raw == &LibRaw::smal_v6_load_raw ) - { - // UNTESTED - d_info->decoder_name = "smal_v6_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; - } - else if (load_raw == &LibRaw::smal_v9_load_raw ) - { - // UNTESTED - d_info->decoder_name = "smal_v9_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; - } - else if (load_raw == &LibRaw::redcine_load_raw) - { - d_info->decoder_name = "redcine_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_HASCURVE; - } - else if (load_raw == &LibRaw::x3f_load_raw ) - { - d_info->decoder_name = "x3f_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_OWNALLOC|LIBRAW_DECODER_FIXEDMAXC | LIBRAW_DECODER_LEGACY_WITH_MARGINS ; - } - else if (load_raw == &LibRaw::pentax_4shot_load_raw ) + else if (load_raw == &LibRaw::nikon_load_sraw) { - d_info->decoder_name = "pentax_4shot_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_OWNALLOC; + d_info->decoder_name = "nikon_load_sraw()"; + d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_FIXEDMAXC; } - else if (load_raw == &LibRaw::deflate_dng_load_raw ) + else if (load_raw == &LibRaw::nikon_yuv_load_raw) { - d_info->decoder_name = "deflate_dng_load_raw()"; - d_info->decoder_flags = LIBRAW_DECODER_OWNALLOC; + d_info->decoder_name = "nikon_load_yuv_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_FIXEDMAXC; } - else if (load_raw == &LibRaw::nikon_load_striped_packed_raw ) - { - d_info->decoder_name = "nikon_load_striped_packed_raw()"; - } -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 - else if (load_raw == &LibRaw::foveon_sd_load_raw ) - { - d_info->decoder_name = "foveon_sd_load_raw()"; - } - else if (load_raw == &LibRaw::foveon_dp_load_raw ) - { - d_info->decoder_name = "foveon_dp_load_raw()"; - } -#endif - else - { - d_info->decoder_name = "Unknown unpack function"; - d_info->decoder_flags = LIBRAW_DECODER_NOTSET; - } - return LIBRAW_SUCCESS; -} - -int LibRaw::adjust_maximum() -{ - ushort real_max; - float auto_threshold; - - if(O.adjust_maximum_thr < 0.00001) - return LIBRAW_SUCCESS; - else if (O.adjust_maximum_thr > 0.99999) - auto_threshold = LIBRAW_DEFAULT_ADJUST_MAXIMUM_THRESHOLD; - else - auto_threshold = O.adjust_maximum_thr; - - - real_max = C.data_maximum; - if (real_max > 0 && real_max < C.maximum && real_max > C.maximum* auto_threshold) - { - C.maximum = real_max; - } - return LIBRAW_SUCCESS; + else if (load_raw == &LibRaw::rollei_load_raw) + { + // UNTESTED + d_info->decoder_name = "rollei_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; + } + else if (load_raw == &LibRaw::phase_one_load_raw) + { + d_info->decoder_name = "phase_one_load_raw()"; + } + else if (load_raw == &LibRaw::phase_one_load_raw_c) + { + d_info->decoder_name = "phase_one_load_raw_c()"; + } + else if (load_raw == &LibRaw::hasselblad_load_raw) + { + d_info->decoder_name = "hasselblad_load_raw()"; + } + else if (load_raw == &LibRaw::leaf_hdr_load_raw) + { + d_info->decoder_name = "leaf_hdr_load_raw()"; + } + else if (load_raw == &LibRaw::unpacked_load_raw) + { + d_info->decoder_name = "unpacked_load_raw()"; + } + else if (load_raw == &LibRaw::unpacked_load_raw_reversed) + { + d_info->decoder_name = "unpacked_load_raw_reversed()"; + d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; + } + else if (load_raw == &LibRaw::sinar_4shot_load_raw) + { + // UNTESTED + d_info->decoder_name = "sinar_4shot_load_raw()"; + } + else if (load_raw == &LibRaw::imacon_full_load_raw) + { + d_info->decoder_name = "imacon_full_load_raw()"; + } + else if (load_raw == &LibRaw::hasselblad_full_load_raw) + { + d_info->decoder_name = "hasselblad_full_load_raw()"; + } + else if (load_raw == &LibRaw::packed_load_raw) + { + d_info->decoder_name = "packed_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED; + } + else if (load_raw == &LibRaw::broadcom_load_raw) + { + // UNTESTED + d_info->decoder_name = "broadcom_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; + } + else if (load_raw == &LibRaw::nokia_load_raw) + { + // UNTESTED + d_info->decoder_name = "nokia_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; + } + else if (load_raw == &LibRaw::canon_rmf_load_raw) + { + // UNTESTED + d_info->decoder_name = "canon_rmf_load_raw()"; + } + else if (load_raw == &LibRaw::panasonic_load_raw) + { + d_info->decoder_name = "panasonic_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED; + } + else if (load_raw == &LibRaw::olympus_load_raw) + { + d_info->decoder_name = "olympus_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED; + } + else if (load_raw == &LibRaw::minolta_rd175_load_raw) + { + // UNTESTED + d_info->decoder_name = "minolta_rd175_load_raw()"; + } + else if (load_raw == &LibRaw::quicktake_100_load_raw) + { + // UNTESTED + d_info->decoder_name = "quicktake_100_load_raw()"; + } + else if (load_raw == &LibRaw::kodak_radc_load_raw) + { + d_info->decoder_name = "kodak_radc_load_raw()"; + } + else if (load_raw == &LibRaw::kodak_jpeg_load_raw) + { + // UNTESTED + RBAYER + d_info->decoder_name = "kodak_jpeg_load_raw()"; + } + else if (load_raw == &LibRaw::lossy_dng_load_raw) + { + // Check rbayer + d_info->decoder_name = "lossy_dng_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_HASCURVE; + } + else if (load_raw == &LibRaw::kodak_dc120_load_raw) + { + d_info->decoder_name = "kodak_dc120_load_raw()"; + } + else if (load_raw == &LibRaw::eight_bit_load_raw) + { + d_info->decoder_name = "eight_bit_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_FIXEDMAXC; + } + else if (load_raw == &LibRaw::kodak_c330_load_raw) + { + d_info->decoder_name = "kodak_yrgb_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_FIXEDMAXC; + } + else if (load_raw == &LibRaw::kodak_c603_load_raw) + { + d_info->decoder_name = "kodak_yrgb_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_FIXEDMAXC; + } + else if (load_raw == &LibRaw::kodak_262_load_raw) + { + d_info->decoder_name = "kodak_262_load_raw()"; // UNTESTED! + d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_FIXEDMAXC; + } + else if (load_raw == &LibRaw::kodak_65000_load_raw) + { + d_info->decoder_name = "kodak_65000_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_HASCURVE; + } + else if (load_raw == &LibRaw::kodak_ycbcr_load_raw) + { + // UNTESTED + d_info->decoder_name = "kodak_ycbcr_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_FIXEDMAXC; + } + else if (load_raw == &LibRaw::kodak_rgb_load_raw) + { + // UNTESTED + d_info->decoder_name = "kodak_rgb_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; + } + else if (load_raw == &LibRaw::sony_load_raw) + { + d_info->decoder_name = "sony_load_raw()"; + } + else if (load_raw == &LibRaw::sony_arw_load_raw) + { + d_info->decoder_name = "sony_arw_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED; + } + else if (load_raw == &LibRaw::sony_arw2_load_raw) + { + d_info->decoder_name = "sony_arw2_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_SONYARW2; + } + else if (load_raw == &LibRaw::sony_arq_load_raw) + { + d_info->decoder_name = "sony_arq_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_LEGACY_WITH_MARGINS; + } + else if (load_raw == &LibRaw::samsung_load_raw) + { + d_info->decoder_name = "samsung_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_TRYRAWSPEED; + } + else if (load_raw == &LibRaw::samsung2_load_raw) + { + d_info->decoder_name = "samsung2_load_raw()"; + } + else if (load_raw == &LibRaw::samsung3_load_raw) + { + d_info->decoder_name = "samsung3_load_raw()"; + } + else if (load_raw == &LibRaw::smal_v6_load_raw) + { + // UNTESTED + d_info->decoder_name = "smal_v6_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; + } + else if (load_raw == &LibRaw::smal_v9_load_raw) + { + // UNTESTED + d_info->decoder_name = "smal_v9_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_FIXEDMAXC; + } + else if (load_raw == &LibRaw::redcine_load_raw) + { + d_info->decoder_name = "redcine_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_HASCURVE; + } + else if (load_raw == &LibRaw::x3f_load_raw) + { + d_info->decoder_name = "x3f_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_OWNALLOC | LIBRAW_DECODER_FIXEDMAXC | LIBRAW_DECODER_LEGACY_WITH_MARGINS; + } + else if (load_raw == &LibRaw::pentax_4shot_load_raw) + { + d_info->decoder_name = "pentax_4shot_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_OWNALLOC; + } + else if (load_raw == &LibRaw::deflate_dng_load_raw) + { + d_info->decoder_name = "deflate_dng_load_raw()"; + d_info->decoder_flags = LIBRAW_DECODER_OWNALLOC; + } + else if (load_raw == &LibRaw::nikon_load_striped_packed_raw) + { + d_info->decoder_name = "nikon_load_striped_packed_raw()"; + } + else + { + d_info->decoder_name = "Unknown unpack function"; + d_info->decoder_flags = LIBRAW_DECODER_NOTSET; + } + return LIBRAW_SUCCESS; } - -void LibRaw:: merror (void *ptr, const char *where) +int LibRaw::adjust_maximum() { - if (ptr) return; - if(callbacks.mem_cb)(*callbacks.mem_cb)(callbacks.memcb_data, - libraw_internal_data.internal_data.input - ?libraw_internal_data.internal_data.input->fname() - :NULL, - where); - throw LIBRAW_EXCEPTION_ALLOC; -} + ushort real_max; + float auto_threshold; + + if (O.adjust_maximum_thr < 0.00001) + return LIBRAW_SUCCESS; + else if (O.adjust_maximum_thr > 0.99999) + auto_threshold = LIBRAW_DEFAULT_ADJUST_MAXIMUM_THRESHOLD; + else + auto_threshold = O.adjust_maximum_thr; + real_max = C.data_maximum; + if (real_max > 0 && real_max < C.maximum && real_max > C.maximum * auto_threshold) + { + C.maximum = real_max; + } + return LIBRAW_SUCCESS; +} +void LibRaw::merror(void *ptr, const char *where) +{ + if (ptr) + return; + if (callbacks.mem_cb) + (*callbacks.mem_cb)( + callbacks.memcb_data, + libraw_internal_data.internal_data.input ? libraw_internal_data.internal_data.input->fname() : NULL, where); + throw LIBRAW_EXCEPTION_ALLOC; +} int LibRaw::open_file(const char *fname, INT64 max_buf_size) { #ifndef WIN32 struct stat st; - if(stat(fname,&st)) + if (stat(fname, &st)) return LIBRAW_IO_ERROR; - int big = (st.st_size > max_buf_size)?1:0; + int big = (st.st_size > max_buf_size) ? 1 : 0; #else struct _stati64 st; - if(_stati64(fname,&st)) + if (_stati64(fname, &st)) return LIBRAW_IO_ERROR; - int big = (st.st_size > max_buf_size)?1:0; + int big = (st.st_size > max_buf_size) ? 1 : 0; #endif LibRaw_abstract_datastream *stream; - try { - if(big) + try + { + if (big) stream = new LibRaw_bigfile_datastream(fname); else stream = new LibRaw_file_datastream(fname); } catch (std::bad_alloc) - { - recycle(); - return LIBRAW_UNSUFFICIENT_MEMORY; - } - if(!stream->valid()) - { - delete stream; - return LIBRAW_IO_ERROR; - } + { + recycle(); + return LIBRAW_UNSUFFICIENT_MEMORY; + } + if (!stream->valid()) + { + delete stream; + return LIBRAW_IO_ERROR; + } ID.input_internal = 0; // preserve from deletion on error int ret = open_datastream(stream); if (ret == LIBRAW_SUCCESS) - { - ID.input_internal =1 ; // flag to delete datastream on recycle - } + { + ID.input_internal = 1; // flag to delete datastream on recycle + } else - { - delete stream; - ID.input_internal = 0; - } + { + delete stream; + ID.input_internal = 0; + } return ret; } #if defined(_WIN32) && !defined(__MINGW32__) && defined(_MSC_VER) && (_MSC_VER > 1310) int LibRaw::open_file(const wchar_t *fname, INT64 max_buf_size) { struct _stati64 st; - if(_wstati64(fname,&st)) + if (_wstati64(fname, &st)) return LIBRAW_IO_ERROR; - int big = (st.st_size > max_buf_size)?1:0; + int big = (st.st_size > max_buf_size) ? 1 : 0; LibRaw_abstract_datastream *stream; - try { - if(big) + try + { + if (big) stream = new LibRaw_bigfile_datastream(fname); else stream = new LibRaw_file_datastream(fname); } catch (std::bad_alloc) - { - recycle(); - return LIBRAW_UNSUFFICIENT_MEMORY; - } - if(!stream->valid()) - { - delete stream; - return LIBRAW_IO_ERROR; - } + { + recycle(); + return LIBRAW_UNSUFFICIENT_MEMORY; + } + if (!stream->valid()) + { + delete stream; + return LIBRAW_IO_ERROR; + } ID.input_internal = 0; // preserve from deletion on error int ret = open_datastream(stream); if (ret == LIBRAW_SUCCESS) - { - ID.input_internal =1 ; // flag to delete datastream on recycle - } + { + ID.input_internal = 1; // flag to delete datastream on recycle + } else - { - delete stream; - ID.input_internal = 0; - } + { + delete stream; + ID.input_internal = 0; + } return ret; } #endif int LibRaw::open_buffer(void *buffer, size_t size) { // this stream will close on recycle() - if(!buffer || buffer==(void*)-1) + if (!buffer || buffer == (void *)-1) return LIBRAW_IO_ERROR; LibRaw_buffer_datastream *stream; - try { - stream = new LibRaw_buffer_datastream(buffer,size); + try + { + stream = new LibRaw_buffer_datastream(buffer, size); } catch (std::bad_alloc) - { - recycle(); - return LIBRAW_UNSUFFICIENT_MEMORY; - } - if(!stream->valid()) - { - delete stream; - return LIBRAW_IO_ERROR; - } + { + recycle(); + return LIBRAW_UNSUFFICIENT_MEMORY; + } + if (!stream->valid()) + { + delete stream; + return LIBRAW_IO_ERROR; + } ID.input_internal = 0; // preserve from deletion on error int ret = open_datastream(stream); if (ret == LIBRAW_SUCCESS) + { + ID.input_internal = 1; // flag to delete datastream on recycle + } + else + { + delete stream; + ID.input_internal = 0; + } + return ret; +} + +int LibRaw::open_bayer(unsigned char *buffer, unsigned datalen, ushort _raw_width, ushort _raw_height, + ushort _left_margin, ushort _top_margin, ushort _right_margin, ushort _bottom_margin, + unsigned char procflags, unsigned char bayer_pattern, unsigned unused_bits, unsigned otherflags, + unsigned black_level) +{ + // this stream will close on recycle() + if (!buffer || buffer == (void *)-1) + return LIBRAW_IO_ERROR; + + LibRaw_buffer_datastream *stream; + try + { + stream = new LibRaw_buffer_datastream(buffer, datalen); + } + catch (std::bad_alloc) + { + recycle(); + return LIBRAW_UNSUFFICIENT_MEMORY; + } + if (!stream->valid()) + { + delete stream; + return LIBRAW_IO_ERROR; + } + ID.input = stream; + SET_PROC_FLAG(LIBRAW_PROGRESS_OPEN); + // From identify + initdata(); + strcpy(imgdata.idata.make, "BayerDump"); + snprintf(imgdata.idata.model, sizeof(imgdata.idata.model) - 1, "%u x %u pixels", _raw_width, _raw_height); + S.flip = procflags >> 2; + libraw_internal_data.internal_output_params.zero_is_bad = procflags & 2; + libraw_internal_data.unpacker_data.data_offset = 0; + S.raw_width = _raw_width; + S.raw_height = _raw_height; + S.left_margin = _left_margin; + S.top_margin = _top_margin; + S.width = S.raw_width - S.left_margin - _right_margin; + S.height = S.raw_height - S.top_margin - _bottom_margin; + + imgdata.idata.filters = 0x1010101 * bayer_pattern; + imgdata.idata.colors = 4 - !((imgdata.idata.filters & imgdata.idata.filters >> 1) & 0x5555); + libraw_internal_data.unpacker_data.load_flags = otherflags; + switch (libraw_internal_data.unpacker_data.tiff_bps = (datalen)*8 / (S.raw_width * S.raw_height)) + { + case 8: + load_raw = &CLASS eight_bit_load_raw; + break; + case 10: + if ((datalen) / S.raw_height * 3 >= S.raw_width * 4) { - ID.input_internal =1 ; // flag to delete datastream on recycle + load_raw = &CLASS android_loose_load_raw; + break; } - else + else if (libraw_internal_data.unpacker_data.load_flags & 1) { - delete stream; - ID.input_internal = 0; + load_raw = &CLASS android_tight_load_raw; + break; } - return ret; + case 12: + libraw_internal_data.unpacker_data.load_flags |= 128; + load_raw = &CLASS packed_load_raw; + break; + case 16: + libraw_internal_data.unpacker_data.order = 0x4949 | 0x404 * (libraw_internal_data.unpacker_data.load_flags & 1); + libraw_internal_data.unpacker_data.tiff_bps -= libraw_internal_data.unpacker_data.load_flags >> 4; + libraw_internal_data.unpacker_data.tiff_bps -= libraw_internal_data.unpacker_data.load_flags = + libraw_internal_data.unpacker_data.load_flags >> 1 & 7; + load_raw = &CLASS unpacked_load_raw; + } + C.maximum = (1 << libraw_internal_data.unpacker_data.tiff_bps) - (1 << unused_bits); + C.black = black_level; + S.iwidth = S.width; + S.iheight = S.height; + imgdata.idata.colors = 3; + imgdata.idata.filters |= ((imgdata.idata.filters >> 2 & 0x22222222) | (imgdata.idata.filters << 2 & 0x88888888)) & + imgdata.idata.filters << 1; + + imgdata.idata.raw_count = 1; + for (int i = 0; i < 4; i++) + imgdata.color.pre_mul[i] = 1.0; + + strcpy(imgdata.idata.cdesc, "RGBG"); + + ID.input_internal = 1; + SET_PROC_FLAG(LIBRAW_PROGRESS_IDENTIFY); + return LIBRAW_SUCCESS; } #ifdef USE_ZLIB -inline unsigned int __DNG_HalfToFloat (ushort halfValue) +inline unsigned int __DNG_HalfToFloat(ushort halfValue) { - int sign = (halfValue >> 15) & 0x00000001; - int exponent = (halfValue >> 10) & 0x0000001f; - int mantissa = halfValue & 0x000003ff; - if (exponent == 0) - { - if (mantissa == 0) - { - return (unsigned int) (sign << 31); - } - else - { - while (!(mantissa & 0x00000400)) - { - mantissa <<= 1; - exponent -= 1; - } - exponent += 1; - mantissa &= ~0x00000400; - } - } - else if (exponent == 31) - { - if (mantissa == 0) - { - return (unsigned int) ((sign << 31) | ((0x1eL + 127 - 15) << 23) | (0x3ffL << 13)); - } - else - { - return 0; - } - } - exponent += (127 - 15); - mantissa <<= 13; - return (unsigned int) ((sign << 31) | (exponent << 23) | mantissa); + int sign = (halfValue >> 15) & 0x00000001; + int exponent = (halfValue >> 10) & 0x0000001f; + int mantissa = halfValue & 0x000003ff; + if (exponent == 0) + { + if (mantissa == 0) + { + return (unsigned int)(sign << 31); + } + else + { + while (!(mantissa & 0x00000400)) + { + mantissa <<= 1; + exponent -= 1; + } + exponent += 1; + mantissa &= ~0x00000400; + } + } + else if (exponent == 31) + { + if (mantissa == 0) + { + return (unsigned int)((sign << 31) | ((0x1eL + 127 - 15) << 23) | (0x3ffL << 13)); + } + else + { + return 0; + } + } + exponent += (127 - 15); + mantissa <<= 13; + return (unsigned int)((sign << 31) | (exponent << 23) | mantissa); } -inline unsigned int __DNG_FP24ToFloat (const unsigned char *input) +inline unsigned int __DNG_FP24ToFloat(const unsigned char *input) { - int sign = (input [0] >> 7) & 0x01; - int exponent = (input [0] ) & 0x7F; - int mantissa = (((int) input [1]) << 8) | input[2]; - if (exponent == 0) - { - if (mantissa == 0) - { - return (unsigned int) (sign << 31); - } - else - { - while (!(mantissa & 0x00010000)) - { - mantissa <<= 1; - exponent -= 1; - } - exponent += 1; - mantissa &= ~0x00010000; - } - } - else if (exponent == 127) - { - if (mantissa == 0) - { - return (unsigned int) ((sign << 31) | ((0x7eL + 128 - 64) << 23) | (0xffffL << 7)); - } - else - { - // Nan -- Just set to zero. - return 0; - } - } - exponent += (128 - 64); - mantissa <<= 7; - return (uint32_t) ((sign << 31) | (exponent << 23) | mantissa); + int sign = (input[0] >> 7) & 0x01; + int exponent = (input[0]) & 0x7F; + int mantissa = (((int)input[1]) << 8) | input[2]; + if (exponent == 0) + { + if (mantissa == 0) + { + return (unsigned int)(sign << 31); + } + else + { + while (!(mantissa & 0x00010000)) + { + mantissa <<= 1; + exponent -= 1; + } + exponent += 1; + mantissa &= ~0x00010000; + } + } + else if (exponent == 127) + { + if (mantissa == 0) + { + return (unsigned int)((sign << 31) | ((0x7eL + 128 - 64) << 23) | (0xffffL << 7)); + } + else + { + // Nan -- Just set to zero. + return 0; + } + } + exponent += (128 - 64); + mantissa <<= 7; + return (uint32_t)((sign << 31) | (exponent << 23) | mantissa); } -inline void DecodeDeltaBytes (unsigned char *bytePtr, int cols, int channels) +inline void DecodeDeltaBytes(unsigned char *bytePtr, int cols, int channels) { - if (channels == 1) - { - unsigned char b0 = bytePtr [0]; - bytePtr += 1; - for (uint32_t col = 1; col < cols; ++col) - { - b0 += bytePtr [0]; - bytePtr [0] = b0; - bytePtr += 1; - } - } - else if (channels == 3) - { - unsigned char b0 = bytePtr [0]; - unsigned char b1 = bytePtr [1]; - unsigned char b2 = bytePtr [2]; - bytePtr += 3; - for (int col = 1; col < cols; ++col) - { - b0 += bytePtr [0]; - b1 += bytePtr [1]; - b2 += bytePtr [2]; - bytePtr [0] = b0; - bytePtr [1] = b1; - bytePtr [2] = b2; - bytePtr += 3; - } - } - else if (channels == 4) - { - unsigned char b0 = bytePtr [0]; - unsigned char b1 = bytePtr [1]; - unsigned char b2 = bytePtr [2]; - unsigned char b3 = bytePtr [3]; - bytePtr += 4; - for (uint32_t col = 1; col < cols; ++col) - { - b0 += bytePtr [0]; - b1 += bytePtr [1]; - b2 += bytePtr [2]; - b3 += bytePtr [3]; - bytePtr [0] = b0; - bytePtr [1] = b1; - bytePtr [2] = b2; - bytePtr [3] = b3; - bytePtr += 4; - } - } - else - { - for (int col = 1; col < cols; ++col) - { - for (int chan = 0; chan < channels; ++chan) - { - bytePtr [chan + channels] += bytePtr [chan]; - } - bytePtr += channels; - } - } + if (channels == 1) + { + unsigned char b0 = bytePtr[0]; + bytePtr += 1; + for (uint32_t col = 1; col < cols; ++col) + { + b0 += bytePtr[0]; + bytePtr[0] = b0; + bytePtr += 1; + } + } + else if (channels == 3) + { + unsigned char b0 = bytePtr[0]; + unsigned char b1 = bytePtr[1]; + unsigned char b2 = bytePtr[2]; + bytePtr += 3; + for (int col = 1; col < cols; ++col) + { + b0 += bytePtr[0]; + b1 += bytePtr[1]; + b2 += bytePtr[2]; + bytePtr[0] = b0; + bytePtr[1] = b1; + bytePtr[2] = b2; + bytePtr += 3; + } + } + else if (channels == 4) + { + unsigned char b0 = bytePtr[0]; + unsigned char b1 = bytePtr[1]; + unsigned char b2 = bytePtr[2]; + unsigned char b3 = bytePtr[3]; + bytePtr += 4; + for (uint32_t col = 1; col < cols; ++col) + { + b0 += bytePtr[0]; + b1 += bytePtr[1]; + b2 += bytePtr[2]; + b3 += bytePtr[3]; + bytePtr[0] = b0; + bytePtr[1] = b1; + bytePtr[2] = b2; + bytePtr[3] = b3; + bytePtr += 4; + } + } + else + { + for (int col = 1; col < cols; ++col) + { + for (int chan = 0; chan < channels; ++chan) + { + bytePtr[chan + channels] += bytePtr[chan]; + } + bytePtr += channels; + } + } } -static void DecodeFPDelta (unsigned char *input, - unsigned char *output, - int cols, - int channels, - int bytesPerSample) +static void DecodeFPDelta(unsigned char *input, unsigned char *output, int cols, int channels, int bytesPerSample) { - DecodeDeltaBytes (input, cols * bytesPerSample, channels); - int32_t rowIncrement = cols * channels; + DecodeDeltaBytes(input, cols * bytesPerSample, channels); + int32_t rowIncrement = cols * channels; - if (bytesPerSample == 2) - { + if (bytesPerSample == 2) + { #if LibRawBigEndian - const unsigned char *input0 = input; - const unsigned char *input1 = input + rowIncrement; + const unsigned char *input0 = input; + const unsigned char *input1 = input + rowIncrement; #else - const unsigned char *input1 = input; - const unsigned char *input0 = input + rowIncrement; + const unsigned char *input1 = input; + const unsigned char *input0 = input + rowIncrement; #endif - for (int col = 0; col < rowIncrement; ++col) - { - output [0] = input0 [col]; - output [1] = input1 [col]; - output += 2; - } - } - else if (bytesPerSample == 3) - { - const unsigned char *input0 = input; - const unsigned char *input1 = input + rowIncrement; - const unsigned char *input2 = input + rowIncrement * 2; - for (int col = 0; col < rowIncrement; ++col) - { - output [0] = input0 [col]; - output [1] = input1 [col]; - output [2] = input2 [col]; - output += 3; - } - } - else - { + for (int col = 0; col < rowIncrement; ++col) + { + output[0] = input0[col]; + output[1] = input1[col]; + output += 2; + } + } + else if (bytesPerSample == 3) + { + const unsigned char *input0 = input; + const unsigned char *input1 = input + rowIncrement; + const unsigned char *input2 = input + rowIncrement * 2; + for (int col = 0; col < rowIncrement; ++col) + { + output[0] = input0[col]; + output[1] = input1[col]; + output[2] = input2[col]; + output += 3; + } + } + else + { #if LibRawBigEndian - const unsigned char *input0 = input; - const unsigned char *input1 = input + rowIncrement; - const unsigned char *input2 = input + rowIncrement * 2; - const unsigned char *input3 = input + rowIncrement * 3; + const unsigned char *input0 = input; + const unsigned char *input1 = input + rowIncrement; + const unsigned char *input2 = input + rowIncrement * 2; + const unsigned char *input3 = input + rowIncrement * 3; #else - const unsigned char *input3 = input; - const unsigned char *input2 = input + rowIncrement; - const unsigned char *input1 = input + rowIncrement * 2; - const unsigned char *input0 = input + rowIncrement * 3; + const unsigned char *input3 = input; + const unsigned char *input2 = input + rowIncrement; + const unsigned char *input1 = input + rowIncrement * 2; + const unsigned char *input0 = input + rowIncrement * 3; #endif - for (int col = 0; col < rowIncrement; ++col) - { - output [0] = input0 [col]; - output [1] = input1 [col]; - output [2] = input2 [col]; - output [3] = input3 [col]; - output += 4; - } - } -} - -static float expandFloats(unsigned char * dst, int tileWidth, int bytesps) { - float max = 0.f; - if (bytesps == 2) { - uint16_t * dst16 = (ushort *) dst; - uint32_t * dst32 = (unsigned int *) dst; - float *f32 = (float*) dst; - for (int index = tileWidth - 1; index >= 0; --index) { - dst32[index] = __DNG_HalfToFloat(dst16[index]); - max = MAX(max,f32[index]); - } - } - else if (bytesps == 3) - { - uint8_t * dst8 = ((unsigned char *) dst) + (tileWidth - 1) * 3; - uint32_t * dst32 = (unsigned int *) dst; - float *f32 = (float*) dst; - for (int index = tileWidth - 1; index >= 0; --index, dst8 -= 3) { - dst32[index] = __DNG_FP24ToFloat(dst8); - max = MAX(max,f32[index]); - } - } - else if (bytesps==4) - { - float *f32 = (float*) dst; - for (int index = 0; index < tileWidth; index++) - max = MAX(max,f32[index]); - } - return max; + for (int col = 0; col < rowIncrement; ++col) + { + output[0] = input0[col]; + output[1] = input1[col]; + output[2] = input2[col]; + output[3] = input3[col]; + output += 4; + } + } } -void LibRaw::deflate_dng_load_raw() +static float expandFloats(unsigned char *dst, int tileWidth, int bytesps) { - struct tiff_ifd_t * ifd = &tiff_ifd[0]; - while (ifd < &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds] && ifd->offset != libraw_internal_data.unpacker_data.data_offset) ++ifd; - if (ifd == &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds]) - { - throw LIBRAW_EXCEPTION_DECODE_RAW; - } - - float *float_raw_image=0; - float max = 0.f; - - if(ifd->samples!=1 && ifd->samples!=3 && ifd->samples !=4) - throw LIBRAW_EXCEPTION_DECODE_RAW; // Only float deflated supported - - if(libraw_internal_data.unpacker_data.tiff_samples != ifd->samples) - throw LIBRAW_EXCEPTION_DECODE_RAW; // Wrong IFD - - - size_t tilesH = (imgdata.sizes.raw_width + libraw_internal_data.unpacker_data.tile_width - 1) / libraw_internal_data.unpacker_data.tile_width; - size_t tilesV = (imgdata.sizes.raw_height + libraw_internal_data.unpacker_data.tile_length - 1) / libraw_internal_data.unpacker_data.tile_length; - size_t tileCnt = tilesH * tilesV; - - - if (ifd->sample_format == 3) - { // Floating point data - float_raw_image = (float*)calloc(tileCnt*libraw_internal_data.unpacker_data.tile_length* libraw_internal_data.unpacker_data.tile_width * ifd->samples,sizeof(float)); - //imgdata.color.maximum = 65535; - //imgdata.color.black = 0; - //memset(imgdata.color.cblack,0,sizeof(imgdata.color.cblack)); - } - else - throw LIBRAW_EXCEPTION_DECODE_RAW; // Only float deflated supported - - int xFactor; - switch(ifd->predictor) - { - case 3: - default: - xFactor = 1; break; - case 34894: xFactor = 2; break; - case 34895: xFactor = 4; break; - } - - if (libraw_internal_data.unpacker_data.tile_length < INT_MAX) - { - if(tileCnt<1 || tileCnt > 1000000) - throw LIBRAW_EXCEPTION_DECODE_RAW; - - size_t *tOffsets = (size_t*)malloc(tileCnt*sizeof(size_t)); - for (int t = 0; t < tileCnt; ++t) - tOffsets[t] = get4(); - - size_t *tBytes = (size_t*) malloc(tileCnt*sizeof(size_t)); - unsigned long maxBytesInTile = 0; - if (tileCnt == 1) - tBytes[0] = maxBytesInTile = ifd->bytes; - else - { - libraw_internal_data.internal_data.input->seek(ifd->bytes, SEEK_SET); - for (size_t t = 0; t < tileCnt; ++t) - { - tBytes[t] = get4(); - maxBytesInTile = MAX(maxBytesInTile,tBytes[t]); - } - } - unsigned tilePixels = libraw_internal_data.unpacker_data.tile_width * libraw_internal_data.unpacker_data.tile_length; - unsigned pixelSize = sizeof(float)*ifd->samples; - unsigned tileBytes = tilePixels*pixelSize; - unsigned tileRowBytes = libraw_internal_data.unpacker_data.tile_width*pixelSize; - - unsigned char *cBuffer = (unsigned char*)malloc(maxBytesInTile); - unsigned char *uBuffer = (unsigned char*)malloc(tileBytes+tileRowBytes); // extra row for decoding - - for (size_t y = 0, t = 0; y < imgdata.sizes.raw_height; y += libraw_internal_data.unpacker_data.tile_length) - { - for (size_t x = 0; x < imgdata.sizes.raw_width; x += libraw_internal_data.unpacker_data.tile_width, ++t) - { - libraw_internal_data.internal_data.input->seek(tOffsets[t], SEEK_SET); - libraw_internal_data.internal_data.input->read(cBuffer, 1, tBytes[t]); - unsigned long dstLen = tileBytes; - int err = uncompress(uBuffer+tileRowBytes, &dstLen, cBuffer, tBytes[t]); - if (err != Z_OK) - { - free(tOffsets); - free(tBytes); - free(cBuffer); - free(uBuffer); - throw LIBRAW_EXCEPTION_DECODE_RAW; - return; - } - else - { - int bytesps = ifd->bps >> 3; - size_t rowsInTile = y + libraw_internal_data.unpacker_data.tile_length > imgdata.sizes.raw_height ? imgdata.sizes.raw_height - y : libraw_internal_data.unpacker_data.tile_length; - size_t colsInTile= x + libraw_internal_data.unpacker_data.tile_width > imgdata.sizes.raw_width ? imgdata.sizes.raw_width - x : libraw_internal_data.unpacker_data.tile_width; - - for (size_t row = 0; row < rowsInTile; ++row) // do not process full tile if not needed - { - unsigned char* dst = uBuffer + row*libraw_internal_data.unpacker_data.tile_width*bytesps*ifd->samples; - unsigned char* src = dst+tileRowBytes; - DecodeFPDelta (src,dst, - libraw_internal_data.unpacker_data.tile_width/ xFactor, - ifd->samples * xFactor, - bytesps); - float lmax = expandFloats(dst, libraw_internal_data.unpacker_data.tile_width*ifd->samples, bytesps); - max = MAX(max,lmax); - unsigned char* dst2 = (unsigned char*)&float_raw_image[((y+row)*imgdata.sizes.raw_width + x)*ifd->samples]; - memmove(dst2,dst,colsInTile*ifd->samples*sizeof(float)); - } - } - } - } - free(tOffsets); - free(tBytes); - free(cBuffer); - free(uBuffer); - } - imgdata.color.fmaximum = max; - - // Set fields according to data format - - imgdata.rawdata.raw_alloc = float_raw_image; - if(ifd->samples == 1) - { - imgdata.rawdata.float_image = float_raw_image; - imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = imgdata.sizes.raw_width*4; - } - else if(ifd->samples == 3) - { - imgdata.rawdata.float3_image = (float(*)[3])float_raw_image; - imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = imgdata.sizes.raw_width*12; - } - else if(ifd->samples == 4) - { - imgdata.rawdata.float4_image = (float(*)[4])float_raw_image; - imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = imgdata.sizes.raw_width*16; - } - - if(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_CONVERTFLOAT_TO_INT) - convertFloatToInt(); // with default settings + float max = 0.f; + if (bytesps == 2) + { + uint16_t *dst16 = (ushort *)dst; + uint32_t *dst32 = (unsigned int *)dst; + float *f32 = (float *)dst; + for (int index = tileWidth - 1; index >= 0; --index) + { + dst32[index] = __DNG_HalfToFloat(dst16[index]); + max = MAX(max, f32[index]); + } + } + else if (bytesps == 3) + { + uint8_t *dst8 = ((unsigned char *)dst) + (tileWidth - 1) * 3; + uint32_t *dst32 = (unsigned int *)dst; + float *f32 = (float *)dst; + for (int index = tileWidth - 1; index >= 0; --index, dst8 -= 3) + { + dst32[index] = __DNG_FP24ToFloat(dst8); + max = MAX(max, f32[index]); + } + } + else if (bytesps == 4) + { + float *f32 = (float *)dst; + for (int index = 0; index < tileWidth; index++) + max = MAX(max, f32[index]); + } + return max; } -#else + void LibRaw::deflate_dng_load_raw() { + struct tiff_ifd_t *ifd = &tiff_ifd[0]; + while (ifd < &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds] && + ifd->offset != libraw_internal_data.unpacker_data.data_offset) + ++ifd; + if (ifd == &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds]) + { + throw LIBRAW_EXCEPTION_DECODE_RAW; + } + + float *float_raw_image = 0; + float max = 0.f; + + if (ifd->samples != 1 && ifd->samples != 3 && ifd->samples != 4) + throw LIBRAW_EXCEPTION_DECODE_RAW; // Only float deflated supported + + if (libraw_internal_data.unpacker_data.tiff_samples != ifd->samples) + throw LIBRAW_EXCEPTION_DECODE_RAW; // Wrong IFD + + size_t tilesH = (imgdata.sizes.raw_width + libraw_internal_data.unpacker_data.tile_width - 1) / + libraw_internal_data.unpacker_data.tile_width; + size_t tilesV = (imgdata.sizes.raw_height + libraw_internal_data.unpacker_data.tile_length - 1) / + libraw_internal_data.unpacker_data.tile_length; + size_t tileCnt = tilesH * tilesV; + + if (ifd->sample_format == 3) + { // Floating point data + float_raw_image = (float *)calloc(tileCnt * libraw_internal_data.unpacker_data.tile_length * + libraw_internal_data.unpacker_data.tile_width * ifd->samples, + sizeof(float)); + // imgdata.color.maximum = 65535; + // imgdata.color.black = 0; + // memset(imgdata.color.cblack,0,sizeof(imgdata.color.cblack)); + } + else + throw LIBRAW_EXCEPTION_DECODE_RAW; // Only float deflated supported + + int xFactor; + switch (ifd->predictor) + { + case 3: + default: + xFactor = 1; + break; + case 34894: + xFactor = 2; + break; + case 34895: + xFactor = 4; + break; + } + + if (libraw_internal_data.unpacker_data.tile_length < INT_MAX) + { + if (tileCnt < 1 || tileCnt > 1000000) + throw LIBRAW_EXCEPTION_DECODE_RAW; + + size_t *tOffsets = (size_t *)malloc(tileCnt * sizeof(size_t)); + for (int t = 0; t < tileCnt; ++t) + tOffsets[t] = get4(); + + size_t *tBytes = (size_t *)malloc(tileCnt * sizeof(size_t)); + unsigned long maxBytesInTile = 0; + if (tileCnt == 1) + tBytes[0] = maxBytesInTile = ifd->bytes; + else + { + libraw_internal_data.internal_data.input->seek(ifd->bytes, SEEK_SET); + for (size_t t = 0; t < tileCnt; ++t) + { + tBytes[t] = get4(); + maxBytesInTile = MAX(maxBytesInTile, tBytes[t]); + } + } + unsigned tilePixels = + libraw_internal_data.unpacker_data.tile_width * libraw_internal_data.unpacker_data.tile_length; + unsigned pixelSize = sizeof(float) * ifd->samples; + unsigned tileBytes = tilePixels * pixelSize; + unsigned tileRowBytes = libraw_internal_data.unpacker_data.tile_width * pixelSize; - throw LIBRAW_EXCEPTION_DECODE_RAW; + unsigned char *cBuffer = (unsigned char *)malloc(maxBytesInTile); + unsigned char *uBuffer = (unsigned char *)malloc(tileBytes + tileRowBytes); // extra row for decoding + + for (size_t y = 0, t = 0; y < imgdata.sizes.raw_height; y += libraw_internal_data.unpacker_data.tile_length) + { + for (size_t x = 0; x < imgdata.sizes.raw_width; x += libraw_internal_data.unpacker_data.tile_width, ++t) + { + libraw_internal_data.internal_data.input->seek(tOffsets[t], SEEK_SET); + libraw_internal_data.internal_data.input->read(cBuffer, 1, tBytes[t]); + unsigned long dstLen = tileBytes; + int err = uncompress(uBuffer + tileRowBytes, &dstLen, cBuffer, tBytes[t]); + if (err != Z_OK) + { + free(tOffsets); + free(tBytes); + free(cBuffer); + free(uBuffer); + throw LIBRAW_EXCEPTION_DECODE_RAW; + return; + } + else + { + int bytesps = ifd->bps >> 3; + size_t rowsInTile = y + libraw_internal_data.unpacker_data.tile_length > imgdata.sizes.raw_height + ? imgdata.sizes.raw_height - y + : libraw_internal_data.unpacker_data.tile_length; + size_t colsInTile = x + libraw_internal_data.unpacker_data.tile_width > imgdata.sizes.raw_width + ? imgdata.sizes.raw_width - x + : libraw_internal_data.unpacker_data.tile_width; + + for (size_t row = 0; row < rowsInTile; ++row) // do not process full tile if not needed + { + unsigned char *dst = uBuffer + row * libraw_internal_data.unpacker_data.tile_width * bytesps * ifd->samples; + unsigned char *src = dst + tileRowBytes; + DecodeFPDelta(src, dst, libraw_internal_data.unpacker_data.tile_width / xFactor, ifd->samples * xFactor, + bytesps); + float lmax = expandFloats(dst, libraw_internal_data.unpacker_data.tile_width * ifd->samples, bytesps); + max = MAX(max, lmax); + unsigned char *dst2 = + (unsigned char *)&float_raw_image[((y + row) * imgdata.sizes.raw_width + x) * ifd->samples]; + memmove(dst2, dst, colsInTile * ifd->samples * sizeof(float)); + } + } + } + } + free(tOffsets); + free(tBytes); + free(cBuffer); + free(uBuffer); + } + imgdata.color.fmaximum = max; + + // Set fields according to data format + + imgdata.rawdata.raw_alloc = float_raw_image; + if (ifd->samples == 1) + { + imgdata.rawdata.float_image = float_raw_image; + imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = imgdata.sizes.raw_width * 4; + } + else if (ifd->samples == 3) + { + imgdata.rawdata.float3_image = (float(*)[3])float_raw_image; + imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = imgdata.sizes.raw_width * 12; + } + else if (ifd->samples == 4) + { + imgdata.rawdata.float4_image = (float(*)[4])float_raw_image; + imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = imgdata.sizes.raw_width * 16; + } + + if (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_CONVERTFLOAT_TO_INT) + convertFloatToInt(); // with default settings } +#else +void LibRaw::deflate_dng_load_raw() { throw LIBRAW_EXCEPTION_DECODE_RAW; } #endif int LibRaw::is_floating_point() { - struct tiff_ifd_t * ifd = &tiff_ifd[0]; - while (ifd < &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds] && ifd->offset != libraw_internal_data.unpacker_data.data_offset) ++ifd; - if (ifd == &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds]) - return 0; + struct tiff_ifd_t *ifd = &tiff_ifd[0]; + while (ifd < &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds] && + ifd->offset != libraw_internal_data.unpacker_data.data_offset) + ++ifd; + if (ifd == &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds]) + return 0; - return ifd->sample_format == 3; + return ifd->sample_format == 3; } int LibRaw::have_fpdata() { - return imgdata.rawdata.float_image || imgdata.rawdata.float3_image || imgdata.rawdata.float4_image; + return imgdata.rawdata.float_image || imgdata.rawdata.float3_image || imgdata.rawdata.float4_image; } +void LibRaw::convertFloatToInt(float dmin /* =4096.f */, float dmax /* =32767.f */, float dtarget /*= 16383.f */) +{ + int samples = 0; + float *data = 0; + if (imgdata.rawdata.float_image) + { + samples = 1; + data = imgdata.rawdata.float_image; + } + else if (imgdata.rawdata.float3_image) + { + samples = 3; + data = (float *)imgdata.rawdata.float3_image; + } + else if (imgdata.rawdata.float4_image) + { + samples = 4; + data = (float *)imgdata.rawdata.float4_image; + } + else + return; + + ushort *raw_alloc = (ushort *)malloc(imgdata.sizes.raw_height * imgdata.sizes.raw_width * + libraw_internal_data.unpacker_data.tiff_samples * sizeof(ushort)); + float tmax = MAX(imgdata.color.maximum, 1); + float datamax = imgdata.color.fmaximum; + + tmax = MAX(tmax, datamax); + tmax = MAX(tmax, 1.f); + + float multip = 1.f; + if (tmax < dmin || tmax > dmax) + { + imgdata.rawdata.color.fnorm = imgdata.color.fnorm = multip = dtarget / tmax; + imgdata.rawdata.color.maximum = imgdata.color.maximum = dtarget; + imgdata.rawdata.color.black = imgdata.color.black = (float)imgdata.color.black * multip; + for (int i = 0; i < sizeof(imgdata.color.cblack) / sizeof(imgdata.color.cblack[0]); i++) + if (i != 4 && i != 5) + imgdata.rawdata.color.cblack[i] = imgdata.color.cblack[i] = (float)imgdata.color.cblack[i] * multip; + } + else + imgdata.rawdata.color.fnorm = imgdata.color.fnorm = 0.f; + + for (size_t i = 0; + i < imgdata.sizes.raw_height * imgdata.sizes.raw_width * libraw_internal_data.unpacker_data.tiff_samples; ++i) + { + float val = MAX(data[i], 0.f); + raw_alloc[i] = (ushort)(val * multip); + } + + if (samples == 1) + { + imgdata.rawdata.raw_alloc = imgdata.rawdata.raw_image = raw_alloc; + imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = imgdata.sizes.raw_width * 2; + } + else if (samples == 3) + { + imgdata.rawdata.raw_alloc = imgdata.rawdata.color3_image = (ushort(*)[3])raw_alloc; + imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = imgdata.sizes.raw_width * 6; + } + else if (samples == 4) + { + imgdata.rawdata.raw_alloc = imgdata.rawdata.color4_image = (ushort(*)[4])raw_alloc; + imgdata.rawdata.sizes.raw_pitch = imgdata.sizes.raw_pitch = imgdata.sizes.raw_width * 8; + } + free(data); // remove old allocation + imgdata.rawdata.float_image = 0; + imgdata.rawdata.float3_image = 0; + imgdata.rawdata.float4_image = 0; +} -void LibRaw::convertFloatToInt(float dmin/* =4096.f */, float dmax/* =32767.f */, float dtarget /*= 16383.f */) +void LibRaw::sony_arq_load_raw() { - int samples = 0; - float *data = 0; - if(imgdata.rawdata.float_image) - { - samples = 1; - data = imgdata.rawdata.float_image; - } - else if (imgdata.rawdata.float3_image) - { - samples = 3; - data = (float*)imgdata.rawdata.float3_image; - } - else if (imgdata.rawdata.float4_image) - { - samples = 4; - data = (float*)imgdata.rawdata.float4_image; - } - else - return; - - ushort *raw_alloc = (ushort*)malloc(imgdata.sizes.raw_height*imgdata.sizes.raw_width*libraw_internal_data.unpacker_data.tiff_samples*sizeof(ushort)); - float tmax = MAX(imgdata.color.maximum,1); - float datamax = imgdata.color.fmaximum; - - tmax = MAX(tmax,datamax); - tmax = MAX(tmax,1.f); - - float multip = 1.f; - if(tmax < dmin || tmax > dmax) - { - imgdata.rawdata.color.fnorm = imgdata.color.fnorm = multip = dtarget / tmax; - imgdata.rawdata.color.maximum = imgdata.color.maximum = dtarget; - imgdata.rawdata.color.black = imgdata.color.black = (float)imgdata.color.black*multip; - for(int i=0; iseek(-2,SEEK_CUR); // avoid wrong eof error + for (row = 0; row < imgdata.sizes.raw_height; row++) + { + unsigned short(*rowp)[4] = (unsigned short(*)[4]) & imgdata.rawdata.raw_image[row * imgdata.sizes.raw_width * 4]; + for (col = 0; col < imgdata.sizes.raw_width; col++) + { + unsigned short g2 = rowp[col][2]; + rowp[col][2] = rowp[col][3]; + rowp[col][3] = g2; + if (((unsigned)(row - imgdata.sizes.top_margin) < imgdata.sizes.height) && + ((unsigned)(col - imgdata.sizes.left_margin) < imgdata.sizes.width) && + (MAX(MAX(rowp[col][0], rowp[col][1]), MAX(rowp[col][2], rowp[col][3])) > imgdata.color.maximum)) + derror(); + } + } } void LibRaw::pentax_4shot_load_raw() { - ushort *plane = (ushort*)malloc(imgdata.sizes.raw_width*imgdata.sizes.raw_height*sizeof(ushort)); - int alloc_sz = imgdata.sizes.raw_width*(imgdata.sizes.raw_height+16)*4*sizeof(ushort); - ushort (*result)[4] = (ushort(*)[4]) malloc(alloc_sz); - struct movement_t - { - int row,col; - } _move[4] = { - {1,1}, - {0,1}, - {0,0}, - {1,0}, - }; - - int tidx = 0; - for(int i=0; i<4; i++) - { - int move_row,move_col; - if(imgdata.params.p4shot_order[i] >= '0' && imgdata.params.p4shot_order[i] <= '3') - { - move_row = (imgdata.params.p4shot_order[i]-'0' & 2)?1:0; - move_col = (imgdata.params.p4shot_order[i]-'0' & 1)?1:0; - } - else - { - move_row = _move[i].row; - move_col = _move[i].col; - } - for(; tidx<16; tidx++) - if(tiff_ifd[tidx].t_width == imgdata.sizes.raw_width && tiff_ifd[tidx].t_height == imgdata.sizes.raw_height && tiff_ifd[tidx].bps>8 && tiff_ifd[tidx].samples == 1 ) - break; - if(tidx>=16) - break; - imgdata.rawdata.raw_image = plane; - ID.input->seek(tiff_ifd[tidx].offset, SEEK_SET); - imgdata.idata.filters = 0xb4b4b4b4; - libraw_internal_data.unpacker_data.data_offset = tiff_ifd[tidx].offset; - (this->*pentax_component_load_raw)(); - for(int row = 0; row < imgdata.sizes.raw_height-move_row; row++) - { - int colors[2]; - for(int c = 0; c < 2; c++ ) - colors[c] = COLOR(row,c); - ushort *srcrow = &plane[imgdata.sizes.raw_width*row]; - ushort (*dstrow)[4] = & result[(imgdata.sizes.raw_width)*(row+move_row)+move_col]; - for(int col = 0; col < imgdata.sizes.raw_width-move_col; col++) - dstrow[col][colors[col%2]] = srcrow[col]; - } - tidx++; - } - // assign things back: - imgdata.sizes.raw_pitch = imgdata.sizes.raw_width*8; - imgdata.idata.filters = 0; - imgdata.rawdata.raw_alloc = imgdata.rawdata.color4_image = result; - free(plane); - imgdata.rawdata.raw_image = 0; + ushort *plane = (ushort *)malloc(imgdata.sizes.raw_width * imgdata.sizes.raw_height * sizeof(ushort)); + int alloc_sz = imgdata.sizes.raw_width * (imgdata.sizes.raw_height + 16) * 4 * sizeof(ushort); + ushort(*result)[4] = (ushort(*)[4])malloc(alloc_sz); + struct movement_t + { + int row, col; + } _move[4] = { + {1, 1}, + {0, 1}, + {0, 0}, + {1, 0}, + }; + + int tidx = 0; + for (int i = 0; i < 4; i++) + { + int move_row, move_col; + if (imgdata.params.p4shot_order[i] >= '0' && imgdata.params.p4shot_order[i] <= '3') + { + move_row = (imgdata.params.p4shot_order[i] - '0' & 2) ? 1 : 0; + move_col = (imgdata.params.p4shot_order[i] - '0' & 1) ? 1 : 0; + } + else + { + move_row = _move[i].row; + move_col = _move[i].col; + } + for (; tidx < 16; tidx++) + if (tiff_ifd[tidx].t_width == imgdata.sizes.raw_width && tiff_ifd[tidx].t_height == imgdata.sizes.raw_height && + tiff_ifd[tidx].bps > 8 && tiff_ifd[tidx].samples == 1) + break; + if (tidx >= 16) + break; + imgdata.rawdata.raw_image = plane; + ID.input->seek(tiff_ifd[tidx].offset, SEEK_SET); + imgdata.idata.filters = 0xb4b4b4b4; + libraw_internal_data.unpacker_data.data_offset = tiff_ifd[tidx].offset; + (this->*pentax_component_load_raw)(); + for (int row = 0; row < imgdata.sizes.raw_height - move_row; row++) + { + int colors[2]; + for (int c = 0; c < 2; c++) + colors[c] = COLOR(row, c); + ushort *srcrow = &plane[imgdata.sizes.raw_width * row]; + ushort(*dstrow)[4] = &result[(imgdata.sizes.raw_width) * (row + move_row) + move_col]; + for (int col = 0; col < imgdata.sizes.raw_width - move_col; col++) + dstrow[col][colors[col % 2]] = srcrow[col]; + } + tidx++; + } + // assign things back: + imgdata.sizes.raw_pitch = imgdata.sizes.raw_width * 8; + imgdata.idata.filters = 0; + imgdata.rawdata.raw_alloc = imgdata.rawdata.color4_image = result; + free(plane); + imgdata.rawdata.raw_image = 0; } void LibRaw::hasselblad_full_load_raw() { int row, col; - for (row=0; row < S.height; row++) - for (col=0; col < S.width; col++) - { - read_shorts (&imgdata.image[row*S.width+col][2], 1); // B - read_shorts (&imgdata.image[row*S.width+col][1], 1); // G - read_shorts (&imgdata.image[row*S.width+col][0], 1); // R - } + for (row = 0; row < S.height; row++) + for (col = 0; col < S.width; col++) + { + read_shorts(&imgdata.image[row * S.width + col][2], 1); // B + read_shorts(&imgdata.image[row * S.width + col][1], 1); // G + read_shorts(&imgdata.image[row * S.width + col][0], 1); // R + } +} + +static inline void unpack7bytesto4x16(unsigned char *src, unsigned short *dest) +{ + dest[0] = (src[0] << 6) | (src[1] >> 2); + dest[1] = ((src[1] & 0x3) << 12) | (src[2] << 4) | (src[3] >> 4); + dest[2] = (src[3] & 0xf) << 10 | (src[4] << 2) | (src[5] >> 6); + dest[3] = ((src[5] & 0x3f) << 8) | src[6]; +} + +static inline void unpack28bytesto16x16ns(unsigned char *src, unsigned short *dest) +{ + dest[0] = (src[3] << 6) | (src[2] >> 2); + dest[1] = ((src[2] & 0x3) << 12) | (src[1] << 4) | (src[0] >> 4); + dest[2] = (src[0] & 0xf) << 10 | (src[7] << 2) | (src[6] >> 6); + dest[3] = ((src[6] & 0x3f) << 8) | src[5]; + dest[4] = (src[4] << 6) | (src[11] >> 2); + dest[5] = ((src[11] & 0x3) << 12) | (src[10] << 4) | (src[9] >> 4); + dest[6] = (src[9] & 0xf) << 10 | (src[8] << 2) | (src[15] >> 6); + dest[7] = ((src[15] & 0x3f) << 8) | src[14]; + dest[8] = (src[13] << 6) | (src[12] >> 2); + dest[9] = ((src[12] & 0x3) << 12) | (src[19] << 4) | (src[18] >> 4); + dest[10] = (src[18] & 0xf) << 10 | (src[17] << 2) | (src[16] >> 6); + dest[11] = ((src[16] & 0x3f) << 8) | src[23]; + dest[12] = (src[22] << 6) | (src[21] >> 2); + dest[13] = ((src[21] & 0x3) << 12) | (src[20] << 4) | (src[27] >> 4); + dest[14] = (src[27] & 0xf) << 10 | (src[26] << 2) | (src[25] >> 6); + dest[15] = ((src[25] & 0x3f) << 8) | src[24]; +} + +#define swab32(x) \ + ((unsigned int)((((unsigned int)(x) & (unsigned int)0x000000ffUL) << 24) | \ + (((unsigned int)(x) & (unsigned int)0x0000ff00UL) << 8) | \ + (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \ + (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24))) + +static inline void swab32arr(unsigned *arr, unsigned len) +{ + for (unsigned i = 0; i < len; i++) + arr[i] = swab32(arr[i]); +} +#undef swab32 + +void LibRaw::fuji_14bit_load_raw() +{ + const unsigned linelen = S.raw_width * 7 / 4; + const unsigned pitch = S.raw_pitch ? S.raw_pitch / 2 : S.raw_width; + unsigned char *buf = (unsigned char *)malloc(linelen); + merror(buf, "fuji_14bit_load_raw()"); + + for (int row = 0; row < S.raw_height; row++) + { + unsigned bytesread = libraw_internal_data.internal_data.input->read(buf, 1, linelen); + unsigned short *dest = &imgdata.rawdata.raw_image[pitch * row]; + if (bytesread % 28) + { + swab32arr((unsigned *)buf, bytesread / 4); + for (int sp = 0, dp = 0; dp < pitch - 3 && sp < linelen - 6 && sp < bytesread - 6; sp += 7, dp += 4) + unpack7bytesto4x16(buf + sp, dest + dp); + } + else + for (int sp = 0, dp = 0; dp < pitch - 15 && sp < linelen - 27 && sp < bytesread - 27; sp += 28, dp += 16) + unpack28bytesto16x16ns(buf + sp, dest + dp); + } + free(buf); } void LibRaw::nikon_load_striped_packed_raw() { - int vbits=0, bwide, rbits, bite,row, col, val, i; - - UINT64 bitbuf=0; - unsigned load_flags = 24; //libraw_internal_data.unpacker_data.load_flags; - unsigned tiff_bps = libraw_internal_data.unpacker_data.tiff_bps; - int tiff_compress = libraw_internal_data.unpacker_data.tiff_compress; - - struct tiff_ifd_t * ifd = &tiff_ifd[0]; - while (ifd < &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds] && ifd->offset != libraw_internal_data.unpacker_data.data_offset) ++ifd; - if (ifd == &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds]) - throw LIBRAW_EXCEPTION_DECODE_RAW; - - if(!ifd->rows_per_strip || !ifd->strip_offsets_count) - return; // not unpacked - int stripcnt = 0; - - bwide = S.raw_width * tiff_bps / 8; - bwide += bwide & load_flags >> 7; - rbits = bwide * 8 - S.raw_width * tiff_bps; - if (load_flags & 1) bwide = bwide * 16 / 15; - bite = 8 + (load_flags & 24); - for (row=0; row < S.raw_height; row++) - { - checkCancel(); - if(!(row%ifd->rows_per_strip)) - { - if(stripcnt >= ifd->strip_offsets_count) - return; // run out of data - libraw_internal_data.internal_data.input->seek(ifd->strip_offsets[stripcnt],SEEK_SET); - stripcnt++; - } - for (col=0; col < S.raw_width; col++) - { - for (vbits -= tiff_bps; vbits < 0; vbits += bite) - { - bitbuf <<= bite; - for (i=0; i < bite; i+=8) - bitbuf |= (unsigned) (libraw_internal_data.internal_data.input->get_char() << i); - } - imgdata.rawdata.raw_image[(row)*S.raw_width+(col)] = bitbuf << (64-tiff_bps-vbits) >> (64-tiff_bps); - } - vbits -= rbits; - } + int vbits = 0, bwide, rbits, bite, row, col, val, i; + + UINT64 bitbuf = 0; + unsigned load_flags = 24; // libraw_internal_data.unpacker_data.load_flags; + unsigned tiff_bps = libraw_internal_data.unpacker_data.tiff_bps; + int tiff_compress = libraw_internal_data.unpacker_data.tiff_compress; + + struct tiff_ifd_t *ifd = &tiff_ifd[0]; + while (ifd < &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds] && + ifd->offset != libraw_internal_data.unpacker_data.data_offset) + ++ifd; + if (ifd == &tiff_ifd[libraw_internal_data.identify_data.tiff_nifds]) + throw LIBRAW_EXCEPTION_DECODE_RAW; + + if (!ifd->rows_per_strip || !ifd->strip_offsets_count) + return; // not unpacked + int stripcnt = 0; + + bwide = S.raw_width * tiff_bps / 8; + bwide += bwide & load_flags >> 7; + rbits = bwide * 8 - S.raw_width * tiff_bps; + if (load_flags & 1) + bwide = bwide * 16 / 15; + bite = 8 + (load_flags & 24); + for (row = 0; row < S.raw_height; row++) + { + checkCancel(); + if (!(row % ifd->rows_per_strip)) + { + if (stripcnt >= ifd->strip_offsets_count) + return; // run out of data + libraw_internal_data.internal_data.input->seek(ifd->strip_offsets[stripcnt], SEEK_SET); + stripcnt++; + } + for (col = 0; col < S.raw_width; col++) + { + for (vbits -= tiff_bps; vbits < 0; vbits += bite) + { + bitbuf <<= bite; + for (i = 0; i < bite; i += 8) + bitbuf |= (unsigned)(libraw_internal_data.internal_data.input->get_char() << i); + } + imgdata.rawdata.raw_image[(row)*S.raw_width + (col)] = bitbuf << (64 - tiff_bps - vbits) >> (64 - tiff_bps); + } + vbits -= rbits; + } } struct foveon_data_t { - const char *make; - const char *model; - const int raw_width,raw_height; - const int white; - const int left_margin,top_margin; - const int width,height; -} foveon_data [] = -{ - {"Sigma","SD9",2304,1531,12000,20,8,2266,1510}, - {"Sigma","SD9",1152,763,12000,10,2,1132,755}, - {"Sigma","SD10",2304,1531,12000,20,8,2266,1510}, - {"Sigma","SD10",1152,763,12000,10,2,1132,755}, - {"Sigma","SD14",2688,1792,14000,18,12,2651,1767}, - {"Sigma","SD14",2688,896,14000,18,6,2651,883}, // 2/3 - {"Sigma","SD14",1344,896,14000,9,6,1326,883}, // 1/2 - {"Sigma","SD15",2688,1792,2900,18,12,2651,1767}, - {"Sigma","SD15",2688,896,2900,18,6,2651,883}, // 2/3 ? - {"Sigma","SD15",1344,896,2900,9,6,1326,883}, // 1/2 ? - {"Sigma","DP1",2688,1792,2100,18,12,2651,1767}, - {"Sigma","DP1",2688,896,2100,18,6,2651,883}, // 2/3 ? - {"Sigma","DP1",1344,896,2100,9,6,1326,883}, // 1/2 ? - {"Sigma","DP1S",2688,1792,2200,18,12,2651,1767}, - {"Sigma","DP1S",2688,896,2200,18,6,2651,883}, // 2/3 - {"Sigma","DP1S",1344,896,2200,9,6,1326,883}, // 1/2 - {"Sigma","DP1X",2688,1792,3560,18,12,2651,1767}, - {"Sigma","DP1X",2688,896,3560,18,6,2651,883}, // 2/3 - {"Sigma","DP1X",1344,896,3560,9,6,1326,883}, // 1/2 - {"Sigma","DP2",2688,1792,2326,13,16,2651,1767}, - {"Sigma","DP2",2688,896,2326,13,8,2651,883}, // 2/3 ?? - {"Sigma","DP2",1344,896,2326,7,8,1325,883}, // 1/2 ?? - {"Sigma","DP2S",2688,1792,2300,18,12,2651,1767}, - {"Sigma","DP2S",2688,896,2300,18,6,2651,883}, // 2/3 - {"Sigma","DP2S",1344,896,2300,9,6,1326,883}, // 1/2 - {"Sigma","DP2X",2688,1792,2300,18,12,2651,1767}, - {"Sigma","DP2X",2688,896,2300,18,6,2651,883}, // 2/3 - {"Sigma","DP2X",1344,896,2300,9,6,1325,883}, // 1/2 - {"Sigma","SD1",4928,3264,3900,12,52,4807,3205}, // Full size - {"Sigma","SD1",4928,1632,3900,12,26,4807,1603}, // 2/3 size - {"Sigma","SD1",2464,1632,3900,6,26,2403,1603}, // 1/2 size - {"Sigma","SD1 Merrill",4928,3264,3900,12,52,4807,3205}, // Full size - {"Sigma","SD1 Merrill",4928,1632,3900,12,26,4807,1603}, // 2/3 size - {"Sigma","SD1 Merrill",2464,1632,3900,6,26,2403,1603}, // 1/2 size - {"Sigma","DP1 Merrill",4928,3264,3900,12,0,4807,3205}, - {"Sigma","DP1 Merrill",2464,1632,3900,12,0,2403,1603}, // 1/2 size - {"Sigma","DP1 Merrill",4928,1632,3900,12,0,4807,1603}, // 2/3 size - {"Sigma","DP2 Merrill",4928,3264,3900,12,0,4807,3205}, - {"Sigma","DP2 Merrill",2464,1632,3900,12,0,2403,1603}, // 1/2 size - {"Sigma","DP2 Merrill",4928,1632,3900,12,0,4807,1603}, // 2/3 size - {"Sigma","DP3 Merrill",4928,3264,3900,12,0,4807,3205}, - {"Sigma","DP3 Merrill",2464,1632,3900,12,0,2403,1603}, // 1/2 size - {"Sigma","DP3 Merrill",4928,1632,3900,12,0,4807,1603}, // 2/3 size - {"Polaroid","x530",1440,1088,2700,10,13,1419,1059}, - // dp2 Q - {"Sigma","dp3 Quattro",5888,3672,16383,204,24,5446,3624}, // full size - {"Sigma","dp3 Quattro",2944,1836,16383,102,12,2723,1812}, // half size - {"Sigma","dp2 Quattro",5888,3672,16383,204,24,5446,3624}, // full size - {"Sigma","dp2 Quattro",2944,1836,16383,102,12,2723,1812}, // half size - {"Sigma","dp1 Quattro",5888,3672,16383,204,24,5446,3624}, // full size - {"Sigma","dp1 Quattro",2944,1836,16383,102,12,2723,1812}, // half size - {"Sigma","dp0 Quattro",5888,3672,16383,204,24,5446,3624}, // full size - {"Sigma","dp0 Quattro",2944,1836,16383,102,12,2723,1812}, // half size - // Sigma sd Quattro - {"Sigma","sd Quattro",5888,3776,16383,204,76,5446,3624}, // full size - {"Sigma","sd Quattro",2944,1888,16383,102,38,2723,1812}, // half size - // Sd Quattro H - {"Sigma","sd Quattro H",6656,4480,16383,224,160,6208,4160}, // full size - {"Sigma","sd Quattro H",3328,2240,16383,112,80,3104,2080}, // half size - {"Sigma","sd Quattro H",5504,3680,16383,0,4,5496,3668}, // full size - {"Sigma","sd Quattro H",2752,1840,16383,0,2,2748,1834}, // half size + const char *make; + const char *model; + const int raw_width, raw_height; + const int white; + const int left_margin, top_margin; + const int width, height; +} foveon_data[] = { + {"Sigma", "SD9", 2304, 1531, 12000, 20, 8, 2266, 1510}, + {"Sigma", "SD9", 1152, 763, 12000, 10, 2, 1132, 755}, + {"Sigma", "SD10", 2304, 1531, 12000, 20, 8, 2266, 1510}, + {"Sigma", "SD10", 1152, 763, 12000, 10, 2, 1132, 755}, + {"Sigma", "SD14", 2688, 1792, 14000, 18, 12, 2651, 1767}, + {"Sigma", "SD14", 2688, 896, 14000, 18, 6, 2651, 883}, // 2/3 + {"Sigma", "SD14", 1344, 896, 14000, 9, 6, 1326, 883}, // 1/2 + {"Sigma", "SD15", 2688, 1792, 2900, 18, 12, 2651, 1767}, + {"Sigma", "SD15", 2688, 896, 2900, 18, 6, 2651, 883}, // 2/3 ? + {"Sigma", "SD15", 1344, 896, 2900, 9, 6, 1326, 883}, // 1/2 ? + {"Sigma", "DP1", 2688, 1792, 2100, 18, 12, 2651, 1767}, + {"Sigma", "DP1", 2688, 896, 2100, 18, 6, 2651, 883}, // 2/3 ? + {"Sigma", "DP1", 1344, 896, 2100, 9, 6, 1326, 883}, // 1/2 ? + {"Sigma", "DP1S", 2688, 1792, 2200, 18, 12, 2651, 1767}, + {"Sigma", "DP1S", 2688, 896, 2200, 18, 6, 2651, 883}, // 2/3 + {"Sigma", "DP1S", 1344, 896, 2200, 9, 6, 1326, 883}, // 1/2 + {"Sigma", "DP1X", 2688, 1792, 3560, 18, 12, 2651, 1767}, + {"Sigma", "DP1X", 2688, 896, 3560, 18, 6, 2651, 883}, // 2/3 + {"Sigma", "DP1X", 1344, 896, 3560, 9, 6, 1326, 883}, // 1/2 + {"Sigma", "DP2", 2688, 1792, 2326, 13, 16, 2651, 1767}, + {"Sigma", "DP2", 2688, 896, 2326, 13, 8, 2651, 883}, // 2/3 ?? + {"Sigma", "DP2", 1344, 896, 2326, 7, 8, 1325, 883}, // 1/2 ?? + {"Sigma", "DP2S", 2688, 1792, 2300, 18, 12, 2651, 1767}, + {"Sigma", "DP2S", 2688, 896, 2300, 18, 6, 2651, 883}, // 2/3 + {"Sigma", "DP2S", 1344, 896, 2300, 9, 6, 1326, 883}, // 1/2 + {"Sigma", "DP2X", 2688, 1792, 2300, 18, 12, 2651, 1767}, + {"Sigma", "DP2X", 2688, 896, 2300, 18, 6, 2651, 883}, // 2/3 + {"Sigma", "DP2X", 1344, 896, 2300, 9, 6, 1325, 883}, // 1/2 + {"Sigma", "SD1", 4928, 3264, 3900, 12, 52, 4807, 3205}, // Full size + {"Sigma", "SD1", 4928, 1632, 3900, 12, 26, 4807, 1603}, // 2/3 size + {"Sigma", "SD1", 2464, 1632, 3900, 6, 26, 2403, 1603}, // 1/2 size + {"Sigma", "SD1 Merrill", 4928, 3264, 3900, 12, 52, 4807, 3205}, // Full size + {"Sigma", "SD1 Merrill", 4928, 1632, 3900, 12, 26, 4807, 1603}, // 2/3 size + {"Sigma", "SD1 Merrill", 2464, 1632, 3900, 6, 26, 2403, 1603}, // 1/2 size + {"Sigma", "DP1 Merrill", 4928, 3264, 3900, 12, 0, 4807, 3205}, + {"Sigma", "DP1 Merrill", 2464, 1632, 3900, 12, 0, 2403, 1603}, // 1/2 size + {"Sigma", "DP1 Merrill", 4928, 1632, 3900, 12, 0, 4807, 1603}, // 2/3 size + {"Sigma", "DP2 Merrill", 4928, 3264, 3900, 12, 0, 4807, 3205}, + {"Sigma", "DP2 Merrill", 2464, 1632, 3900, 12, 0, 2403, 1603}, // 1/2 size + {"Sigma", "DP2 Merrill", 4928, 1632, 3900, 12, 0, 4807, 1603}, // 2/3 size + {"Sigma", "DP3 Merrill", 4928, 3264, 3900, 12, 0, 4807, 3205}, + {"Sigma", "DP3 Merrill", 2464, 1632, 3900, 12, 0, 2403, 1603}, // 1/2 size + {"Sigma", "DP3 Merrill", 4928, 1632, 3900, 12, 0, 4807, 1603}, // 2/3 size + {"Polaroid", "x530", 1440, 1088, 2700, 10, 13, 1419, 1059}, + // dp2 Q + {"Sigma", "dp3 Quattro", 5888, 3672, 16383, 204, 24, 5446, 3624}, // full size + {"Sigma", "dp3 Quattro", 2944, 1836, 16383, 102, 12, 2723, 1812}, // half size + {"Sigma", "dp2 Quattro", 5888, 3672, 16383, 204, 24, 5446, 3624}, // full size + {"Sigma", "dp2 Quattro", 2944, 1836, 16383, 102, 12, 2723, 1812}, // half size + {"Sigma", "dp1 Quattro", 5888, 3672, 16383, 204, 24, 5446, 3624}, // full size + {"Sigma", "dp1 Quattro", 2944, 1836, 16383, 102, 12, 2723, 1812}, // half size + {"Sigma", "dp0 Quattro", 5888, 3672, 16383, 204, 24, 5446, 3624}, // full size + {"Sigma", "dp0 Quattro", 2944, 1836, 16383, 102, 12, 2723, 1812}, // half size + // Sigma sd Quattro + {"Sigma", "sd Quattro", 5888, 3776, 16383, 204, 76, 5446, 3624}, // full size + {"Sigma", "sd Quattro", 2944, 1888, 16383, 102, 38, 2723, 1812}, // half size + // Sd Quattro H + {"Sigma", "sd Quattro H", 6656, 4480, 16383, 224, 160, 6208, 4160}, // full size + {"Sigma", "sd Quattro H", 3328, 2240, 16383, 112, 80, 3104, 2080}, // half size + {"Sigma", "sd Quattro H", 5504, 3680, 16383, 0, 4, 5496, 3668}, // full size + {"Sigma", "sd Quattro H", 2752, 1840, 16383, 0, 2, 2748, 1834}, // half size }; -const int foveon_count = sizeof(foveon_data)/sizeof(foveon_data[0]); - +const int foveon_count = sizeof(foveon_data) / sizeof(foveon_data[0]); int LibRaw::open_datastream(LibRaw_abstract_datastream *stream) { - if(!stream) + if (!stream) return ENOENT; - if(!stream->valid()) + if (!stream->valid()) return LIBRAW_IO_ERROR; recycle(); + if(callbacks.pre_identify_cb) + { + int r = (callbacks.pre_identify_cb)(this); + if(r == 1) goto final; + } + - try { + try + { ID.input = stream; SET_PROC_FLAG(LIBRAW_PROGRESS_OPEN); identify(); + if(callbacks.post_identify_cb) + (callbacks.post_identify_cb)(this); + + + // Linear max from 14-bit camera, but on 12-bit data? + if(( !strcasecmp(imgdata.idata.make, "Sony") /* || !strcasecmp(imgdata.idata.make, "Nikon") */) + && imgdata.color.maximum > 0 && imgdata.color.linear_max[0] > imgdata.color.maximum + && imgdata.color.linear_max[0] <= imgdata.color.maximum*4) + for(int c = 0; c<4; c++) + imgdata.color.linear_max[c] /= 4; + + if (!strcasecmp(imgdata.idata.make, "Canon") && (load_raw == &LibRaw::canon_sraw_load_raw) && + imgdata.sizes.raw_width > 0) + { + float ratio = float(imgdata.sizes.raw_height) / float(imgdata.sizes.raw_width); + if ((ratio < 0.57 || ratio > 0.75) && imgdata.makernotes.canon.SensorHeight > 1 && + imgdata.makernotes.canon.SensorWidth > 1) + { + imgdata.sizes.raw_width = imgdata.makernotes.canon.SensorWidth; + imgdata.sizes.left_margin = imgdata.makernotes.canon.SensorLeftBorder; + imgdata.sizes.iwidth = imgdata.sizes.width = + imgdata.makernotes.canon.SensorRightBorder - imgdata.makernotes.canon.SensorLeftBorder + 1; + imgdata.sizes.raw_height = imgdata.makernotes.canon.SensorHeight; + imgdata.sizes.top_margin = imgdata.makernotes.canon.SensorTopBorder; + imgdata.sizes.iheight = imgdata.sizes.height = + imgdata.makernotes.canon.SensorBottomBorder - imgdata.makernotes.canon.SensorTopBorder + 1; + libraw_internal_data.unpacker_data.load_flags |= 256; // reset width/height in canon_sraw_load_raw() + imgdata.sizes.raw_pitch = 8 * imgdata.sizes.raw_width; + } + else if (imgdata.sizes.raw_width == 4032 && imgdata.sizes.raw_height == 3402 && + !strcasecmp(imgdata.idata.model, "EOS 80D")) // 80D hardcoded + { + imgdata.sizes.raw_width = 4536; + imgdata.sizes.left_margin = 28; + imgdata.sizes.iwidth = imgdata.sizes.width = imgdata.sizes.raw_width - imgdata.sizes.left_margin; + imgdata.sizes.raw_height = 3024; + imgdata.sizes.top_margin = 8; + imgdata.sizes.iheight = imgdata.sizes.height = imgdata.sizes.raw_height - imgdata.sizes.top_margin; + libraw_internal_data.unpacker_data.load_flags |= 256; + imgdata.sizes.raw_pitch = 8 * imgdata.sizes.raw_width; + } + } - if (!strcasecmp(imgdata.idata.make, "Canon") && (load_raw == &LibRaw::canon_sraw_load_raw) && imgdata.sizes.raw_width>0) - { - float ratio = float(imgdata.sizes.raw_height) / float(imgdata.sizes.raw_width); - if((ratio < 0.57 || ratio > 0.75) && imgdata.makernotes.canon.SensorHeight>1 && imgdata.makernotes.canon.SensorWidth > 1) - { - imgdata.sizes.raw_width = imgdata.makernotes.canon.SensorWidth; - imgdata.sizes.left_margin = imgdata.makernotes.canon.SensorLeftBorder; - imgdata.sizes.iwidth = imgdata.sizes.width = imgdata.makernotes.canon.SensorRightBorder - imgdata.makernotes.canon.SensorLeftBorder+1; - imgdata.sizes.raw_height = imgdata.makernotes.canon.SensorHeight; - imgdata.sizes.top_margin = imgdata.makernotes.canon.SensorTopBorder; - imgdata.sizes.iheight = imgdata.sizes.height = imgdata.makernotes.canon.SensorBottomBorder - imgdata.makernotes.canon.SensorTopBorder+1; - libraw_internal_data.unpacker_data.load_flags |= 256; // reset width/height in canon_sraw_load_raw() - imgdata.sizes.raw_pitch = 8*imgdata.sizes.raw_width; - } - else if(imgdata.sizes.raw_width == 4032 && imgdata.sizes.raw_height == 3402 && !strcasecmp(imgdata.idata.model, "EOS 80D")) // 80D hardcoded - { - imgdata.sizes.raw_width = 4536; - imgdata.sizes.left_margin = 28; - imgdata.sizes.iwidth = imgdata.sizes.width = imgdata.sizes.raw_width - imgdata.sizes.left_margin; - imgdata.sizes.raw_height = 3024; - imgdata.sizes.top_margin = 8; - imgdata.sizes.iheight = imgdata.sizes.height = imgdata.sizes.raw_height - imgdata.sizes.top_margin; - libraw_internal_data.unpacker_data.load_flags |= 256; - imgdata.sizes.raw_pitch = 8*imgdata.sizes.raw_width; - } - } - - // XTrans Compressed? - if (!imgdata.idata.dng_version && !strcasecmp(imgdata.idata.make, "Fujifilm") && (load_raw == &LibRaw::unpacked_load_raw) ) - { - if (imgdata.sizes.raw_width * imgdata.sizes.raw_height * 2 != libraw_internal_data.unpacker_data.data_size) - parse_xtrans_header(); - - if(imgdata.idata.filters == 9) - { - // Adjust top/left margins for X-Trans - int newtm = imgdata.sizes.top_margin%6?(imgdata.sizes.top_margin/6+1)*6 : imgdata.sizes.top_margin; - int newlm = imgdata.sizes.left_margin%6?(imgdata.sizes.left_margin/6+1)*6 : imgdata.sizes.left_margin; - if(newtm != imgdata.sizes.top_margin || newlm != imgdata.sizes.left_margin) - { - imgdata.sizes.height -= (newtm - imgdata.sizes.top_margin); - imgdata.sizes.top_margin = newtm; - imgdata.sizes.width -= (newlm - imgdata.sizes.left_margin); - imgdata.sizes.left_margin = newlm; - for(int c = 0; c < 36; c++) - imgdata.idata.xtrans[0][c] = imgdata.idata.xtrans_abs[0][c]; - } - } - } + // XTrans Compressed? + if (!imgdata.idata.dng_version && !strcasecmp(imgdata.idata.make, "Fujifilm") && + (load_raw == &LibRaw::unpacked_load_raw)) + { + if (imgdata.sizes.raw_width * imgdata.sizes.raw_height * 2 != libraw_internal_data.unpacker_data.data_size) + { + if (imgdata.sizes.raw_width * imgdata.sizes.raw_height * 7 / 4 == libraw_internal_data.unpacker_data.data_size) + load_raw = &LibRaw::fuji_14bit_load_raw; + else + parse_fuji_compressed_header(); + } + if (imgdata.idata.filters == 9) + { + // Adjust top/left margins for X-Trans + int newtm = imgdata.sizes.top_margin % 6 ? (imgdata.sizes.top_margin / 6 + 1) * 6 : imgdata.sizes.top_margin; + int newlm = imgdata.sizes.left_margin % 6 ? (imgdata.sizes.left_margin / 6 + 1) * 6 : imgdata.sizes.left_margin; + if (newtm != imgdata.sizes.top_margin || newlm != imgdata.sizes.left_margin) + { + imgdata.sizes.height -= (newtm - imgdata.sizes.top_margin); + imgdata.sizes.top_margin = newtm; + imgdata.sizes.width -= (newlm - imgdata.sizes.left_margin); + imgdata.sizes.left_margin = newlm; + for (int c1 = 0; c1 < 6; c1++) + for (int c2 = 0; c2 < 6; c2++) + imgdata.idata.xtrans[c1][c2] = imgdata.idata.xtrans_abs[c1][c2]; + } + } + } // Fix DNG white balance if needed - if(imgdata.idata.dng_version && (imgdata.idata.filters == 0) && imgdata.idata.colors > 1 && imgdata.idata.colors < 5) + if (imgdata.idata.dng_version && (imgdata.idata.filters == 0) && imgdata.idata.colors > 1 && + imgdata.idata.colors < 5) + { + float delta[4] = {0.f, 0.f, 0.f, 0.f}; + int black[4]; + for (int c = 0; c < 4; c++) + black[c] = imgdata.color.dng_levels.dng_black + imgdata.color.dng_levels.dng_cblack[c]; + for (int c = 0; c < imgdata.idata.colors; c++) + delta[c] = imgdata.color.dng_levels.dng_whitelevel[c] - black[c]; + float mindelta = delta[0], maxdelta = delta[0]; + for (int c = 1; c < imgdata.idata.colors; c++) { - float delta[4]={0.f,0.f,0.f,0.f}; - for(int c = 0; c < imgdata.idata.colors ; c++ ) - delta[c] = imgdata.color.dng_levels.dng_whitelevel[c] - imgdata.color.dng_levels.dng_blacklevel[c]; - float mindelta = delta[0],maxdelta = delta[0]; - for(int c = 1; c < imgdata.idata.colors; c++) - { - if(mindelta > delta[c]) mindelta = delta[c]; - if(maxdelta < delta[c]) maxdelta = delta[c]; - } - if(mindelta > 1 && maxdelta < (mindelta *20)) // safety - { - for(int c = 0; c < imgdata.idata.colors; c++) - { - imgdata.color.cam_mul[c] /= (delta[c]/maxdelta); - imgdata.color.pre_mul[c] /= (delta[c]/maxdelta); - } - imgdata.color.maximum = imgdata.color.cblack[0]+maxdelta; - } + if (mindelta > delta[c]) + mindelta = delta[c]; + if (maxdelta < delta[c]) + maxdelta = delta[c]; + } + if (mindelta > 1 && maxdelta < (mindelta * 20)) // safety + { + for (int c = 0; c < imgdata.idata.colors; c++) + { + imgdata.color.cam_mul[c] /= (delta[c] / maxdelta); + imgdata.color.pre_mul[c] /= (delta[c] / maxdelta); + } + imgdata.color.maximum = imgdata.color.cblack[0] + maxdelta; } + } - if(imgdata.idata.dng_version && - ( - (!strcasecmp(imgdata.idata.make,"Leica") && !strcasecmp(imgdata.idata.model,"D-LUX (Typ 109)")) - || - (!strcasecmp(imgdata.idata.make,"Panasonic") && !strcasecmp(imgdata.idata.model,"LX100")) - ) - ) + if (imgdata.idata.dng_version && + ((!strcasecmp(imgdata.idata.make, "Leica") && !strcasecmp(imgdata.idata.model, "D-LUX (Typ 109)")) || + (!strcasecmp(imgdata.idata.make, "Panasonic") && !strcasecmp(imgdata.idata.model, "LX100")))) imgdata.sizes.width = 4288; - if (!strncasecmp(imgdata.idata.make, "Sony", 4) && imgdata.idata.dng_version) - { - if(S.raw_width == 3984) S.width = 3925; - else if (S.raw_width == 4288) S.width = S.raw_width-32; - else if (S.raw_width == 4928 && S.height < 3280) S.width = S.raw_width-8; - else if (S.raw_width == 5504) S.width = S.raw_width-(S.height > 3664 ? 8 : 32); - else if (S.raw_width == 6048) - { - S.width = S.raw_width-24; - if (strstr(imgdata.idata.model,"RX1") || strstr(imgdata.idata.model,"A99")) S.width -= 6; - } - else if (S.raw_width == 7392) S.width = S.raw_width-30; - else if(S.raw_width == 8000) S.width = S.raw_width - 32; - } - - if(!strcasecmp(imgdata.idata.make,"Pentax") && /*!strcasecmp(imgdata.idata.model,"K-3 II") &&*/ imgdata.idata.raw_count == 4 && (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_PENTAX_PS_ALLFRAMES)) - { - imgdata.idata.raw_count = 1; - imgdata.idata.filters = 0; - imgdata.idata.colors = 4; - IO.mix_green = 1; - pentax_component_load_raw = load_raw; - load_raw= &LibRaw::pentax_4shot_load_raw; - } - - if (!imgdata.idata.dng_version && !strcmp(imgdata.idata.make, "Leaf") && !strcmp(imgdata.idata.model, "Credo 50")) - { - imgdata.color.pre_mul[0] = 1.f / 0.3984f; - imgdata.color.pre_mul[2] = 1.f / 0.7666f; - imgdata.color.pre_mul[1] = imgdata.color.pre_mul[3] = 1.0; - } - - // S3Pro DNG patch - if(imgdata.idata.dng_version && !strcmp(imgdata.idata.make,"Fujifilm") && !strcmp(imgdata.idata.model,"S3Pro") && imgdata.sizes.raw_width == 4288 ) - { - imgdata.sizes.left_margin++; - imgdata.sizes.width--; - } - if(imgdata.idata.dng_version && !strcmp(imgdata.idata.make,"Fujifilm") && !strcmp(imgdata.idata.model,"S5Pro") && imgdata.sizes.raw_width == 4288 ) - { - imgdata.sizes.left_margin++; - imgdata.sizes.width--; - } - if(!imgdata.idata.dng_version && !strcmp(imgdata.idata.make,"Fujifilm") - && (!strncmp(imgdata.idata.model,"S20Pro",6) || !strncmp(imgdata.idata.model,"F700",4)) - ) - { - imgdata.sizes.raw_width/=2; - load_raw= &LibRaw::unpacked_load_raw_fuji_f700s20; - } - if(load_raw == &LibRaw::packed_load_raw && !strcasecmp(imgdata.idata.make,"Nikon") - && !libraw_internal_data.unpacker_data.load_flags - && (!strncasecmp(imgdata.idata.model,"D810",4) || !strcasecmp(imgdata.idata.model,"D4S")) - && libraw_internal_data.unpacker_data.data_size*2 == imgdata.sizes.raw_height*imgdata.sizes.raw_width*3) - { - libraw_internal_data.unpacker_data.load_flags = 80; - } - // Adjust BL for Sony A900/A850 - if(load_raw == &LibRaw::packed_load_raw && !strcasecmp(imgdata.idata.make,"Sony")) // 12 bit sony, but metadata may be for 14-bit range + if (!strncasecmp(imgdata.idata.make, "Sony", 4) && imgdata.idata.dng_version && + !(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_USE_DNG_DEFAULT_CROP)) + { + if (S.raw_width == 3984) + S.width = 3925; + else if (S.raw_width == 4288) + S.width = S.raw_width - 32; + else if (S.raw_width == 4928 && S.height < 3280) + S.width = S.raw_width - 8; + else if (S.raw_width == 5504) + S.width = S.raw_width - (S.height > 3664 ? 8 : 32); + } + + if (!strcasecmp(imgdata.idata.make, "Pentax") && + /*!strcasecmp(imgdata.idata.model,"K-3 II") &&*/ imgdata.idata.raw_count == 4 && + (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_PENTAX_PS_ALLFRAMES)) + { + imgdata.idata.raw_count = 1; + imgdata.idata.filters = 0; + imgdata.idata.colors = 4; + IO.mix_green = 1; + pentax_component_load_raw = load_raw; + load_raw = &LibRaw::pentax_4shot_load_raw; + } + + if (!imgdata.idata.dng_version && !strcmp(imgdata.idata.make, "Leaf") && !strcmp(imgdata.idata.model, "Credo 50")) + { + imgdata.color.pre_mul[0] = 1.f / 0.3984f; + imgdata.color.pre_mul[2] = 1.f / 0.7666f; + imgdata.color.pre_mul[1] = imgdata.color.pre_mul[3] = 1.0; + } + + // S3Pro DNG patch + if (imgdata.idata.dng_version && !strcmp(imgdata.idata.make, "Fujifilm") && !strcmp(imgdata.idata.model, "S3Pro") && + imgdata.sizes.raw_width == 4288) + { + imgdata.sizes.left_margin++; + imgdata.sizes.width--; + } + if (imgdata.idata.dng_version && !strcmp(imgdata.idata.make, "Fujifilm") && !strcmp(imgdata.idata.model, "S5Pro") && + imgdata.sizes.raw_width == 4288) + { + imgdata.sizes.left_margin++; + imgdata.sizes.width--; + } + if (!imgdata.idata.dng_version && !strcmp(imgdata.idata.make, "Fujifilm") && + (!strncmp(imgdata.idata.model, "S20Pro", 6) || !strncmp(imgdata.idata.model, "F700", 4))) + { + imgdata.sizes.raw_width /= 2; + load_raw = &LibRaw::unpacked_load_raw_fuji_f700s20; + } + if (load_raw == &LibRaw::packed_load_raw && !strcasecmp(imgdata.idata.make, "Nikon") && + !libraw_internal_data.unpacker_data.load_flags && + (!strncasecmp(imgdata.idata.model, "D810", 4) || !strcasecmp(imgdata.idata.model, "D4S")) && + libraw_internal_data.unpacker_data.data_size * 2 == imgdata.sizes.raw_height * imgdata.sizes.raw_width * 3) + { + libraw_internal_data.unpacker_data.load_flags = 80; + } + // Adjust BL for Sony A900/A850 + if (load_raw == &LibRaw::packed_load_raw && + !strcasecmp(imgdata.idata.make, "Sony")) // 12 bit sony, but metadata may be for 14-bit range + { + if (C.maximum > 4095) + C.maximum = 4095; + if (C.black > 256 || C.cblack[0] > 256) { - if(C.maximum>4095) - C.maximum = 4095; - if(C.black > 256 || C.cblack[0] > 256) - { - C.black /=4; - for(int c=0; c< 4; c++) - C.cblack[c]/=4; - for(int c=0; c< C.cblack[4]*C.cblack[5];c++) - C.cblack[6+c]/=4; - } + C.black /= 4; + for (int c = 0; c < 4; c++) + C.cblack[c] /= 4; + for (int c = 0; c < C.cblack[4] * C.cblack[5]; c++) + C.cblack[6 + c] /= 4; } - if( load_raw == &LibRaw::nikon_yuv_load_raw ) // Is it Nikon sRAW? + } + if (load_raw == &LibRaw::nikon_yuv_load_raw) // Is it Nikon sRAW? + { + load_raw = &LibRaw::nikon_load_sraw; + C.black = 0; + memset(C.cblack, 0, sizeof(C.cblack)); + imgdata.idata.filters = 0; + libraw_internal_data.unpacker_data.tiff_samples = 3; + imgdata.idata.colors = 3; + double beta_1 = -5.79342238397656E-02; + double beta_2 = 3.28163551282665; + double beta_3 = -8.43136004842678; + double beta_4 = 1.03533181861023E+01; + for (int i = 0; i <= 3072; i++) { - load_raw= &LibRaw::nikon_load_sraw; - C.black =0; - memset(C.cblack,0,sizeof(C.cblack)); - imgdata.idata.filters = 0; - libraw_internal_data.unpacker_data.tiff_samples=3; - imgdata.idata.colors = 3; - double beta_1 = -5.79342238397656E-02; - double beta_2 = 3.28163551282665; - double beta_3 = -8.43136004842678; - double beta_4 = 1.03533181861023E+01; - for(int i=0; i<=3072;i++) - { - double x = (double)i/3072.; - double y = (1.-exp(-beta_1*x-beta_2*x*x-beta_3*x*x*x-beta_4*x*x*x*x)); - if(y<0.)y=0.; - imgdata.color.curve[i] = (y*16383.); - } - for(int i=0;i<3;i++) - for(int j=0;j<4;j++) - imgdata.color.rgb_cam[i][j]=float(i==j); + double x = (double)i / 3072.; + double y = (1. - exp(-beta_1 * x - beta_2 * x * x - beta_3 * x * x * x - beta_4 * x * x * x * x)); + if (y < 0.) + y = 0.; + imgdata.color.curve[i] = (y * 16383.); } + for (int i = 0; i < 3; i++) + for (int j = 0; j < 4; j++) + imgdata.color.rgb_cam[i][j] = float(i == j); + } // Adjust BL for Nikon 12bit - if(( - load_raw == &LibRaw::nikon_load_raw - || load_raw == &LibRaw::packed_load_raw) - && !strcasecmp(imgdata.idata.make,"Nikon") - && strncmp(imgdata.idata.model,"COOLPIX",7) -// && strncmp(imgdata.idata.model,"1 ",2) - && libraw_internal_data.unpacker_data.tiff_bps == 12) - { - C.maximum = 4095; - C.black /=4; - for(int c=0; c< 4; c++) - C.cblack[c]/=4; - for(int c=0; c< C.cblack[4]*C.cblack[5];c++) - C.cblack[6+c]/=4; - } + if ((load_raw == &LibRaw::nikon_load_raw || load_raw == &LibRaw::packed_load_raw) && + !strcasecmp(imgdata.idata.make, "Nikon") && + strncmp(imgdata.idata.model, "COOLPIX", 7) + // && strncmp(imgdata.idata.model,"1 ",2) + && libraw_internal_data.unpacker_data.tiff_bps == 12) + { + C.maximum = 4095; + C.black /= 4; + for (int c = 0; c < 4; c++) + C.cblack[c] /= 4; + for (int c = 0; c < C.cblack[4] * C.cblack[5]; c++) + C.cblack[6 + c] /= 4; + } // Adjust Highlight Linearity limit - if (C.linear_max[0] < 0) { - if (imgdata.idata.dng_version) { - for (int c=0; c<4; c++) - C.linear_max[c] = -1 * C.linear_max[c] + imgdata.color.cblack[c+6]; - } else { - for (int c=0; c<4; c++) - C.linear_max[c] = -1 * C.linear_max[c] + imgdata.color.cblack[c]; + if (C.linear_max[0] < 0) + { + if (imgdata.idata.dng_version) + { + for (int c = 0; c < 4; c++) + C.linear_max[c] = -1 * C.linear_max[c] + imgdata.color.cblack[c + 6]; + } + else + { + for (int c = 0; c < 4; c++) + C.linear_max[c] = -1 * C.linear_max[c] + imgdata.color.cblack[c]; } } - if (!strcasecmp(imgdata.idata.make,"Nikon") && (!C.linear_max[0]) && (C.maximum > 1024) && (load_raw != &LibRaw::nikon_load_sraw)) { - C.linear_max[0] = - C.linear_max[1] = - C.linear_max[2] = - C.linear_max[3] = - (long) ((float)(C.maximum) / 1.07f); + if (!strcasecmp(imgdata.idata.make, "Nikon") && (!C.linear_max[0]) && (C.maximum > 1024) && + (load_raw != &LibRaw::nikon_load_sraw)) + { + C.linear_max[0] = C.linear_max[1] = C.linear_max[2] = C.linear_max[3] = (long)((float)(C.maximum) / 1.07f); } // Correct WB for Samsung GX20 - if (!strcasecmp(imgdata.idata.make,"Samsung") && !strcasecmp(imgdata.idata.model,"GX20")) { - C.WB_Coeffs[LIBRAW_WBI_Daylight][2] = (int) ((float) (C.WB_Coeffs[LIBRAW_WBI_Daylight][2]) * 2.56f); - C.WB_Coeffs[LIBRAW_WBI_Shade][2] = (int) ((float) (C.WB_Coeffs[LIBRAW_WBI_Shade][2]) * 2.56f); - C.WB_Coeffs[LIBRAW_WBI_Cloudy][2] = (int) ((float) (C.WB_Coeffs[LIBRAW_WBI_Cloudy][2]) * 2.56f); - C.WB_Coeffs[LIBRAW_WBI_Tungsten][2] = (int) ((float) (C.WB_Coeffs[LIBRAW_WBI_Tungsten][2]) * 2.56f); - C.WB_Coeffs[LIBRAW_WBI_FL_D][2] = (int) ((float) (C.WB_Coeffs[LIBRAW_WBI_FL_D][2]) * 2.56f); - C.WB_Coeffs[LIBRAW_WBI_FL_N][2] = (int) ((float) (C.WB_Coeffs[LIBRAW_WBI_FL_N][2]) * 2.56f); - C.WB_Coeffs[LIBRAW_WBI_FL_W][2] = (int) ((float) (C.WB_Coeffs[LIBRAW_WBI_FL_W][2]) * 2.56f); - C.WB_Coeffs[LIBRAW_WBI_Flash][2] = (int) ((float) (C.WB_Coeffs[LIBRAW_WBI_Flash][2]) * 2.56f); - for (int c=0; c<64; c++) { - if (imgdata.color.WBCT_Coeffs[c][0] > 0.0f) { + if (!strcasecmp(imgdata.idata.make, "Samsung") && !strcasecmp(imgdata.idata.model, "GX20")) + { + C.WB_Coeffs[LIBRAW_WBI_Daylight][2] = (int)((float)(C.WB_Coeffs[LIBRAW_WBI_Daylight][2]) * 2.56f); + C.WB_Coeffs[LIBRAW_WBI_Shade][2] = (int)((float)(C.WB_Coeffs[LIBRAW_WBI_Shade][2]) * 2.56f); + C.WB_Coeffs[LIBRAW_WBI_Cloudy][2] = (int)((float)(C.WB_Coeffs[LIBRAW_WBI_Cloudy][2]) * 2.56f); + C.WB_Coeffs[LIBRAW_WBI_Tungsten][2] = (int)((float)(C.WB_Coeffs[LIBRAW_WBI_Tungsten][2]) * 2.56f); + C.WB_Coeffs[LIBRAW_WBI_FL_D][2] = (int)((float)(C.WB_Coeffs[LIBRAW_WBI_FL_D][2]) * 2.56f); + C.WB_Coeffs[LIBRAW_WBI_FL_N][2] = (int)((float)(C.WB_Coeffs[LIBRAW_WBI_FL_N][2]) * 2.56f); + C.WB_Coeffs[LIBRAW_WBI_FL_W][2] = (int)((float)(C.WB_Coeffs[LIBRAW_WBI_FL_W][2]) * 2.56f); + C.WB_Coeffs[LIBRAW_WBI_Flash][2] = (int)((float)(C.WB_Coeffs[LIBRAW_WBI_Flash][2]) * 2.56f); + for (int c = 0; c < 64; c++) + { + if (imgdata.color.WBCT_Coeffs[c][0] > 0.0f) + { imgdata.color.WBCT_Coeffs[c][3] *= 2.56f; } } } - // Adjust BL for Panasonic - if(load_raw == &LibRaw::panasonic_load_raw && (!strcasecmp(imgdata.idata.make,"Panasonic") || !strcasecmp(imgdata.idata.make,"Leica") || !strcasecmp(imgdata.idata.make,"YUNEEC")) - && ID.pana_black[0] && ID.pana_black[1] && ID.pana_black[2]) - { - C.black=0; - C.cblack[0] = ID.pana_black[0]+ID.pana_black[3]; - C.cblack[1] = C.cblack[3] = ID.pana_black[1]+ID.pana_black[3]; - C.cblack[2] = ID.pana_black[2]+ID.pana_black[3]; - int i = C.cblack[3]; - for(int c=0; c<3; c++) if(i>C.cblack[c]) i = C.cblack[c]; - for(int c=0; c< 4; c++) C.cblack[c]-=i; - C.black = i; - } + // Adjust BL for Panasonic + if (load_raw == &LibRaw::panasonic_load_raw && + (!strcasecmp(imgdata.idata.make, "Panasonic") || !strcasecmp(imgdata.idata.make, "Leica") || + !strcasecmp(imgdata.idata.make, "YUNEEC")) && + ID.pana_black[0] && ID.pana_black[1] && ID.pana_black[2]) + { + if(libraw_internal_data.unpacker_data.pana_encoding == 5) + libraw_internal_data.internal_output_params.zero_is_bad = 0; + C.black = 0; + int add = libraw_internal_data.unpacker_data.pana_encoding == 4?15:0; + C.cblack[0] = ID.pana_black[0]+add; + C.cblack[1] = C.cblack[3] = ID.pana_black[1]+add; + C.cblack[2] = ID.pana_black[2]+add; + int i = C.cblack[3]; + for (int c = 0; c < 3; c++) + if (i > C.cblack[c]) + i = C.cblack[c]; + for (int c = 0; c < 4; c++) + C.cblack[c] -= i; + C.black = i; + } // Adjust sizes for X3F processing - if(load_raw == &LibRaw::x3f_load_raw) + if (load_raw == &LibRaw::x3f_load_raw) { - for(int i=0; i< foveon_count;i++) - if(!strcasecmp(imgdata.idata.make,foveon_data[i].make) && !strcasecmp(imgdata.idata.model,foveon_data[i].model) - && imgdata.sizes.raw_width == foveon_data[i].raw_width - && imgdata.sizes.raw_height == foveon_data[i].raw_height - ) - { - imgdata.sizes.top_margin = foveon_data[i].top_margin; - imgdata.sizes.left_margin = foveon_data[i].left_margin; - imgdata.sizes.width = imgdata.sizes.iwidth = foveon_data[i].width; - imgdata.sizes.height = imgdata.sizes.iheight = foveon_data[i].height; - C.maximum = foveon_data[i].white; - break; - } + for (int i = 0; i < foveon_count; i++) + if (!strcasecmp(imgdata.idata.make, foveon_data[i].make) && + !strcasecmp(imgdata.idata.model, foveon_data[i].model) && + imgdata.sizes.raw_width == foveon_data[i].raw_width && + imgdata.sizes.raw_height == foveon_data[i].raw_height) + { + imgdata.sizes.top_margin = foveon_data[i].top_margin; + imgdata.sizes.left_margin = foveon_data[i].left_margin; + imgdata.sizes.width = imgdata.sizes.iwidth = foveon_data[i].width; + imgdata.sizes.height = imgdata.sizes.iheight = foveon_data[i].height; + C.maximum = foveon_data[i].white; + break; + } } #if 0 size_t bytes = ID.input->size()-libraw_internal_data.unpacker_data.data_offset; float bpp = float(bytes)/float(S.raw_width)/float(S.raw_height); float bpp2 = float(bytes)/float(S.width)/float(S.height); printf("RawSize: %dx%d data offset: %d data size:%d bpp: %g bpp2: %g\n",S.raw_width,S.raw_height,libraw_internal_data.unpacker_data.data_offset,bytes,bpp,bpp2); if(!strcasecmp(imgdata.idata.make,"Hasselblad") && bpp == 6.0f) { load_raw = &LibRaw::hasselblad_full_load_raw; S.width = S.raw_width; S.height = S.raw_height; P1.filters = 0; P1.colors=3; P1.raw_count=1; C.maximum=0xffff; printf("3 channel hassy found\n"); } #endif - if(C.profile_length) - { - if(C.profile) free(C.profile); - C.profile = malloc(C.profile_length); - merror(C.profile,"LibRaw::open_file()"); - ID.input->seek(ID.profile_offset,SEEK_SET); - ID.input->read(C.profile,C.profile_length,1); - } + if (C.profile_length) + { + if (C.profile) + free(C.profile); + C.profile = malloc(C.profile_length); + merror(C.profile, "LibRaw::open_file()"); + ID.input->seek(ID.profile_offset, SEEK_SET); + ID.input->read(C.profile, C.profile_length, 1); + } SET_PROC_FLAG(LIBRAW_PROGRESS_IDENTIFY); } - catch ( LibRaw_exceptions err) { + catch (LibRaw_exceptions err) + { EXCEPTION_HANDLER(err); } - catch (std::exception ee) { + catch (std::exception ee) + { EXCEPTION_HANDLER(LIBRAW_EXCEPTION_IO_CORRUPT); } - if(P1.raw_count < 1) - return LIBRAW_FILE_UNSUPPORTED; +final:; + if (P1.raw_count < 1) + return LIBRAW_FILE_UNSUPPORTED; write_fun = &LibRaw::write_ppm_tiff; if (load_raw == &LibRaw::kodak_ycbcr_load_raw) - { - S.height += S.height & 1; - S.width += S.width & 1; - } + { + S.height += S.height & 1; + S.width += S.width & 1; + } - IO.shrink = P1.filters && (O.half_size || - ((O.threshold || O.aber[0] != 1 || O.aber[2] != 1) )); + IO.shrink = P1.filters && (O.half_size || ((O.threshold || O.aber[0] != 1 || O.aber[2] != 1))); + if (IO.shrink && P1.filters >= 1000) + { + S.width &= 65534; + S.height &= 65534; + } S.iheight = (S.height + IO.shrink) >> IO.shrink; - S.iwidth = (S.width + IO.shrink) >> IO.shrink; + S.iwidth = (S.width + IO.shrink) >> IO.shrink; // Save color,sizes and internal data into raw_image fields - memmove(&imgdata.rawdata.color,&imgdata.color,sizeof(imgdata.color)); - memmove(&imgdata.rawdata.sizes,&imgdata.sizes,sizeof(imgdata.sizes)); - memmove(&imgdata.rawdata.iparams,&imgdata.idata,sizeof(imgdata.idata)); - memmove(&imgdata.rawdata.ioparams,&libraw_internal_data.internal_output_params,sizeof(libraw_internal_data.internal_output_params)); + memmove(&imgdata.rawdata.color, &imgdata.color, sizeof(imgdata.color)); + memmove(&imgdata.rawdata.sizes, &imgdata.sizes, sizeof(imgdata.sizes)); + memmove(&imgdata.rawdata.iparams, &imgdata.idata, sizeof(imgdata.idata)); + memmove(&imgdata.rawdata.ioparams, &libraw_internal_data.internal_output_params, + sizeof(libraw_internal_data.internal_output_params)); SET_PROC_FLAG(LIBRAW_PROGRESS_SIZE_ADJUST); - return LIBRAW_SUCCESS; } #ifdef USE_RAWSPEED void LibRaw::fix_after_rawspeed(int bl) { if (load_raw == &LibRaw::lossy_dng_load_raw) C.maximum = 0xffff; else if (load_raw == &LibRaw::sony_load_raw) C.maximum = 0x3ff0; } #else -void LibRaw::fix_after_rawspeed(int) -{ -} +void LibRaw::fix_after_rawspeed(int) {} #endif void LibRaw::clearCancelFlag() { #ifdef WIN32 - InterlockedExchange(&_exitflag, 0); + InterlockedExchange(&_exitflag, 0); #else - __sync_fetch_and_and(&_exitflag, 0); + __sync_fetch_and_and(&_exitflag, 0); #endif #ifdef RAWSPEED_FASTEXIT - if (_rawspeed_decoder) - { - RawDecoder *d = static_cast(_rawspeed_decoder); - d->resumeProcessing(); - } + if (_rawspeed_decoder) + { + RawDecoder *d = static_cast(_rawspeed_decoder); + d->resumeProcessing(); + } #endif - } void LibRaw::setCancelFlag() { #ifdef WIN32 - InterlockedExchange(&_exitflag,1); + InterlockedExchange(&_exitflag, 1); #else - __sync_fetch_and_add(&_exitflag,1); + __sync_fetch_and_add(&_exitflag, 1); #endif #ifdef RAWSPEED_FASTEXIT - if(_rawspeed_decoder) - { - RawDecoder *d = static_cast(_rawspeed_decoder); - d->cancelProcessing(); - } + if (_rawspeed_decoder) + { + RawDecoder *d = static_cast(_rawspeed_decoder); + d->cancelProcessing(); + } #endif } void LibRaw::checkCancel() { #ifdef WIN32 - if(InterlockedExchange(&_exitflag,0)) + if (InterlockedExchange(&_exitflag, 0)) throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK; #else - if( __sync_fetch_and_and(&_exitflag,0)) + if (__sync_fetch_and_and(&_exitflag, 0)) throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK; #endif } int LibRaw::try_rawspeed() { #ifdef USE_RAWSPEED - int ret=LIBRAW_SUCCESS; - - int rawspeed_ignore_errors = 0; - if (imgdata.idata.dng_version && imgdata.idata.colors == 3 && !strcasecmp(imgdata.idata.software, "Adobe Photoshop Lightroom 6.1.1 (Windows)")) - rawspeed_ignore_errors = 1; - - // RawSpeed Supported, - INT64 spos = ID.input->tell(); - void *_rawspeed_buffer = 0; - try - { - // printf("Using rawspeed\n"); - ID.input->seek(0,SEEK_SET); - INT64 _rawspeed_buffer_sz = ID.input->size()+32; - _rawspeed_buffer = malloc(_rawspeed_buffer_sz); - if(!_rawspeed_buffer) throw LIBRAW_EXCEPTION_ALLOC; - ID.input->read(_rawspeed_buffer,_rawspeed_buffer_sz,1); - FileMap map((uchar8*)_rawspeed_buffer,_rawspeed_buffer_sz); - RawParser t(&map); - RawDecoder *d = 0; - CameraMetaDataLR *meta = static_cast(_rawspeed_camerameta); - d = t.getDecoder(); - if(!d) throw "Unable to find decoder"; - try { - d->checkSupport(meta); - } - catch (const RawDecoderException& e) - { - imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED_UNSUPPORTED; - throw e; - } - d->interpolateBadPixels = FALSE; - d->applyStage1DngOpcodes = FALSE; - _rawspeed_decoder = static_cast(d); - d->decodeRaw(); - d->decodeMetaData(meta); - RawImage r = d->mRaw; - if( r->errors.size()>0 && !rawspeed_ignore_errors) - { - delete d; - _rawspeed_decoder = 0; - throw 1; - } - if (r->isCFA) - { - imgdata.rawdata.raw_image = (ushort*) r->getDataUncropped(0,0); - } - else if(r->getCpp()==4) - { - imgdata.rawdata.color4_image = (ushort(*)[4]) r->getDataUncropped(0,0); - if(r->whitePoint > 0 && r->whitePoint < 65536) - C.maximum = r->whitePoint; - } else if(r->getCpp() == 3) - { - imgdata.rawdata.color3_image = (ushort(*)[3]) r->getDataUncropped(0,0); - if(r->whitePoint > 0 && r->whitePoint < 65536) - C.maximum = r->whitePoint; - } - else - { - delete d; - _rawspeed_decoder = 0; - ret = LIBRAW_UNSPECIFIED_ERROR; - } - if(_rawspeed_decoder) - { - // set sizes - iPoint2D rsdim = r->getUncroppedDim(); - S.raw_pitch = r->pitch; - S.raw_width = rsdim.x; - S.raw_height = rsdim.y; - //C.maximum = r->whitePoint; - fix_after_rawspeed(r->blackLevel); - } - free(_rawspeed_buffer); - _rawspeed_buffer = 0; - imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED_PROCESSED; - } - catch (const RawDecoderException& RDE) - { - imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED_PROBLEM; - if (_rawspeed_buffer) - { - free(_rawspeed_buffer); - _rawspeed_buffer = 0; - } - const char *p = RDE.what(); - if (!strncmp(RDE.what(), "Decoder canceled", strlen("Decoder canceled"))) - throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK; - ret = LIBRAW_UNSPECIFIED_ERROR; - } - catch (...) - { - // We may get here due to cancellation flag - imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED_PROBLEM; - if(_rawspeed_buffer) - { - free(_rawspeed_buffer); - _rawspeed_buffer = 0; - } - ret = LIBRAW_UNSPECIFIED_ERROR; - } - ID.input->seek(spos,SEEK_SET); - - return ret; + int ret = LIBRAW_SUCCESS; + + int rawspeed_ignore_errors = 0; + if (imgdata.idata.dng_version && imgdata.idata.colors == 3 && + !strcasecmp(imgdata.idata.software, "Adobe Photoshop Lightroom 6.1.1 (Windows)")) + rawspeed_ignore_errors = 1; + + // RawSpeed Supported, + INT64 spos = ID.input->tell(); + void *_rawspeed_buffer = 0; + try + { + // printf("Using rawspeed\n"); + ID.input->seek(0, SEEK_SET); + INT64 _rawspeed_buffer_sz = ID.input->size() + 32; + _rawspeed_buffer = malloc(_rawspeed_buffer_sz); + if (!_rawspeed_buffer) + throw LIBRAW_EXCEPTION_ALLOC; + ID.input->read(_rawspeed_buffer, _rawspeed_buffer_sz, 1); + FileMap map((uchar8 *)_rawspeed_buffer, _rawspeed_buffer_sz); + RawParser t(&map); + RawDecoder *d = 0; + CameraMetaDataLR *meta = static_cast(_rawspeed_camerameta); + d = t.getDecoder(); + if (!d) + throw "Unable to find decoder"; + try + { + d->checkSupport(meta); + } + catch (const RawDecoderException &e) + { + imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED_UNSUPPORTED; + throw e; + } + d->interpolateBadPixels = FALSE; + d->applyStage1DngOpcodes = FALSE; + _rawspeed_decoder = static_cast(d); + d->decodeRaw(); + d->decodeMetaData(meta); + RawImage r = d->mRaw; + if (r->errors.size() > 0 && !rawspeed_ignore_errors) + { + delete d; + _rawspeed_decoder = 0; + throw 1; + } + if (r->isCFA) + { + imgdata.rawdata.raw_image = (ushort *)r->getDataUncropped(0, 0); + } + else if (r->getCpp() == 4) + { + imgdata.rawdata.color4_image = (ushort(*)[4])r->getDataUncropped(0, 0); + if (r->whitePoint > 0 && r->whitePoint < 65536) + C.maximum = r->whitePoint; + } + else if (r->getCpp() == 3) + { + imgdata.rawdata.color3_image = (ushort(*)[3])r->getDataUncropped(0, 0); + if (r->whitePoint > 0 && r->whitePoint < 65536) + C.maximum = r->whitePoint; + } + else + { + delete d; + _rawspeed_decoder = 0; + ret = LIBRAW_UNSPECIFIED_ERROR; + } + if (_rawspeed_decoder) + { + // set sizes + iPoint2D rsdim = r->getUncroppedDim(); + S.raw_pitch = r->pitch; + S.raw_width = rsdim.x; + S.raw_height = rsdim.y; + // C.maximum = r->whitePoint; + fix_after_rawspeed(r->blackLevel); + } + free(_rawspeed_buffer); + _rawspeed_buffer = 0; + imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED_PROCESSED; + } + catch (const RawDecoderException &RDE) + { + imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED_PROBLEM; + if (_rawspeed_buffer) + { + free(_rawspeed_buffer); + _rawspeed_buffer = 0; + } + const char *p = RDE.what(); + if (!strncmp(RDE.what(), "Decoder canceled", strlen("Decoder canceled"))) + throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK; + ret = LIBRAW_UNSPECIFIED_ERROR; + } + catch (...) + { + // We may get here due to cancellation flag + imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED_PROBLEM; + if (_rawspeed_buffer) + { + free(_rawspeed_buffer); + _rawspeed_buffer = 0; + } + ret = LIBRAW_UNSPECIFIED_ERROR; + } + ID.input->seek(spos, SEEK_SET); + + return ret; #else - return LIBRAW_NOT_IMPLEMENTED; + return LIBRAW_NOT_IMPLEMENTED; #endif } int LibRaw::valid_for_dngsdk() { #ifndef USE_DNGSDK - return 0; + return 0; #else - if(!imgdata.idata.dng_version) - return 0; - if(!imgdata.params.use_dngsdk) - return 0; - if (load_raw == &LibRaw::lossy_dng_load_raw) - return 0; - if(is_floating_point() && (imgdata.params.use_dngsdk & LIBRAW_DNG_FLOAT)) - return 1; - if(!imgdata.idata.filters && (imgdata.params.use_dngsdk & LIBRAW_DNG_LINEAR)) - return 1; - if(libraw_internal_data.unpacker_data.tiff_bps == 8 && (imgdata.params.use_dngsdk & LIBRAW_DNG_8BIT)) - return 1; - if(libraw_internal_data.unpacker_data.tiff_compress == 8 && (imgdata.params.use_dngsdk & LIBRAW_DNG_DEFLATE)) - return 1; - if(libraw_internal_data.unpacker_data.tiff_samples == 2 ) - return 0; // Always deny 2-samples (old fuji superccd) - if(imgdata.idata.filters == 9 && (imgdata.params.use_dngsdk & LIBRAW_DNG_XTRANS)) - return 1; - if(is_fuji_rotated()) - return 0; // refuse - if(imgdata.params.use_dngsdk & LIBRAW_DNG_OTHER) - return 1; - return 0; + if (!imgdata.idata.dng_version) + return 0; + if (!imgdata.params.use_dngsdk) + return 0; + if (load_raw == &LibRaw::lossy_dng_load_raw) + return 0; + if (is_floating_point() && (imgdata.params.use_dngsdk & LIBRAW_DNG_FLOAT)) + return 1; + if (!imgdata.idata.filters && (imgdata.params.use_dngsdk & LIBRAW_DNG_LINEAR)) + return 1; + if (libraw_internal_data.unpacker_data.tiff_bps == 8 && (imgdata.params.use_dngsdk & LIBRAW_DNG_8BIT)) + return 1; + if (libraw_internal_data.unpacker_data.tiff_compress == 8 && (imgdata.params.use_dngsdk & LIBRAW_DNG_DEFLATE)) + return 1; + if (libraw_internal_data.unpacker_data.tiff_samples == 2) + return 0; // Always deny 2-samples (old fuji superccd) + if (imgdata.idata.filters == 9 && (imgdata.params.use_dngsdk & LIBRAW_DNG_XTRANS)) + return 1; + if (is_fuji_rotated()) + return 0; // refuse + if (imgdata.params.use_dngsdk & LIBRAW_DNG_OTHER) + return 1; + return 0; #endif } - int LibRaw::is_curve_linear() { - for (int i=0; i < 0x10000; i++) - if(imgdata.color.curve[i] != i) - return 0; - return 1; + for (int i = 0; i < 0x10000; i++) + if (imgdata.color.curve[i] != i) + return 0; + return 1; } - int LibRaw::try_dngsdk() { #ifdef USE_DNGSDK - if(!dnghost) - return LIBRAW_UNSPECIFIED_ERROR; - - dng_host *host = static_cast(dnghost); - - try - { - libraw_dng_stream stream(libraw_internal_data.internal_data.input); - - AutoPtr negative; - negative.Reset (host->Make_dng_negative ()); - - dng_info info; - info.Parse (*host, stream); - info.PostParse (*host); - - if (!info.IsValidDNG ()) - { - return LIBRAW_DATA_ERROR; - } - negative->Parse (*host, stream, info); - negative->PostParse (*host, stream, info); - negative->ReadStage1Image (*host, stream, info); - dng_simple_image *stage2 = (dng_simple_image *)negative->Stage1Image (); - if(stage2->Bounds().W() != S.raw_width || stage2->Bounds().H()!= S.raw_height) - { - return LIBRAW_DATA_ERROR; - } - - int pplanes = stage2->Planes(); - int ptype = stage2->PixelType(); - - dng_pixel_buffer buffer; - stage2->GetPixelBuffer(buffer); - - int pixels = stage2->Bounds().H () * stage2->Bounds().W () * pplanes; - if(ptype == ttByte ) - imgdata.rawdata.raw_alloc = malloc(pixels * TagTypeSize(ttShort)); - else - imgdata.rawdata.raw_alloc = malloc(pixels * TagTypeSize(ptype)); - - if(ptype == ttShort && !is_curve_linear()) - { - ushort *src = (ushort *)buffer.fData; - ushort *dst = (ushort*)imgdata.rawdata.raw_alloc; - for(int i = 0; i < pixels; i++) - dst[i] = imgdata.color.curve[src[i]]; - S.raw_pitch = S.raw_width*pplanes*TagTypeSize(ptype); - } - else if(ptype == ttByte) - { - unsigned char *src = (unsigned char *)buffer.fData; - ushort *dst = (ushort*)imgdata.rawdata.raw_alloc; - if(is_curve_linear()) - { - for(int i = 0; i < pixels; i++) - dst[i] = src[i]; - } - else - { - for(int i = 0; i < pixels; i++) - dst[i] = imgdata.color.curve[src[i]]; - } - S.raw_pitch = S.raw_width*pplanes*TagTypeSize(ttShort); - } - else - { - memmove(imgdata.rawdata.raw_alloc,buffer.fData,pixels * TagTypeSize(ptype)); - S.raw_pitch = S.raw_width*pplanes*TagTypeSize(ptype); - } - - switch(ptype) - { - case ttFloat: - if(pplanes==1) - imgdata.rawdata.float_image = (float*)imgdata.rawdata.raw_alloc; - else if(pplanes == 3) - imgdata.rawdata.float3_image = (float (*)[3])imgdata.rawdata.raw_alloc; - else if(pplanes == 4) - imgdata.rawdata.float4_image = (float (*)[4])imgdata.rawdata.raw_alloc; - break; - - case ttByte: - case ttShort: - if(pplanes==1) - imgdata.rawdata.raw_image = (ushort*)imgdata.rawdata.raw_alloc; - else if(pplanes == 3) - imgdata.rawdata.color3_image = (ushort(*)[3])imgdata.rawdata.raw_alloc; - else if(pplanes == 4) - imgdata.rawdata.color4_image = (ushort(*)[4])imgdata.rawdata.raw_alloc; - break; - default: - /* do nothing */ - break; - } - } - catch (...) - { - return LIBRAW_UNSPECIFIED_ERROR; - } - return imgdata.rawdata.raw_alloc?LIBRAW_SUCCESS:LIBRAW_UNSPECIFIED_ERROR; + if (!dnghost) + return LIBRAW_UNSPECIFIED_ERROR; + + dng_host *host = static_cast(dnghost); + + try + { + libraw_dng_stream stream(libraw_internal_data.internal_data.input); + + AutoPtr negative; + negative.Reset(host->Make_dng_negative()); + + dng_info info; + info.Parse(*host, stream); + info.PostParse(*host); + + if (!info.IsValidDNG()) + { + return LIBRAW_DATA_ERROR; + } + negative->Parse(*host, stream, info); + negative->PostParse(*host, stream, info); + negative->ReadStage1Image(*host, stream, info); + dng_simple_image *stage2 = (dng_simple_image *)negative->Stage1Image(); + if (stage2->Bounds().W() != S.raw_width || stage2->Bounds().H() != S.raw_height) + { + return LIBRAW_DATA_ERROR; + } + + int pplanes = stage2->Planes(); + int ptype = stage2->PixelType(); + + dng_pixel_buffer buffer; + stage2->GetPixelBuffer(buffer); + + int pixels = stage2->Bounds().H() * stage2->Bounds().W() * pplanes; + if (ptype == ttByte) + imgdata.rawdata.raw_alloc = malloc(pixels * TagTypeSize(ttShort)); + else + imgdata.rawdata.raw_alloc = malloc(pixels * TagTypeSize(ptype)); + + if (ptype == ttShort && !is_curve_linear()) + { + ushort *src = (ushort *)buffer.fData; + ushort *dst = (ushort *)imgdata.rawdata.raw_alloc; + for (int i = 0; i < pixels; i++) + dst[i] = imgdata.color.curve[src[i]]; + S.raw_pitch = S.raw_width * pplanes * TagTypeSize(ptype); + } + else if (ptype == ttByte) + { + unsigned char *src = (unsigned char *)buffer.fData; + ushort *dst = (ushort *)imgdata.rawdata.raw_alloc; + if (is_curve_linear()) + { + for (int i = 0; i < pixels; i++) + dst[i] = src[i]; + } + else + { + for (int i = 0; i < pixels; i++) + dst[i] = imgdata.color.curve[src[i]]; + } + S.raw_pitch = S.raw_width * pplanes * TagTypeSize(ttShort); + } + else + { + memmove(imgdata.rawdata.raw_alloc, buffer.fData, pixels * TagTypeSize(ptype)); + S.raw_pitch = S.raw_width * pplanes * TagTypeSize(ptype); + } + + switch (ptype) + { + case ttFloat: + if (pplanes == 1) + imgdata.rawdata.float_image = (float *)imgdata.rawdata.raw_alloc; + else if (pplanes == 3) + imgdata.rawdata.float3_image = (float(*)[3])imgdata.rawdata.raw_alloc; + else if (pplanes == 4) + imgdata.rawdata.float4_image = (float(*)[4])imgdata.rawdata.raw_alloc; + break; + + case ttByte: + case ttShort: + if (pplanes == 1) + imgdata.rawdata.raw_image = (ushort *)imgdata.rawdata.raw_alloc; + else if (pplanes == 3) + imgdata.rawdata.color3_image = (ushort(*)[3])imgdata.rawdata.raw_alloc; + else if (pplanes == 4) + imgdata.rawdata.color4_image = (ushort(*)[4])imgdata.rawdata.raw_alloc; + break; + default: + /* do nothing */ + break; + } + } + catch (...) + { + return LIBRAW_UNSPECIFIED_ERROR; + } + return imgdata.rawdata.raw_alloc ? LIBRAW_SUCCESS : LIBRAW_UNSPECIFIED_ERROR; #else - return LIBRAW_UNSPECIFIED_ERROR; + return LIBRAW_UNSPECIFIED_ERROR; #endif } void LibRaw::set_dng_host(void *p) { #ifdef USE_DNGSDK - dnghost = p; + dnghost = p; #endif } int LibRaw::unpack(void) { CHECK_ORDER_HIGH(LIBRAW_PROGRESS_LOAD_RAW); CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY); - try { + try + { - if(!libraw_internal_data.internal_data.input) + if (!libraw_internal_data.internal_data.input) return LIBRAW_INPUT_CLOSED; - RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW,0,2); + RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW, 0, 2); if (O.shot_select >= P1.raw_count) return LIBRAW_REQUEST_FOR_NONEXISTENT_IMAGE; - if(!load_raw) + if (!load_raw) return LIBRAW_UNSPECIFIED_ERROR; // already allocated ? - if(imgdata.image) - { - free(imgdata.image); - imgdata.image = 0; - } - if(imgdata.rawdata.raw_alloc) - { - free(imgdata.rawdata.raw_alloc); - imgdata.rawdata.raw_alloc = 0; - } + if (imgdata.image) + { + free(imgdata.image); + imgdata.image = 0; + } + if (imgdata.rawdata.raw_alloc) + { + free(imgdata.rawdata.raw_alloc); + imgdata.rawdata.raw_alloc = 0; + } if (libraw_internal_data.unpacker_data.meta_length) - { - libraw_internal_data.internal_data.meta_data = - (char *) malloc (libraw_internal_data.unpacker_data.meta_length); - merror (libraw_internal_data.internal_data.meta_data, "LibRaw::unpack()"); - } + { + libraw_internal_data.internal_data.meta_data = (char *)malloc(libraw_internal_data.unpacker_data.meta_length); + merror(libraw_internal_data.internal_data.meta_data, "LibRaw::unpack()"); + } libraw_decoder_info_t decoder_info; get_decoder_info(&decoder_info); int save_iwidth = S.iwidth, save_iheight = S.iheight, save_shrink = IO.shrink; int rwidth = S.raw_width, rheight = S.raw_height; - if( !IO.fuji_width) - { - // adjust non-Fuji allocation - if(rwidth < S.width + S.left_margin) - rwidth = S.width + S.left_margin; - if(rheight < S.height + S.top_margin) - rheight = S.height + S.top_margin; - } - if(rwidth > 65535 || rheight > 65535) // No way to make image larger than 64k pix + if (!IO.fuji_width) + { + // adjust non-Fuji allocation + if (rwidth < S.width + S.left_margin) + rwidth = S.width + S.left_margin; + if (rheight < S.height + S.top_margin) + rheight = S.height + S.top_margin; + } + if (rwidth > 65535 || rheight > 65535) // No way to make image larger than 64k pix throw LIBRAW_EXCEPTION_IO_CORRUPT; + imgdata.rawdata.raw_image = 0; imgdata.rawdata.color4_image = 0; imgdata.rawdata.color3_image = 0; - imgdata.rawdata.float_image = 0; - imgdata.rawdata.float3_image = 0; + imgdata.rawdata.float_image = 0; + imgdata.rawdata.float3_image = 0; #ifdef USE_DNGSDK - if(imgdata.idata.dng_version && dnghost && valid_for_dngsdk() && load_raw != &LibRaw::pentax_4shot_load_raw) - { - int rr = try_dngsdk(); - } + if (imgdata.idata.dng_version && dnghost && imgdata.idata.raw_count == 1 && valid_for_dngsdk() && + load_raw != &LibRaw::pentax_4shot_load_raw) + { + // Data size check + INT64 pixcount = INT64(MAX(S.width, S.raw_width)) * INT64(MAX(S.height, S.raw_height)); + INT64 planecount = (imgdata.idata.filters || P1.colors == 1)?1: LIM(P1.colors,3,4); + INT64 samplesize = is_floating_point()?4:2; + INT64 bytes = pixcount * planecount * samplesize; + if(bytes > LIBRAW_MAX_ALLOC_MB * INT64(1024 * 1024)) throw LIBRAW_EXCEPTION_TOOBIG; + + // find ifd to check sample + int rr = try_dngsdk(); + } #endif #ifdef USE_RAWSPEED - if(!raw_was_read()) - { - int rawspeed_enabled = 1; - - if(imgdata.idata.dng_version && libraw_internal_data.unpacker_data.tiff_samples == 2) - rawspeed_enabled = 0; - - if(imgdata.idata.raw_count > 1) - rawspeed_enabled = 0; - - // Disable rawspeed for double-sized Oly files - if(!strncasecmp(imgdata.idata.make,"Olympus",7) && - ( ( imgdata.sizes.raw_width > 6000) || !strncasecmp(imgdata.idata.model,"SH-2",4) || !strncasecmp(imgdata.idata.model,"SH-3",4) || !strncasecmp(imgdata.idata.model,"TG-4",4)) - ) - rawspeed_enabled = 0; - - if(imgdata.idata.dng_version && imgdata.idata.filters==0 && libraw_internal_data.unpacker_data.tiff_bps == 8) // Disable for 8 bit - rawspeed_enabled = 0; - - if(load_raw == &LibRaw::packed_load_raw && !strncasecmp(imgdata.idata.make,"Nikon",5) && !strncasecmp(imgdata.idata.model,"E",1) ) - rawspeed_enabled = 0; - - // RawSpeed Supported, - if(O.use_rawspeed && rawspeed_enabled - && !(is_sraw() && (O.raw_processing_options & (LIBRAW_PROCESSING_SRAW_NO_RGB | LIBRAW_PROCESSING_SRAW_NO_INTERPOLATE))) - && (decoder_info.decoder_flags & LIBRAW_DECODER_TRYRAWSPEED) && _rawspeed_camerameta) - { - int rr = try_rawspeed(); - } - } -#endif - if(!raw_was_read()) //RawSpeed failed or not run + if (!raw_was_read()) + { + int rawspeed_enabled = 1; + + if (imgdata.idata.dng_version && libraw_internal_data.unpacker_data.tiff_samples == 2) + rawspeed_enabled = 0; + + if(libraw_internal_data.unpacker_data.pana_encoding == 5) + rawspeed_enabled = 0; + + if (imgdata.idata.raw_count > 1) + rawspeed_enabled = 0; + if (!strncasecmp(imgdata.idata.software, "Magic", 5)) + rawspeed_enabled = 0; + // Disable rawspeed for double-sized Oly files + if (!strncasecmp(imgdata.idata.make, "Olympus", 7) && + ((imgdata.sizes.raw_width > 6000) || !strncasecmp(imgdata.idata.model, "SH-2", 4) || + !strncasecmp(imgdata.idata.model, "SH-3", 4) || !strncasecmp(imgdata.idata.model, "TG-4", 4) || + !strncasecmp(imgdata.idata.model, "TG-5", 4))) + rawspeed_enabled = 0; + + if (!strncasecmp(imgdata.idata.make, "Canon", 5) && !strcasecmp(imgdata.idata.model, "EOS 6D Mark II")) + rawspeed_enabled = 0; + + if (imgdata.idata.dng_version && imgdata.idata.filters == 0 && + libraw_internal_data.unpacker_data.tiff_bps == 8) // Disable for 8 bit + rawspeed_enabled = 0; + + if (load_raw == &LibRaw::packed_load_raw && !strncasecmp(imgdata.idata.make, "Nikon", 5) && + (!strncasecmp(imgdata.idata.model, "E", 1) || !strncasecmp(imgdata.idata.model, "COOLPIX B", 9))) + rawspeed_enabled = 0; + + // RawSpeed Supported, + if (O.use_rawspeed && rawspeed_enabled && + !(is_sraw() && + (O.raw_processing_options & (LIBRAW_PROCESSING_SRAW_NO_RGB | LIBRAW_PROCESSING_SRAW_NO_INTERPOLATE))) && + (decoder_info.decoder_flags & LIBRAW_DECODER_TRYRAWSPEED) && _rawspeed_camerameta) { - // Not allocated on RawSpeed call, try call LibRaow - int zero_rawimage = 0; - if(decoder_info.decoder_flags & LIBRAW_DECODER_OWNALLOC) - { - // x3f foveon decoder and DNG float - // Do nothing! Decoder will allocate data internally - } - else if(imgdata.idata.filters || P1.colors == 1) // Bayer image or single color -> decode to raw_image - { + INT64 pixcount = INT64(MAX(S.width, S.raw_width)) * INT64(MAX(S.height, S.raw_height)); + INT64 planecount = (imgdata.idata.filters || P1.colors == 1)?1: LIM(P1.colors,3,4); + INT64 bytes = pixcount * planecount * 2; // sample size is always 2 for rawspeed + if(bytes > LIBRAW_MAX_ALLOC_MB * INT64(1024 * 1024)) throw LIBRAW_EXCEPTION_TOOBIG; - if(INT64(rwidth)*INT64(rheight+8)*sizeof(imgdata.rawdata.raw_image[0]) > LIBRAW_MAX_ALLOC_MB * INT64(1024*1024)) - throw LIBRAW_EXCEPTION_ALLOC; - - imgdata.rawdata.raw_alloc = malloc(rwidth*(rheight+8)*sizeof(imgdata.rawdata.raw_image[0])); - imgdata.rawdata.raw_image = (ushort*) imgdata.rawdata.raw_alloc; - if(!S.raw_pitch) - S.raw_pitch = S.raw_width*2; // Bayer case, not set before - } - else // NO LEGACY FLAG if (decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY) - { - // sRAW and old Foveon decoders only, so extra buffer size is just 1/4 - S.iwidth = S.width; - S.iheight= S.height; - IO.shrink = 0; - if(!S.raw_pitch) - S.raw_pitch = (decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY_WITH_MARGINS) ? S.raw_width*8 : S.width*8; - // allocate image as temporary buffer, size - imgdata.rawdata.raw_alloc = 0; - if(INT64(MAX(S.width,S.raw_width))*INT64(MAX(S.height,S.raw_height))*sizeof(*imgdata.image) > LIBRAW_MAX_ALLOC_MB * INT64(1024*1024)) - throw LIBRAW_EXCEPTION_ALLOC; - - imgdata.image = (ushort (*)[4]) calloc(unsigned(MAX(S.width,S.raw_width))*unsigned(MAX(S.height,S.raw_height)),sizeof(*imgdata.image)); - if(!(decoder_info.decoder_flags & LIBRAW_DECODER_ADOBECOPYPIXEL)) - { - imgdata.rawdata.raw_image = (ushort*) imgdata.image ; - zero_rawimage = 1; - } - } - ID.input->seek(libraw_internal_data.unpacker_data.data_offset, SEEK_SET); - - unsigned m_save = C.maximum; - if(load_raw == &LibRaw::unpacked_load_raw && !strcasecmp(imgdata.idata.make,"Nikon")) - C.maximum=65535; - (this->*load_raw)(); - if(zero_rawimage) - imgdata.rawdata.raw_image = 0; - if(load_raw == &LibRaw::unpacked_load_raw && !strcasecmp(imgdata.idata.make,"Nikon")) - C.maximum = m_save; - if(decoder_info.decoder_flags & LIBRAW_DECODER_OWNALLOC) - { - // x3f foveon decoder only: do nothing + int rr = try_rawspeed(); + } + } +#endif + if (!raw_was_read()) // RawSpeed failed or not run + { + // Not allocated on RawSpeed call, try call LibRaow + int zero_rawimage = 0; + if (decoder_info.decoder_flags & LIBRAW_DECODER_OWNALLOC) + { + // x3f foveon decoder and DNG float + // Do nothing! Decoder will allocate data internally + } + if (decoder_info.decoder_flags & LIBRAW_DECODER_3CHANNEL) + { + if (INT64(rwidth) * INT64(rheight + 8) * sizeof(imgdata.rawdata.raw_image[0]) * 3 > + LIBRAW_MAX_ALLOC_MB * INT64(1024 * 1024)) + throw LIBRAW_EXCEPTION_TOOBIG; + + imgdata.rawdata.raw_alloc = malloc(rwidth * (rheight + 8) * sizeof(imgdata.rawdata.raw_image[0]) * 3); + imgdata.rawdata.color3_image = (ushort(*)[3])imgdata.rawdata.raw_alloc; + if (!S.raw_pitch) + S.raw_pitch = S.raw_width * 6; + } + else if (imgdata.idata.filters || P1.colors == 1) // Bayer image or single color -> decode to raw_image + { + if (INT64(rwidth) * INT64(rheight + 8) * sizeof(imgdata.rawdata.raw_image[0]) > + LIBRAW_MAX_ALLOC_MB * INT64(1024 * 1024)) + throw LIBRAW_EXCEPTION_TOOBIG; + imgdata.rawdata.raw_alloc = malloc(rwidth * (rheight + 8) * sizeof(imgdata.rawdata.raw_image[0])); + imgdata.rawdata.raw_image = (ushort *)imgdata.rawdata.raw_alloc; + if (!S.raw_pitch) + S.raw_pitch = S.raw_width * 2; // Bayer case, not set before + } + else // NO LEGACY FLAG if (decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY) + { + if (decoder_info.decoder_flags & LIBRAW_DECODER_ADOBECOPYPIXEL) + { + S.raw_pitch = S.raw_width * 8; + } + else + { + S.iwidth = S.width; + S.iheight = S.height; + IO.shrink = 0; + if (!S.raw_pitch) + S.raw_pitch = + (decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY_WITH_MARGINS) ? S.raw_width * 8 : S.width * 8; + } + // sRAW and old Foveon decoders only, so extra buffer size is just 1/4 + // allocate image as temporary buffer, size + if (INT64(MAX(S.width, S.raw_width)) * INT64(MAX(S.height, S.raw_height)+8) * sizeof(*imgdata.image) > + LIBRAW_MAX_ALLOC_MB * INT64(1024 * 1024)) + throw LIBRAW_EXCEPTION_TOOBIG; - } - else if (!(imgdata.idata.filters || P1.colors == 1) ) // legacy decoder, ownalloc handled above - { - // successfully decoded legacy image, attach image to raw_alloc - imgdata.rawdata.raw_alloc = imgdata.image; - imgdata.rawdata.color4_image = (ushort (*)[4]) imgdata.rawdata.raw_alloc; - imgdata.image = 0; - // Restore saved values. Note: Foveon have masked frame - // Other 4-color legacy data: no borders - if(!(libraw_internal_data.unpacker_data.load_flags & 256)) - { - S.raw_width = S.width; - S.left_margin = 0; - S.raw_height = S.height; - S.top_margin = 0; - } - } + imgdata.rawdata.raw_alloc = 0; + imgdata.image = (ushort(*)[4])calloc( + unsigned(MAX(S.width, S.raw_width)) * unsigned(MAX(S.height, S.raw_height)+8), sizeof(*imgdata.image)); + if (!(decoder_info.decoder_flags & LIBRAW_DECODER_ADOBECOPYPIXEL)) + { + imgdata.rawdata.raw_image = (ushort *)imgdata.image; + zero_rawimage = 1; + } + } + ID.input->seek(libraw_internal_data.unpacker_data.data_offset, SEEK_SET); + + unsigned m_save = C.maximum; + if (load_raw == &LibRaw::unpacked_load_raw && !strcasecmp(imgdata.idata.make, "Nikon")) + C.maximum = 65535; + (this->*load_raw)(); + if (zero_rawimage) + imgdata.rawdata.raw_image = 0; + if (load_raw == &LibRaw::unpacked_load_raw && !strcasecmp(imgdata.idata.make, "Nikon")) + C.maximum = m_save; + if (decoder_info.decoder_flags & LIBRAW_DECODER_OWNALLOC) + { + // x3f foveon decoder only: do nothing + } + else if (!(imgdata.idata.filters || P1.colors == 1)) // legacy decoder, ownalloc handled above + { + // successfully decoded legacy image, attach image to raw_alloc + imgdata.rawdata.raw_alloc = imgdata.image; + imgdata.rawdata.color4_image = (ushort(*)[4])imgdata.rawdata.raw_alloc; + imgdata.image = 0; + // Restore saved values. Note: Foveon have masked frame + // Other 4-color legacy data: no borders + if (!(libraw_internal_data.unpacker_data.load_flags & 256) && + !(decoder_info.decoder_flags & LIBRAW_DECODER_ADOBECOPYPIXEL) && + !(decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY_WITH_MARGINS)) + { + S.raw_width = S.width; + S.left_margin = 0; + S.raw_height = S.height; + S.top_margin = 0; + } } + } - if(imgdata.rawdata.raw_image) + if (imgdata.rawdata.raw_image) crop_masked_pixels(); // calculate black levels // recover image sizes S.iwidth = save_iwidth; S.iheight = save_iheight; IO.shrink = save_shrink; // adjust black to possible maximum unsigned int i = C.cblack[3]; unsigned int c; - for(c=0;c<3;c++) - if (i > C.cblack[c]) i = C.cblack[c]; - for (c=0;c<4;c++) + for (c = 0; c < 3; c++) + if (i > C.cblack[c]) + i = C.cblack[c]; + for (c = 0; c < 4; c++) C.cblack[c] -= i; C.black += i; // Save color,sizes and internal data into raw_image fields - memmove(&imgdata.rawdata.color,&imgdata.color,sizeof(imgdata.color)); - memmove(&imgdata.rawdata.sizes,&imgdata.sizes,sizeof(imgdata.sizes)); - memmove(&imgdata.rawdata.iparams,&imgdata.idata,sizeof(imgdata.idata)); - memmove(&imgdata.rawdata.ioparams,&libraw_internal_data.internal_output_params,sizeof(libraw_internal_data.internal_output_params)); + memmove(&imgdata.rawdata.color, &imgdata.color, sizeof(imgdata.color)); + memmove(&imgdata.rawdata.sizes, &imgdata.sizes, sizeof(imgdata.sizes)); + memmove(&imgdata.rawdata.iparams, &imgdata.idata, sizeof(imgdata.idata)); + memmove(&imgdata.rawdata.ioparams, &libraw_internal_data.internal_output_params, + sizeof(libraw_internal_data.internal_output_params)); SET_PROC_FLAG(LIBRAW_PROGRESS_LOAD_RAW); - RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW,1,2); + RUN_CALLBACK(LIBRAW_PROGRESS_LOAD_RAW, 1, 2); return 0; } - catch ( LibRaw_exceptions err) { + catch (LibRaw_exceptions err) + { EXCEPTION_HANDLER(err); } - catch (std::exception ee) { + catch (std::exception ee) + { EXCEPTION_HANDLER(LIBRAW_EXCEPTION_IO_CORRUPT); } } void LibRaw::unpacked_load_raw_fuji_f700s20() { int base_offset = 0; int row_size = imgdata.sizes.raw_width * 2; // in bytes - if(imgdata.idata.raw_count==2 && imgdata.params.shot_select) - { - libraw_internal_data.internal_data.input->seek(-row_size,SEEK_CUR); - base_offset = row_size; // in bytes - } - unsigned char *buffer = (unsigned char*)malloc(row_size*2); - for(int row = 0; row < imgdata.sizes.raw_height; row++) - { - read_shorts((ushort*)buffer,imgdata.sizes.raw_width * 2); - memmove(&imgdata.rawdata.raw_image[row*imgdata.sizes.raw_pitch/2],buffer+base_offset,row_size); - } + if (imgdata.idata.raw_count == 2 && imgdata.params.shot_select) + { + libraw_internal_data.internal_data.input->seek(-row_size, SEEK_CUR); + base_offset = row_size; // in bytes + } + unsigned char *buffer = (unsigned char *)malloc(row_size * 2); + for (int row = 0; row < imgdata.sizes.raw_height; row++) + { + read_shorts((ushort *)buffer, imgdata.sizes.raw_width * 2); + memmove(&imgdata.rawdata.raw_image[row * imgdata.sizes.raw_pitch / 2], buffer + base_offset, row_size); + } free(buffer); } void LibRaw::nikon_load_sraw() { // We're already seeked to data! - unsigned char *rd = (unsigned char *)malloc(3*(imgdata.sizes.raw_width+2)); - if(!rd) throw LIBRAW_EXCEPTION_ALLOC; - try { - int row,col; - for(row = 0; row < imgdata.sizes.raw_height; row++) + unsigned char *rd = (unsigned char *)malloc(3 * (imgdata.sizes.raw_width + 2)); + if (!rd) + throw LIBRAW_EXCEPTION_ALLOC; + try + { + int row, col; + for (row = 0; row < imgdata.sizes.raw_height; row++) + { + checkCancel(); + libraw_internal_data.internal_data.input->read(rd, 3, imgdata.sizes.raw_width); + for (col = 0; col < imgdata.sizes.raw_width - 1; col += 2) { - checkCancel(); - libraw_internal_data.internal_data.input->read(rd,3,imgdata.sizes.raw_width); - for(col = 0; col < imgdata.sizes.raw_width-1;col+=2) - { - int bi = col*3; - ushort bits1 = (rd[bi+1] &0xf)<<8| rd[bi]; // 3,0,1 - ushort bits2 = rd[bi+2] << 4 | ((rd[bi+1]>>4)& 0xf); //452 - ushort bits3 = ((rd[bi+4] & 0xf)<<8) | rd[bi+3]; // 967 - ushort bits4 = rd[bi+5] << 4 | ((rd[bi+4]>>4)& 0xf); // ab8 - imgdata.image[row*imgdata.sizes.raw_width+col][0]=bits1; - imgdata.image[row*imgdata.sizes.raw_width+col][1]=bits3; - imgdata.image[row*imgdata.sizes.raw_width+col][2]=bits4; - imgdata.image[row*imgdata.sizes.raw_width+col+1][0]=bits2; - imgdata.image[row*imgdata.sizes.raw_width+col+1][1]=2048; - imgdata.image[row*imgdata.sizes.raw_width+col+1][2]=2048; - } + int bi = col * 3; + ushort bits1 = (rd[bi + 1] & 0xf) << 8 | rd[bi]; // 3,0,1 + ushort bits2 = rd[bi + 2] << 4 | ((rd[bi + 1] >> 4) & 0xf); // 452 + ushort bits3 = ((rd[bi + 4] & 0xf) << 8) | rd[bi + 3]; // 967 + ushort bits4 = rd[bi + 5] << 4 | ((rd[bi + 4] >> 4) & 0xf); // ab8 + imgdata.image[row * imgdata.sizes.raw_width + col][0] = bits1; + imgdata.image[row * imgdata.sizes.raw_width + col][1] = bits3; + imgdata.image[row * imgdata.sizes.raw_width + col][2] = bits4; + imgdata.image[row * imgdata.sizes.raw_width + col + 1][0] = bits2; + imgdata.image[row * imgdata.sizes.raw_width + col + 1][1] = 2048; + imgdata.image[row * imgdata.sizes.raw_width + col + 1][2] = 2048; } - }catch (...) { + } + } + catch (...) + { free(rd); - throw ; + throw; } free(rd); C.maximum = 0xfff; // 12 bit? - if(imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SRAW_NO_INTERPOLATE) - { - return; // no CbCr interpolation - } + if (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_SRAW_NO_INTERPOLATE) + { + return; // no CbCr interpolation + } // Interpolate CC channels - int row,col; - for(row = 0; row < imgdata.sizes.raw_height; row++) + int row, col; + for (row = 0; row < imgdata.sizes.raw_height; row++) + { + checkCancel(); // will throw out + for (col = 0; col < imgdata.sizes.raw_width; col += 2) { - checkCancel(); // will throw out - for(col = 0; col < imgdata.sizes.raw_width;col+=2) - { - int col2 = col1.f) Y = 1.f; - if(Y>0.803f) Ch2 = Ch3 = 0.5f; - float r = Y + 1.40200f*(Ch3 - 0.5f); - if(r<0.f) r=0.f; - if(r>1.f) r=1.f; - float g = Y - 0.34414f*(Ch2-0.5f) - 0.71414*(Ch3 - 0.5f) ; - if(g>1.f) g = 1.f; - if(g<0.f) g = 0.f; - float b = Y + 1.77200*(Ch2-0.5f); - if(b>1.f) b = 1.f; - if(b<0.f) b = 0.f; - imgdata.image[row*imgdata.sizes.raw_width+col][0]=imgdata.color.curve[int(r*3072.f)]; - imgdata.image[row*imgdata.sizes.raw_width+col][1]=imgdata.color.curve[int(g*3072.f)]; - imgdata.image[row*imgdata.sizes.raw_width+col][2]=imgdata.color.curve[int(b*3072.f)]; - } + float Y = float(imgdata.image[row * imgdata.sizes.raw_width + col][0]) / 2549.f; + float Ch2 = float(imgdata.image[row * imgdata.sizes.raw_width + col][1] - 1280) / 1536.f; + float Ch3 = float(imgdata.image[row * imgdata.sizes.raw_width + col][2] - 1280) / 1536.f; + if (Y > 1.f) + Y = 1.f; + if (Y > 0.803f) + Ch2 = Ch3 = 0.5f; + float r = Y + 1.40200f * (Ch3 - 0.5f); + if (r < 0.f) + r = 0.f; + if (r > 1.f) + r = 1.f; + float g = Y - 0.34414f * (Ch2 - 0.5f) - 0.71414 * (Ch3 - 0.5f); + if (g > 1.f) + g = 1.f; + if (g < 0.f) + g = 0.f; + float b = Y + 1.77200 * (Ch2 - 0.5f); + if (b > 1.f) + b = 1.f; + if (b < 0.f) + b = 0.f; + imgdata.image[row * imgdata.sizes.raw_width + col][0] = imgdata.color.curve[int(r * 3072.f)]; + imgdata.image[row * imgdata.sizes.raw_width + col][1] = imgdata.color.curve[int(g * 3072.f)]; + imgdata.image[row * imgdata.sizes.raw_width + col][2] = imgdata.color.curve[int(b * 3072.f)]; } - C.maximum=16383; + } + C.maximum = 16383; } void LibRaw::free_image(void) { - if(imgdata.image) - { - free(imgdata.image); - imgdata.image = 0; - imgdata.progress_flags - = LIBRAW_PROGRESS_START|LIBRAW_PROGRESS_OPEN - |LIBRAW_PROGRESS_IDENTIFY|LIBRAW_PROGRESS_SIZE_ADJUST|LIBRAW_PROGRESS_LOAD_RAW; - } + if (imgdata.image) + { + free(imgdata.image); + imgdata.image = 0; + imgdata.progress_flags = LIBRAW_PROGRESS_START | LIBRAW_PROGRESS_OPEN | LIBRAW_PROGRESS_IDENTIFY | + LIBRAW_PROGRESS_SIZE_ADJUST | LIBRAW_PROGRESS_LOAD_RAW; + } } - void LibRaw::raw2image_start() { // restore color,sizes and internal data into raw_image fields - memmove(&imgdata.color,&imgdata.rawdata.color,sizeof(imgdata.color)); - memmove(&imgdata.sizes,&imgdata.rawdata.sizes,sizeof(imgdata.sizes)); - memmove(&imgdata.idata,&imgdata.rawdata.iparams,sizeof(imgdata.idata)); - memmove(&libraw_internal_data.internal_output_params,&imgdata.rawdata.ioparams,sizeof(libraw_internal_data.internal_output_params)); + memmove(&imgdata.color, &imgdata.rawdata.color, sizeof(imgdata.color)); + memmove(&imgdata.sizes, &imgdata.rawdata.sizes, sizeof(imgdata.sizes)); + memmove(&imgdata.idata, &imgdata.rawdata.iparams, sizeof(imgdata.idata)); + memmove(&libraw_internal_data.internal_output_params, &imgdata.rawdata.ioparams, + sizeof(libraw_internal_data.internal_output_params)); if (O.user_flip >= 0) S.flip = O.user_flip; - switch ((S.flip+3600) % 360) - { - case 270: S.flip = 5; break; - case 180: S.flip = 3; break; - case 90: S.flip = 6; break; - } + switch ((S.flip + 3600) % 360) + { + case 270: + S.flip = 5; + break; + case 180: + S.flip = 3; + break; + case 90: + S.flip = 6; + break; + } // adjust for half mode! - IO.shrink = P1.filters && (O.half_size || - ((O.threshold || O.aber[0] != 1 || O.aber[2] != 1) )); + IO.shrink = P1.filters && (O.half_size || ((O.threshold || O.aber[0] != 1 || O.aber[2] != 1))); S.iheight = (S.height + IO.shrink) >> IO.shrink; - S.iwidth = (S.width + IO.shrink) >> IO.shrink; - + S.iwidth = (S.width + IO.shrink) >> IO.shrink; } int LibRaw::is_phaseone_compressed() { return (load_raw == &LibRaw::phase_one_load_raw_c || load_raw == &LibRaw::phase_one_load_raw); } -int LibRaw::is_canon_600() -{ - return load_raw == &LibRaw::canon_600_load_raw; -} +int LibRaw::is_canon_600() { return load_raw == &LibRaw::canon_600_load_raw; } int LibRaw::raw2image(void) { CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW); - try { + try + { raw2image_start(); if (is_phaseone_compressed()) + { + phase_one_allocate_tempbuffer(); + int rc = phase_one_subtract_black((ushort *)imgdata.rawdata.raw_alloc, imgdata.rawdata.raw_image); + if (rc == 0) + rc = phase_one_correct(); + if (rc != 0) { - phase_one_allocate_tempbuffer(); - int rc = phase_one_subtract_black((ushort*)imgdata.rawdata.raw_alloc,imgdata.rawdata.raw_image); - if(rc == 0) - rc = phase_one_correct(); - if(rc!=0) - { - phase_one_free_tempbuffer(); - return rc; - } + phase_one_free_tempbuffer(); + return rc; } + } // free and re-allocate image bitmap - if(imgdata.image) - { - imgdata.image = (ushort (*)[4]) realloc (imgdata.image,S.iheight*S.iwidth *sizeof (*imgdata.image)); - memset(imgdata.image,0,S.iheight*S.iwidth *sizeof (*imgdata.image)); - } + if (imgdata.image) + { + imgdata.image = (ushort(*)[4])realloc(imgdata.image, S.iheight * S.iwidth * sizeof(*imgdata.image)); + memset(imgdata.image, 0, S.iheight * S.iwidth * sizeof(*imgdata.image)); + } else - imgdata.image = (ushort (*)[4]) calloc (S.iheight*S.iwidth, sizeof (*imgdata.image)); + imgdata.image = (ushort(*)[4])calloc(S.iheight * S.iwidth, sizeof(*imgdata.image)); - merror (imgdata.image, "raw2image()"); + merror(imgdata.image, "raw2image()"); libraw_decoder_info_t decoder_info; get_decoder_info(&decoder_info); // Move saved bitmap to imgdata.image - if( imgdata.idata.filters || P1.colors == 1) + if (imgdata.idata.filters || P1.colors == 1) + { + if (IO.fuji_width) { - if (IO.fuji_width) { - unsigned r,c; - int row,col; - for (row=0; row < S.raw_height-S.top_margin*2; row++) { - for (col=0; col < IO.fuji_width << !libraw_internal_data.unpacker_data.fuji_layout; col++) { - if (libraw_internal_data.unpacker_data.fuji_layout) { - r = IO.fuji_width - 1 - col + (row >> 1); - c = col + ((row+1) >> 1); - } else { - r = IO.fuji_width - 1 + row - (col >> 1); - c = row + ((col+1) >> 1); - } - if (r < S.height && c < S.width) - imgdata.image[((r)>>IO.shrink)*S.iwidth+((c)>>IO.shrink)][FC(r,c)] - = imgdata.rawdata.raw_image[(row+S.top_margin)*S.raw_pitch/2+(col+S.left_margin)]; + unsigned r, c; + int row, col; + for (row = 0; row < S.raw_height - S.top_margin * 2; row++) + { + for (col = 0; col < IO.fuji_width << !libraw_internal_data.unpacker_data.fuji_layout; col++) + { + if (libraw_internal_data.unpacker_data.fuji_layout) + { + r = IO.fuji_width - 1 - col + (row >> 1); + c = col + ((row + 1) >> 1); + } + else + { + r = IO.fuji_width - 1 + row - (col >> 1); + c = row + ((col + 1) >> 1); } + if (r < S.height && c < S.width) + imgdata.image[((r) >> IO.shrink) * S.iwidth + ((c) >> IO.shrink)][FC(r, c)] = + imgdata.rawdata.raw_image[(row + S.top_margin) * S.raw_pitch / 2 + (col + S.left_margin)]; } } - else { - int row,col; - for (row=0; row < S.height; row++) - for (col=0; col < S.width; col++) - imgdata.image[((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)][fcol(row,col)] - = imgdata.rawdata.raw_image[(row+S.top_margin)*S.raw_pitch/2+(col+S.left_margin)]; - } } + else + { + int row, col; + for (row = 0; row < S.height; row++) + for (col = 0; col < S.width; col++) + imgdata.image[((row) >> IO.shrink) * S.iwidth + ((col) >> IO.shrink)][fcol(row, col)] = + imgdata.rawdata.raw_image[(row + S.top_margin) * S.raw_pitch / 2 + (col + S.left_margin)]; + } + } else // if(decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY) + { + if (imgdata.rawdata.color4_image) { - if(imgdata.rawdata.color4_image) - { - if(S.width*8 == S.raw_pitch) - memmove(imgdata.image,imgdata.rawdata.color4_image,S.width*S.height*sizeof(*imgdata.image)); - else - { - for(int row = 0; row < S.height; row++) - memmove(&imgdata.image[row*S.width], - &imgdata.rawdata.color4_image[(row+S.top_margin)*S.raw_pitch/8+S.left_margin], - S.width*sizeof(*imgdata.image)); - } - } - else if(imgdata.rawdata.color3_image) - { - unsigned char *c3image = (unsigned char*) imgdata.rawdata.color3_image; - for(int row = 0; row < S.height; row++) - { - ushort (*srcrow)[3] = (ushort (*)[3]) &c3image[(row+S.top_margin)*S.raw_pitch]; - ushort (*dstrow)[4] = (ushort (*)[4]) &imgdata.image[row*S.width]; - for(int col=0; col < S.width; col++) - { - for(int c=0; c< 3; c++) - dstrow[col][c] = srcrow[S.left_margin+col][c]; - dstrow[col][3]=0; - } - } - } + if (S.width * 8 == S.raw_pitch) + memmove(imgdata.image, imgdata.rawdata.color4_image, S.width * S.height * sizeof(*imgdata.image)); else + { + for (int row = 0; row < S.height; row++) + memmove(&imgdata.image[row * S.width], + &imgdata.rawdata.color4_image[(row + S.top_margin) * S.raw_pitch / 8 + S.left_margin], + S.width * sizeof(*imgdata.image)); + } + } + else if (imgdata.rawdata.color3_image) + { + unsigned char *c3image = (unsigned char *)imgdata.rawdata.color3_image; + for (int row = 0; row < S.height; row++) + { + ushort(*srcrow)[3] = (ushort(*)[3]) & c3image[(row + S.top_margin) * S.raw_pitch]; + ushort(*dstrow)[4] = (ushort(*)[4]) & imgdata.image[row * S.width]; + for (int col = 0; col < S.width; col++) { - // legacy decoder, but no data? - throw LIBRAW_EXCEPTION_DECODE_RAW; + for (int c = 0; c < 3; c++) + dstrow[col][c] = srcrow[S.left_margin + col][c]; + dstrow[col][3] = 0; } + } + } + else + { + // legacy decoder, but no data? + throw LIBRAW_EXCEPTION_DECODE_RAW; } + } // Free PhaseOne separate copy allocated at function start if (is_phaseone_compressed()) - { - phase_one_free_tempbuffer(); - } + { + phase_one_free_tempbuffer(); + } // hack - clear later flags! if (load_raw == &CLASS canon_600_load_raw && S.width < S.raw_width) - { - canon_600_correct(); - } + { + canon_600_correct(); + } - imgdata.progress_flags - = LIBRAW_PROGRESS_START|LIBRAW_PROGRESS_OPEN | LIBRAW_PROGRESS_RAW2_IMAGE - |LIBRAW_PROGRESS_IDENTIFY|LIBRAW_PROGRESS_SIZE_ADJUST|LIBRAW_PROGRESS_LOAD_RAW; + imgdata.progress_flags = LIBRAW_PROGRESS_START | LIBRAW_PROGRESS_OPEN | LIBRAW_PROGRESS_RAW2_IMAGE | + LIBRAW_PROGRESS_IDENTIFY | LIBRAW_PROGRESS_SIZE_ADJUST | LIBRAW_PROGRESS_LOAD_RAW; return 0; } - catch ( LibRaw_exceptions err) { + catch (LibRaw_exceptions err) + { EXCEPTION_HANDLER(err); } } void LibRaw::phase_one_allocate_tempbuffer() { // Allocate temp raw_image buffer - imgdata.rawdata.raw_image = (ushort*)malloc(S.raw_pitch*S.raw_height); - merror (imgdata.rawdata.raw_image, "phase_one_prepare_to_correct()"); + imgdata.rawdata.raw_image = (ushort *)malloc(S.raw_pitch * S.raw_height); + merror(imgdata.rawdata.raw_image, "phase_one_prepare_to_correct()"); } void LibRaw::phase_one_free_tempbuffer() { - free(imgdata.rawdata.raw_image); - imgdata.rawdata.raw_image = (ushort*) imgdata.rawdata.raw_alloc; + free(imgdata.rawdata.raw_image); + imgdata.rawdata.raw_image = (ushort *)imgdata.rawdata.raw_alloc; } int LibRaw::phase_one_subtract_black(ushort *src, ushort *dest) { try + { + if (O.user_black < 0 && O.user_cblack[0] <= -1000000 && O.user_cblack[1] <= -1000000 && + O.user_cblack[2] <= -1000000 && O.user_cblack[3] <= -1000000) { - if (O.user_black < 0 && O.user_cblack[0] <= -1000000 && O.user_cblack[1] <= -1000000 && O.user_cblack[2] <= -1000000 && O.user_cblack[3] <= -1000000) + if (!imgdata.rawdata.ph1_cblack || !imgdata.rawdata.ph1_rblack) + { + register int bl = imgdata.color.phase_one_data.t_black; + for (int row = 0; row < S.raw_height; row++) { - if (!imgdata.rawdata.ph1_cblack || !imgdata.rawdata.ph1_rblack) - { - register int bl = imgdata.color.phase_one_data.t_black; - for (int row = 0; row < S.raw_height; row++) - { - checkCancel(); - for (int col = 0; col < S.raw_width; col++) - { - int idx = row*S.raw_width + col; - int val = int(src[idx]) - bl; - dest[idx] = val>0 ? val : 0; - } - } - } - else - { - register int bl = imgdata.color.phase_one_data.t_black; - for (int row = 0; row < S.raw_height; row++) - { - checkCancel(); - for (int col = 0; col < S.raw_width; col++) - { - int idx = row*S.raw_width + col; - int val = int(src[idx]) - bl - + imgdata.rawdata.ph1_cblack[row][col >= imgdata.rawdata.color.phase_one_data.split_col] - + imgdata.rawdata.ph1_rblack[col][row >= imgdata.rawdata.color.phase_one_data.split_row]; - dest[idx] = val>0 ? val : 0; - } - } - } + checkCancel(); + for (int col = 0; col < S.raw_width; col++) + { + int idx = row * S.raw_width + col; + int val = int(src[idx]) - bl; + dest[idx] = val > 0 ? val : 0; + } } - else // black set by user interaction + } + else + { + register int bl = imgdata.color.phase_one_data.t_black; + for (int row = 0; row < S.raw_height; row++) { - // Black level in cblack! - for (int row = 0; row < S.raw_height; row++) - { - checkCancel(); - unsigned short cblk[16]; - for (int cc = 0; cc < 16; cc++) - cblk[cc] = C.cblack[fcol(row, cc)]; - for (int col = 0; col < S.raw_width; col++) - { - int idx = row*S.raw_width + col; - ushort val = src[idx]; - ushort bl = cblk[col & 0xf]; - dest[idx] = val>bl ? val - bl : 0; - } - } + checkCancel(); + for (int col = 0; col < S.raw_width; col++) + { + int idx = row * S.raw_width + col; + int val = int(src[idx]) - bl + + imgdata.rawdata.ph1_cblack[row][col >= imgdata.rawdata.color.phase_one_data.split_col] + + imgdata.rawdata.ph1_rblack[col][row >= imgdata.rawdata.color.phase_one_data.split_row]; + dest[idx] = val > 0 ? val : 0; + } } - return 0; + } + } + else // black set by user interaction + { + // Black level in cblack! + for (int row = 0; row < S.raw_height; row++) + { + checkCancel(); + unsigned short cblk[16]; + for (int cc = 0; cc < 16; cc++) + cblk[cc] = C.cblack[fcol(row, cc)]; + for (int col = 0; col < S.raw_width; col++) + { + int idx = row * S.raw_width + col; + ushort val = src[idx]; + ushort bl = cblk[col & 0xf]; + dest[idx] = val > bl ? val - bl : 0; + } + } } - catch (LibRaw_exceptions err) { + return 0; + } + catch (LibRaw_exceptions err) + { return LIBRAW_CANCELLED_BY_CALLBACK; } } -void LibRaw::copy_fuji_uncropped(unsigned short cblack[4],unsigned short *dmaxp) +void LibRaw::copy_fuji_uncropped(unsigned short cblack[4], unsigned short *dmaxp) { int row; #if defined(LIBRAW_USE_OPENMP) #pragma omp parallel for default(shared) #endif - for (row=0; row < S.raw_height-S.top_margin*2; row++) + for (row = 0; row < S.raw_height - S.top_margin * 2; row++) + { + int col; + unsigned short ldmax = 0; + for (col = 0; col < IO.fuji_width << !libraw_internal_data.unpacker_data.fuji_layout; col++) { - int col; - unsigned short ldmax = 0; - for (col=0; col < IO.fuji_width << !libraw_internal_data.unpacker_data.fuji_layout; col++) + unsigned r, c; + if (libraw_internal_data.unpacker_data.fuji_layout) + { + r = IO.fuji_width - 1 - col + (row >> 1); + c = col + ((row + 1) >> 1); + } + else + { + r = IO.fuji_width - 1 + row - (col >> 1); + c = row + ((col + 1) >> 1); + } + if (r < S.height && c < S.width) + { + unsigned short val = imgdata.rawdata.raw_image[(row + S.top_margin) * S.raw_pitch / 2 + (col + S.left_margin)]; + int cc = FC(r, c); + if (val > cblack[cc]) { - unsigned r,c; - if (libraw_internal_data.unpacker_data.fuji_layout) { - r = IO.fuji_width - 1 - col + (row >> 1); - c = col + ((row+1) >> 1); - } else { - r = IO.fuji_width - 1 + row - (col >> 1); - c = row + ((col+1) >> 1); - } - if (r < S.height && c < S.width) - { - unsigned short val = imgdata.rawdata.raw_image[(row+S.top_margin)*S.raw_pitch/2+(col+S.left_margin)]; - int cc = FC(r,c); - if(val>cblack[cc]) - { - val-=cblack[cc]; - if(val>ldmax)ldmax = val; - } - else - val = 0; - imgdata.image[((r)>>IO.shrink)*S.iwidth+((c)>>IO.shrink)][cc] = val; - } + val -= cblack[cc]; + if (val > ldmax) + ldmax = val; } + else + val = 0; + imgdata.image[((r) >> IO.shrink) * S.iwidth + ((c) >> IO.shrink)][cc] = val; + } + } #if defined(LIBRAW_USE_OPENMP) #pragma omp critical(dataupdate) #endif - { - if(*dmaxp < ldmax) - *dmaxp = ldmax; - } + { + if (*dmaxp < ldmax) + *dmaxp = ldmax; } + } } -void LibRaw::copy_bayer(unsigned short cblack[4],unsigned short *dmaxp) +void LibRaw::copy_bayer(unsigned short cblack[4], unsigned short *dmaxp) { // Both cropped and uncropped int row; #if defined(LIBRAW_USE_OPENMP) #pragma omp parallel for default(shared) #endif - for (row=0; row < S.height; row++) + for (row = 0; row < S.height; row++) + { + int col; + unsigned short ldmax = 0; + for (col = 0; col < S.width; col++) { - int col; - unsigned short ldmax = 0; - for (col=0; col < S.width; col++) - { - unsigned short val = imgdata.rawdata.raw_image[(row+S.top_margin)*S.raw_pitch/2+(col+S.left_margin)]; - int cc = fcol(row,col); - if(val>cblack[cc]) - { - val-=cblack[cc]; - if(val>ldmax)ldmax = val; - } - else - val = 0; - imgdata.image[((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)][cc] = val; - } + unsigned short val = imgdata.rawdata.raw_image[(row + S.top_margin) * S.raw_pitch / 2 + (col + S.left_margin)]; + int cc = fcol(row, col); + if (val > cblack[cc]) + { + val -= cblack[cc]; + if (val > ldmax) + ldmax = val; + } + else + val = 0; + imgdata.image[((row) >> IO.shrink) * S.iwidth + ((col) >> IO.shrink)][cc] = val; + } #if defined(LIBRAW_USE_OPENMP) #pragma omp critical(dataupdate) #endif - { - if(*dmaxp < ldmax) - *dmaxp = ldmax; - } + { + if (*dmaxp < ldmax) + *dmaxp = ldmax; } + } } - int LibRaw::raw2image_ex(int do_subtract_black) { CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW); - try { + try + { raw2image_start(); // Compressed P1 files with bl data! if (is_phaseone_compressed()) + { + phase_one_allocate_tempbuffer(); + int rc = phase_one_subtract_black((ushort *)imgdata.rawdata.raw_alloc, imgdata.rawdata.raw_image); + if (rc == 0) + rc = phase_one_correct(); + if (rc != 0) { - phase_one_allocate_tempbuffer(); - int rc = phase_one_subtract_black((ushort*)imgdata.rawdata.raw_alloc,imgdata.rawdata.raw_image); - if(rc == 0) - rc = phase_one_correct(); - if(rc!=0) - { - phase_one_free_tempbuffer(); - return rc; - } + phase_one_free_tempbuffer(); + return rc; } + } // process cropping int do_crop = 0; unsigned save_width = S.width; - if (~O.cropbox[2] && ~O.cropbox[3] -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 - && load_raw != &LibRaw::foveon_sd_load_raw -#endif - ) // Foveon SD to be cropped later + if (~O.cropbox[2] && ~O.cropbox[3]) + { + int crop[4], c, filt; + for (int c = 0; c < 4; c++) { - int crop[4],c,filt; - for(int c=0;c<4;c++) - { - crop[c] = O.cropbox[c]; - if(crop[c]<0) - crop[c]=0; - } + crop[c] = O.cropbox[c]; + if (crop[c] < 0) + crop[c] = 0; + } - if(IO.fuji_width && imgdata.idata.filters >= 1000) - { - crop[0] = (crop[0]/4)*4; - crop[1] = (crop[1]/4)*4; - if(!libraw_internal_data.unpacker_data.fuji_layout) - { - crop[2]*=sqrt(2.0); - crop[3]/=sqrt(2.0); - } - crop[2] = (crop[2]/4+1)*4; - crop[3] = (crop[3]/4+1)*4; - } - else if (imgdata.idata.filters == 1) - { - crop[0] = (crop[0]/16)*16; - crop[1] = (crop[1]/16)*16; - } - else if(imgdata.idata.filters == LIBRAW_XTRANS) - { - crop[0] = (crop[0]/6)*6; - crop[1] = (crop[1]/6)*6; - } - do_crop = 1; - - crop[2] = MIN (crop[2], (signed) S.width-crop[0]); - crop[3] = MIN (crop[3], (signed) S.height-crop[1]); - if (crop[2] <= 0 || crop[3] <= 0) - throw LIBRAW_EXCEPTION_BAD_CROP; - - // adjust sizes! - S.left_margin+=crop[0]; - S.top_margin+=crop[1]; - S.width=crop[2]; - S.height=crop[3]; - - S.iheight = (S.height + IO.shrink) >> IO.shrink; - S.iwidth = (S.width + IO.shrink) >> IO.shrink; - if(!IO.fuji_width && imgdata.idata.filters && imgdata.idata.filters >= 1000) - { - for (filt=c=0; c < 16; c++) - filt |= FC((c >> 1)+(crop[1]), - (c & 1)+(crop[0])) << c*2; - imgdata.idata.filters = filt; - } + if (IO.fuji_width && imgdata.idata.filters >= 1000) + { + crop[0] = (crop[0] / 4) * 4; + crop[1] = (crop[1] / 4) * 4; + if (!libraw_internal_data.unpacker_data.fuji_layout) + { + crop[2] *= sqrt(2.0); + crop[3] /= sqrt(2.0); + } + crop[2] = (crop[2] / 4 + 1) * 4; + crop[3] = (crop[3] / 4 + 1) * 4; } + else if (imgdata.idata.filters == 1) + { + crop[0] = (crop[0] / 16) * 16; + crop[1] = (crop[1] / 16) * 16; + } + else if (imgdata.idata.filters == LIBRAW_XTRANS) + { + crop[0] = (crop[0] / 6) * 6; + crop[1] = (crop[1] / 6) * 6; + } + do_crop = 1; + + crop[2] = MIN(crop[2], (signed)S.width - crop[0]); + crop[3] = MIN(crop[3], (signed)S.height - crop[1]); + if (crop[2] <= 0 || crop[3] <= 0) + throw LIBRAW_EXCEPTION_BAD_CROP; + + // adjust sizes! + S.left_margin += crop[0]; + S.top_margin += crop[1]; + S.width = crop[2]; + S.height = crop[3]; + + S.iheight = (S.height + IO.shrink) >> IO.shrink; + S.iwidth = (S.width + IO.shrink) >> IO.shrink; + if (!IO.fuji_width && imgdata.idata.filters && imgdata.idata.filters >= 1000) + { + for (filt = c = 0; c < 16; c++) + filt |= FC((c >> 1) + (crop[1]), (c & 1) + (crop[0])) << c * 2; + imgdata.idata.filters = filt; + } + } int alloc_width = S.iwidth; int alloc_height = S.iheight; - if(IO.fuji_width && do_crop) - { - int IO_fw = S.width >> !libraw_internal_data.unpacker_data.fuji_layout; - int t_alloc_width = (S.height >> libraw_internal_data.unpacker_data.fuji_layout) + IO_fw; - int t_alloc_height = t_alloc_width - 1; - alloc_height = (t_alloc_height + IO.shrink) >> IO.shrink; - alloc_width = (t_alloc_width + IO.shrink) >> IO.shrink; - } - int alloc_sz = alloc_width*alloc_height; + if (IO.fuji_width && do_crop) + { + int IO_fw = S.width >> !libraw_internal_data.unpacker_data.fuji_layout; + int t_alloc_width = (S.height >> libraw_internal_data.unpacker_data.fuji_layout) + IO_fw; + int t_alloc_height = t_alloc_width - 1; + alloc_height = (t_alloc_height + IO.shrink) >> IO.shrink; + alloc_width = (t_alloc_width + IO.shrink) >> IO.shrink; + } + int alloc_sz = alloc_width * alloc_height; - if(imgdata.image) - { - imgdata.image = (ushort (*)[4]) realloc (imgdata.image,alloc_sz *sizeof (*imgdata.image)); - memset(imgdata.image,0,alloc_sz *sizeof (*imgdata.image)); - } + if (imgdata.image) + { + imgdata.image = (ushort(*)[4])realloc(imgdata.image, alloc_sz * sizeof(*imgdata.image)); + memset(imgdata.image, 0, alloc_sz * sizeof(*imgdata.image)); + } else - imgdata.image = (ushort (*)[4]) calloc (alloc_sz, sizeof (*imgdata.image)); - merror (imgdata.image, "raw2image_ex()"); + imgdata.image = (ushort(*)[4])calloc(alloc_sz, sizeof(*imgdata.image)); + merror(imgdata.image, "raw2image_ex()"); libraw_decoder_info_t decoder_info; get_decoder_info(&decoder_info); // Adjust black levels - unsigned short cblack[4]={0,0,0,0}; + unsigned short cblack[4] = {0, 0, 0, 0}; unsigned short dmax = 0; - if(do_subtract_black) - { - adjust_bl(); - for(int i=0; i< 4; i++) - cblack[i] = (unsigned short)C.cblack[i]; - } + if (do_subtract_black) + { + adjust_bl(); + for (int i = 0; i < 4; i++) + cblack[i] = (unsigned short)C.cblack[i]; + } // Move saved bitmap to imgdata.image - if(imgdata.idata.filters || P1.colors == 1) - { - if (IO.fuji_width) - { - if(do_crop) - { - IO.fuji_width = S.width >> !libraw_internal_data.unpacker_data.fuji_layout; - int IO_fwidth = (S.height >> libraw_internal_data.unpacker_data.fuji_layout) + IO.fuji_width; - int IO_fheight = IO_fwidth - 1; - - int row,col; - for(row=0;row> 1); - c = col + ((row+1) >> 1); - } else { - r = IO.fuji_width - 1 + row - (col >> 1); - c = row + ((col+1) >> 1); - } - - unsigned short val = imgdata.rawdata.raw_image[(row+S.top_margin)*S.raw_pitch/2 - +(col+S.left_margin)]; - int cc = FCF(row,col); - if(val > cblack[cc]) - { - val-=cblack[cc]; - if(dmax < val) dmax = val; - } - else - val = 0; - imgdata.image[((r) >> IO.shrink)*alloc_width + ((c) >> IO.shrink)][cc] = val; - } - } - S.height = IO_fheight; - S.width = IO_fwidth; - S.iheight = (S.height + IO.shrink) >> IO.shrink; - S.iwidth = (S.width + IO.shrink) >> IO.shrink; - S.raw_height -= 2*S.top_margin; - } - else - { - copy_fuji_uncropped(cblack,&dmax); - } - } // end Fuji - else - { - copy_bayer(cblack,&dmax); - } - } - else //if(decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY) + if (imgdata.idata.filters || P1.colors == 1) + { + if (IO.fuji_width) { - if(imgdata.rawdata.color4_image) + if (do_crop) + { + IO.fuji_width = S.width >> !libraw_internal_data.unpacker_data.fuji_layout; + int IO_fwidth = (S.height >> libraw_internal_data.unpacker_data.fuji_layout) + IO.fuji_width; + int IO_fheight = IO_fwidth - 1; + + int row, col; + for (row = 0; row < S.height; row++) { - if(S.raw_pitch != S.width*8) + for (col = 0; col < S.width; col++) + { + int r, c; + if (libraw_internal_data.unpacker_data.fuji_layout) { - for(int row = 0; row < S.height; row++) - memmove(&imgdata.image[row*S.width], - &imgdata.rawdata.color4_image[(row+S.top_margin)*S.raw_pitch/8+S.left_margin], - S.width*sizeof(*imgdata.image)); + r = IO.fuji_width - 1 - col + (row >> 1); + c = col + ((row + 1) >> 1); } - else + else { - // legacy is always 4channel and not shrinked! - memmove(imgdata.image,imgdata.rawdata.color4_image,S.width*S.height*sizeof(*imgdata.image)); + r = IO.fuji_width - 1 + row - (col >> 1); + c = row + ((col + 1) >> 1); } - } - else if(imgdata.rawdata.color3_image) - { - unsigned char *c3image = (unsigned char*) imgdata.rawdata.color3_image; - for(int row = 0; row < S.height; row++) + + unsigned short val = + imgdata.rawdata.raw_image[(row + S.top_margin) * S.raw_pitch / 2 + (col + S.left_margin)]; + int cc = FCF(row, col); + if (val > cblack[cc]) { - ushort (*srcrow)[3] = (ushort (*)[3]) &c3image[(row+S.top_margin)*S.raw_pitch]; - ushort (*dstrow)[4] = (ushort (*)[4]) &imgdata.image[row*S.width]; - for(int col=0; col < S.width; col++) - { - for(int c=0; c< 3; c++) - dstrow[col][c] = srcrow[S.left_margin+col][c]; - dstrow[col][3]=0; - } + val -= cblack[cc]; + if (dmax < val) + dmax = val; } + else + val = 0; + imgdata.image[((r) >> IO.shrink) * alloc_width + ((c) >> IO.shrink)][cc] = val; + } } + S.height = IO_fheight; + S.width = IO_fwidth; + S.iheight = (S.height + IO.shrink) >> IO.shrink; + S.iwidth = (S.width + IO.shrink) >> IO.shrink; + S.raw_height -= 2 * S.top_margin; + } + else + { + copy_fuji_uncropped(cblack, &dmax); + } + } // end Fuji + else + { + copy_bayer(cblack, &dmax); + } + } + else // if(decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY) + { + if (imgdata.rawdata.color4_image) + { + if (S.raw_pitch != S.width * 8) + { + for (int row = 0; row < S.height; row++) + memmove(&imgdata.image[row * S.width], + &imgdata.rawdata.color4_image[(row + S.top_margin) * S.raw_pitch / 8 + S.left_margin], + S.width * sizeof(*imgdata.image)); + } else + { + // legacy is always 4channel and not shrinked! + memmove(imgdata.image, imgdata.rawdata.color4_image, S.width * S.height * sizeof(*imgdata.image)); + } + } + else if (imgdata.rawdata.color3_image) + { + unsigned char *c3image = (unsigned char *)imgdata.rawdata.color3_image; + for (int row = 0; row < S.height; row++) + { + ushort(*srcrow)[3] = (ushort(*)[3]) & c3image[(row + S.top_margin) * S.raw_pitch]; + ushort(*dstrow)[4] = (ushort(*)[4]) & imgdata.image[row * S.width]; + for (int col = 0; col < S.width; col++) { - // legacy decoder, but no data? - throw LIBRAW_EXCEPTION_DECODE_RAW; + for (int c = 0; c < 3; c++) + dstrow[col][c] = srcrow[S.left_margin + col][c]; + dstrow[col][3] = 0; } + } } + else + { + // legacy decoder, but no data? + throw LIBRAW_EXCEPTION_DECODE_RAW; + } + } // Free PhaseOne separate copy allocated at function start if (is_phaseone_compressed()) - { - phase_one_free_tempbuffer(); - } + { + phase_one_free_tempbuffer(); + } if (load_raw == &CLASS canon_600_load_raw && S.width < S.raw_width) - { - canon_600_correct(); - } + { + canon_600_correct(); + } - if(do_subtract_black) - { - C.data_maximum = (int)dmax; - C.maximum -= C.black; - // ZERO(C.cblack); - C.cblack[0]=C.cblack[1]=C.cblack[2]=C.cblack[3]=0; - C.black = 0; - } + if (do_subtract_black) + { + C.data_maximum = (int)dmax; + C.maximum -= C.black; + // ZERO(C.cblack); + C.cblack[0] = C.cblack[1] = C.cblack[2] = C.cblack[3] = 0; + C.black = 0; + } // hack - clear later flags! - imgdata.progress_flags - = LIBRAW_PROGRESS_START|LIBRAW_PROGRESS_OPEN | LIBRAW_PROGRESS_RAW2_IMAGE - |LIBRAW_PROGRESS_IDENTIFY|LIBRAW_PROGRESS_SIZE_ADJUST|LIBRAW_PROGRESS_LOAD_RAW; + imgdata.progress_flags = LIBRAW_PROGRESS_START | LIBRAW_PROGRESS_OPEN | LIBRAW_PROGRESS_RAW2_IMAGE | + LIBRAW_PROGRESS_IDENTIFY | LIBRAW_PROGRESS_SIZE_ADJUST | LIBRAW_PROGRESS_LOAD_RAW; return 0; } - catch ( LibRaw_exceptions err) { + catch (LibRaw_exceptions err) + { EXCEPTION_HANDLER(err); } } #if 1 -libraw_processed_image_t * LibRaw::dcraw_make_mem_thumb(int *errcode) +libraw_processed_image_t *LibRaw::dcraw_make_mem_thumb(int *errcode) { - if(!T.thumb) + if (!T.thumb) + { + if (!ID.toffset && !(imgdata.thumbnail.tlength > 0 && load_raw == &LibRaw::broadcom_load_raw) // RPi + ) { - if ( !ID.toffset - && !(imgdata.thumbnail.tlength>0 && load_raw == &LibRaw::broadcom_load_raw) // RPi - ) - { - if(errcode) *errcode= LIBRAW_NO_THUMBNAIL; - } - else - { - if(errcode) *errcode= LIBRAW_OUT_OF_ORDER_CALL; - } - return NULL; + if (errcode) + *errcode = LIBRAW_NO_THUMBNAIL; } - - if (T.tformat == LIBRAW_THUMBNAIL_BITMAP) + else { - libraw_processed_image_t * ret = - (libraw_processed_image_t *)::malloc(sizeof(libraw_processed_image_t)+T.tlength); + if (errcode) + *errcode = LIBRAW_OUT_OF_ORDER_CALL; + } + return NULL; + } - if(!ret) - { - if(errcode) *errcode= ENOMEM; - return NULL; - } + if (T.tformat == LIBRAW_THUMBNAIL_BITMAP) + { + libraw_processed_image_t *ret = (libraw_processed_image_t *)::malloc(sizeof(libraw_processed_image_t) + T.tlength); - memset(ret,0,sizeof(libraw_processed_image_t)); - ret->type = LIBRAW_IMAGE_BITMAP; - ret->height = T.theight; - ret->width = T.twidth; - ret->colors = 3; - ret->bits = 8; - ret->data_size = T.tlength; - memmove(ret->data,T.thumb,T.tlength); - if(errcode) *errcode= 0; - return ret; - } - else if (T.tformat == LIBRAW_THUMBNAIL_JPEG) + if (!ret) { - ushort exif[5]; - int mk_exif = 0; - if(strcmp(T.thumb+6,"Exif")) mk_exif = 1; + if (errcode) + *errcode = ENOMEM; + return NULL; + } - int dsize = T.tlength + mk_exif * (sizeof(exif)+sizeof(tiff_hdr)); + memset(ret, 0, sizeof(libraw_processed_image_t)); + ret->type = LIBRAW_IMAGE_BITMAP; + ret->height = T.theight; + ret->width = T.twidth; + ret->colors = 3; + ret->bits = 8; + ret->data_size = T.tlength; + memmove(ret->data, T.thumb, T.tlength); + if (errcode) + *errcode = 0; + return ret; + } + else if (T.tformat == LIBRAW_THUMBNAIL_JPEG) + { + ushort exif[5]; + int mk_exif = 0; + if (strcmp(T.thumb + 6, "Exif")) + mk_exif = 1; - libraw_processed_image_t * ret = - (libraw_processed_image_t *)::malloc(sizeof(libraw_processed_image_t)+dsize); + int dsize = T.tlength + mk_exif * (sizeof(exif) + sizeof(tiff_hdr)); - if(!ret) - { - if(errcode) *errcode= ENOMEM; - return NULL; - } + libraw_processed_image_t *ret = (libraw_processed_image_t *)::malloc(sizeof(libraw_processed_image_t) + dsize); - memset(ret,0,sizeof(libraw_processed_image_t)); + if (!ret) + { + if (errcode) + *errcode = ENOMEM; + return NULL; + } - ret->type = LIBRAW_IMAGE_JPEG; - ret->data_size = dsize; + memset(ret, 0, sizeof(libraw_processed_image_t)); - ret->data[0] = 0xff; - ret->data[1] = 0xd8; - if(mk_exif) - { - struct tiff_hdr th; - memcpy (exif, "\xff\xe1 Exif\0\0", 10); - exif[1] = htons (8 + sizeof th); - memmove(ret->data+2,exif,sizeof(exif)); - tiff_head (&th, 0); - memmove(ret->data+(2+sizeof(exif)),&th,sizeof(th)); - memmove(ret->data+(2+sizeof(exif)+sizeof(th)),T.thumb+2,T.tlength-2); - } - else - { - memmove(ret->data+2,T.thumb+2,T.tlength-2); - } - if(errcode) *errcode= 0; - return ret; + ret->type = LIBRAW_IMAGE_JPEG; + ret->data_size = dsize; + ret->data[0] = 0xff; + ret->data[1] = 0xd8; + if (mk_exif) + { + struct tiff_hdr th; + memcpy(exif, "\xff\xe1 Exif\0\0", 10); + exif[1] = htons(8 + sizeof th); + memmove(ret->data + 2, exif, sizeof(exif)); + tiff_head(&th, 0); + memmove(ret->data + (2 + sizeof(exif)), &th, sizeof(th)); + memmove(ret->data + (2 + sizeof(exif) + sizeof(th)), T.thumb + 2, T.tlength - 2); } - else + else { - if(errcode) *errcode= LIBRAW_UNSUPPORTED_THUMBNAIL; - return NULL; + memmove(ret->data + 2, T.thumb + 2, T.tlength - 2); } + if (errcode) + *errcode = 0; + return ret; + } + else + { + if (errcode) + *errcode = LIBRAW_UNSUPPORTED_THUMBNAIL; + return NULL; + } } - - // jlb // macros for copying pixels to either BGR or RGB formats -#define FORBGR for(c=P1.colors-1; c >=0 ; c--) -#define FORRGB for(c=0; c < P1.colors ; c++) +#define FORBGR for (c = P1.colors - 1; c >= 0; c--) +#define FORRGB for (c = 0; c < P1.colors; c++) -void LibRaw::get_mem_image_format(int* width, int* height, int* colors, int* bps) const +void LibRaw::get_mem_image_format(int *width, int *height, int *colors, int *bps) const { - if (S.flip & 4) { + if (S.flip & 4) + { *width = S.height; *height = S.width; } - else { + else + { *width = S.width; *height = S.height; } *colors = P1.colors; *bps = O.output_bps; } -int LibRaw::copy_mem_image(void* scan0, int stride, int bgr) +int LibRaw::copy_mem_image(void *scan0, int stride, int bgr) { - // the image memory pointed to by scan0 is assumed to be in the format returned by get_mem_image_format - if((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) < LIBRAW_PROGRESS_PRE_INTERPOLATE) - return LIBRAW_OUT_OF_ORDER_CALL; + // the image memory pointed to by scan0 is assumed to be in the format returned by get_mem_image_format + if ((imgdata.progress_flags & LIBRAW_PROGRESS_THUMB_MASK) < LIBRAW_PROGRESS_PRE_INTERPOLATE) + return LIBRAW_OUT_OF_ORDER_CALL; - if(libraw_internal_data.output_data.histogram) + if (libraw_internal_data.output_data.histogram) + { + int perc, val, total, t_white = 0x2000, c; + perc = S.width * S.height * O.auto_bright_thr; + if (IO.fuji_width) + perc /= 2; + if (!((O.highlight & ~2) || O.no_auto_bright)) + for (t_white = c = 0; c < P1.colors; c++) { - int perc, val, total, t_white=0x2000,c; - perc = S.width * S.height * O.auto_bright_thr; - if (IO.fuji_width) perc /= 2; - if (!((O.highlight & ~2) || O.no_auto_bright)) - for (t_white=c=0; c < P1.colors; c++) { - for (val=0x2000, total=0; --val > 32; ) - if ((total += libraw_internal_data.output_data.histogram[c][val]) > perc) break; - if (t_white < val) t_white = val; - } - gamma_curve (O.gamm[0], O.gamm[1], 2, (t_white << 3)/O.bright); + for (val = 0x2000, total = 0; --val > 32;) + if ((total += libraw_internal_data.output_data.histogram[c][val]) > perc) + break; + if (t_white < val) + t_white = val; } + gamma_curve(O.gamm[0], O.gamm[1], 2, (t_white << 3) / O.bright); + } - int s_iheight = S.iheight; - int s_iwidth = S.iwidth; - int s_width = S.width; - int s_hwight = S.height; + int s_iheight = S.iheight; + int s_iwidth = S.iwidth; + int s_width = S.width; + int s_hwight = S.height; - S.iheight = S.height; - S.iwidth = S.width; + S.iheight = S.height; + S.iwidth = S.width; - if (S.flip & 4) SWAP(S.height,S.width); - uchar *ppm; - ushort *ppm2; - int c, row, col, soff, rstep, cstep; + if (S.flip & 4) + SWAP(S.height, S.width); + uchar *ppm; + ushort *ppm2; + int c, row, col, soff, rstep, cstep; - soff = flip_index (0, 0); - cstep = flip_index (0, 1) - soff; - rstep = flip_index (1, 0) - flip_index (0, S.width); + soff = flip_index(0, 0); + cstep = flip_index(0, 1) - soff; + rstep = flip_index(1, 0) - flip_index(0, S.width); - for (row=0; row < S.height; row++, soff += rstep) + for (row = 0; row < S.height; row++, soff += rstep) + { + uchar *bufp = ((uchar *)scan0) + row * stride; + ppm2 = (ushort *)(ppm = bufp); + // keep trivial decisions in the outer loop for speed + if (bgr) + { + if (O.output_bps == 8) { - uchar *bufp = ((uchar*)scan0)+row*stride; - ppm2 = (ushort*) (ppm = bufp); - // keep trivial decisions in the outer loop for speed - if (bgr) { - if (O.output_bps == 8) { - for (col=0; col < S.width; col++, soff += cstep) - FORBGR *ppm++ = imgdata.color.curve[imgdata.image[soff][c]]>>8; - } - else { - for (col=0; col < S.width; col++, soff += cstep) - FORBGR *ppm2++ = imgdata.color.curve[imgdata.image[soff][c]]; - } - } - else { - if (O.output_bps == 8) { - for (col=0; col < S.width; col++, soff += cstep) - FORRGB *ppm++ = imgdata.color.curve[imgdata.image[soff][c]]>>8; - } - else { - for (col=0; col < S.width; col++, soff += cstep) - FORRGB *ppm2++ = imgdata.color.curve[imgdata.image[soff][c]]; - } - } - -// bufp += stride; // go to the next line + for (col = 0; col < S.width; col++, soff += cstep) + FORBGR *ppm++ = imgdata.color.curve[imgdata.image[soff][c]] >> 8; + } + else + { + for (col = 0; col < S.width; col++, soff += cstep) + FORBGR *ppm2++ = imgdata.color.curve[imgdata.image[soff][c]]; + } + } + else + { + if (O.output_bps == 8) + { + for (col = 0; col < S.width; col++, soff += cstep) + FORRGB *ppm++ = imgdata.color.curve[imgdata.image[soff][c]] >> 8; } + else + { + for (col = 0; col < S.width; col++, soff += cstep) + FORRGB *ppm2++ = imgdata.color.curve[imgdata.image[soff][c]]; + } + } - S.iheight = s_iheight; - S.iwidth = s_iwidth; - S.width = s_width; - S.height = s_hwight; - - return 0; + // bufp += stride; // go to the next line + } + S.iheight = s_iheight; + S.iwidth = s_iwidth; + S.width = s_width; + S.height = s_hwight; + return 0; } #undef FORBGR #undef FORRGB - - libraw_processed_image_t *LibRaw::dcraw_make_mem_image(int *errcode) { - int width, height, colors, bps; - get_mem_image_format(&width, &height, &colors, &bps); - int stride = width * (bps/8) * colors; - unsigned ds = height * stride; - libraw_processed_image_t *ret = (libraw_processed_image_t*)::malloc(sizeof(libraw_processed_image_t)+ds); - if(!ret) - { - if(errcode) *errcode= ENOMEM; - return NULL; - } - memset(ret,0,sizeof(libraw_processed_image_t)); + int width, height, colors, bps; + get_mem_image_format(&width, &height, &colors, &bps); + int stride = width * (bps / 8) * colors; + unsigned ds = height * stride; + libraw_processed_image_t *ret = (libraw_processed_image_t *)::malloc(sizeof(libraw_processed_image_t) + ds); + if (!ret) + { + if (errcode) + *errcode = ENOMEM; + return NULL; + } + memset(ret, 0, sizeof(libraw_processed_image_t)); - // metadata init - ret->type = LIBRAW_IMAGE_BITMAP; - ret->height = height; - ret->width = width; - ret->colors = colors; - ret->bits = bps; - ret->data_size = ds; - copy_mem_image(ret->data, stride, 0); + // metadata init + ret->type = LIBRAW_IMAGE_BITMAP; + ret->height = height; + ret->width = width; + ret->colors = colors; + ret->bits = bps; + ret->data_size = ds; + copy_mem_image(ret->data, stride, 0); - return ret; + return ret; } #undef FORC #undef FORCC #undef SWAP #endif - int LibRaw::dcraw_ppm_tiff_writer(const char *filename) { CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW); - if(!imgdata.image) + if (!imgdata.image) return LIBRAW_OUT_OF_ORDER_CALL; - if(!filename) + if (!filename) return ENOENT; - FILE *f = fopen(filename,"wb"); + FILE *f = fopen(filename, "wb"); - if(!f) + if (!f) return errno; - try { - if(!libraw_internal_data.output_data.histogram) - { - libraw_internal_data.output_data.histogram = - (int (*)[LIBRAW_HISTOGRAM_SIZE]) malloc(sizeof(*libraw_internal_data.output_data.histogram)*4); - merror(libraw_internal_data.output_data.histogram,"LibRaw::dcraw_ppm_tiff_writer()"); - } + try + { + if (!libraw_internal_data.output_data.histogram) + { + libraw_internal_data.output_data.histogram = + (int(*)[LIBRAW_HISTOGRAM_SIZE])malloc(sizeof(*libraw_internal_data.output_data.histogram) * 4); + merror(libraw_internal_data.output_data.histogram, "LibRaw::dcraw_ppm_tiff_writer()"); + } libraw_internal_data.internal_data.output = f; write_ppm_tiff(); SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP); libraw_internal_data.internal_data.output = NULL; fclose(f); return 0; } - catch ( LibRaw_exceptions err) { + catch (LibRaw_exceptions err) + { fclose(f); EXCEPTION_HANDLER(err); } } -#define THUMB_READ_BEYOND 16384 +#define THUMB_READ_BEYOND 16384 void LibRaw::kodak_thumb_loader() { - INT64 est_datasize = T.theight * T.twidth / 3; // is 0.3 bytes per pixel good estimate? - if (ID.toffset < 0) - throw LIBRAW_EXCEPTION_IO_CORRUPT; + INT64 est_datasize = T.theight * T.twidth / 3; // is 0.3 bytes per pixel good estimate? + if (ID.toffset < 0) + throw LIBRAW_EXCEPTION_IO_CORRUPT; - if (ID.toffset + est_datasize > ID.input->size() + THUMB_READ_BEYOND) - throw LIBRAW_EXCEPTION_IO_EOF; + if (ID.toffset + est_datasize > ID.input->size() + THUMB_READ_BEYOND) + throw LIBRAW_EXCEPTION_IO_EOF; - // some kodak cameras - ushort s_height = S.height, s_width = S.width,s_iwidth = S.iwidth,s_iheight=S.iheight; + // some kodak cameras + ushort s_height = S.height, s_width = S.width, s_iwidth = S.iwidth, s_iheight = S.iheight; ushort s_flags = libraw_internal_data.unpacker_data.load_flags; libraw_internal_data.unpacker_data.load_flags = 12; int s_colors = P1.colors; unsigned s_filters = P1.filters; - ushort (*s_image)[4] = imgdata.image; + ushort(*s_image)[4] = imgdata.image; S.height = T.theight; - S.width = T.twidth; + S.width = T.twidth; P1.filters = 0; if (thumb_load_raw == &CLASS kodak_ycbcr_load_raw) - { - S.height += S.height & 1; - S.width += S.width & 1; - } + { + S.height += S.height & 1; + S.width += S.width & 1; + } - imgdata.image = (ushort (*)[4]) calloc (S.iheight*S.iwidth, sizeof (*imgdata.image)); - merror (imgdata.image, "LibRaw::kodak_thumb_loader()"); + imgdata.image = (ushort(*)[4])calloc(S.iheight * S.iwidth, sizeof(*imgdata.image)); + merror(imgdata.image, "LibRaw::kodak_thumb_loader()"); ID.input->seek(ID.toffset, SEEK_SET); // read kodak thumbnail into T.image[] - try { - (this->*thumb_load_raw)(); - } catch (...) + try { - free(imgdata.image); - imgdata.image = s_image; + (this->*thumb_load_raw)(); + } + catch (...) + { + free(imgdata.image); + imgdata.image = s_image; - T.twidth = 0; - S.width = s_width; + T.twidth = 0; + S.width = s_width; - S.iwidth = s_iwidth; - S.iheight = s_iheight; + S.iwidth = s_iwidth; + S.iheight = s_iheight; - T.theight = 0; - S.height = s_height; + T.theight = 0; + S.height = s_height; - T.tcolors = 0; - P1.colors = s_colors; + T.tcolors = 0; + P1.colors = s_colors; - P1.filters = s_filters; - T.tlength=0; - libraw_internal_data.unpacker_data.load_flags = s_flags; - return; + P1.filters = s_filters; + T.tlength = 0; + libraw_internal_data.unpacker_data.load_flags = s_flags; + return; } - // copy-n-paste from image pipe -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#define LIM(x,min,max) MAX(min,MIN(x,max)) +// copy-n-paste from image pipe +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define LIM(x, min, max) MAX(min, MIN(x, max)) #ifndef CLIP -#define CLIP(x) LIM(x,0,65535) +#define CLIP(x) LIM(x, 0, 65535) #endif -#define SWAP(a,b) { a ^= b; a ^= (b ^= a); } +#define SWAP(a, b) \ + { \ + a ^= b; \ + a ^= (b ^= a); \ + } // from scale_colors { - double dmax; + double dmax; float scale_mul[4]; - int c,val; - for (dmax=DBL_MAX, c=0; c < 3; c++) + int c, val; + for (dmax = DBL_MAX, c = 0; c < 3; c++) if (dmax > C.pre_mul[c]) dmax = C.pre_mul[c]; - for( c=0; c< 3; c++) + for (c = 0; c < 3; c++) scale_mul[c] = (C.pre_mul[c] / dmax) * 65535.0 / C.maximum; scale_mul[3] = scale_mul[1]; size_t size = S.height * S.width; - for (unsigned i=0; i < size*4 ; i++) - { - val = imgdata.image[0][i]; - if(!val) continue; - val *= scale_mul[i & 3]; - imgdata.image[0][i] = CLIP(val); - } + for (unsigned i = 0; i < size * 4; i++) + { + val = imgdata.image[0][i]; + if (!val) + continue; + val *= scale_mul[i & 3]; + imgdata.image[0][i] = CLIP(val); + } } // from convert_to_rgb ushort *img; - int row,col; + int row, col; - int (*t_hist)[LIBRAW_HISTOGRAM_SIZE] = (int (*)[LIBRAW_HISTOGRAM_SIZE]) calloc(sizeof(*t_hist),4); - merror (t_hist, "LibRaw::kodak_thumb_loader()"); + int(*t_hist)[LIBRAW_HISTOGRAM_SIZE] = (int(*)[LIBRAW_HISTOGRAM_SIZE])calloc(sizeof(*t_hist), 4); + merror(t_hist, "LibRaw::kodak_thumb_loader()"); - float out[3], - out_cam[3][4] = - { - {2.81761312, -1.98369181, 0.166078627, 0}, - {-0.111855984, 1.73688626, -0.625030339, 0}, - {-0.0379119813, -0.891268849, 1.92918086, 0} - }; + float out[3], out_cam[3][4] = {{2.81761312, -1.98369181, 0.166078627, 0}, + {-0.111855984, 1.73688626, -0.625030339, 0}, + {-0.0379119813, -0.891268849, 1.92918086, 0}}; - for (img=imgdata.image[0], row=0; row < S.height; row++) - for (col=0; col < S.width; col++, img+=4) + for (img = imgdata.image[0], row = 0; row < S.height; row++) + for (col = 0; col < S.width; col++, img += 4) + { + out[0] = out[1] = out[2] = 0; + int c; + for (c = 0; c < 3; c++) { - out[0] = out[1] = out[2] = 0; - int c; - for(c=0;c<3;c++) - { - out[0] += out_cam[0][c] * img[c]; - out[1] += out_cam[1][c] * img[c]; - out[2] += out_cam[2][c] * img[c]; - } - for(c=0; c<3; c++) - img[c] = CLIP((int) out[c]); - for(c=0; c> 3]++; - + out[0] += out_cam[0][c] * img[c]; + out[1] += out_cam[1][c] * img[c]; + out[2] += out_cam[2][c] * img[c]; } + for (c = 0; c < 3; c++) + img[c] = CLIP((int)out[c]); + for (c = 0; c < P1.colors; c++) + t_hist[c][img[c] >> 3]++; + } // from gamma_lut - int (*save_hist)[LIBRAW_HISTOGRAM_SIZE] = libraw_internal_data.output_data.histogram; + int(*save_hist)[LIBRAW_HISTOGRAM_SIZE] = libraw_internal_data.output_data.histogram; libraw_internal_data.output_data.histogram = t_hist; // make curve output curve! - ushort (*t_curve) = (ushort*) calloc(sizeof(C.curve),1); - merror (t_curve, "LibRaw::kodak_thumb_loader()"); - memmove(t_curve,C.curve,sizeof(C.curve)); - memset(C.curve,0,sizeof(C.curve)); + ushort(*t_curve) = (ushort *)calloc(sizeof(C.curve), 1); + merror(t_curve, "LibRaw::kodak_thumb_loader()"); + memmove(t_curve, C.curve, sizeof(C.curve)); + memset(C.curve, 0, sizeof(C.curve)); { - int perc, val, total, t_white=0x2000,c; + int perc, val, total, t_white = 0x2000, c; - perc = S.width * S.height * 0.01; /* 99th percentile white level */ - if (IO.fuji_width) perc /= 2; + perc = S.width * S.height * 0.01; /* 99th percentile white level */ + if (IO.fuji_width) + perc /= 2; if (!((O.highlight & ~2) || O.no_auto_bright)) - for (t_white=c=0; c < P1.colors; c++) { - for (val=0x2000, total=0; --val > 32; ) - if ((total += libraw_internal_data.output_data.histogram[c][val]) > perc) break; - if (t_white < val) t_white = val; + for (t_white = c = 0; c < P1.colors; c++) + { + for (val = 0x2000, total = 0; --val > 32;) + if ((total += libraw_internal_data.output_data.histogram[c][val]) > perc) + break; + if (t_white < val) + t_white = val; } - gamma_curve (O.gamm[0], O.gamm[1], 2, (t_white << 3)/O.bright); + gamma_curve(O.gamm[0], O.gamm[1], 2, (t_white << 3) / O.bright); } libraw_internal_data.output_data.histogram = save_hist; free(t_hist); // from write_ppm_tiff - copy pixels into bitmap - S.iheight = S.height; - S.iwidth = S.width; - if (S.flip & 4) SWAP(S.height,S.width); + int s_flip = imgdata.sizes.flip; + if (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_NO_ROTATE_FOR_KODAK_THUMBNAILS) + imgdata.sizes.flip = 0; - if(T.thumb) free(T.thumb); - T.thumb = (char*) calloc (S.width * S.height, P1.colors); - merror (T.thumb, "LibRaw::kodak_thumb_loader()"); + S.iheight = S.height; + S.iwidth = S.width; + if (S.flip & 4) + SWAP(S.height, S.width); + + if (T.thumb) + free(T.thumb); + T.thumb = (char *)calloc(S.width * S.height, P1.colors); + merror(T.thumb, "LibRaw::kodak_thumb_loader()"); T.tlength = S.width * S.height * P1.colors; -// from write_tiff_ppm + // from write_tiff_ppm { - int soff = flip_index(0, 0); - int cstep = flip_index(0, 1) - soff; - int rstep = flip_index(1, 0) - flip_index(0, S.width); + int soff = flip_index(0, 0); + int cstep = flip_index(0, 1) - soff; + int rstep = flip_index(1, 0) - flip_index(0, S.width); - for (int row = 0; row < S.height; row++, soff += rstep) - { - char *ppm = T.thumb + row*S.width*P1.colors; - for (int col = 0; col < S.width; col++, soff += cstep) - for (int c = 0; c < P1.colors; c++) - ppm[col*P1.colors + c] = imgdata.color.curve[imgdata.image[soff][c]] >> 8; - } + for (int row = 0; row < S.height; row++, soff += rstep) + { + char *ppm = T.thumb + row * S.width * P1.colors; + for (int col = 0; col < S.width; col++, soff += cstep) + for (int c = 0; c < P1.colors; c++) + ppm[col * P1.colors + c] = imgdata.color.curve[imgdata.image[soff][c]] >> 8; + } } memmove(C.curve, t_curve, sizeof(C.curve)); free(t_curve); // restore variables free(imgdata.image); imgdata.image = s_image; + if (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_NO_ROTATE_FOR_KODAK_THUMBNAILS) + imgdata.sizes.flip = s_flip; + T.twidth = S.width; S.width = s_width; S.iwidth = s_iwidth; S.iheight = s_iheight; T.theight = S.height; S.height = s_height; T.tcolors = P1.colors; P1.colors = s_colors; P1.filters = s_filters; libraw_internal_data.unpacker_data.load_flags = s_flags; } #undef MIN #undef MAX #undef LIM #undef CLIP #undef SWAP - // ������� thumbnail �� �����, ������ thumb_format � ������������ � �������� int LibRaw::thumbOK(INT64 maxsz) { - if (!ID.input) return 0; - if (!ID.toffset - && !(imgdata.thumbnail.tlength > 0 && load_raw == &LibRaw::broadcom_load_raw) // RPi - ) return 0; - INT64 fsize = ID.input->size(); - if (fsize > 0x7fffffffU) return 0; // No thumb for raw > 2Gb - int tsize = 0; - int tcol = (T.tcolors > 0 && T.tcolors < 4) ? T.tcolors : 3; - if (write_thumb == &LibRaw::jpeg_thumb) - tsize = T.tlength; - else if (write_thumb == &LibRaw::ppm_thumb) - tsize = tcol * T.twidth * T.theight; - else if (write_thumb == &LibRaw::ppm16_thumb) - tsize = tcol * T.twidth * T.theight * 2; - else if (write_thumb == &LibRaw::x3f_thumb_loader) - { - tsize = x3f_thumb_size(); - } - else // Kodak => no check - tsize = 1; - if (tsize < 0) - return 0; - if (maxsz > 0 && tsize > maxsz) - return 0; - return (tsize + ID.toffset <= fsize) ? 1 : 0; + if (!ID.input) + return 0; + if (!ID.toffset && !(imgdata.thumbnail.tlength > 0 && load_raw == &LibRaw::broadcom_load_raw) // RPi + ) + return 0; + INT64 fsize = ID.input->size(); + if (fsize > 0x7fffffffU) + return 0; // No thumb for raw > 2Gb + int tsize = 0; + int tcol = (T.tcolors > 0 && T.tcolors < 4) ? T.tcolors : 3; + if (write_thumb == &LibRaw::jpeg_thumb) + tsize = T.tlength; + else if (write_thumb == &LibRaw::ppm_thumb) + tsize = tcol * T.twidth * T.theight; + else if (write_thumb == &LibRaw::ppm16_thumb) + tsize = tcol * T.twidth * T.theight * + ((imgdata.params.raw_processing_options & LIBRAW_PROCESSING_USE_PPM16_THUMBS) ? 2 : 1); + else if (write_thumb == &LibRaw::x3f_thumb_loader) + { + tsize = x3f_thumb_size(); + } + else // Kodak => no check + tsize = 1; + if (tsize < 0) + return 0; + if (maxsz > 0 && tsize > maxsz) + return 0; + return (tsize + ID.toffset <= fsize) ? 1 : 0; +} + +#ifndef NO_JPEG +struct jpegErrorManager +{ + struct jpeg_error_mgr pub; + jmp_buf setjmp_buffer; +}; + +static void jpegErrorExit(j_common_ptr cinfo) +{ + jpegErrorManager *myerr = (jpegErrorManager *)cinfo->err; + longjmp(myerr->setjmp_buffer, 1); } +#endif int LibRaw::unpack_thumb(void) { - CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY); - CHECK_ORDER_BIT(LIBRAW_PROGRESS_THUMB_LOAD); - - try { - if (!libraw_internal_data.internal_data.input) - return LIBRAW_INPUT_CLOSED; - - if (!ID.toffset && - !(imgdata.thumbnail.tlength > 0 && load_raw == &LibRaw::broadcom_load_raw) // RPi - ) - { - return LIBRAW_NO_THUMBNAIL; - } - else if (thumb_load_raw) - { - kodak_thumb_loader(); - T.tformat = LIBRAW_THUMBNAIL_BITMAP; - SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD); - return 0; - } - else - { - if (write_thumb == &LibRaw::x3f_thumb_loader) - { - INT64 tsize = x3f_thumb_size(); - if (tsize < 2048 ||INT64(ID.toffset) + tsize < 1) - throw LIBRAW_EXCEPTION_IO_CORRUPT; - - if (INT64(ID.toffset) + tsize > ID.input->size() + THUMB_READ_BEYOND) - throw LIBRAW_EXCEPTION_IO_EOF; - } - else - { - if (INT64(ID.toffset) + INT64(T.tlength) < 1) - throw LIBRAW_EXCEPTION_IO_CORRUPT; - - if (INT64(ID.toffset) + INT64(T.tlength) > ID.input->size() + THUMB_READ_BEYOND) - throw LIBRAW_EXCEPTION_IO_EOF; - } - - ID.input->seek(ID.toffset, SEEK_SET); - if ( write_thumb == &LibRaw::jpeg_thumb) - { - if(T.thumb) free(T.thumb); - T.thumb = (char *) malloc (T.tlength); - merror (T.thumb, "jpeg_thumb()"); - ID.input->read (T.thumb, 1, T.tlength); - T.thumb[0] = 0xff; - T.thumb[1] = 0xd8; - T.tcolors = 3; - T.tformat = LIBRAW_THUMBNAIL_JPEG; - SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD); - return 0; - } - else if (write_thumb == &LibRaw::ppm_thumb) - { - T.tlength = T.twidth * T.theight*3; - if(T.thumb) free(T.thumb); + CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY); + CHECK_ORDER_BIT(LIBRAW_PROGRESS_THUMB_LOAD); - T.thumb = (char *) malloc (T.tlength); - merror (T.thumb, "ppm_thumb()"); + try + { + if (!libraw_internal_data.internal_data.input) + return LIBRAW_INPUT_CLOSED; - ID.input->read(T.thumb, 1, T.tlength); + int t_colors = libraw_internal_data.unpacker_data.thumb_misc >> 5 & 7; + int t_bytesps = (libraw_internal_data.unpacker_data.thumb_misc & 31) / 8; - T.tformat = LIBRAW_THUMBNAIL_BITMAP; - SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD); - return 0; + if (!ID.toffset && !(imgdata.thumbnail.tlength > 0 && load_raw == &LibRaw::broadcom_load_raw) // RPi + ) + { + return LIBRAW_NO_THUMBNAIL; + } + else if (thumb_load_raw) + { + kodak_thumb_loader(); + T.tformat = LIBRAW_THUMBNAIL_BITMAP; + SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD); + return 0; + } + else + { + if (write_thumb == &LibRaw::x3f_thumb_loader) + { + INT64 tsize = x3f_thumb_size(); + if (tsize < 2048 || INT64(ID.toffset) + tsize < 1) + throw LIBRAW_EXCEPTION_IO_CORRUPT; - } - else if (write_thumb == &LibRaw::ppm16_thumb) - { - T.tlength = T.twidth * T.theight*3; - ushort *t_thumb = (ushort*)calloc(T.tlength,2); - ID.input->read(t_thumb,2,T.tlength); - if ((libraw_internal_data.unpacker_data.order == 0x4949) == (ntohs(0x1234) == 0x1234)) - swab ((char*)t_thumb, (char*)t_thumb, T.tlength*2); - - if(T.thumb) free(T.thumb); - T.thumb = (char *) malloc (T.tlength); - merror (T.thumb, "ppm_thumb()"); - for (int i=0; i < T.tlength; i++) - T.thumb[i] = t_thumb[i] >> 8; - free(t_thumb); - T.tformat = LIBRAW_THUMBNAIL_BITMAP; - SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD); - return 0; + if (INT64(ID.toffset) + tsize > ID.input->size() + THUMB_READ_BEYOND) + throw LIBRAW_EXCEPTION_IO_EOF; + } + else + { + if (INT64(ID.toffset) + INT64(T.tlength) < 1) + throw LIBRAW_EXCEPTION_IO_CORRUPT; - } - else if (write_thumb == &LibRaw::x3f_thumb_loader) + if (INT64(ID.toffset) + INT64(T.tlength) > ID.input->size() + THUMB_READ_BEYOND) + throw LIBRAW_EXCEPTION_IO_EOF; + } + + ID.input->seek(ID.toffset, SEEK_SET); + if (write_thumb == &LibRaw::jpeg_thumb) + { + if (T.thumb) + free(T.thumb); + T.thumb = (char *)malloc(T.tlength); + merror(T.thumb, "jpeg_thumb()"); + ID.input->read(T.thumb, 1, T.tlength); + unsigned char *tthumb = (unsigned char *)T.thumb; + tthumb[0] = 0xff; + tthumb[1] = 0xd8; +#ifdef NO_JPEG + T.tcolors = 3; +#else + { + jpegErrorManager jerr; + struct jpeg_decompress_struct cinfo; + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = jpegErrorExit; + if (setjmp(jerr.setjmp_buffer)) { - x3f_thumb_loader(); + err2: + // Error in original JPEG thumb, read it again because + // original bytes 0-1 was damaged above + jpeg_destroy_decompress(&cinfo); + T.tcolors = 3; + T.tformat = LIBRAW_THUMBNAIL_UNKNOWN; + ID.input->seek(ID.toffset, SEEK_SET); + ID.input->read(T.thumb, 1, T.tlength); SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD); return 0; } -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 - else if (write_thumb == &LibRaw::foveon_thumb) + jpeg_create_decompress(&cinfo); + jpeg_mem_src(&cinfo, (unsigned char *)T.thumb, T.tlength); + int rc = jpeg_read_header(&cinfo, TRUE); + if (rc != 1) + goto err2; + T.tcolors = (cinfo.num_components > 0 && cinfo.num_components <= 3) ? cinfo.num_components : 3; + jpeg_destroy_decompress(&cinfo); + } +#endif + T.tformat = LIBRAW_THUMBNAIL_JPEG; + SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD); + return 0; + } + else if (write_thumb == &LibRaw::ppm_thumb) + { + if (t_bytesps > 1) + throw LIBRAW_EXCEPTION_IO_CORRUPT; // 8-bit thumb, but parsed for more bits + int t_length = T.twidth * T.theight * t_colors; + + if (T.tlength && T.tlength < t_length) // try to find tiff ifd with needed offset + { + int pifd = -1; + for (int ii = 0; ii < libraw_internal_data.identify_data.tiff_nifds && ii < LIBRAW_IFD_MAXCOUNT; ii++) + if (tiff_ifd[ii].offset == libraw_internal_data.internal_data.toffset) // found + { + pifd = ii; + break; + } + if (pifd >= 0 && tiff_ifd[pifd].strip_offsets_count && tiff_ifd[pifd].strip_byte_counts_count) { - foveon_thumb_loader(); - // may return with error, so format is set in - // foveon thumb loader itself + // We found it, calculate final size + unsigned total_size = 0; + for (int i = 0; i < tiff_ifd[pifd].strip_byte_counts_count; i++) + total_size += tiff_ifd[pifd].strip_byte_counts[i]; + if (total_size != t_length) // recalculate colors + { + if (total_size == T.twidth * T.tlength * 3) + T.tcolors = 3; + else if (total_size == T.twidth * T.tlength) + T.tcolors = 1; + } + T.tlength = total_size; + if (T.thumb) + free(T.thumb); + T.thumb = (char *)malloc(T.tlength); + merror(T.thumb, "ppm_thumb()"); + + char *dest = T.thumb; + INT64 pos = ID.input->tell(); + + for (int i = 0; i < tiff_ifd[pifd].strip_byte_counts_count && i < tiff_ifd[pifd].strip_offsets_count; i++) + { + int remain = T.tlength; + int sz = tiff_ifd[pifd].strip_byte_counts[i]; + int off = tiff_ifd[pifd].strip_offsets[i]; + if (off >= 0 && off + sz <= ID.input->size() && sz <= remain) + { + ID.input->seek(off, SEEK_SET); + ID.input->read(dest, sz, 1); + remain -= sz; + dest += sz; + } + } + ID.input->seek(pos, SEEK_SET); + T.tformat = LIBRAW_THUMBNAIL_BITMAP; SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD); return 0; } - // else if -- all other write_thumb cases! -#endif + } + + if (!T.tlength) + T.tlength = t_length; + if (T.thumb) + free(T.thumb); + + T.thumb = (char *)malloc(T.tlength); + if (!T.tcolors) + T.tcolors = t_colors; + merror(T.thumb, "ppm_thumb()"); + + ID.input->read(T.thumb, 1, T.tlength); + + T.tformat = LIBRAW_THUMBNAIL_BITMAP; + SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD); + return 0; + } + else if (write_thumb == &LibRaw::ppm16_thumb) + { + if (t_bytesps > 2) + throw LIBRAW_EXCEPTION_IO_CORRUPT; // 16-bit thumb, but parsed for more bits + int o_bps = (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_USE_PPM16_THUMBS) ? 2 : 1; + int o_length = T.twidth * T.theight * t_colors * o_bps; + int i_length = T.twidth * T.theight * t_colors * 2; + if (!T.tlength) + T.tlength = o_length; + ushort *t_thumb = (ushort *)calloc(i_length, 1); + ID.input->read(t_thumb, 1, i_length); + if ((libraw_internal_data.unpacker_data.order == 0x4949) == (ntohs(0x1234) == 0x1234)) + swab((char *)t_thumb, (char *)t_thumb, i_length); + + if (T.thumb) + free(T.thumb); + if ((imgdata.params.raw_processing_options & LIBRAW_PROCESSING_USE_PPM16_THUMBS)) + { + T.thumb = (char *)t_thumb; + T.tformat = LIBRAW_THUMBNAIL_BITMAP16; + } else - { - return LIBRAW_UNSUPPORTED_THUMBNAIL; - } + { + T.thumb = (char *)malloc(o_length); + merror(T.thumb, "ppm_thumb()"); + for (int i = 0; i < o_length; i++) + T.thumb[i] = t_thumb[i] >> 8; + free(t_thumb); + T.tformat = LIBRAW_THUMBNAIL_BITMAP; + } + SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD); + return 0; + } + else if (write_thumb == &LibRaw::x3f_thumb_loader) + { + x3f_thumb_loader(); + SET_PROC_FLAG(LIBRAW_PROGRESS_THUMB_LOAD); + return 0; + } + else + { + return LIBRAW_UNSUPPORTED_THUMBNAIL; } + } // last resort return LIBRAW_UNSUPPORTED_THUMBNAIL; } - catch ( LibRaw_exceptions err) { + catch (LibRaw_exceptions err) + { EXCEPTION_HANDLER(err); } - } int LibRaw::dcraw_thumb_writer(const char *fname) { -// CHECK_ORDER_LOW(LIBRAW_PROGRESS_THUMB_LOAD); + // CHECK_ORDER_LOW(LIBRAW_PROGRESS_THUMB_LOAD); - if(!fname) + if (!fname) return ENOENT; - FILE *tfp = fopen(fname,"wb"); + FILE *tfp = fopen(fname, "wb"); - if(!tfp) + if (!tfp) return errno; - if(!T.thumb) + if (!T.thumb) + { + fclose(tfp); + return LIBRAW_OUT_OF_ORDER_CALL; + } + + try + { + switch (T.tformat) { + case LIBRAW_THUMBNAIL_JPEG: + jpeg_thumb_writer(tfp, T.thumb, T.tlength); + break; + case LIBRAW_THUMBNAIL_BITMAP: + fprintf(tfp, "P6\n%d %d\n255\n", T.twidth, T.theight); + fwrite(T.thumb, 1, T.tlength, tfp); + break; + default: fclose(tfp); - return LIBRAW_OUT_OF_ORDER_CALL; + return LIBRAW_UNSUPPORTED_THUMBNAIL; } - - try { - switch (T.tformat) - { - case LIBRAW_THUMBNAIL_JPEG: - jpeg_thumb_writer (tfp,T.thumb,T.tlength); - break; - case LIBRAW_THUMBNAIL_BITMAP: - fprintf (tfp, "P6\n%d %d\n255\n", T.twidth, T.theight); - fwrite (T.thumb, 1, T.tlength, tfp); - break; - default: - fclose(tfp); - return LIBRAW_UNSUPPORTED_THUMBNAIL; - } fclose(tfp); return 0; } - catch ( LibRaw_exceptions err) { + catch (LibRaw_exceptions err) + { fclose(tfp); EXCEPTION_HANDLER(err); } } int LibRaw::adjust_sizes_info_only(void) { CHECK_ORDER_LOW(LIBRAW_PROGRESS_IDENTIFY); raw2image_start(); if (O.use_fuji_rotate) + { + if (IO.fuji_width) { - if (IO.fuji_width) - { - IO.fuji_width = (IO.fuji_width - 1 + IO.shrink) >> IO.shrink; - S.iwidth = (ushort)(IO.fuji_width / sqrt(0.5)); - S.iheight = (ushort)( (S.iheight - IO.fuji_width) / sqrt(0.5)); - } - else - { - if (S.pixel_aspect < 0.995) S.iheight = (ushort)( S.iheight / S.pixel_aspect + 0.5); - if (S.pixel_aspect > 1.005) S.iwidth = (ushort) (S.iwidth * S.pixel_aspect + 0.5); - } + IO.fuji_width = (IO.fuji_width - 1 + IO.shrink) >> IO.shrink; + S.iwidth = (ushort)(IO.fuji_width / sqrt(0.5)); + S.iheight = (ushort)((S.iheight - IO.fuji_width) / sqrt(0.5)); } - SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE); - if ( S.flip & 4) + else { - unsigned short t = S.iheight; - S.iheight=S.iwidth; - S.iwidth = t; - SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP); + if (S.pixel_aspect < 0.995) + S.iheight = (ushort)(S.iheight / S.pixel_aspect + 0.5); + if (S.pixel_aspect > 1.005) + S.iwidth = (ushort)(S.iwidth * S.pixel_aspect + 0.5); } + } + SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE); + if (S.flip & 4) + { + unsigned short t = S.iheight; + S.iheight = S.iwidth; + S.iwidth = t; + SET_PROC_FLAG(LIBRAW_PROGRESS_FLIP); + } return 0; } int LibRaw::subtract_black() { adjust_bl(); return subtract_black_internal(); } int LibRaw::subtract_black_internal() { CHECK_ORDER_LOW(LIBRAW_PROGRESS_RAW2_IMAGE); - try { - if(!is_phaseone_compressed() && (C.cblack[0] || C.cblack[1] || C.cblack[2] || C.cblack[3] || (C.cblack[4] && C.cblack[5]) )) + try + { + if (!is_phaseone_compressed() && + (C.cblack[0] || C.cblack[1] || C.cblack[2] || C.cblack[3] || (C.cblack[4] && C.cblack[5]))) + { +#define BAYERC(row, col, c) imgdata.image[((row) >> IO.shrink) * S.iwidth + ((col) >> IO.shrink)][c] + int cblk[4], i; + for (i = 0; i < 4; i++) + cblk[i] = C.cblack[i]; + + int size = S.iheight * S.iwidth; +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define LIM(x, min, max) MAX(min, MIN(x, max)) +#define CLIP(x) LIM(x, 0, 65535) + int dmax = 0; + if (C.cblack[4] && C.cblack[5]) { -#define BAYERC(row,col,c) imgdata.image[((row) >> IO.shrink)*S.iwidth + ((col) >> IO.shrink)][c] - int cblk[4],i; - for(i=0;i<4;i++) - cblk[i] = C.cblack[i]; - - int size = S.iheight * S.iwidth; -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#define LIM(x,min,max) MAX(min,MIN(x,max)) -#define CLIP(x) LIM(x,0,65535) - int dmax = 0; - if(C.cblack[4] && C.cblack[5]) - { - for(i=0; i< size*4; i++) - { - int val = imgdata.image[0][i]; - val -= C.cblack[6 + i/4 / S.iwidth % C.cblack[4] * C.cblack[5] + - i/4 % S.iwidth % C.cblack[5]]; - val -= cblk[i & 3]; - imgdata.image[0][i] = CLIP(val); - if(dmax < val) dmax = val; - } - } - else - { - for(i=0; i< size*4; i++) - { - int val = imgdata.image[0][i]; - val -= cblk[i & 3]; - imgdata.image[0][i] = CLIP(val); - if(dmax < val) dmax = val; - } - } - C.data_maximum = dmax & 0xffff; + for (i = 0; i < size * 4; i++) + { + int val = imgdata.image[0][i]; + val -= C.cblack[6 + i / 4 / S.iwidth % C.cblack[4] * C.cblack[5] + i / 4 % S.iwidth % C.cblack[5]]; + val -= cblk[i & 3]; + imgdata.image[0][i] = CLIP(val); + if (dmax < val) + dmax = val; + } + } + else + { + for (i = 0; i < size * 4; i++) + { + int val = imgdata.image[0][i]; + val -= cblk[i & 3]; + imgdata.image[0][i] = CLIP(val); + if (dmax < val) + dmax = val; + } + } + C.data_maximum = dmax & 0xffff; #undef MIN #undef MAX #undef LIM #undef CLIP - C.maximum -= C.black; - ZERO(C.cblack); // Yeah, we used cblack[6+] values too! - C.black = 0; + C.maximum -= C.black; + ZERO(C.cblack); // Yeah, we used cblack[6+] values too! + C.black = 0; #undef BAYERC - } + } else - { - // Nothing to Do, maximum is already calculated, black level is 0, so no change - // only calculate channel maximum; - int idx; - ushort *p = (ushort*)imgdata.image; - int dmax = 0; - for(idx=0;idx8) shift = 8; - if(shift<0.25) shift = 0.25; - if(smooth < 0.0) smooth = 0.0; - if(smooth > 1.0) smooth = 1.0; - - unsigned short *lut = (ushort*)malloc((TBLN+1)*sizeof(unsigned short)); - - if(shift <=1.0) - { - for(int i=0;i<=TBLN;i++) - lut[i] = (unsigned short)((float)i*shift); - } + if (shift > 8) + shift = 8; + if (shift < 0.25) + shift = 0.25; + if (smooth < 0.0) + smooth = 0.0; + if (smooth > 1.0) + smooth = 1.0; + + unsigned short *lut = (ushort *)malloc((TBLN + 1) * sizeof(unsigned short)); + + if (shift <= 1.0) + { + for (int i = 0; i <= TBLN; i++) + lut[i] = (unsigned short)((float)i * shift); + } else + { + float x1, x2, y1, y2; + + float cstops = log(shift) / log(2.0f); + float room = cstops * 2; + float roomlin = powf(2.0f, room); + x2 = (float)TBLN; + x1 = (x2 + 1) / roomlin - 1; + y1 = x1 * shift; + y2 = x2 * (1 + (1 - smooth) * (shift - 1)); + float sq3x = powf(x1 * x1 * x2, 1.0f / 3.0f); + float B = (y2 - y1 + shift * (3 * x1 - 3.0f * sq3x)) / (x2 + 2.0f * x1 - 3.0f * sq3x); + float A = (shift - B) * 3.0f * powf(x1 * x1, 1.0f / 3.0f); + float CC = y2 - A * powf(x2, 1.0f / 3.0f) - B * x2; + for (int i = 0; i <= TBLN; i++) { - float x1,x2,y1,y2; - - float cstops = log(shift)/log(2.0f); - float room = cstops*2; - float roomlin = powf(2.0f,room); - x2 = (float)TBLN; - x1 = (x2+1)/roomlin-1; - y1 = x1*shift; - y2 = x2*(1+(1-smooth)*(shift-1)); - float sq3x=powf(x1*x1*x2,1.0f/3.0f); - float B = (y2-y1+shift*(3*x1-3.0f*sq3x)) / (x2+2.0f*x1-3.0f*sq3x); - float A = (shift - B)*3.0f*powf(x1*x1,1.0f/3.0f); - float CC = y2 - A*powf(x2,1.0f/3.0f)-B*x2; - for(int i=0;i<=TBLN;i++) - { - float X = (float)i; - float Y = A*powf(X,1.0f/3.0f)+B*X+CC; - if(iTBLN?TBLN:(unsigned short)(Y)); - } - } - for(int i=0; i< S.height*S.width; i++) - { - imgdata.image[i][0] = lut[imgdata.image[i][0]]; - imgdata.image[i][1] = lut[imgdata.image[i][1]]; - imgdata.image[i][2] = lut[imgdata.image[i][2]]; - imgdata.image[i][3] = lut[imgdata.image[i][3]]; + float X = (float)i; + float Y = A * powf(X, 1.0f / 3.0f) + B * X + CC; + if (i < x1) + lut[i] = (unsigned short)((float)i * shift); + else + lut[i] = Y < 0 ? 0 : (Y > TBLN ? TBLN : (unsigned short)(Y)); } + } + for (int i = 0; i < S.height * S.width; i++) + { + imgdata.image[i][0] = lut[imgdata.image[i][0]]; + imgdata.image[i][1] = lut[imgdata.image[i][1]]; + imgdata.image[i][2] = lut[imgdata.image[i][2]]; + imgdata.image[i][3] = lut[imgdata.image[i][3]]; + } - if(C.data_maximum <=TBLN) + if (C.data_maximum <= TBLN) C.data_maximum = lut[C.data_maximum]; - if(C.maximum <= TBLN) + if (C.maximum <= TBLN) C.maximum = lut[C.maximum]; - // no need to adjust the minumum, black is already subtracted free(lut); } -#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 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) void LibRaw::convert_to_rgb_loop(float out_cam[3][4]) { - int row,col,c; + int row, col, c; float out[3]; ushort *img; - memset(libraw_internal_data.output_data.histogram,0,sizeof(int)*LIBRAW_HISTOGRAM_SIZE*4); - for (img=imgdata.image[0], row=0; row < S.height; row++) - for (col=0; col < S.width; col++, img+=4) { - if (!libraw_internal_data.internal_output_params.raw_color) { + memset(libraw_internal_data.output_data.histogram, 0, sizeof(int) * LIBRAW_HISTOGRAM_SIZE * 4); + for (img = imgdata.image[0], row = 0; row < S.height; row++) + for (col = 0; col < S.width; col++, img += 4) + { + if (!libraw_internal_data.internal_output_params.raw_color) + { out[0] = out[1] = out[2] = 0; - for(c=0; c< imgdata.idata.colors; c++) { + for (c = 0; c < imgdata.idata.colors; c++) + { out[0] += out_cam[0][c] * img[c]; out[1] += out_cam[1][c] * img[c]; out[2] += out_cam[2][c] * img[c]; } - for(c=0;c<3;c++) img[c] = CLIP((int) out[c]); + for (c = 0; c < 3; c++) + img[c] = CLIP((int)out[c]); } - for(c=0; c< imgdata.idata.colors; c++) libraw_internal_data.output_data.histogram[c][img[c] >> 3]++; + for (c = 0; c < imgdata.idata.colors; c++) + libraw_internal_data.output_data.histogram[c][img[c] >> 3]++; } - } void LibRaw::scale_colors_loop(float scale_mul[4]) { - unsigned size = S.iheight*S.iwidth; - + unsigned size = S.iheight * S.iwidth; if (C.cblack[4] && C.cblack[5]) + { + int val; + for (unsigned i = 0; i < size * 4; i++) { - int val; - for (unsigned i=0; i < size*4; i++) - { - if (!(val = imgdata.image[0][i])) continue; - val -= C.cblack[6 + i/4 / S.iwidth % C.cblack[4] * C.cblack[5] + - i/4 % S.iwidth % C.cblack[5]]; - val -= C.cblack[i & 3]; - val *= scale_mul[i & 3]; - imgdata.image[0][i] = CLIP(val); - } + if (!(val = imgdata.image[0][i])) + continue; + val -= C.cblack[6 + i / 4 / S.iwidth % C.cblack[4] * C.cblack[5] + i / 4 % S.iwidth % C.cblack[5]]; + val -= C.cblack[i & 3]; + val *= scale_mul[i & 3]; + imgdata.image[0][i] = CLIP(val); } - else if(C.cblack[0]||C.cblack[1]||C.cblack[2]||C.cblack[3]) + } + else if (C.cblack[0] || C.cblack[1] || C.cblack[2] || C.cblack[3]) + { + for (unsigned i = 0; i < size * 4; i++) { - for (unsigned i=0; i < size*4; i++) - { - int val = imgdata.image[0][i]; - if (!val) continue; - val -= C.cblack[i & 3]; - val *= scale_mul[i & 3]; - imgdata.image[0][i] = CLIP(val); - } + int val = imgdata.image[0][i]; + if (!val) + continue; + val -= C.cblack[i & 3]; + val *= scale_mul[i & 3]; + imgdata.image[0][i] = CLIP(val); } + } else // BL is zero + { + for (unsigned i = 0; i < size * 4; i++) { - for (unsigned i=0; i < size*4; i++) - { - int val = imgdata.image[0][i]; - val *= scale_mul[i & 3]; - imgdata.image[0][i] = CLIP(val); - } + int val = imgdata.image[0][i]; + val *= scale_mul[i & 3]; + imgdata.image[0][i] = CLIP(val); } + } } void LibRaw::adjust_bl() { - int clear_repeat=0; - if (O.user_black >= 0) - { - C.black = O.user_black; - clear_repeat = 1; - } - for(int i=0; i<4; i++) - if(O.user_cblack[i]>-1000000) - { - C.cblack[i] = O.user_cblack[i]; - clear_repeat = 1; - } - - if(clear_repeat) - C.cblack[4]=C.cblack[5]=0; - - // Add common part to cblack[] early - if (imgdata.idata.filters > 1000 && (C.cblack[4]+1)/2 == 1 && (C.cblack[5]+1)/2 == 1) - { - int clrs[4]; - int lastg = -1, gcnt = 0; - for(int c = 0; c < 4; c++) - { - clrs[c] = FC(c/2,c%2); - if(clrs[c]==1) - { - gcnt++; - lastg = c; - } - } - if(gcnt>1 && lastg>=0) - clrs[lastg] = 3; - for(int c=0; c<4; c++) - C.cblack[clrs[c]] += C.cblack[6 + c/2 % C.cblack[4] * C.cblack[5] + c%2 % C.cblack[5]]; - C.cblack[4]=C.cblack[5]=0; - //imgdata.idata.filters = sfilters; - } - else if(imgdata.idata.filters <= 1000 && C.cblack[4]==1 && C.cblack[5]==1) // Fuji RAF dng - { - for(int c=0; c<4; c++) - C.cblack[c] += C.cblack[6]; - C.cblack[4]=C.cblack[5]=0; - } + int clear_repeat = 0; + if (O.user_black >= 0) + { + C.black = O.user_black; + clear_repeat = 1; + } + for (int i = 0; i < 4; i++) + if (O.user_cblack[i] > -1000000) + { + C.cblack[i] = O.user_cblack[i]; + clear_repeat = 1; + } + + if (clear_repeat) + C.cblack[4] = C.cblack[5] = 0; + + // Add common part to cblack[] early + if (imgdata.idata.filters > 1000 && (C.cblack[4] + 1) / 2 == 1 && (C.cblack[5] + 1) / 2 == 1) + { + int clrs[4]; + int lastg = -1, gcnt = 0; + for (int c = 0; c < 4; c++) + { + clrs[c] = FC(c / 2, c % 2); + if (clrs[c] == 1) + { + gcnt++; + lastg = c; + } + } + if (gcnt > 1 && lastg >= 0) + clrs[lastg] = 3; + for (int c = 0; c < 4; c++) + C.cblack[clrs[c]] += C.cblack[6 + c / 2 % C.cblack[4] * C.cblack[5] + c % 2 % C.cblack[5]]; + C.cblack[4] = C.cblack[5] = 0; + // imgdata.idata.filters = sfilters; + } + else if (imgdata.idata.filters <= 1000 && C.cblack[4] == 1 && C.cblack[5] == 1) // Fuji RAF dng + { + for (int c = 0; c < 4; c++) + C.cblack[c] += C.cblack[6]; + C.cblack[4] = C.cblack[5] = 0; + } // remove common part from C.cblack[] int i = C.cblack[3]; int c; - for(c=0;c<3;c++) if (i > C.cblack[c]) i = C.cblack[c]; + for (c = 0; c < 3; c++) + if (i > C.cblack[c]) + i = C.cblack[c]; - for(c=0;c<4;c++) C.cblack[c] -= i; // remove common part + for (c = 0; c < 4; c++) + C.cblack[c] -= i; // remove common part C.black += i; // Now calculate common part for cblack[6+] part and move it to C.black - if(C.cblack[4] && C.cblack[5]) + if (C.cblack[4] && C.cblack[5]) + { + i = C.cblack[6]; + for (c = 1; c < C.cblack[4] * C.cblack[5]; c++) + if (i > C.cblack[6 + c]) + i = C.cblack[6 + c]; + // Remove i from cblack[6+] + int nonz = 0; + for (c = 0; c < C.cblack[4] * C.cblack[5]; c++) { - i = C.cblack[6]; - for(c=1; cC.cblack[6+c]) i = C.cblack[6+c]; - // Remove i from cblack[6+] - int nonz=0; - for(c=0; c= 0) quality = O.user_qual; + if (O.user_qual >= 0) + quality = O.user_qual; - if(!subtract_inline || !C.data_maximum) - { - adjust_bl(); - subtract_black_internal(); - } + if (!subtract_inline || !C.data_maximum) + { + adjust_bl(); + subtract_black_internal(); + } - if(!(di.decoder_flags & LIBRAW_DECODER_FIXEDMAXC)) - adjust_maximum(); + if (!(di.decoder_flags & LIBRAW_DECODER_FIXEDMAXC)) + adjust_maximum(); - if (O.user_sat > 0) C.maximum = O.user_sat; + if (O.user_sat > 0) + C.maximum = O.user_sat; if (P1.is_foveon) + { + if (load_raw == &LibRaw::x3f_load_raw) { - if(load_raw == &LibRaw::x3f_load_raw) - { - // Filter out zeroes - for (int i=0; i < S.height*S.width*4; i++) - if ((short) imgdata.image[0][i] < 0) imgdata.image[0][i] = 0; - } -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 - else if(load_raw == &LibRaw::foveon_dp_load_raw) - { - for (int i=0; i < S.height*S.width*4; i++) - if ((short) imgdata.image[0][i] < 0) imgdata.image[0][i] = 0; - } - else - { - foveon_interpolate(); - } -#endif - SET_PROC_FLAG(LIBRAW_PROGRESS_FOVEON_INTERPOLATE); + // Filter out zeroes + for (int i = 0; i < S.height * S.width * 4; i++) + if ((short)imgdata.image[0][i] < 0) + imgdata.image[0][i] = 0; } + SET_PROC_FLAG(LIBRAW_PROGRESS_FOVEON_INTERPOLATE); + } if (O.green_matching && !O.half_size) - { - green_matching(); - } + { + green_matching(); + } - if ( -#ifdef LIBRAW_DEMOSAIC_PACK_GPL2 - (!P1.is_foveon || (O.raw_processing_options & LIBRAW_PROCESSING_FORCE_FOVEON_X3F)) && -#endif - !O.no_auto_scale) - { - scale_colors(); - SET_PROC_FLAG(LIBRAW_PROGRESS_SCALE_COLORS); - } + if(callbacks.pre_scalecolors_cb) + (callbacks.pre_scalecolors_cb)(this); + + if (!O.no_auto_scale) + { + scale_colors(); + SET_PROC_FLAG(LIBRAW_PROGRESS_SCALE_COLORS); + } + + if(callbacks.pre_preinterpolate_cb) + (callbacks.pre_preinterpolate_cb)(this); pre_interpolate(); SET_PROC_FLAG(LIBRAW_PROGRESS_PRE_INTERPOLATE); - if (O.dcb_iterations >= 0) iterations = O.dcb_iterations; - if (O.dcb_enhance_fl >=0 ) dcb_enhance = O.dcb_enhance_fl; - if (O.fbdd_noiserd >=0 ) noiserd = O.fbdd_noiserd; - if (O.eeci_refine >=0 ) eeci_refine_fl = O.eeci_refine; - if (O.es_med_passes >0 ) es_med_passes_fl = O.es_med_passes; - - // LIBRAW_DEMOSAIC_PACK_GPL3 + if (O.dcb_iterations >= 0) + iterations = O.dcb_iterations; + if (O.dcb_enhance_fl >= 0) + dcb_enhance = O.dcb_enhance_fl; + if (O.fbdd_noiserd >= 0) + noiserd = O.fbdd_noiserd; - if (!O.half_size && O.cfa_green >0) {thresh=O.green_thresh ;green_equilibrate(thresh);} - if (O.exp_correc >0) {expos=O.exp_shift ; preser=O.exp_preser; exp_bef(expos,preser);} - if (O.ca_correc >0 ) {cablue=O.cablue; cared=O.cared; CA_correct_RT(cablue, cared);} - if (O.cfaline >0 ) {linenoise=O.linenoise; cfa_linedn(linenoise);} - if (O.cfa_clean >0 ) {lclean=O.lclean; cclean=O.cclean; cfa_impulse_gauss(lclean,cclean);} + /* pre-exposure correction callback */ - if (P1.filters && !O.no_interpolation) - { - if (noiserd>0 && P1.colors==3 && P1.filters) fbdd(noiserd); - - if(P1.filters>1000 && interpolate_bayer) - (this->*interpolate_bayer)(); - else if(P1.filters==9 && interpolate_xtrans) - (this->*interpolate_xtrans)(); - else if (quality == 0) - lin_interpolate(); - else if (quality == 1 || P1.colors > 3) - vng_interpolate(); - else if (quality == 2 && P1.filters > 1000) - ppg_interpolate(); - else if (P1.filters == LIBRAW_XTRANS) - { - // Fuji X-Trans - xtrans_interpolate(quality>2?3:1); - } - else if (quality == 3) - ahd_interpolate(); // really don't need it here due to fallback op - else if (quality == 4) - dcb(iterations, dcb_enhance); - // LIBRAW_DEMOSAIC_PACK_GPL2 - else if (quality == 5) - ahd_interpolate_mod(); - else if (quality == 6) - afd_interpolate_pl(2,1); - else if (quality == 7) - vcd_interpolate(0); - else if (quality == 8) - vcd_interpolate(12); - else if (quality == 9) - lmmse_interpolate(1); - - // LIBRAW_DEMOSAIC_PACK_GPL3 - else if (quality == 10) - amaze_demosaic_RT(); - // LGPL2 - else if (quality == 11) - dht_interpolate(); - else if (quality == 12) - aahd_interpolate(); - // fallback to AHD - else - { - ahd_interpolate(); - imgdata.process_warnings |= LIBRAW_WARN_FALLBACK_TO_AHD; - } + if (O.exp_correc > 0) + { + expos = O.exp_shift; + preser = O.exp_preser; + exp_bef(expos, preser); + } + if(callbacks.pre_interpolate_cb) + (callbacks.pre_interpolate_cb)(this); - SET_PROC_FLAG(LIBRAW_PROGRESS_INTERPOLATE); + /* post-exposure correction fallback */ + if (P1.filters && !O.no_interpolation) + { + if (noiserd > 0 && P1.colors == 3 && P1.filters) + fbdd(noiserd); + + if (P1.filters > 1000 && callbacks.interpolate_bayer_cb) + (callbacks.interpolate_bayer_cb)(this); + else if (P1.filters == 9 && callbacks.interpolate_xtrans_cb) + (callbacks.interpolate_xtrans_cb)(this); + else if (quality == 0) + lin_interpolate(); + else if (quality == 1 || P1.colors > 3) + vng_interpolate(); + else if (quality == 2 && P1.filters > 1000) + ppg_interpolate(); + else if (P1.filters == LIBRAW_XTRANS) + { + // Fuji X-Trans + xtrans_interpolate(quality > 2 ? 3 : 1); } - if (IO.mix_green) + else if (quality == 3) + ahd_interpolate(); // really don't need it here due to fallback op + else if (quality == 4) + dcb(iterations, dcb_enhance); + + else if (quality == 11) + dht_interpolate(); + else if (quality == 12) + aahd_interpolate(); + // fallback to AHD + else { - for (P1.colors=3, i=0; i < S.height * S.width; i++) - imgdata.image[i][1] = (imgdata.image[i][1] + imgdata.image[i][3]) >> 1; - SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN); + ahd_interpolate(); + imgdata.process_warnings |= LIBRAW_WARN_FALLBACK_TO_AHD; } - if(!P1.is_foveon) - { - if (P1.colors == 3) - { + SET_PROC_FLAG(LIBRAW_PROGRESS_INTERPOLATE); + } + if (IO.mix_green) + { + for (P1.colors = 3, i = 0; i < S.height * S.width; i++) + imgdata.image[i][1] = (imgdata.image[i][1] + imgdata.image[i][3]) >> 1; + SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN); + } - if (quality == 8) - { - if (eeci_refine_fl == 1) refinement(); - if (O.med_passes > 0) median_filter_new(); - if (es_med_passes_fl > 0) es_median_filter(); - } - else { - median_filter(); - } - SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER); - } - } + if(callbacks.post_interpolate_cb) + (callbacks.post_interpolate_cb)(this); + else if (!P1.is_foveon && P1.colors == 3 && O.med_passes > 0) + { + median_filter(); + SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER); + } if (O.highlight == 2) - { - blend_highlights(); - SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS); - } + { + blend_highlights(); + SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS); + } if (O.highlight > 2) - { - recover_highlights(); - SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS); - } + { + recover_highlights(); + SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS); + } if (O.use_fuji_rotate) - { - fuji_rotate(); - SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE); - } + { + fuji_rotate(); + SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE); + } - if(!libraw_internal_data.output_data.histogram) - { - libraw_internal_data.output_data.histogram = (int (*)[LIBRAW_HISTOGRAM_SIZE]) malloc(sizeof(*libraw_internal_data.output_data.histogram)*4); - merror(libraw_internal_data.output_data.histogram,"LibRaw::dcraw_process()"); - } + if (!libraw_internal_data.output_data.histogram) + { + libraw_internal_data.output_data.histogram = + (int(*)[LIBRAW_HISTOGRAM_SIZE])malloc(sizeof(*libraw_internal_data.output_data.histogram) * 4); + merror(libraw_internal_data.output_data.histogram, "LibRaw::dcraw_process()"); + } #ifndef NO_LCMS - if(O.camera_profile) - { - apply_profile(O.camera_profile,O.output_profile); - SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE); - } + if (O.camera_profile) + { + apply_profile(O.camera_profile, O.output_profile); + SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE); + } #endif + if(callbacks.pre_converttorgb_cb) + (callbacks.pre_converttorgb_cb)(this); + convert_to_rgb(); SET_PROC_FLAG(LIBRAW_PROGRESS_CONVERT_RGB); + if(callbacks.post_converttorgb_cb) + (callbacks.post_converttorgb_cb)(this); + if (O.use_fuji_rotate) - { - stretch(); - SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH); - } + { + stretch(); + SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH); + } O.four_color_rgb = save_4color; // also, restore return 0; } - catch ( LibRaw_exceptions err) { + catch (LibRaw_exceptions err) + { EXCEPTION_HANDLER(err); } } +// clang-format off // Supported cameras: -static const char *static_camera_list[] = -{ -"Adobe Digital Negative (DNG)", -"AgfaPhoto DC-833m", -"Alcatel 5035D", -"Apple iPad Pro", -"Apple iPhone SE", -"Apple iPhone 6s", -"Apple iPhone 6 plus", -"Apple iPhone 7", -"Apple iPhone 7 plus", -"Apple QuickTake 100", -"Apple QuickTake 150", -"Apple QuickTake 200", -"ARRIRAW format", -"AVT F-080C", -"AVT F-145C", -"AVT F-201C", -"AVT F-510C", -"AVT F-810C", -"Baumer TXG14", -"BlackMagic Cinema Camera", -"BlackMagic Micro Cinema Camera", -"BlackMagic Pocket Cinema Camera", -"BlackMagic Production Camera 4k", -"BlackMagic URSA", -"BlackMagic URSA Mini", -"Canon PowerShot 600", -"Canon PowerShot A5", -"Canon PowerShot A5 Zoom", -"Canon PowerShot A50", -"Canon PowerShot A460 (CHDK hack)", -"Canon PowerShot A470 (CHDK hack)", -"Canon PowerShot A530 (CHDK hack)", -"Canon PowerShot A550 (CHDK hack)", -"Canon PowerShot A570 (CHDK hack)", -"Canon PowerShot A590 (CHDK hack)", -"Canon PowerShot A610 (CHDK hack)", -"Canon PowerShot A620 (CHDK hack)", -"Canon PowerShot A630 (CHDK hack)", -"Canon PowerShot A640 (CHDK hack)", -"Canon PowerShot A650 (CHDK hack)", -"Canon PowerShot A710 IS (CHDK hack)", -"Canon PowerShot A720 IS (CHDK hack)", -"Canon PowerShot A3300 IS (CHDK hack)", -"Canon PowerShot Pro70", -"Canon PowerShot Pro90 IS", -"Canon PowerShot Pro1", -"Canon PowerShot G1", -"Canon PowerShot G1 X", -"Canon PowerShot G1 X Mark II", -"Canon PowerShot G2", -"Canon PowerShot G3", -"Canon PowerShot G3 X", -"Canon PowerShot G5", -"Canon PowerShot G5 X", -"Canon PowerShot G6", -"Canon PowerShot G7 (CHDK hack)", -"Canon PowerShot G7 X", -"Canon PowerShot G7 X Mark II", -"Canon PowerShot G9", -"Canon PowerShot G9 X", -"Canon PowerShot G10", -"Canon PowerShot G11", -"Canon PowerShot G12", -"Canon PowerShot G15", -"Canon PowerShot G16", -"Canon PowerShot S2 IS (CHDK hack)", -"Canon PowerShot S3 IS (CHDK hack)", -"Canon PowerShot S5 IS (CHDK hack)", -"Canon PowerShot SD300 (CHDK hack)", -"Canon PowerShot SD950 (CHDK hack)", -"Canon PowerShot S30", -"Canon PowerShot S40", -"Canon PowerShot S45", -"Canon PowerShot S50", -"Canon PowerShot S60", -"Canon PowerShot S70", -"Canon PowerShot S90", -"Canon PowerShot S95", -"Canon PowerShot S100", -"Canon PowerShot S110", -"Canon PowerShot S120", -"Canon PowerShot SX1 IS", -"Canon PowerShot SX50 HS", -"Canon PowerShot SX60 HS", -"Canon PowerShot SX110 IS (CHDK hack)", -"Canon PowerShot SX120 IS (CHDK hack)", -"Canon PowerShot SX220 HS (CHDK hack)", -"Canon PowerShot SX20 IS (CHDK hack)", -"Canon PowerShot SX30 IS (CHDK hack)", -"Canon PowerShot IXUS 160 (CHDK hack)", -"Canon EOS D30", -"Canon EOS D60", -"Canon EOS 5D", -"Canon EOS 5DS", -"Canon EOS 5DS R", -"Canon EOS 5D Mark II", -"Canon EOS 5D Mark III", -"Canon EOS 5D Mark IV", -"Canon EOS 6D", -"Canon EOS 7D", -"Canon EOS 7D Mark II", -"Canon EOS 10D", -"Canon EOS 20D", -"Canon EOS 20Da", -"Canon EOS 30D", -"Canon EOS 40D", -"Canon EOS 50D", -"Canon EOS 60D", -"Canon EOS 60Da", -"Canon EOS 70D", -"Canon EOS 80D", -"Canon EOS 300D / Digital Rebel / Kiss Digital", -"Canon EOS 350D / Digital Rebel XT / Kiss Digital N", -"Canon EOS 400D / Digital Rebel XTi / Kiss Digital X", -"Canon EOS 450D / Digital Rebel XSi / Kiss Digital X2", -"Canon EOS 500D / Digital Rebel T1i / Kiss Digital X3", -"Canon EOS 550D / Digital Rebel T2i / Kiss Digital X4", -"Canon EOS 600D / Digital Rebel T3i / Kiss Digital X5", -"Canon EOS 650D / Digital Rebel T4i / Kiss Digital X6i", -"Canon EOS 700D / Digital Rebel T5i", -"Canon EOS 750D / Digital Rebel T6i", -"Canon EOS 760D / Digital Rebel T6S", -"Canon EOS 100D / Digital Rebel SL1", -"Canon EOS 1000D / Digital Rebel XS / Kiss Digital F", -"Canon EOS 1100D / Digital Rebel T3 / Kiss Digital X50", -"Canon EOS 1200D", -"Canon EOS 1300D", -"Canon EOS C500", -"Canon EOS D2000C", -"Canon EOS M", -"Canon EOS M2", -"Canon EOS M3", -"Canon EOS M5", -"Canon EOS M10", -"Canon EOS-1D", -"Canon EOS-1DS", -"Canon EOS-1D C", -"Canon EOS-1D X", -"Canon EOS-1D Mark II", -"Canon EOS-1D Mark II N", -"Canon EOS-1D Mark III", -"Canon EOS-1D Mark IV", -"Canon EOS-1Ds Mark II", -"Canon EOS-1Ds Mark III", -"Canon EOS-1D X Mark II", -"Casio QV-2000UX", -"Casio QV-3000EX", -"Casio QV-3500EX", -"Casio QV-4000", -"Casio QV-5700", -"Casio QV-R41", -"Casio QV-R51", -"Casio QV-R61", -"Casio EX-F1", -"Casio EX-FC300S", -"Casio EX-FC400S", -"Casio EX-FH20", -"Casio EX-FH25", -"Casio EX-FH100", -"Casio EX-S20", -"Casio EX-S100", -"Casio EX-Z4", -"Casio EX-Z50", -"Casio EX-Z500", -"Casio EX-Z55", -"Casio EX-Z60", -"Casio EX-Z75", -"Casio EX-Z750", -"Casio EX-Z8", -"Casio EX-Z850", -"Casio EX-Z1050", -"Casio EX-ZR100", -"Casio EX-Z1080", -"Casio EX-ZR700", -"Casio EX-ZR710", -"Casio EX-ZR750", -"Casio EX-ZR800", -"Casio EX-ZR850", -"Casio EX-ZR1000", -"Casio EX-ZR1100", -"Casio EX-ZR1200", -"Casio EX-ZR1300", -"Casio EX-ZR1500", -"Casio EX-ZR3000", -"Casio EX-ZR4000/5000", -"Casio EX-100", -"Casio EX-100F", -"Casio EX-10", -"Casio Exlim Pro 505", -"Casio Exlim Pro 600", -"Casio Exlim Pro 700", -"Contax N Digital", -"Creative PC-CAM 600", -"Digital Bolex D16", -"Digital Bolex D16M", -"DJI 4384x3288", -"DXO One", -"Epson R-D1", -"Epson R-D1s", -"Epson R-D1x", -"Foculus 531C", -"FujiFilm E505", -"FujiFilm E550", -"FujiFilm E900", -"FujiFilm F700", -"FujiFilm F710", -"FujiFilm F800", -"FujiFilm F810", -"FujiFilm S2Pro", -"FujiFilm S3Pro", -"FujiFilm S5Pro", -"FujiFilm S20Pro", -"FujiFilm S1", -"FujiFilm S100FS", -"FujiFilm S5000", -"FujiFilm S5100/S5500", -"FujiFilm S5200/S5600", -"FujiFilm S6000fd", -"FujiFilm S7000", -"FujiFilm S9000/S9500", -"FujiFilm S9100/S9600", -"FujiFilm S200EXR", -"FujiFilm S205EXR", -"FujiFilm SL1000", -"FujiFilm HS10/HS11", -"FujiFilm HS20EXR", -"FujiFilm HS22EXR", -"FujiFilm HS30EXR", -"FujiFilm HS33EXR", -"FujiFilm HS35EXR", -"FujiFilm HS50EXR", -"FujiFilm F505EXR", -"FujiFilm F550EXR", -"FujiFilm F600EXR", -"FujiFilm F605EXR", -"FujiFilm F770EXR", -"FujiFilm F775EXR", -"FujiFilm F800EXR", -"FujiFilm F900EXR", -"FujiFilm X-Pro1", -"FujiFilm X-Pro2", -"FujiFilm X-S1", -"FujiFilm XQ1", -"FujiFilm XQ2", -"FujiFilm X100", -"FujiFilm X100S", -"FujiFilm X100T", -"FujiFilm X10", -"FujiFilm X20", -"FujiFilm X30", -"FujiFilm X70", -"FujiFilm X-A1", -"FujiFilm X-A2", -"FujiFilm X-E1", -"FujiFilm X-E2", -"FujiFilm X-E2S", -"FujiFilm X-M1", -"FujiFilm XF1", -"FujiFilm X-T1", -"FujiFilm X-T1 Graphite Silver", -"FujiFilm X-T2", -"FujiFilm X-T10", -"FujiFilm IS-1", -"Gione E7", -"GITUP GIT2", -"Google Pixel", -"Google Pixel XL", -"Hasselblad H5D-60", -"Hasselblad H5D-50", -"Hasselblad H5D-50c", -"Hasselblad H5D-40", -"Hasselblad H4D-60", -"Hasselblad H4D-50", -"Hasselblad H4D-40", -"Hasselblad H4D-31", -"Hasselblad H3DII-22", -"Hasselblad H3DII-31", -"Hasselblad H3DII-39", -"Hasselblad H3DII-50", -"Hasselblad H3D-22", -"Hasselblad H3D-31", -"Hasselblad H3D-39", -"Hasselblad H2D-22", -"Hasselblad H2D-39", -"Hasselblad CFV", -"Hasselblad CFH", -"Hasselblad CF-22", -"Hasselblad CF-31", -"Hasselblad CF-39", -"Hasselblad V96C", -"Hasselblad Lusso", -"Hasselblad Lunar", -"Hasselblad True Zoom", -"Hasselblad Stellar", -"Hasselblad Stellar II", -"Hasselblad HV", -"Hasselblad X1D", -"HTC UltraPixel", -"HTC MyTouch 4G", -"HTC One (A9)", -"HTC One (M9)", -"HTC 10", -"Huawei P9", -"Imacon Ixpress 96, 96C", -"Imacon Ixpress 384, 384C (single shot only)", -"Imacon Ixpress 132C", -"Imacon Ixpress 528C (single shot only)", -"ISG 2020x1520", -"Ikonoskop A-Cam dII Panchromatic", -"Ikonoskop A-Cam dII", -"Kinefinity KineMINI", -"Kinefinity KineRAW Mini", -"Kinefinity KineRAW S35", -"Kodak DC20", -"Kodak DC25", -"Kodak DC40", -"Kodak DC50", -"Kodak DC120", -"Kodak DCS200", -"Kodak DCS315C", -"Kodak DCS330C", -"Kodak DCS420", -"Kodak DCS460", -"Kodak DCS460A", -"Kodak DCS460D", -"Kodak DCS520C", -"Kodak DCS560C", -"Kodak DCS620C", -"Kodak DCS620X", -"Kodak DCS660C", -"Kodak DCS660M", -"Kodak DCS720X", -"Kodak DCS760C", -"Kodak DCS760M", -"Kodak EOSDCS1", -"Kodak EOSDCS3B", -"Kodak NC2000F", -"Kodak ProBack", -"Kodak PB645C", -"Kodak PB645H", -"Kodak PB645M", -"Kodak DCS Pro 14n", -"Kodak DCS Pro 14nx", -"Kodak DCS Pro SLR/c", -"Kodak DCS Pro SLR/n", -"Kodak C330", -"Kodak C603", -"Kodak P850", -"Kodak P880", -"Kodak S-1", -"Kodak Z980", -"Kodak Z981", -"Kodak Z990", -"Kodak Z1015", -"Kodak KAI-0340", -"Konica KD-400Z", -"Konica KD-510Z", -"Leaf AFi 5", -"Leaf AFi 6", -"Leaf AFi 7", -"Leaf AFi-II 6", -"Leaf AFi-II 7", -"Leaf AFi-II 10", -"Leaf AFi-II 10R", -"Leaf Aptus-II 5", -"Leaf Aptus-II 6", -"Leaf Aptus-II 7", -"Leaf Aptus-II 8", -"Leaf Aptus-II 10", -"Leaf Aptus-II 12", -"Leaf Aptus-II 12R", -"Leaf Aptus 17", -"Leaf Aptus 22", -"Leaf Aptus 54S", -"Leaf Aptus 65", -"Leaf Aptus 65S", -"Leaf Aptus 75", -"Leaf Aptus 75S", -"Leaf Cantare", -"Leaf Cantare XY", -"Leaf CatchLight", -"Leaf CMost", -"Leaf Credo 40", -"Leaf Credo 50", -"Leaf Credo 60", -"Leaf Credo 80 (low compression mode only)", -"Leaf DCB-II", -"Leaf Valeo 6", -"Leaf Valeo 11", -"Leaf Valeo 17", -"Leaf Valeo 17wi", -"Leaf Valeo 22", -"Leaf Valeo 22wi", -"Leaf Volare", -"Lenovo a820", -"Leica C (Typ 112)", -"Leica Digilux 2", -"Leica Digilux 3", -"Leica Digital-Modul-R", -"Leica D-LUX2", -"Leica D-LUX3", -"Leica D-LUX4", -"Leica D-LUX5", -"Leica D-LUX6", -"Leica D-Lux (Typ 109)", -"Leica M8", -"Leica M8.2", -"Leica M9", -"Leica M (Typ 240)", -"Leica M (Typ 262)", -"Leica Monochrom (Typ 240)", -"Leica Monochrom (Typ 246)", -"Leica M-D (Typ 262)", -"Leica M-E", -"Leica M-P", -"Leica R8", -"Leica Q (Typ 116)", -"Leica S", -"Leica S2", -"Leica S (Typ 007)", -"Leica SL (Typ 601)", -"Leica T (Typ 701)", -"Leica TL", -"Leica X1", -"Leica X (Typ 113)", -"Leica X2", -"Leica X-E (Typ 102)", -"Leica X-U (Typ 113)", -"Leica V-LUX1", -"Leica V-LUX2", -"Leica V-LUX3", -"Leica V-LUX4", -"Leica V-Lux (Typ 114)", -"Leica X VARIO (Typ 107)", -"LG G3", -"LG G4", -"Logitech Fotoman Pixtura", -"Mamiya ZD", -"Matrix 4608x3288", -"Meizy MX4", -"Micron 2010", -"Minolta RD175", -"Minolta DiMAGE 5", -"Minolta DiMAGE 7", -"Minolta DiMAGE 7i", -"Minolta DiMAGE 7Hi", -"Minolta DiMAGE A1", -"Minolta DiMAGE A2", -"Minolta DiMAGE A200", -"Minolta DiMAGE G400", -"Minolta DiMAGE G500", -"Minolta DiMAGE G530", -"Minolta DiMAGE G600", -"Minolta DiMAGE Z2", -"Minolta Alpha/Dynax/Maxxum 5D", -"Minolta Alpha/Dynax/Maxxum 7D", -"Motorola PIXL", -"Nikon D1", -"Nikon D1H", -"Nikon D1X", -"Nikon D2H", -"Nikon D2Hs", -"Nikon D2X", -"Nikon D2Xs", -"Nikon D3", -"Nikon D3s", -"Nikon D3X", -"Nikon D4", -"Nikon D4s", -"Nikon D40", -"Nikon D40X", -"Nikon D5", -"Nikon D50", -"Nikon D60", -"Nikon D70", -"Nikon D70s", -"Nikon D80", -"Nikon D90", -"Nikon D100", -"Nikon D200", -"Nikon D300", -"Nikon D300s", -"Nikon D500", -"Nikon D600", -"Nikon D610", -"Nikon D700", -"Nikon D750", -"Nikon D800", -"Nikon D800E", -"Nikon D810", -"Nikon D810A", -"Nikon D3000", -"Nikon D3100", -"Nikon D3200", -"Nikon D3300", -"Nikon D3400", -"Nikon D5000", -"Nikon D5100", -"Nikon D5200", -"Nikon D5300", -"Nikon D5500", -"Nikon D7000", -"Nikon D7100", -"Nikon D7200", -"Nikon Df", -"Nikon 1 AW1", -"Nikon 1 J1", -"Nikon 1 J2", -"Nikon 1 J3", -"Nikon 1 J4", -"Nikon 1 J5", -"Nikon 1 S1", -"Nikon 1 S2", -"Nikon 1 V1", -"Nikon 1 V2", -"Nikon 1 V3", -"Nikon E700 (\"DIAG RAW\" hack)", -"Nikon E800 (\"DIAG RAW\" hack)", -"Nikon E880 (\"DIAG RAW\" hack)", -"Nikon E900 (\"DIAG RAW\" hack)", -"Nikon E950 (\"DIAG RAW\" hack)", -"Nikon E990 (\"DIAG RAW\" hack)", -"Nikon E995 (\"DIAG RAW\" hack)", -"Nikon E2100 (\"DIAG RAW\" hack)", -"Nikon E2500 (\"DIAG RAW\" hack)", -"Nikon E3200 (\"DIAG RAW\" hack)", -"Nikon E3700 (\"DIAG RAW\" hack)", -"Nikon E4300 (\"DIAG RAW\" hack)", -"Nikon E4500 (\"DIAG RAW\" hack)", -"Nikon E5000", -"Nikon E5400", -"Nikon E5700", -"Nikon E8400", -"Nikon E8700", -"Nikon E8800", -"Nikon Coolpix A", -"Nikon Coolpix P330", -"Nikon Coolpix P340", -"Nikon Coolpix P6000", -"Nikon Coolpix P7000", -"Nikon Coolpix P7100", -"Nikon Coolpix P7700", -"Nikon Coolpix P7800", -"Nikon Coolpix S6 (\"DIAG RAW\" hack)", -"Nikon Coolscan NEF", -"Nokia N95", -"Nokia X2", -"Nokia 1200x1600", -"Nokia Lumia 950 XL", -"Nokia Lumia 1020", -"Nokia Lumia 1520", -"Olympus AIR A01", -"Olympus C3030Z", -"Olympus C5050Z", -"Olympus C5060Z", -"Olympus C7070WZ", -"Olympus C70Z,C7000Z", -"Olympus C740UZ", -"Olympus C770UZ", -"Olympus C8080WZ", -"Olympus X200,D560Z,C350Z", -"Olympus E-1", -"Olympus E-3", -"Olympus E-5", -"Olympus E-10", -"Olympus E-20", -"Olympus E-30", -"Olympus E-300", -"Olympus E-330", -"Olympus E-400", -"Olympus E-410", -"Olympus E-420", -"Olympus E-450", -"Olympus E-500", -"Olympus E-510", -"Olympus E-520", -"Olympus E-600", -"Olympus E-620", -"Olympus E-P1", -"Olympus E-P2", -"Olympus E-P3", -"Olympus E-P5", -"Olympus E-PL1", -"Olympus E-PL1s", -"Olympus E-PL2", -"Olympus E-PL3", -"Olympus E-PL5", -"Olympus E-PL6", -"Olympus E-PL7", -"Olympus E-PL8", -"Olympus E-PM1", -"Olympus E-PM2", -"Olympus E-M1", -"Olympus E-M1 Mark II", -"Olympus E-M10", -"Olympus E-M10 Mark II", -"Olympus E-M5", -"Olympus E-M5 Mark II", -"Olympus Pen F", -"Olympus SP310", -"Olympus SP320", -"Olympus SP350", -"Olympus SP500UZ", -"Olympus SP510UZ", -"Olympus SP550UZ", -"Olympus SP560UZ", -"Olympus SP565UZ", -"Olympus SP570UZ", -"Olympus STYLUS1", -"Olympus STYLUS1s", -"Olympus SH-2", -"Olympus SH-3", -"Olympus TG-4", -"Olympus XZ-1", -"Olympus XZ-2", -"Olympus XZ-10", -"OmniVision 4688", -"OmniVision OV5647", -"OmniVision OV5648", -"OmniVision OV8850", -"OmniVision 13860", -"Panasonic DMC-CM1", -"Panasonic DMC-FZ8", -"Panasonic DMC-FZ18", -"Panasonic DMC-FZ28", -"Panasonic DMC-FZ30", -"Panasonic DMC-FZ35/FZ38", -"Panasonic DMC-FZ40", -"Panasonic DMC-FZ50", -"Panasonic DMC-FZ7", -"Panasonic DMC-FZ70", -"Panasonic DMC-FZ100", -"Panasonic DMC-FZ150", -"Panasonic DMC-FZ200", -"Panasonic DMC-FZ300/330", -"Panasonic DMC-FZ1000", -"Panasonic DMC-FZ2000/2500/FZH1", -"Panasonic DMC-FX150", -"Panasonic DMC-G1", -"Panasonic DMC-G10", -"Panasonic DMC-G2", -"Panasonic DMC-G3", -"Panasonic DMC-G5", -"Panasonic DMC-G6", -"Panasonic DMC-G7/G70", -"Panasonic DMC-G8/80/81/85", -"Panasonic DMC-GF1", -"Panasonic DMC-GF2", -"Panasonic DMC-GF3", -"Panasonic DMC-GF5", -"Panasonic DMC-GF6", -"Panasonic DMC-GF7", -"Panasonic DMC-GH1", -"Panasonic DMC-GH2", -"Panasonic DMC-GH3", -"Panasonic DMC-GH4", -"Panasonic AG-GH4", -"Panasonic DMC-GM1", -"Panasonic DMC-GM1s", -"Panasonic DMC-GM5", -"Panasonic DMC-GX1", -"Panasonic DMC-GX7", -"Panasonic DMC-GX8", -"Panasonic DMC-GX80/85", -"Panasonic DMC-L1", -"Panasonic DMC-L10", -"Panasonic DMC-LC1", -"Panasonic DMC-LX1", -"Panasonic DMC-LF1", -"Panasonic DMC-LX2", -"Panasonic DMC-LX3", -"Panasonic DMC-LX5", -"Panasonic DMC-LX7", -"Panasonic DMC-LX9/10/15", -"Panasonic DMC-LX100", -"Panasonic DMC-TZ60/61/SZ40", -"Panasonic DMC-TZ70/71/ZS50", -"Panasonic DMC-TZ80/81/85/ZS60", -"Panasonic DMC-TZ100/101/ZS100", -"Pentax *ist D", -"Pentax *ist DL", -"Pentax *ist DL2", -"Pentax *ist DS", -"Pentax *ist DS2", -"Pentax GR", -"Pentax K10D", -"Pentax K20D", -"Pentax K100D", -"Pentax K100D Super", -"Pentax K110D", -"Pentax K200D", -"Pentax K2000/K-m", -"Pentax K-x", -"Pentax K-r", -"Pentax K-01", -"Pentax K-1", -"Pentax K-3", -"Pentax K-3 II", -"Pentax K-30", -"Pentax K-5", -"Pentax K-5 II", -"Pentax K-5 IIs", -"Pentax K-50", -"Pentax K-500", -"Pentax K-7", -"Pentax K-70", -"Pentax K-S1", -"Pentax K-S2", -"Pentax MX-1", -"Pentax Q", -"Pentax Q7", -"Pentax Q10", -"Pentax QS-1", -"Pentax Optio S", -"Pentax Optio S4", -"Pentax Optio 33WR", -"Pentax Optio 750Z", -"Pentax 645D", -"Pentax 645Z", -"PhaseOne IQ140", -"PhaseOne IQ150", -"PhaseOne IQ160", -"PhaseOne IQ180", -"PhaseOne IQ180 IR", -"PhaseOne IQ250", -"PhaseOne IQ260", -"PhaseOne IQ260 Achromatic", -"PhaseOne IQ280", -"PhaseOne IQ3 50MP", -"PhaseOne IQ3 60MP", -"PhaseOne IQ3 80MP", -"PhaseOne IQ3 100MP", -"PhaseOne LightPhase", -"PhaseOne Achromatic+", -"PhaseOne H 10", -"PhaseOne H 20", -"PhaseOne H 25", -"PhaseOne P 20", -"PhaseOne P 20+", -"PhaseOne P 21", -"PhaseOne P 25", -"PhaseOne P 25+", -"PhaseOne P 30", -"PhaseOne P 30+", -"PhaseOne P 40+", -"PhaseOne P 45", -"PhaseOne P 45+", -"PhaseOne P 65", -"PhaseOne P 65+", -"Photron BC2-HD", -"Pixelink A782", -"Polaroid x530", -"RaspberryPi Camera", -"RaspberryPi Camera V2", -"Ricoh GR", -"Ricoh GR Digital", -"Ricoh GR Digital II", -"Ricoh GR Digital III", -"Ricoh GR Digital IV", -"Ricoh GR II", -"Ricoh GX100", -"Ricoh GX200", -"Ricoh GXR MOUNT A12", -"Ricoh GXR MOUNT A16 24-85mm F3.5-5.5", -"Ricoh GXR, S10 24-72mm F2.5-4.4 VC", -"Ricoh GXR, GR A12 50mm F2.5 MACRO", -"Ricoh GXR, GR LENS A12 28mm F2.5", -"Ricoh GXR, GXR P10", +static const char *static_camera_list[] = { + "Adobe Digital Negative (DNG)", + "AgfaPhoto DC-833m", + "Alcatel 5035D", + "Apple iPad Pro", + "Apple iPhone SE", + "Apple iPhone 6s", + "Apple iPhone 6 plus", + "Apple iPhone 7", + "Apple iPhone 7 plus", + "Apple iPhone 8", + "Apple iPhone 8 plus", + "Apple iPhone X", + "Apple QuickTake 100", + "Apple QuickTake 150", + "Apple QuickTake 200", + "ARRIRAW format", + "AVT F-080C", + "AVT F-145C", + "AVT F-201C", + "AVT F-510C", + "AVT F-810C", + "Baumer TXG14", + "BlackMagic Cinema Camera", + "BlackMagic Micro Cinema Camera", + "BlackMagic Pocket Cinema Camera", + "BlackMagic Production Camera 4k", + "BlackMagic URSA", + "BlackMagic URSA Mini 4k", + "BlackMagic URSA Mini 4.6k", + "BlackMagic URSA Mini Pro 4.6k", + "Canon PowerShot 600", + "Canon PowerShot A5", + "Canon PowerShot A5 Zoom", + "Canon PowerShot A50", + "Canon PowerShot A410 (CHDK hack)", + "Canon PowerShot A460 (CHDK hack)", + "Canon PowerShot A470 (CHDK hack)", + "Canon PowerShot A530 (CHDK hack)", + "Canon PowerShot A540 (CHDK hack)", + "Canon PowerShot A550 (CHDK hack)", + "Canon PowerShot A570 (CHDK hack)", + "Canon PowerShot A590 (CHDK hack)", + "Canon PowerShot A610 (CHDK hack)", + "Canon PowerShot A620 (CHDK hack)", + "Canon PowerShot A630 (CHDK hack)", + "Canon PowerShot A640 (CHDK hack)", + "Canon PowerShot A650 (CHDK hack)", + "Canon PowerShot A710 IS (CHDK hack)", + "Canon PowerShot A720 IS (CHDK hack)", + "Canon PowerShot A3300 IS (CHDK hack)", + "Canon PowerShot D10 (CHDK hack)", + "Canon PowerShot ELPH 130 IS (CHDK hack)", + "Canon PowerShot ELPH 160 IS (CHDK hack)", + "Canon PowerShot Pro70", + "Canon PowerShot Pro90 IS", + "Canon PowerShot Pro1", + "Canon PowerShot G1", + "Canon PowerShot G1 X", + "Canon PowerShot G1 X Mark II", + "Canon PowerShot G1 X Mark III", + "Canon PowerShot G2", + "Canon PowerShot G3", + "Canon PowerShot G3 X", + "Canon PowerShot G5", + "Canon PowerShot G5 X", + "Canon PowerShot G6", + "Canon PowerShot G7 (CHDK hack)", + "Canon PowerShot G7 X", + "Canon PowerShot G7 X Mark II", + "Canon PowerShot G9", + "Canon PowerShot G9 X", + "Canon PowerShot G9 X Mark II", + "Canon PowerShot G10", + "Canon PowerShot G11", + "Canon PowerShot G12", + "Canon PowerShot G15", + "Canon PowerShot G16", + "Canon PowerShot S2 IS (CHDK hack)", + "Canon PowerShot S3 IS (CHDK hack)", + "Canon PowerShot S5 IS (CHDK hack)", + "Canon PowerShot SD300 (CHDK hack)", + "Canon PowerShot SD750 (CHDK hack)", + "Canon PowerShot SD950 (CHDK hack)", + "Canon PowerShot S30", + "Canon PowerShot S40", + "Canon PowerShot S45", + "Canon PowerShot S50", + "Canon PowerShot S60", + "Canon PowerShot S70", + "Canon PowerShot S90", + "Canon PowerShot S95", + "Canon PowerShot S100", + "Canon PowerShot S110", + "Canon PowerShot S120", + "Canon PowerShot SX1 IS", + "Canon PowerShot SX50 HS", + "Canon PowerShot SX60 HS", + "Canon PowerShot SX100 IS (CHDK hack)", + "Canon PowerShot SX110 IS (CHDK hack)", + "Canon PowerShot SX120 IS (CHDK hack)", + "Canon PowerShot SX130 IS (CHDK hack)", + "Canon PowerShot SX160 IS (CHDK hack)", + "Canon PowerShot SX220 HS (CHDK hack)", + "Canon PowerShot SX510 HS (CHDK hack)", + "Canon PowerShot SX10 IS (CHDK hack)", + "Canon PowerShot SX20 IS (CHDK hack)", + "Canon PowerShot SX30 IS (CHDK hack)", + "Canon PowerShot IXUS 160 (CHDK hack)", + "Canon PowerShot IXUS 900Ti (CHDK hack)", + "Canon EOS D30", + "Canon EOS D60", + "Canon EOS 5D", + "Canon EOS 5DS", + "Canon EOS 5DS R", + "Canon EOS 5D Mark II", + "Canon EOS 5D Mark III", + "Canon EOS 5D Mark IV", + "Canon EOS 6D", + "Canon EOS 6D Mark II", + "Canon EOS 7D", + "Canon EOS 7D Mark II", + "Canon EOS 10D", + "Canon EOS 20D", + "Canon EOS 20Da", + "Canon EOS 30D", + "Canon EOS 40D", + "Canon EOS 50D", + "Canon EOS 60D", + "Canon EOS 60Da", + "Canon EOS 70D", + "Canon EOS 77D", + "Canon EOS 80D", + "Canon EOS 200D", + "Canon EOS 300D / Digital Rebel / Kiss Digital", + "Canon EOS 350D / Digital Rebel XT / Kiss Digital N", + "Canon EOS 400D / Digital Rebel XTi / Kiss Digital X", + "Canon EOS 450D / Digital Rebel XSi / Kiss Digital X2", + "Canon EOS 500D / Digital Rebel T1i / Kiss Digital X3", + "Canon EOS 550D / Digital Rebel T2i / Kiss Digital X4", + "Canon EOS 600D / Digital Rebel T3i / Kiss Digital X5", + "Canon EOS 650D / Digital Rebel T4i / Kiss Digital X6i", + "Canon EOS 700D / Digital Rebel T5i", + "Canon EOS 750D / Digital Rebel T6i", + "Canon EOS 760D / Digital Rebel T6S", + "Canon EOS 800D", + "Canon EOS 100D / Digital Rebel SL1", + "Canon EOS 1000D / Digital Rebel XS / Kiss Digital F", + "Canon EOS 1100D / Digital Rebel T3 / Kiss Digital X50", + "Canon EOS 1200D", + "Canon EOS 1300D", + "Canon EOS C500", + "Canon EOS D2000C", + "Canon EOS M", + "Canon EOS M2", + "Canon EOS M3", + "Canon EOS M5", + "Canon EOS M6", + "Canon EOS M10", + "Canon EOS M100", + "Canon EOS-1D", + "Canon EOS-1DS", + "Canon EOS-1D C", + "Canon EOS-1D X", + "Canon EOS-1D Mark II", + "Canon EOS-1D Mark II N", + "Canon EOS-1D Mark III", + "Canon EOS-1D Mark IV", + "Canon EOS-1Ds Mark II", + "Canon EOS-1Ds Mark III", + "Canon EOS-1D X Mark II", + "Casio QV-2000UX", + "Casio QV-3000EX", + "Casio QV-3500EX", + "Casio QV-4000", + "Casio QV-5700", + "Casio QV-R41", + "Casio QV-R51", + "Casio QV-R61", + "Casio EX-F1", + "Casio EX-FC300S", + "Casio EX-FC400S", + "Casio EX-FH20", + "Casio EX-FH25", + "Casio EX-FH100", + "Casio EX-P600", + "Casio EX-S20", + "Casio EX-S100", + "Casio EX-Z4", + "Casio EX-Z50", + "Casio EX-Z500", + "Casio EX-Z55", + "Casio EX-Z60", + "Casio EX-Z75", + "Casio EX-Z750", + "Casio EX-Z8", + "Casio EX-Z850", + "Casio EX-Z1050", + "Casio EX-ZR100", + "Casio EX-Z1080", + "Casio EX-ZR700", + "Casio EX-ZR710", + "Casio EX-ZR750", + "Casio EX-ZR800", + "Casio EX-ZR850", + "Casio EX-ZR1000", + "Casio EX-ZR1100", + "Casio EX-ZR1200", + "Casio EX-ZR1300", + "Casio EX-ZR1500", + "Casio EX-ZR3000", + "Casio EX-ZR4000/5000", + "Casio EX-ZR4100/5100", + "Casio EX-100", + "Casio EX-100F", + "Casio EX-10", + "Casio Exlim Pro 505", + "Casio Exlim Pro 600", + "Casio Exlim Pro 700", + "Contax N Digital", + "Creative PC-CAM 600", + "Digital Bolex D16", + "Digital Bolex D16M", + "DJI 4384x3288", + "DJI Phantom4 Pro/Pro+", + "DJI Zenmuse X5", + "DJI Zenmuse X5R", + "DXO One", + "Epson R-D1", + "Epson R-D1s", + "Epson R-D1x", + "Foculus 531C", + "FujiFilm E505", + "FujiFilm E550", + "FujiFilm E900", + "FujiFilm F700", + "FujiFilm F710", + "FujiFilm F800", + "FujiFilm F810", + "FujiFilm S2Pro", + "FujiFilm S3Pro", + "FujiFilm S5Pro", + "FujiFilm S20Pro", + "FujiFilm S1", + "FujiFilm S100FS", + "FujiFilm S5000", + "FujiFilm S5100/S5500", + "FujiFilm S5200/S5600", + "FujiFilm S6000fd", + "FujiFilm S6500fd", + "FujiFilm S7000", + "FujiFilm S9000/S9500", + "FujiFilm S9100/S9600", + "FujiFilm S200EXR", + "FujiFilm S205EXR", + "FujiFilm SL1000", + "FujiFilm HS10/HS11", + "FujiFilm HS20EXR", + "FujiFilm HS22EXR", + "FujiFilm HS30EXR", + "FujiFilm HS33EXR", + "FujiFilm HS35EXR", + "FujiFilm HS50EXR", + "FujiFilm F505EXR", + "FujiFilm F550EXR", + "FujiFilm F600EXR", + "FujiFilm F605EXR", + "FujiFilm F770EXR", + "FujiFilm F775EXR", + "FujiFilm F800EXR", + "FujiFilm F900EXR", + "FujiFilm GFX 50S", + "FujiFilm X-Pro1", + "FujiFilm X-Pro2", + "FujiFilm X-S1", + "FujiFilm XQ1", + "FujiFilm XQ2", + "FujiFilm X100", + "FujiFilm X100f", + "FujiFilm X100S", + "FujiFilm X100T", + "FujiFilm X10", + "FujiFilm X20", + "FujiFilm X30", + "FujiFilm X70", + "FujiFilm X-A1", + "FujiFilm X-A2", + "FujiFilm X-A3", + "FujiFilm X-A5", + "FujiFilm X-A10", + "FujiFilm X-A20", + "FujiFilm X-E1", + "FujiFilm X-E2", + "FujiFilm X-E2S", + "FujiFilm X-E3", + "FujiFilm X-M1", + "FujiFilm XF1", + "FujiFilm X-H1", + "FujiFilm X-T1", + "FujiFilm X-T1 Graphite Silver", + "FujiFilm X-T2", + "FujiFilm X-T10", + "FujiFilm X-T20", + "FujiFilm IS-1", + "Gione E7", + "GITUP GIT2", + "GITUP GIT2P", + "Google Pixel", + "Google Pixel XL", + "Hasselblad H2D-22", + "Hasselblad H2D-39", + "Hasselblad H3DII-22", + "Hasselblad H3DII-31", + "Hasselblad H3DII-39", + "Hasselblad H3DII-50", + "Hasselblad H3D-22", + "Hasselblad H3D-31", + "Hasselblad H3D-39", + "Hasselblad H4D-60", + "Hasselblad H4D-50", + "Hasselblad H4D-40", + "Hasselblad H4D-31", + "Hasselblad H5D-60", + "Hasselblad H5D-50", + "Hasselblad H5D-50c", + "Hasselblad H5D-40", + "Hasselblad H6D-100c", + "Hasselblad A6D-100c", // Aerial camera + "Hasselblad CFV", + "Hasselblad CFV-50", + "Hasselblad CFH", + "Hasselblad CF-22", + "Hasselblad CF-31", + "Hasselblad CF-39", + "Hasselblad V96C", + "Hasselblad Lusso", + "Hasselblad Lunar", + "Hasselblad True Zoom", + "Hasselblad Stellar", + "Hasselblad Stellar II", + "Hasselblad HV", + "Hasselblad X1D", + "HTC UltraPixel", + "HTC MyTouch 4G", + "HTC One (A9)", + "HTC One (M9)", + "HTC 10", + "Huawei P9 (EVA-L09/AL00)", + "Huawei Honor6a", + "Huawei Honor9", + "Huawei Mate10 (BLA-L29)", + "Imacon Ixpress 96, 96C", + "Imacon Ixpress 384, 384C (single shot only)", + "Imacon Ixpress 132C", + "Imacon Ixpress 528C (single shot only)", + "ISG 2020x1520", + "Ikonoskop A-Cam dII Panchromatic", + "Ikonoskop A-Cam dII", + "Kinefinity KineMINI", + "Kinefinity KineRAW Mini", + "Kinefinity KineRAW S35", + "Kodak DC20", + "Kodak DC25", + "Kodak DC40", + "Kodak DC50", + "Kodak DC120", + "Kodak DCS200", + "Kodak DCS315C", + "Kodak DCS330C", + "Kodak DCS420", + "Kodak DCS460", + "Kodak DCS460A", + "Kodak DCS460D", + "Kodak DCS520C", + "Kodak DCS560C", + "Kodak DCS620C", + "Kodak DCS620X", + "Kodak DCS660C", + "Kodak DCS660M", + "Kodak DCS720X", + "Kodak DCS760C", + "Kodak DCS760M", + "Kodak EOSDCS1", + "Kodak EOSDCS3B", + "Kodak NC2000F", + "Kodak ProBack", + "Kodak PB645C", + "Kodak PB645H", + "Kodak PB645M", + "Kodak DCS Pro 14n", + "Kodak DCS Pro 14nx", + "Kodak DCS Pro SLR/c", + "Kodak DCS Pro SLR/n", + "Kodak C330", + "Kodak C603", + "Kodak P850", + "Kodak P880", + "Kodak S-1", + "Kodak Z980", + "Kodak Z981", + "Kodak Z990", + "Kodak Z1015", + "Kodak KAI-0340", + "Konica KD-400Z", + "Konica KD-510Z", + "Leaf AFi 5", + "Leaf AFi 6", + "Leaf AFi 7", + "Leaf AFi-II 6", + "Leaf AFi-II 7", + "Leaf AFi-II 10", + "Leaf AFi-II 10R", + "Leaf Aptus-II 5", + "Leaf Aptus-II 6", + "Leaf Aptus-II 7", + "Leaf Aptus-II 8", + "Leaf Aptus-II 10", + "Leaf Aptus-II 12", + "Leaf Aptus-II 12R", + "Leaf Aptus 17", + "Leaf Aptus 22", + "Leaf Aptus 54S", + "Leaf Aptus 65", + "Leaf Aptus 65S", + "Leaf Aptus 75", + "Leaf Aptus 75S", + "Leaf Cantare", + "Leaf Cantare XY", + "Leaf CatchLight", + "Leaf CMost", + "Leaf Credo 40", + "Leaf Credo 50", + "Leaf Credo 60", + "Leaf Credo 80 (low compression mode only)", + "Leaf DCB-II", + "Leaf Valeo 6", + "Leaf Valeo 11", + "Leaf Valeo 17", + "Leaf Valeo 17wi", + "Leaf Valeo 22", + "Leaf Valeo 22wi", + "Leaf Volare", + "Lenovo a820", + "Leica C (Typ 112)", + "Leica CL", + "Leica Digilux 2", + "Leica Digilux 3", + "Leica Digital-Modul-R", + "Leica D-LUX2", + "Leica D-LUX3", + "Leica D-LUX4", + "Leica D-LUX5", + "Leica D-LUX6", + "Leica D-Lux (Typ 109)", + "Leica M8", + "Leica M8.2", + "Leica M9", + "Leica M10", + "Leica M (Typ 240)", + "Leica M (Typ 262)", + "Leica Monochrom (Typ 240)", + "Leica Monochrom (Typ 246)", + "Leica M-D (Typ 262)", + "Leica M-E", + "Leica M-P", + "Leica R8", + "Leica Q (Typ 116)", + "Leica S", + "Leica S2", + "Leica S (Typ 007)", + "Leica SL (Typ 601)", + "Leica T (Typ 701)", + "Leica TL", + "Leica TL2", + "Leica X1", + "Leica X (Typ 113)", + "Leica X2", + "Leica X-E (Typ 102)", + "Leica X-U (Typ 113)", + "Leica V-LUX1", + "Leica V-LUX2", + "Leica V-LUX3", + "Leica V-LUX4", + "Leica V-Lux (Typ 114)", + "Leica X VARIO (Typ 107)", + "LG G3", + "LG G4", + "LG V20 (F800K)", + "LG VS995", + "Logitech Fotoman Pixtura", + "Mamiya ZD", + "Matrix 4608x3288", + "Meizy MX4", + "Micron 2010", + "Minolta RD175", + "Minolta DiMAGE 5", + "Minolta DiMAGE 7", + "Minolta DiMAGE 7i", + "Minolta DiMAGE 7Hi", + "Minolta DiMAGE A1", + "Minolta DiMAGE A2", + "Minolta DiMAGE A200", + "Minolta DiMAGE G400", + "Minolta DiMAGE G500", + "Minolta DiMAGE G530", + "Minolta DiMAGE G600", + "Minolta DiMAGE Z2", + "Minolta Alpha/Dynax/Maxxum 5D", + "Minolta Alpha/Dynax/Maxxum 7D", + "Motorola PIXL", + "Nikon D1", + "Nikon D1H", + "Nikon D1X", + "Nikon D2H", + "Nikon D2Hs", + "Nikon D2X", + "Nikon D2Xs", + "Nikon D3", + "Nikon D3s", + "Nikon D3X", + "Nikon D4", + "Nikon D4s", + "Nikon D40", + "Nikon D40X", + "Nikon D5", + "Nikon D50", + "Nikon D60", + "Nikon D70", + "Nikon D70s", + "Nikon D80", + "Nikon D90", + "Nikon D100", + "Nikon D200", + "Nikon D300", + "Nikon D300s", + "Nikon D500", + "Nikon D600", + "Nikon D610", + "Nikon D700", + "Nikon D750", + "Nikon D800", + "Nikon D800E", + "Nikon D810", + "Nikon D810A", + "Nikon D850", + "Nikon D3000", + "Nikon D3100", + "Nikon D3200", + "Nikon D3300", + "Nikon D3400", + "Nikon D5000", + "Nikon D5100", + "Nikon D5200", + "Nikon D5300", + "Nikon D5500", + "Nikon D5600", + "Nikon D7000", + "Nikon D7100", + "Nikon D7200", + "Nikon D7500", + "Nikon Df", + "Nikon 1 AW1", + "Nikon 1 J1", + "Nikon 1 J2", + "Nikon 1 J3", + "Nikon 1 J4", + "Nikon 1 J5", + "Nikon 1 S1", + "Nikon 1 S2", + "Nikon 1 V1", + "Nikon 1 V2", + "Nikon 1 V3", + "Nikon E700 (\"DIAG RAW\" hack)", + "Nikon E800 (\"DIAG RAW\" hack)", + "Nikon E880 (\"DIAG RAW\" hack)", + "Nikon E900 (\"DIAG RAW\" hack)", + "Nikon E950 (\"DIAG RAW\" hack)", + "Nikon E990 (\"DIAG RAW\" hack)", + "Nikon E995 (\"DIAG RAW\" hack)", + "Nikon E2100 (\"DIAG RAW\" hack)", + "Nikon E2500 (\"DIAG RAW\" hack)", + "Nikon E3200 (\"DIAG RAW\" hack)", + "Nikon E3700 (\"DIAG RAW\" hack)", + "Nikon E4300 (\"DIAG RAW\" hack)", + "Nikon E4500 (\"DIAG RAW\" hack)", + "Nikon E5000", + "Nikon E5400", + "Nikon E5700", + "Nikon E8400", + "Nikon E8700", + "Nikon E8800", + "Nikon Coolpix A", + "Nikon Coolpix B700", + "Nikon Coolpix P330", + "Nikon Coolpix P340", + "Nikon Coolpix P6000", + "Nikon Coolpix P7000", + "Nikon Coolpix P7100", + "Nikon Coolpix P7700", + "Nikon Coolpix P7800", + "Nikon Coolpix S6 (\"DIAG RAW\" hack)", + "Nikon Coolscan NEF", + "Nokia N95", + "Nokia X2", + "Nokia 1200x1600", + "Nokia Lumia 950 XL", + "Nokia Lumia 1020", + "Nokia Lumia 1520", + "Olympus AIR A01", + "Olympus C3030Z", + "Olympus C5050Z", + "Olympus C5060Z", + "Olympus C7070WZ", + "Olympus C70Z,C7000Z", + "Olympus C740UZ", + "Olympus C770UZ", + "Olympus C8080WZ", + "Olympus X200,D560Z,C350Z", + "Olympus E-1", + "Olympus E-3", + "Olympus E-5", + "Olympus E-10", + "Olympus E-20", + "Olympus E-30", + "Olympus E-300", + "Olympus E-330", + "Olympus E-400", + "Olympus E-410", + "Olympus E-420", + "Olympus E-450", + "Olympus E-500", + "Olympus E-510", + "Olympus E-520", + "Olympus E-600", + "Olympus E-620", + "Olympus E-P1", + "Olympus E-P2", + "Olympus E-P3", + "Olympus E-P5", + "Olympus E-PL1", + "Olympus E-PL1s", + "Olympus E-PL2", + "Olympus E-PL3", + "Olympus E-PL5", + "Olympus E-PL6", + "Olympus E-PL7", + "Olympus E-PL8", + "Olympus E-PL9", + "Olympus E-PM1", + "Olympus E-PM2", + "Olympus E-M1", + "Olympus E-M1 Mark II", + "Olympus E-M10", + "Olympus E-M10 Mark II", + "Olympus E-M10 Mark III", + "Olympus E-M5", + "Olympus E-M5 Mark II", + "Olympus Pen F", + "Olympus SP310", + "Olympus SP320", + "Olympus SP350", + "Olympus SP500UZ", + "Olympus SP510UZ", + "Olympus SP550UZ", + "Olympus SP560UZ", + "Olympus SP565UZ", + "Olympus SP570UZ", + "Olympus STYLUS1", + "Olympus STYLUS1s", + "Olympus SH-2", + "Olympus SH-3", + "Olympus TG-4", + "Olympus TG-5", + "Olympus XZ-1", + "Olympus XZ-2", + "Olympus XZ-10", + "OmniVision 4688", + "OmniVision OV5647", + "OmniVision OV5648", + "OmniVision OV8850", + "OmniVision 13860", + "OnePlus One", + "OnePlus A3303", + "OnePlus A5000", + "Panasonic DMC-CM1", + "Panasonic DMC-FZ8", + "Panasonic DMC-FZ18", + "Panasonic DMC-FZ28", + "Panasonic DMC-FZ30", + "Panasonic DMC-FZ35/FZ38", + "Panasonic DMC-FZ40", + "Panasonic DMC-FZ45", + "Panasonic DMC-FZ50", + "Panasonic DMC-FZ7", + "Panasonic DMC-FZ70", + "Panasonic DMC-FZ72", + "Panasonic DC-FZ80/82", + "Panasonic DMC-FZ100", + "Panasonic DMC-FZ150", + "Panasonic DMC-FZ200", + "Panasonic DMC-FZ300/330", + "Panasonic DMC-FZ1000", + "Panasonic DMC-FZ2000/2500/FZH1", + "Panasonic DMC-FX150", + "Panasonic DMC-G1", + "Panasonic DMC-G10", + "Panasonic DMC-G2", + "Panasonic DMC-G3", + "Panasonic DMC-G5", + "Panasonic DMC-G6", + "Panasonic DMC-G7/G70", + "Panasonic DMC-G8/80/81/85", + "Panasonic DC-G9", + "Panasonic DMC-GF1", + "Panasonic DMC-GF2", + "Panasonic DMC-GF3", + "Panasonic DMC-GF5", + "Panasonic DMC-GF6", + "Panasonic DMC-GF7", + "Panasonic DC-GF10/GF90", + "Panasonic DMC-GH1", + "Panasonic DMC-GH2", + "Panasonic DMC-GH3", + "Panasonic DMC-GH4", + "Panasonic AG-GH4", + "Panasonic DC-GH5", + "Panasonic DC-GH5S", + "Panasonic DMC-GM1", + "Panasonic DMC-GM1s", + "Panasonic DMC-GM5", + "Panasonic DMC-GX1", + "Panasonic DMC-GX7", + "Panasonic DMC-GX8", + "Panasonic DC-GX9", + "Panasonic DMC-GX80/85", + "Panasonic DC-GX800/850/GF9", + "Panasonic DMC-L1", + "Panasonic DMC-L10", + "Panasonic DMC-LC1", + "Panasonic DMC-LF1", + "Panasonic DMC-LX1", + "Panasonic DMC-LX2", + "Panasonic DMC-LX3", + "Panasonic DMC-LX5", + "Panasonic DMC-LX7", + "Panasonic DMC-LX9/10/15", + "Panasonic DMC-LX100", + "Panasonic DMC-TZ60/61/SZ40", + "Panasonic DMC-TZ70/71/ZS50", + "Panasonic DMC-TZ80/81/85/ZS60", + "Panasonic DC-ZS70 (DC-TZ90/91/92, DC-T93)", + "Panasonic DC-TZ100/101/ZS100", + "Panasonic DC-TZ200/ZS200", + "PARROT Bebop 2", + "PARROT Bebop Drone", + "Pentax *ist D", + "Pentax *ist DL", + "Pentax *ist DL2", + "Pentax *ist DS", + "Pentax *ist DS2", + "Pentax GR", + "Pentax K10D", + "Pentax K20D", + "Pentax K100D", + "Pentax K100D Super", + "Pentax K110D", + "Pentax K200D", + "Pentax K2000/K-m", + "Pentax KP", + "Pentax K-x", + "Pentax K-r", + "Pentax K-01", + "Pentax K-1", + "Pentax K-3", + "Pentax K-3 II", + "Pentax K-30", + "Pentax K-5", + "Pentax K-5 II", + "Pentax K-5 IIs", + "Pentax K-50", + "Pentax K-500", + "Pentax K-7", + "Pentax K-70", + "Pentax K-S1", + "Pentax K-S2", + "Pentax MX-1", + "Pentax Q", + "Pentax Q7", + "Pentax Q10", + "Pentax QS-1", + "Pentax Optio S", + "Pentax Optio S4", + "Pentax Optio 33WR", + "Pentax Optio 750Z", + "Pentax 645D", + "Pentax 645Z", + "PhaseOne IQ140", + "PhaseOne IQ150", + "PhaseOne IQ160", + "PhaseOne IQ180", + "PhaseOne IQ180 IR", + "PhaseOne IQ250", + "PhaseOne IQ260", + "PhaseOne IQ260 Achromatic", + "PhaseOne IQ280", + "PhaseOne IQ3 50MP", + "PhaseOne IQ3 60MP", + "PhaseOne IQ3 80MP", + "PhaseOne IQ3 100MP", + "PhaseOne IQ3 100MP Trichromatic", + "PhaseOne LightPhase", + "PhaseOne Achromatic+", + "PhaseOne H 10", + "PhaseOne H 20", + "PhaseOne H 25", + "PhaseOne P 20", + "PhaseOne P 20+", + "PhaseOne P 21", + "PhaseOne P 25", + "PhaseOne P 25+", + "PhaseOne P 30", + "PhaseOne P 30+", + "PhaseOne P 40+", + "PhaseOne P 45", + "PhaseOne P 45+", + "PhaseOne P 65", + "PhaseOne P 65+", + "Photron BC2-HD", + "Pixelink A782", + "Polaroid x530", + "RaspberryPi Camera", + "RaspberryPi Camera V2", + "Ricoh GR", + "Ricoh GR Digital", + "Ricoh GR Digital II", + "Ricoh GR Digital III", + "Ricoh GR Digital IV", + "Ricoh GR II", + "Ricoh GX100", + "Ricoh GX200", + "Ricoh GXR MOUNT A12", + "Ricoh GXR MOUNT A16 24-85mm F3.5-5.5", + "Ricoh GXR, S10 24-72mm F2.5-4.4 VC", + "Ricoh GXR, GR A12 50mm F2.5 MACRO", + "Ricoh GXR, GR LENS A12 28mm F2.5", + "Ricoh GXR, GXR P10", #ifndef NO_JASPER -"Redcode R3D format", + "Redcode R3D format", #endif -"Rollei d530flex", -"RoverShot 3320af", -"Samsung EX1", -"Samsung EX2F", -"Samsung GX-1L", -"Samsung GX-1S", -"Samsung GX10", -"Samsung GX20", -"Samsung Galaxy NX (EK-GN120)", -"Samsung Galaxy S7 (SM-G935F)", -"Samsung NX1", -"Samsung NX5", -"Samsung NX10", -"Samsung NX11", -"Samsung NX100", -"Samsung NX1000", -"Samsung NX1100", -"Samsung NX20", -"Samsung NX200", -"Samsung NX210", -"Samsung NX2000", -"Samsung NX30", -"Samsung NX300", -"Samsung NX300M", -"Samsung NX3000", -"Samsung NX500", -"Samsung NX mini", -"Samsung Pro815", -"Samsung WB550", -"Samsung WB2000", -"Samsung S85 (hacked)", -"Samsung S850 (hacked)", -"Samsung Galaxy S3", -"Samsung Galaxy S7", -"Samsung Galaxy S7 Edge", -"Samsung Galaxy Nexus", -"Sarnoff 4096x5440", -"Seitz 6x17", -"Seitz Roundshot D3", -"Seitz Roundshot D2X", -"Seitz Roundshot D2Xs", -"Sigma SD9", -"Sigma SD10", -"Sigma SD14", -"Sigma SD15", -"Sigma SD1", -"Sigma SD1 Merill", -"Sigma DP1", -"Sigma DP1 Merill", -"Sigma DP1S", -"Sigma DP1X", -"Sigma DP2", -"Sigma DP2 Merill", -"Sigma DP2S", -"Sigma DP2X", -"Sigma DP3 Merill", -"Sigma dp0 Quattro", -"Sigma dp1 Quattro", -"Sigma dp2 Quattro", -"Sigma dp3 Quattro", -"Sigma sd Quattro", -"Sigma sd Quattro H", -"Sinar eMotion 22", -"Sinar eMotion 54", -"Sinar eSpirit 65", -"Sinar eMotion 75", -"Sinar eVolution 75", -"Sinar 3072x2048", -"Sinar 4080x4080", -"Sinar 4080x5440", -"Sinar STI format", -"Sinar Sinarback 54", -"SMaL Ultra-Pocket 3", -"SMaL Ultra-Pocket 4", -"SMaL Ultra-Pocket 5", -"Sony A7", -"Sony A7 II", -"Sony A7R", -"Sony A7R II", -"Sony A7S", -"Sony A7S II", -"Sony ILCA-68 (A68)", -"Sony ILCA-77M2 (A77-II)", -"Sony ILCA-99M2 (A99-II)", -"Sony ILCE-3000", -"Sony ILCE-5000", -"Sony ILCE-5100", -"Sony ILCE-6000", -"Sony ILCE-6300", -"Sony ILCE-6500", -"Sony ILCE-QX1", -"Sony DSC-F828", -"Sony DSC-R1", -"Sony DSC-RX1", -"Sony DSC-RX1R", -"Sony DSC-RX1R II", -"Sony DSC-RX10", -"Sony DSC-RX10II", -"Sony DSC-RX10III", -"Sony DSC-RX100", -"Sony DSC-RX100II", -"Sony DSC-RX100III", -"Sony DSC-RX100IV", -"Sony DSC-RX100V", -"Sony DSC-V3", -"Sony DSLR-A100", -"Sony DSLR-A200", -"Sony DSLR-A230", -"Sony DSLR-A290", -"Sony DSLR-A300", -"Sony DSLR-A330", -"Sony DSLR-A350", -"Sony DSLR-A380", -"Sony DSLR-A390", -"Sony DSLR-A450", -"Sony DSLR-A500", -"Sony DSLR-A550", -"Sony DSLR-A560", -"Sony DSLR-A580", -"Sony DSLR-A700", -"Sony DSLR-A850", -"Sony DSLR-A900", -"Sony NEX-3", -"Sony NEX-3N", -"Sony NEX-5", -"Sony NEX-5N", -"Sony NEX-5R", -"Sony NEX-5T", -"Sony NEX-6", -"Sony NEX-7", -"Sony NEX-C3", -"Sony NEX-F3", -"Sony NEX-VG20", -"Sony NEX-VG30", -"Sony NEX-VG900", -"Sony SLT-A33", -"Sony SLT-A35", -"Sony SLT-A37", -"Sony SLT-A55V", -"Sony SLT-A57", -"Sony SLT-A58", -"Sony SLT-A65V", -"Sony SLT-A77V", -"Sony SLT-A99V", -"Sony XCD-SX910CR", -"Sony IMX135-mipi 13mp", -"Sony IMX135-QCOM", -"Sony IMX072-mipi", -"Sony IMX214", -"Sony IMX219", -"Sony IMX230", -"Sony IMX298-mipi 16mp", -"Sony IMX219-mipi 8mp", -"Sony Xperia L", -"STV680 VGA", -"PtGrey GRAS-50S5C", -"JaiPulnix BB-500CL", -"JaiPulnix BB-500GE", -"SVS SVS625CL", -"YUNEEC CGO4", -"Xiaomi MI3", -"Xiaomi RedMi Note3 Pro", - NULL + "Rollei d530flex", + "RoverShot 3320af", + "Samsung EX1", + "Samsung EX2F", + "Samsung GX-1L", + "Samsung GX-1S", + "Samsung GX10", + "Samsung GX20", + "Samsung Galaxy Nexus", + "Samsung Galaxy NX (EK-GN120)", + "Samsung Galaxy S3", + "Samsung Galaxy S6 (SM-G920F)", + "Samsung Galaxy S7", + "Samsung Galaxy S7 Edge", + "Samsung Galaxy S8 (SM-G950U)", + "Samsung NX1", + "Samsung NX5", + "Samsung NX10", + "Samsung NX11", + "Samsung NX100", + "Samsung NX1000", + "Samsung NX1100", + "Samsung NX20", + "Samsung NX200", + "Samsung NX210", + "Samsung NX2000", + "Samsung NX30", + "Samsung NX300", + "Samsung NX300M", + "Samsung NX3000", + "Samsung NX500", + "Samsung NX mini", + "Samsung Pro815", + "Samsung WB550", + "Samsung WB2000", + "Samsung S85 (hacked)", + "Samsung S850 (hacked)", + "Sarnoff 4096x5440", + "Seitz 6x17", + "Seitz Roundshot D3", + "Seitz Roundshot D2X", + "Seitz Roundshot D2Xs", + "Sigma SD9 (raw decode only)", + "Sigma SD10 (raw decode only)", + "Sigma SD14 (raw decode only)", + "Sigma SD15 (raw decode only)", + "Sigma SD1", + "Sigma SD1 Merill", + "Sigma DP1", + "Sigma DP1 Merill", + "Sigma DP1S", + "Sigma DP1X", + "Sigma DP2", + "Sigma DP2 Merill", + "Sigma DP2S", + "Sigma DP2X", + "Sigma DP3 Merill", + "Sigma dp0 Quattro", + "Sigma dp1 Quattro", + "Sigma dp2 Quattro", + "Sigma dp3 Quattro", + "Sigma sd Quattro", + "Sigma sd Quattro H", + "Sinar eMotion 22", + "Sinar eMotion 54", + "Sinar eSpirit 65", + "Sinar eMotion 75", + "Sinar eVolution 75", + "Sinar 3072x2048", + "Sinar 4080x4080", + "Sinar 4080x5440", + "Sinar STI format", + "Sinar Sinarback 54", + "SMaL Ultra-Pocket 3", + "SMaL Ultra-Pocket 4", + "SMaL Ultra-Pocket 5", + "Sony A7", + "Sony A7 II", + "Sony A7R", + "Sony A7R II", + "Sony A7R III", + "Sony A7S", + "Sony A7S II", + "Sony A9", + "Sony ILCA-68 (A68)", + "Sony ILCA-77M2 (A77-II)", + "Sony ILCA-99M2 (A99-II)", + "Sony ILCE-3000", + "Sony ILCE-5000", + "Sony ILCE-5100", + "Sony ILCE-6000", + "Sony ILCE-6300", + "Sony ILCE-6500", + "Sony ILCE-QX1", + "Sony DSC-F828", + "Sony DSC-R1", + "Sony DSC-RX0", + "Sony DSC-RX1", + "Sony DSC-RX1R", + "Sony DSC-RX1R II", + "Sony DSC-RX10", + "Sony DSC-RX10II", + "Sony DSC-RX10III", + "Sony DSC-RX10IV", + "Sony DSC-RX100", + "Sony DSC-RX100II", + "Sony DSC-RX100III", + "Sony DSC-RX100IV", + "Sony DSC-RX100V", + "Sony DSC-V3", + "Sony DSLR-A100", + "Sony DSLR-A200", + "Sony DSLR-A230", + "Sony DSLR-A290", + "Sony DSLR-A300", + "Sony DSLR-A330", + "Sony DSLR-A350", + "Sony DSLR-A380", + "Sony DSLR-A390", + "Sony DSLR-A450", + "Sony DSLR-A500", + "Sony DSLR-A550", + "Sony DSLR-A560", + "Sony DSLR-A580", + "Sony DSLR-A700", + "Sony DSLR-A850", + "Sony DSLR-A900", + "Sony NEX-3", + "Sony NEX-3N", + "Sony NEX-5", + "Sony NEX-5N", + "Sony NEX-5R", + "Sony NEX-5T", + "Sony NEX-6", + "Sony NEX-7", + "Sony NEX-C3", + "Sony NEX-F3", + "Sony NEX-VG20", + "Sony NEX-VG30", + "Sony NEX-VG900", + "Sony SLT-A33", + "Sony SLT-A35", + "Sony SLT-A37", + "Sony SLT-A55V", + "Sony SLT-A57", + "Sony SLT-A58", + "Sony SLT-A65V", + "Sony SLT-A77V", + "Sony SLT-A99V", + "Sony XCD-SX910CR", + "Sony IMX135-mipi 13mp", + "Sony IMX135-QCOM", + "Sony IMX072-mipi", + "Sony IMX214", + "Sony IMX219", + "Sony IMX230", + "Sony IMX298-mipi 16mp", + "Sony IMX219-mipi 8mp", + "Sony Xperia L", + "STV680 VGA", + "PtGrey GRAS-50S5C", + "JaiPulnix BB-500CL", + "JaiPulnix BB-500GE", + "SVS SVS625CL", + "Yi M1", + "YUNEEC CGO3", + "YUNEEC CGO3P", + "YUNEEC CGO4", + "Xiaomi MI3", + "Xiaomi RedMi Note3 Pro", + "Xiaoyi YIAC3 (YI 4k)", + NULL }; +// clang-format on -const char** LibRaw::cameraList() { return static_camera_list;} -int LibRaw::cameraCount() { return (sizeof(static_camera_list)/sizeof(static_camera_list[0]))-1; } - +const char **LibRaw::cameraList() { return static_camera_list; } +int LibRaw::cameraCount() { return (sizeof(static_camera_list) / sizeof(static_camera_list[0])) - 1; } -const char * LibRaw::strprogress(enum LibRaw_progress p) +const char *LibRaw::strprogress(enum LibRaw_progress p) { - switch(p) - { - case LIBRAW_PROGRESS_START: - return "Starting"; - case LIBRAW_PROGRESS_OPEN : - return "Opening file"; - case LIBRAW_PROGRESS_IDENTIFY : - return "Reading metadata"; - case LIBRAW_PROGRESS_SIZE_ADJUST: - return "Adjusting size"; - case LIBRAW_PROGRESS_LOAD_RAW: - return "Reading RAW data"; - case LIBRAW_PROGRESS_REMOVE_ZEROES: - return "Clearing zero values"; - case LIBRAW_PROGRESS_BAD_PIXELS : - return "Removing dead pixels"; - case LIBRAW_PROGRESS_DARK_FRAME: - return "Subtracting dark frame data"; - case LIBRAW_PROGRESS_FOVEON_INTERPOLATE: - return "Interpolating Foveon sensor data"; - case LIBRAW_PROGRESS_SCALE_COLORS: - return "Scaling colors"; - case LIBRAW_PROGRESS_PRE_INTERPOLATE: - return "Pre-interpolating"; - case LIBRAW_PROGRESS_INTERPOLATE: - return "Interpolating"; - case LIBRAW_PROGRESS_MIX_GREEN : - return "Mixing green channels"; - case LIBRAW_PROGRESS_MEDIAN_FILTER : - return "Median filter"; - case LIBRAW_PROGRESS_HIGHLIGHTS: - return "Highlight recovery"; - case LIBRAW_PROGRESS_FUJI_ROTATE : - return "Rotating Fuji diagonal data"; - case LIBRAW_PROGRESS_FLIP : - return "Flipping image"; - case LIBRAW_PROGRESS_APPLY_PROFILE: - return "ICC conversion"; - case LIBRAW_PROGRESS_CONVERT_RGB: - return "Converting to RGB"; - case LIBRAW_PROGRESS_STRETCH: - return "Stretching image"; - case LIBRAW_PROGRESS_THUMB_LOAD: - return "Loading thumbnail"; - default: - return "Some strange things"; - } + switch (p) + { + case LIBRAW_PROGRESS_START: + return "Starting"; + case LIBRAW_PROGRESS_OPEN: + return "Opening file"; + case LIBRAW_PROGRESS_IDENTIFY: + return "Reading metadata"; + case LIBRAW_PROGRESS_SIZE_ADJUST: + return "Adjusting size"; + case LIBRAW_PROGRESS_LOAD_RAW: + return "Reading RAW data"; + case LIBRAW_PROGRESS_REMOVE_ZEROES: + return "Clearing zero values"; + case LIBRAW_PROGRESS_BAD_PIXELS: + return "Removing dead pixels"; + case LIBRAW_PROGRESS_DARK_FRAME: + return "Subtracting dark frame data"; + case LIBRAW_PROGRESS_FOVEON_INTERPOLATE: + return "Interpolating Foveon sensor data"; + case LIBRAW_PROGRESS_SCALE_COLORS: + return "Scaling colors"; + case LIBRAW_PROGRESS_PRE_INTERPOLATE: + return "Pre-interpolating"; + case LIBRAW_PROGRESS_INTERPOLATE: + return "Interpolating"; + case LIBRAW_PROGRESS_MIX_GREEN: + return "Mixing green channels"; + case LIBRAW_PROGRESS_MEDIAN_FILTER: + return "Median filter"; + case LIBRAW_PROGRESS_HIGHLIGHTS: + return "Highlight recovery"; + case LIBRAW_PROGRESS_FUJI_ROTATE: + return "Rotating Fuji diagonal data"; + case LIBRAW_PROGRESS_FLIP: + return "Flipping image"; + case LIBRAW_PROGRESS_APPLY_PROFILE: + return "ICC conversion"; + case LIBRAW_PROGRESS_CONVERT_RGB: + return "Converting to RGB"; + case LIBRAW_PROGRESS_STRETCH: + return "Stretching image"; + case LIBRAW_PROGRESS_THUMB_LOAD: + return "Loading thumbnail"; + default: + return "Some strange things"; + } } #undef ID - #include "../internal/libraw_x3f.cpp" -void x3f_clear(void *p) -{ - x3f_delete((x3f_t*)p); -} +void x3f_clear(void *p) { x3f_delete((x3f_t *)p); } static void utf2char(utf16_t *str, char *buffer, unsigned bufsz) { if(bufsz<1) return; buffer[bufsz-1] = 0; char *b = buffer; while (*str != 0x00 && --bufsz>0) { char *chr = (char *)str; *b++ = *chr; str++; } *b = 0; } static void *lr_memmem(const void *l, size_t l_len, const void *s, size_t s_len) { - register char *cur, *last; - const char *cl = (const char *)l; - const char *cs = (const char *)s; + register char *cur, *last; + const char *cl = (const char *)l; + const char *cs = (const char *)s; - /* we need something to compare */ - if (l_len == 0 || s_len == 0) - return NULL; + /* we need something to compare */ + if (l_len == 0 || s_len == 0) + return NULL; - /* "s" must be smaller or equal to "l" */ - if (l_len < s_len) - return NULL; + /* "s" must be smaller or equal to "l" */ + if (l_len < s_len) + return NULL; - /* special case where s_len == 1 */ - if (s_len == 1) - return (void*)memchr(l, (int)*cs, l_len); + /* special case where s_len == 1 */ + if (s_len == 1) + return (void *)memchr(l, (int)*cs, l_len); - /* the last position where its possible to find "s" in "l" */ - last = (char *)cl + l_len - s_len; + /* the last position where its possible to find "s" in "l" */ + last = (char *)cl + l_len - s_len; - for (cur = (char *)cl; cur <= last; cur++) - if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0) - return cur; - return NULL; + for (cur = (char *)cl; cur <= last; cur++) + if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0) + return cur; + return NULL; } void LibRaw::parse_x3f() { x3f_t *x3f = x3f_new_from_file(libraw_internal_data.internal_data.input); - if(!x3f) - return; + if (!x3f) + return; _x3f_data = x3f; x3f_header_t *H = NULL; x3f_directory_section_t *DS = NULL; H = &x3f->header; // Parse RAW size from RAW section x3f_directory_entry_t *DE = x3f_get_raw(x3f); - if(!DE) return; + if (!DE) + return; imgdata.sizes.flip = H->rotation; x3f_directory_entry_header_t *DEH = &DE->header; x3f_image_data_t *ID = &DEH->data_subsection.image_data; imgdata.sizes.raw_width = ID->columns; imgdata.sizes.raw_height = ID->rows; // Parse other params from property section + DE = x3f_get_prop(x3f); - if((x3f_load_data(x3f,DE) == X3F_OK)) - { - // Parse property list - DEH = &DE->header; - x3f_property_list_t *PL = &DEH->data_subsection.property_list; - utf16_t *datap = (utf16_t*) PL->data; - uint32_t maxitems = PL->data_size/sizeof(utf16_t); - if (PL->property_table.size != 0) { - int i; - x3f_property_t *P = PL->property_table.element; - for (i=0; inum_properties; i++) { - char name[100], value[100]; - int noffset = (P[i].name - datap); - int voffset = (P[i].value - datap); - if(noffset < 0 || noffset>maxitems || voffset<0 || voffset>maxitems) - throw LIBRAW_EXCEPTION_IO_CORRUPT; - int maxnsize = maxitems - (P[i].name - datap); - int maxvsize = maxitems - (P[i].value - datap); - utf2char(P[i].name, name,MIN(maxnsize,sizeof(name))); - utf2char(P[i].value, value,MIN(maxvsize,sizeof(value))); - if (!strcmp (name, "ISO")) - imgdata.other.iso_speed = atoi(value); - if (!strcmp (name, "CAMMANUF")) - strcpy (imgdata.idata.make, value); - if (!strcmp (name, "CAMMODEL")) - strcpy (imgdata.idata.model, value); - if (!strcmp (name, "CAMSERIAL")) - strcpy (imgdata.shootinginfo.BodySerial, value); - if (!strcmp (name, "WB_DESC")) - strcpy (imgdata.color.model2, value); - if (!strcmp (name, "TIME")) - imgdata.other.timestamp = atoi(value); - if (!strcmp (name, "SHUTTER")) - imgdata.other.shutter = atof(value); - if (!strcmp (name, "APERTURE")) - imgdata.other.aperture = atof(value); - if (!strcmp (name, "FLENGTH")) - imgdata.other.focal_len = atof(value); - if (!strcmp (name, "FLEQ35MM")) - imgdata.lens.makernotes.FocalLengthIn35mmFormat = atof(value); - if (!strcmp (name, "LENSARANGE")) - { - char *sp; - imgdata.lens.makernotes.MaxAp4CurFocal = imgdata.lens.makernotes.MinAp4CurFocal = atof(value); - sp = strrchr (value, ' '); - if (sp) - { - imgdata.lens.makernotes.MinAp4CurFocal = atof(sp); - if (imgdata.lens.makernotes.MaxAp4CurFocal > imgdata.lens.makernotes.MinAp4CurFocal) - my_swap (float, imgdata.lens.makernotes.MaxAp4CurFocal, imgdata.lens.makernotes.MinAp4CurFocal); - } - } - if (!strcmp (name, "LENSFRANGE")) - { - char *sp; - imgdata.lens.makernotes.MinFocal = imgdata.lens.makernotes.MaxFocal = atof(value); - sp = strrchr (value, ' '); - if (sp) - { - imgdata.lens.makernotes.MaxFocal = atof(sp); - if ((imgdata.lens.makernotes.MaxFocal + 0.17f) < imgdata.lens.makernotes.MinFocal) - my_swap (float, imgdata.lens.makernotes.MaxFocal, imgdata.lens.makernotes.MinFocal); - } - } - if (!strcmp (name, "LENSMODEL")) - { - char *sp; - imgdata.lens.makernotes.LensID = strtol (value, &sp, 16); // atoi(value); - if (imgdata.lens.makernotes.LensID) - imgdata.lens.makernotes.LensMount = Sigma_X3F; - } - } - imgdata.idata.raw_count=1; - load_raw = &LibRaw::x3f_load_raw; - imgdata.sizes.raw_pitch = imgdata.sizes.raw_width*6; - imgdata.idata.is_foveon = 1; - libraw_internal_data.internal_output_params.raw_color=1; // Force adobe coeff - imgdata.color.maximum=0x3fff; // To be reset by color table - libraw_internal_data.unpacker_data.order = 0x4949; - } + if ((x3f_load_data(x3f, DE) == X3F_OK)) + { + // Parse property list + DEH = &DE->header; + x3f_property_list_t *PL = &DEH->data_subsection.property_list; + utf16_t *datap = (utf16_t*) PL->data; + uint32_t maxitems = PL->data_size/sizeof(utf16_t); + if (PL->property_table.size != 0) + { + int i; + x3f_property_t *P = PL->property_table.element; + for (i = 0; i < PL->num_properties; i++) + { + char name[100], value[100]; + int noffset = (P[i].name - datap); + int voffset = (P[i].value - datap); + if(noffset < 0 || noffset>maxitems || voffset<0 || voffset>maxitems) + throw LIBRAW_EXCEPTION_IO_CORRUPT; + int maxnsize = maxitems - (P[i].name - datap); + int maxvsize = maxitems - (P[i].value - datap); + utf2char(P[i].name, name,MIN(maxnsize,sizeof(name))); + utf2char(P[i].value, value,MIN(maxvsize,sizeof(value))); + if (!strcmp(name, "ISO")) + imgdata.other.iso_speed = atoi(value); + if (!strcmp(name, "CAMMANUF")) + strcpy(imgdata.idata.make, value); + if (!strcmp(name, "CAMMODEL")) + strcpy(imgdata.idata.model, value); + if (!strcmp(name, "CAMSERIAL")) + strcpy(imgdata.shootinginfo.BodySerial, value); + if (!strcmp(name, "WB_DESC")) + strcpy(imgdata.color.model2, value); + if (!strcmp(name, "TIME")) + imgdata.other.timestamp = atoi(value); + if (!strcmp(name, "SHUTTER")) + imgdata.other.shutter = atof(value); + if (!strcmp(name, "APERTURE")) + imgdata.other.aperture = atof(value); + if (!strcmp(name, "FLENGTH")) + imgdata.other.focal_len = atof(value); + if (!strcmp(name, "FLEQ35MM")) + imgdata.lens.makernotes.FocalLengthIn35mmFormat = atof(value); + if (!strcmp(name, "IMAGERTEMP")) + imgdata.other.SensorTemperature = atof(value); + if (!strcmp(name, "LENSARANGE")) + { + char *sp; + imgdata.lens.makernotes.MaxAp4CurFocal = imgdata.lens.makernotes.MinAp4CurFocal = atof(value); + sp = strrchr(value, ' '); + if (sp) + { + imgdata.lens.makernotes.MinAp4CurFocal = atof(sp); + if (imgdata.lens.makernotes.MaxAp4CurFocal > imgdata.lens.makernotes.MinAp4CurFocal) + my_swap(float, imgdata.lens.makernotes.MaxAp4CurFocal, imgdata.lens.makernotes.MinAp4CurFocal); + } + } + if (!strcmp(name, "LENSFRANGE")) + { + char *sp; + imgdata.lens.makernotes.MinFocal = imgdata.lens.makernotes.MaxFocal = atof(value); + sp = strrchr(value, ' '); + if (sp) + { + imgdata.lens.makernotes.MaxFocal = atof(sp); + if ((imgdata.lens.makernotes.MaxFocal + 0.17f) < imgdata.lens.makernotes.MinFocal) + my_swap(float, imgdata.lens.makernotes.MaxFocal, imgdata.lens.makernotes.MinFocal); + } + } + if (!strcmp(name, "LENSMODEL")) + { + char *sp; + imgdata.lens.makernotes.LensID = strtol(value, &sp, 16); // atoi(value); + if (imgdata.lens.makernotes.LensID) + imgdata.lens.makernotes.LensMount = Sigma_X3F; + } + } + imgdata.idata.raw_count = 1; + load_raw = &LibRaw::x3f_load_raw; + imgdata.sizes.raw_pitch = imgdata.sizes.raw_width * 6; + imgdata.idata.is_foveon = 1; + libraw_internal_data.internal_output_params.raw_color = 1; // Force adobe coeff + imgdata.color.maximum = 0x3fff; // To be reset by color table + libraw_internal_data.unpacker_data.order = 0x4949; + } } else { - // No property list - if(imgdata.sizes.raw_width == 5888 ||imgdata.sizes.raw_width == 2944 - || imgdata.sizes.raw_width == 6656 ||imgdata.sizes.raw_width == 3328 - || imgdata.sizes.raw_width == 5504 ||imgdata.sizes.raw_width == 2752 - ) // Quattro - { - imgdata.idata.raw_count=1; - load_raw = &LibRaw::x3f_load_raw; - imgdata.sizes.raw_pitch = imgdata.sizes.raw_width*6; - imgdata.idata.is_foveon = 1; - libraw_internal_data.internal_output_params.raw_color=1; // Force adobe coeff - libraw_internal_data.unpacker_data.order = 0x4949; - strcpy (imgdata.idata.make, "SIGMA"); + // No property list + if (imgdata.sizes.raw_width == 5888 || imgdata.sizes.raw_width == 2944 || imgdata.sizes.raw_width == 6656 || + imgdata.sizes.raw_width == 3328 || imgdata.sizes.raw_width == 5504 || + imgdata.sizes.raw_width == 2752) // Quattro + { + imgdata.idata.raw_count = 1; + load_raw = &LibRaw::x3f_load_raw; + imgdata.sizes.raw_pitch = imgdata.sizes.raw_width * 6; + imgdata.idata.is_foveon = 1; + libraw_internal_data.internal_output_params.raw_color = 1; // Force adobe coeff + libraw_internal_data.unpacker_data.order = 0x4949; + strcpy(imgdata.idata.make, "SIGMA"); #if 1 - // Try to find model number in first 2048 bytes; - int pos = libraw_internal_data.internal_data.input->tell(); - libraw_internal_data.internal_data.input->seek(0,SEEK_SET); - unsigned char buf[2048]; - libraw_internal_data.internal_data.input->read(buf,2048,1); - libraw_internal_data.internal_data.input->seek(pos,SEEK_SET); - unsigned char *fnd=(unsigned char*)lr_memmem(buf,2048,"SIGMA dp",8); - unsigned char *fndsd=(unsigned char*)lr_memmem(buf,2048,"sd Quatt",8); - if(fnd) - { - unsigned char *nm = fnd+8; - snprintf(imgdata.idata.model,64,"dp%c Quattro",*nm<='9' && *nm >='0' ? *nm: '2'); - } - else if(fndsd) - { - snprintf(imgdata.idata.model,64,"%s",fndsd); - } - else + // Try to find model number in first 2048 bytes; + int pos = libraw_internal_data.internal_data.input->tell(); + libraw_internal_data.internal_data.input->seek(0, SEEK_SET); + unsigned char buf[2048]; + libraw_internal_data.internal_data.input->read(buf, 2048, 1); + libraw_internal_data.internal_data.input->seek(pos, SEEK_SET); + unsigned char *fnd = (unsigned char *)lr_memmem(buf, 2048, "SIGMA dp", 8); + unsigned char *fndsd = (unsigned char *)lr_memmem(buf, 2048, "sd Quatt", 8); + if (fnd) + { + unsigned char *nm = fnd + 8; + snprintf(imgdata.idata.model, 64, "dp%c Quattro", *nm <= '9' && *nm >= '0' ? *nm : '2'); + } + else if (fndsd) + { + snprintf(imgdata.idata.model, 64, "%s", fndsd); + } + else #endif - if(imgdata.sizes.raw_width == 6656 ||imgdata.sizes.raw_width == 3328 ) - strcpy (imgdata.idata.model, "sd Quattro H"); - else - strcpy (imgdata.idata.model, "dp2 Quattro"); - } - //else + if (imgdata.sizes.raw_width == 6656 || imgdata.sizes.raw_width == 3328) + strcpy(imgdata.idata.model, "sd Quattro H"); + else + strcpy(imgdata.idata.model, "dp2 Quattro"); + } + // else } // Try to get thumbnail data LibRaw_thumbnail_formats format = LIBRAW_THUMBNAIL_UNKNOWN; - if( (DE = x3f_get_thumb_jpeg(x3f))) - { - format = LIBRAW_THUMBNAIL_JPEG; - } - else if( (DE = x3f_get_thumb_plain(x3f))) - { - format = LIBRAW_THUMBNAIL_BITMAP; - } - if(DE) - { - x3f_directory_entry_header_t *DEH = &DE->header; - x3f_image_data_t *ID = &DEH->data_subsection.image_data; - imgdata.thumbnail.twidth = ID->columns; - imgdata.thumbnail.theight = ID->rows; - imgdata.thumbnail.tcolors = 3; - imgdata.thumbnail.tformat = format; - libraw_internal_data.internal_data.toffset = DE->input.offset; - write_thumb = &LibRaw::x3f_thumb_loader; - } + if ((DE = x3f_get_thumb_jpeg(x3f))) + { + format = LIBRAW_THUMBNAIL_JPEG; + } + else if ((DE = x3f_get_thumb_plain(x3f))) + { + format = LIBRAW_THUMBNAIL_BITMAP; + } + if (DE) + { + x3f_directory_entry_header_t *DEH = &DE->header; + x3f_image_data_t *ID = &DEH->data_subsection.image_data; + imgdata.thumbnail.twidth = ID->columns; + imgdata.thumbnail.theight = ID->rows; + imgdata.thumbnail.tcolors = 3; + imgdata.thumbnail.tformat = format; + libraw_internal_data.internal_data.toffset = DE->input.offset; + write_thumb = &LibRaw::x3f_thumb_loader; + } } INT64 LibRaw::x3f_thumb_size() { - try { - x3f_t *x3f = (x3f_t*)_x3f_data; - if (!x3f) return -1; // No data pointer set - x3f_directory_entry_t *DE = x3f_get_thumb_jpeg(x3f); - if (!DE) - DE = x3f_get_thumb_plain(x3f); - if (!DE) - return -1; - int64_t p = x3f_load_data_size(x3f, DE); - if (p < 0 || p > 0xffffffff) - return -1; - return p; - } - catch (...) - { - return -1; - } + try + { + x3f_t *x3f = (x3f_t *)_x3f_data; + if (!x3f) + return -1; // No data pointer set + x3f_directory_entry_t *DE = x3f_get_thumb_jpeg(x3f); + if (!DE) + DE = x3f_get_thumb_plain(x3f); + if (!DE) + return -1; + int64_t p = x3f_load_data_size(x3f, DE); + if (p < 0 || p > 0xffffffff) + return -1; + return p; + } + catch (...) + { + return -1; + } } void LibRaw::x3f_thumb_loader() { - try - { - x3f_t *x3f = (x3f_t*)_x3f_data; - if (!x3f) return; // No data pointer set - x3f_directory_entry_t *DE = x3f_get_thumb_jpeg(x3f); - if (!DE) - DE = x3f_get_thumb_plain(x3f); - if (!DE) - return; - if (X3F_OK != x3f_load_data(x3f, DE)) - throw LIBRAW_EXCEPTION_IO_CORRUPT; - x3f_directory_entry_header_t *DEH = &DE->header; - x3f_image_data_t *ID = &DEH->data_subsection.image_data; - imgdata.thumbnail.twidth = ID->columns; - imgdata.thumbnail.theight = ID->rows; - imgdata.thumbnail.tcolors = 3; - if (imgdata.thumbnail.tformat == LIBRAW_THUMBNAIL_JPEG) - { - imgdata.thumbnail.thumb = (char*)malloc(ID->data_size); - merror(imgdata.thumbnail.thumb, "LibRaw::x3f_thumb_loader()"); - memmove(imgdata.thumbnail.thumb, ID->data, ID->data_size); - imgdata.thumbnail.tlength = ID->data_size; - } - else if (imgdata.thumbnail.tformat == LIBRAW_THUMBNAIL_BITMAP) - { - imgdata.thumbnail.tlength = ID->columns * ID->rows * 3; - imgdata.thumbnail.thumb = (char*)malloc(ID->columns * ID->rows * 3); - merror(imgdata.thumbnail.thumb, "LibRaw::x3f_thumb_loader()"); - char *src0 = (char*)ID->data; - for (int row = 0; row < ID->rows; row++) - { - int offset = row * ID->row_stride; - if (offset + ID->columns * 3 > ID->data_size) - break; - char *dest = &imgdata.thumbnail.thumb[row*ID->columns * 3]; - char *src = &src0[offset]; - memmove(dest, src, ID->columns * 3); - } - } - } - catch (...) - { - // do nothing - } + try + { + x3f_t *x3f = (x3f_t *)_x3f_data; + if (!x3f) + return; // No data pointer set + x3f_directory_entry_t *DE = x3f_get_thumb_jpeg(x3f); + if (!DE) + DE = x3f_get_thumb_plain(x3f); + if (!DE) + return; + if (X3F_OK != x3f_load_data(x3f, DE)) + throw LIBRAW_EXCEPTION_IO_CORRUPT; + x3f_directory_entry_header_t *DEH = &DE->header; + x3f_image_data_t *ID = &DEH->data_subsection.image_data; + imgdata.thumbnail.twidth = ID->columns; + imgdata.thumbnail.theight = ID->rows; + imgdata.thumbnail.tcolors = 3; + if (imgdata.thumbnail.tformat == LIBRAW_THUMBNAIL_JPEG) + { + imgdata.thumbnail.thumb = (char *)malloc(ID->data_size); + merror(imgdata.thumbnail.thumb, "LibRaw::x3f_thumb_loader()"); + memmove(imgdata.thumbnail.thumb, ID->data, ID->data_size); + imgdata.thumbnail.tlength = ID->data_size; + } + else if (imgdata.thumbnail.tformat == LIBRAW_THUMBNAIL_BITMAP) + { + imgdata.thumbnail.tlength = ID->columns * ID->rows * 3; + imgdata.thumbnail.thumb = (char *)malloc(ID->columns * ID->rows * 3); + merror(imgdata.thumbnail.thumb, "LibRaw::x3f_thumb_loader()"); + char *src0 = (char *)ID->data; + for (int row = 0; row < ID->rows; row++) + { + int offset = row * ID->row_stride; + if (offset + ID->columns * 3 > ID->data_size) + break; + char *dest = &imgdata.thumbnail.thumb[row * ID->columns * 3]; + char *src = &src0[offset]; + memmove(dest, src, ID->columns * 3); + } + } + } + catch (...) + { + // do nothing + } } -static inline uint32_t _clampbits(int x, uint32_t n) { - uint32_t _y_temp; - if( (_y_temp=x>>n) ) - x = ~_y_temp >> (32-n); - return x; +static inline uint32_t _clampbits(int x, uint32_t n) +{ + uint32_t _y_temp; + if ((_y_temp = x >> n)) + x = ~_y_temp >> (32 - n); + return x; } void LibRaw::x3f_dpq_interpolate_rg() { - int w = imgdata.sizes.raw_width/2; - int h = imgdata.sizes.raw_height/2; - unsigned short *image = (ushort*)imgdata.rawdata.color3_image; - - for (int color = 0; color < 2; color++) - { - for (int y = 2; y < (h-2); y++) - { - uint16_t* row0 = &image[imgdata.sizes.raw_width*3*(y*2)+color]; // dst[1] - uint16_t row0_3 = row0[3]; - uint16_t* row1 = &image[imgdata.sizes.raw_width*3*(y*2+1)+color]; //dst1[1] - uint16_t row1_3 = row1[3]; - for (int x = 2; x < (w-2); x++) - { - row1[0]=row1[3]=row0[3]=row0[0]; - row0 += 6; - row1 += 6; - } - } - } + int w = imgdata.sizes.raw_width / 2; + int h = imgdata.sizes.raw_height / 2; + unsigned short *image = (ushort *)imgdata.rawdata.color3_image; + + for (int color = 0; color < 2; color++) + { + for (int y = 2; y < (h - 2); y++) + { + uint16_t *row0 = &image[imgdata.sizes.raw_width * 3 * (y * 2) + color]; // dst[1] + uint16_t row0_3 = row0[3]; + uint16_t *row1 = &image[imgdata.sizes.raw_width * 3 * (y * 2 + 1) + color]; // dst1[1] + uint16_t row1_3 = row1[3]; + for (int x = 2; x < (w - 2); x++) + { + row1[0] = row1[3] = row0[3] = row0[0]; + row0 += 6; + row1 += 6; + } + } + } } -#define _ABS(a) ((a)<0?-(a):(a)) +#define _ABS(a) ((a) < 0 ? -(a) : (a)) #undef CLIP -#define CLIP(value,high) ((value)>(high)?(high):(value)) +#define CLIP(value, high) ((value) > (high) ? (high) : (value)) void LibRaw::x3f_dpq_interpolate_af(int xstep, int ystep, int scale) { - unsigned short *image = (ushort*)imgdata.rawdata.color3_image; - unsigned int rowpitch = imgdata.rawdata.sizes.raw_pitch/2; // in 16-bit words - // Interpolate single pixel - for(int y = 0; y < imgdata.rawdata.sizes.height+imgdata.rawdata.sizes.top_margin; y+=ystep) - { - if(yimgdata.rawdata.sizes.raw_height-scale) break; - uint16_t* row0 = &image[imgdata.sizes.raw_width*3*y]; // Ðаша Ñтрока - uint16_t* row_minus = &image[imgdata.sizes.raw_width*3*(y-scale)]; // Строка выше - uint16_t* row_plus = &image[imgdata.sizes.raw_width*3*(y+scale)]; // Строка ниже - for(int x = 0; x < imgdata.rawdata.sizes.width+imgdata.rawdata.sizes.left_margin; x+= xstep) - { - if(ximgdata.rawdata.sizes.raw_width-scale) break; - uint16_t* pixel0 = &row0[x*3]; - uint16_t* pixel_top = &row_minus[x*3]; - uint16_t* pixel_bottom = &row_plus[x*3]; - uint16_t* pixel_left = &row0[(x-scale)*3]; - uint16_t* pixel_right = &row0[(x+scale)*3]; - uint16_t* pixf = pixel_top; - if(_ABS(pixf[2]-pixel0[2])>_ABS(pixel_bottom[2]-pixel0[2])) - pixf = pixel_bottom; - if(_ABS(pixf[2]-pixel0[2])>_ABS(pixel_left[2]-pixel0[2])) - pixf = pixel_left; - if(_ABS(pixf[2]-pixel0[2])>_ABS(pixel_right[2]-pixel0[2])) - pixf = pixel_right; - int blocal = pixel0[2],bnear = pixf[2]; - if(blocal < imgdata.color.black+16 || bnear < imgdata.color.black+16 ) - { - if(pixel0[0] < imgdata.color.black) pixel0[0] = imgdata.color.black; - if(pixel0[1] < imgdata.color.black) pixel0[1] = imgdata.color.black; - pixel0[0] = CLIP((pixel0[0] - imgdata.color.black)*4 + imgdata.color.black,16383); - pixel0[1] = CLIP((pixel0[1] - imgdata.color.black)*4 + imgdata.color.black,16383); - } - else - { - float multip = float(bnear - imgdata.color.black)/float(blocal-imgdata.color.black); - if(pixel0[0] < imgdata.color.black) pixel0[0] = imgdata.color.black; - if(pixel0[1] < imgdata.color.black) pixel0[1] = imgdata.color.black; - float pixf0 = pixf[0]; - if(pixf0 < imgdata.color.black) pixf0 = imgdata.color.black; - float pixf1 = pixf[1]; - if(pixf1 < imgdata.color.black) pixf1 = imgdata.color.black; - - pixel0[0] = CLIP(((float(pixf0-imgdata.color.black)*multip + imgdata.color.black)+((pixel0[0]-imgdata.color.black)*3.75 + imgdata.color.black))/2,16383); - pixel0[1] = CLIP(((float(pixf1-imgdata.color.black)*multip + imgdata.color.black)+((pixel0[1]-imgdata.color.black)*3.75 + imgdata.color.black))/2,16383); - //pixel0[1] = float(pixf[1]-imgdata.color.black)*multip + imgdata.color.black; - } - } - } + unsigned short *image = (ushort *)imgdata.rawdata.color3_image; + unsigned int rowpitch = imgdata.rawdata.sizes.raw_pitch / 2; // in 16-bit words + // Interpolate single pixel + for (int y = 0; y < imgdata.rawdata.sizes.height + imgdata.rawdata.sizes.top_margin; y += ystep) + { + if (y < imgdata.rawdata.sizes.top_margin) + continue; + if (y < scale) + continue; + if (y > imgdata.rawdata.sizes.raw_height - scale) + break; + uint16_t *row0 = &image[imgdata.sizes.raw_width * 3 * y]; // Ðаша Ñтрока + uint16_t *row_minus = &image[imgdata.sizes.raw_width * 3 * (y - scale)]; // Строка выше + uint16_t *row_plus = &image[imgdata.sizes.raw_width * 3 * (y + scale)]; // Строка ниже + for (int x = 0; x < imgdata.rawdata.sizes.width + imgdata.rawdata.sizes.left_margin; x += xstep) + { + if (x < imgdata.rawdata.sizes.left_margin) + continue; + if (x < scale) + continue; + if (x > imgdata.rawdata.sizes.raw_width - scale) + break; + uint16_t *pixel0 = &row0[x * 3]; + uint16_t *pixel_top = &row_minus[x * 3]; + uint16_t *pixel_bottom = &row_plus[x * 3]; + uint16_t *pixel_left = &row0[(x - scale) * 3]; + uint16_t *pixel_right = &row0[(x + scale) * 3]; + uint16_t *pixf = pixel_top; + if (_ABS(pixf[2] - pixel0[2]) > _ABS(pixel_bottom[2] - pixel0[2])) + pixf = pixel_bottom; + if (_ABS(pixf[2] - pixel0[2]) > _ABS(pixel_left[2] - pixel0[2])) + pixf = pixel_left; + if (_ABS(pixf[2] - pixel0[2]) > _ABS(pixel_right[2] - pixel0[2])) + pixf = pixel_right; + int blocal = pixel0[2], bnear = pixf[2]; + if (blocal < imgdata.color.black + 16 || bnear < imgdata.color.black + 16) + { + if (pixel0[0] < imgdata.color.black) + pixel0[0] = imgdata.color.black; + if (pixel0[1] < imgdata.color.black) + pixel0[1] = imgdata.color.black; + pixel0[0] = CLIP((pixel0[0] - imgdata.color.black) * 4 + imgdata.color.black, 16383); + pixel0[1] = CLIP((pixel0[1] - imgdata.color.black) * 4 + imgdata.color.black, 16383); + } + else + { + float multip = float(bnear - imgdata.color.black) / float(blocal - imgdata.color.black); + if (pixel0[0] < imgdata.color.black) + pixel0[0] = imgdata.color.black; + if (pixel0[1] < imgdata.color.black) + pixel0[1] = imgdata.color.black; + float pixf0 = pixf[0]; + if (pixf0 < imgdata.color.black) + pixf0 = imgdata.color.black; + float pixf1 = pixf[1]; + if (pixf1 < imgdata.color.black) + pixf1 = imgdata.color.black; + + pixel0[0] = CLIP(((float(pixf0 - imgdata.color.black) * multip + imgdata.color.black) + + ((pixel0[0] - imgdata.color.black) * 3.75 + imgdata.color.black)) / + 2, + 16383); + pixel0[1] = CLIP(((float(pixf1 - imgdata.color.black) * multip + imgdata.color.black) + + ((pixel0[1] - imgdata.color.black) * 3.75 + imgdata.color.black)) / + 2, + 16383); + // pixel0[1] = float(pixf[1]-imgdata.color.black)*multip + imgdata.color.black; + } + } + } } -void LibRaw::x3f_dpq_interpolate_af_sd(int xstart,int ystart, int xend, int yend, int xstep, int ystep, int scale) +void LibRaw::x3f_dpq_interpolate_af_sd(int xstart, int ystart, int xend, int yend, int xstep, int ystep, int scale) { - unsigned short *image = (ushort*)imgdata.rawdata.color3_image; - unsigned int rowpitch = imgdata.rawdata.sizes.raw_pitch/2; // in 16-bit words - // Interpolate single pixel - for(int y = ystart; y< yend && y < imgdata.rawdata.sizes.height+imgdata.rawdata.sizes.top_margin; y+=ystep) - { - uint16_t* row0 = &image[imgdata.sizes.raw_width*3*y]; // Ðаша Ñтрока - uint16_t* row1 = &image[imgdata.sizes.raw_width*3*(y+1)]; // Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ñтрока - uint16_t* row_minus = &image[imgdata.sizes.raw_width*3*(y-scale)]; // Строка выше - uint16_t* row_plus = &image[imgdata.sizes.raw_width*3*(y+scale)]; // Строка ниже AF-point (scale=2 -> ниже row1 - uint16_t* row_minus1 = &image[imgdata.sizes.raw_width*3*(y-1)]; - for(int x = xstart; x< xend && x < imgdata.rawdata.sizes.width+imgdata.rawdata.sizes.left_margin; x+= xstep) - { - uint16_t* pixel00 = &row0[x*3]; // Current pixel - float sumR = 0.f,sumG=0.f; - float cnt = 0.f; - for(int xx = -scale; xx <= scale; xx+= scale) - { - sumR += row_minus[(x+xx)*3]; - sumR += row_plus[(x+xx)*3]; - sumG += row_minus[(x+xx)*3+1]; - sumG += row_plus[(x+xx)*3+1]; - cnt +=1.f; - if(xx) - { - cnt +=1.f; - sumR += row0[(x+xx)*3]; - sumG += row0[(x+xx)*3+1]; - } - } - pixel00[0] = sumR/8.f; - pixel00[1] = sumG/8.f; - - if(scale == 2) - { - uint16_t* pixel0B = &row0[x*3+3]; // right pixel - uint16_t* pixel1B = &row1[x*3+3]; // right pixel - float sumG0 = 0, sumG1 = 0.f; - float cnt = 0.f; - for(int xx = -scale; xx <= scale; xx+= scale) - { - sumG0 += row_minus1[(x+xx)*3+2]; - sumG1 += row_plus[(x+xx)*3+2]; - cnt +=1.f; - if(xx) - { - sumG0 += row0[(x+xx)*3+2]; - sumG1 += row1[(x+xx)*3+2]; - cnt +=1.f; - } - } - pixel0B[2] = sumG0/cnt; - pixel1B[2] = sumG1/cnt; - } - - // uint16_t* pixel10 = &row1[x*3]; // Pixel below current -// uint16_t* pixel_bottom = &row_plus[x*3]; - } - } -} + unsigned short *image = (ushort *)imgdata.rawdata.color3_image; + unsigned int rowpitch = imgdata.rawdata.sizes.raw_pitch / 2; // in 16-bit words + // Interpolate single pixel + for (int y = ystart; y < yend && y < imgdata.rawdata.sizes.height + imgdata.rawdata.sizes.top_margin; y += ystep) + { + uint16_t *row0 = &image[imgdata.sizes.raw_width * 3 * y]; // Ðаша Ñтрока + uint16_t *row1 = &image[imgdata.sizes.raw_width * 3 * (y + 1)]; // Ð¡Ð»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ñтрока + uint16_t *row_minus = &image[imgdata.sizes.raw_width * 3 * (y - scale)]; // Строка выше + uint16_t *row_plus = + &image[imgdata.sizes.raw_width * 3 * (y + scale)]; // Строка ниже AF-point (scale=2 -> ниже row1 + uint16_t *row_minus1 = &image[imgdata.sizes.raw_width * 3 * (y - 1)]; + for (int x = xstart; x < xend && x < imgdata.rawdata.sizes.width + imgdata.rawdata.sizes.left_margin; x += xstep) + { + uint16_t *pixel00 = &row0[x * 3]; // Current pixel + float sumR = 0.f, sumG = 0.f; + float cnt = 0.f; + for (int xx = -scale; xx <= scale; xx += scale) + { + sumR += row_minus[(x + xx) * 3]; + sumR += row_plus[(x + xx) * 3]; + sumG += row_minus[(x + xx) * 3 + 1]; + sumG += row_plus[(x + xx) * 3 + 1]; + cnt += 1.f; + if (xx) + { + cnt += 1.f; + sumR += row0[(x + xx) * 3]; + sumG += row0[(x + xx) * 3 + 1]; + } + } + pixel00[0] = sumR / 8.f; + pixel00[1] = sumG / 8.f; + + if (scale == 2) + { + uint16_t *pixel0B = &row0[x * 3 + 3]; // right pixel + uint16_t *pixel1B = &row1[x * 3 + 3]; // right pixel + float sumG0 = 0, sumG1 = 0.f; + float cnt = 0.f; + for (int xx = -scale; xx <= scale; xx += scale) + { + sumG0 += row_minus1[(x + xx) * 3 + 2]; + sumG1 += row_plus[(x + xx) * 3 + 2]; + cnt += 1.f; + if (xx) + { + sumG0 += row0[(x + xx) * 3 + 2]; + sumG1 += row1[(x + xx) * 3 + 2]; + cnt += 1.f; + } + } + pixel0B[2] = sumG0 / cnt; + pixel1B[2] = sumG1 / cnt; + } + // uint16_t* pixel10 = &row1[x*3]; // Pixel below current + // uint16_t* pixel_bottom = &row_plus[x*3]; + } + } +} void LibRaw::x3f_load_raw() { - // already in try/catch - int raise_error=0; - x3f_t *x3f = (x3f_t*)_x3f_data; - if(!x3f) return; // No data pointer set - if(X3F_OK == x3f_load_data(x3f, x3f_get_raw(x3f))) - { - x3f_directory_entry_t *DE = x3f_get_raw(x3f); - x3f_directory_entry_header_t *DEH = &DE->header; - x3f_image_data_t *ID = &DEH->data_subsection.image_data; - if(!ID) - throw LIBRAW_EXCEPTION_IO_CORRUPT; - x3f_quattro_t *Q = ID->quattro; - x3f_huffman_t *HUF = ID->huffman; - x3f_true_t *TRU = ID->tru; - uint16_t *data = NULL; - if(ID->rows != S.raw_height || ID->columns != S.raw_width) + // already in try/catch + int raise_error = 0; + x3f_t *x3f = (x3f_t *)_x3f_data; + if (!x3f) + return; // No data pointer set + if (X3F_OK == x3f_load_data(x3f, x3f_get_raw(x3f))) + { + x3f_directory_entry_t *DE = x3f_get_raw(x3f); + x3f_directory_entry_header_t *DEH = &DE->header; + x3f_image_data_t *ID = &DEH->data_subsection.image_data; + if (!ID) + throw LIBRAW_EXCEPTION_IO_CORRUPT; + x3f_quattro_t *Q = ID->quattro; + x3f_huffman_t *HUF = ID->huffman; + x3f_true_t *TRU = ID->tru; + uint16_t *data = NULL; + if (ID->rows != S.raw_height || ID->columns != S.raw_width) + { + raise_error = 1; + goto end; + } + if (HUF != NULL) + data = HUF->x3rgb16.data; + if (TRU != NULL) + data = TRU->x3rgb16.data; + if (data == NULL) + { + raise_error = 1; + goto end; + } + + size_t datasize = S.raw_height * S.raw_width * 3 * sizeof(unsigned short); + S.raw_pitch = S.raw_width * 3 * sizeof(unsigned short); + if (!(imgdata.rawdata.raw_alloc = malloc(datasize))) + throw LIBRAW_EXCEPTION_ALLOC; + + imgdata.rawdata.color3_image = (ushort(*)[3])imgdata.rawdata.raw_alloc; + if (HUF) + memmove(imgdata.rawdata.raw_alloc, data, datasize); + else if (TRU && (!Q || !Q->quattro_layout)) + memmove(imgdata.rawdata.raw_alloc, data, datasize); + else if (TRU && Q) + { + // Move quattro data in place + // R/B plane + for (int prow = 0; prow < TRU->x3rgb16.rows && prow < S.raw_height / 2; prow++) + { + ushort(*destrow)[3] = + (unsigned short(*)[3]) & imgdata.rawdata.color3_image[prow * 2 * S.raw_pitch / 3 / sizeof(ushort)][0]; + ushort(*srcrow)[3] = (unsigned short(*)[3]) & data[prow * TRU->x3rgb16.row_stride]; + for (int pcol = 0; pcol < TRU->x3rgb16.columns && pcol < S.raw_width / 2; pcol++) { - raise_error = 1; - goto end; + destrow[pcol * 2][0] = srcrow[pcol][0]; + destrow[pcol * 2][1] = srcrow[pcol][1]; } - if (HUF != NULL) - data = HUF->x3rgb16.data; - if (TRU != NULL) - data = TRU->x3rgb16.data; - if (data == NULL) - { - raise_error = 1; - goto end; - } - - size_t datasize = S.raw_height*S.raw_width*3*sizeof(unsigned short); - S.raw_pitch = S.raw_width*3*sizeof(unsigned short); - if(!(imgdata.rawdata.raw_alloc = malloc(datasize))) - throw LIBRAW_EXCEPTION_ALLOC; - - imgdata.rawdata.color3_image = (ushort (*)[3])imgdata.rawdata.raw_alloc; - if(HUF) - memmove(imgdata.rawdata.raw_alloc,data,datasize); - else if(TRU && (!Q || !Q->quattro_layout)) - memmove(imgdata.rawdata.raw_alloc,data,datasize); - else if(TRU && Q) - { - // Move quattro data in place - // R/B plane - for(int prow = 0; prow < TRU->x3rgb16.rows && prow < S.raw_height/2; prow++) - { - ushort (*destrow)[3] = (unsigned short (*)[3]) &imgdata.rawdata.color3_image[prow*2*S.raw_pitch/3/sizeof(ushort)][0]; - ushort (*srcrow)[3] = (unsigned short (*)[3]) &data[prow*TRU->x3rgb16.row_stride]; - for(int pcol = 0; pcol < TRU->x3rgb16.columns && pcol < S.raw_width/2; pcol++) - { - destrow[pcol*2][0] = srcrow[pcol][0]; - destrow[pcol*2][1] = srcrow[pcol][1]; - } - } - for(int row = 0; row < Q->top16.rows && row < S.raw_height; row++) - { - ushort (*destrow)[3] = (unsigned short (*)[3]) &imgdata.rawdata.color3_image[row*S.raw_pitch/3/sizeof(ushort)][0]; - ushort (*srcrow) = (unsigned short *) &Q->top16.data[row * Q->top16.columns]; - for(int col = 0; col < Q->top16.columns && col < S.raw_width; col++) - destrow[col][2] = srcrow[col]; - } - } + } + for (int row = 0; row < Q->top16.rows && row < S.raw_height; row++) + { + ushort(*destrow)[3] = + (unsigned short(*)[3]) & imgdata.rawdata.color3_image[row * S.raw_pitch / 3 / sizeof(ushort)][0]; + ushort(*srcrow) = (unsigned short *)&Q->top16.data[row * Q->top16.columns]; + for (int col = 0; col < Q->top16.columns && col < S.raw_width; col++) + destrow[col][2] = srcrow[col]; + } + } #if 1 - if(TRU && Q && (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_DP2Q_INTERPOLATEAF) - ) - { - if(imgdata.sizes.raw_width == 5888 && imgdata.sizes.raw_height == 3672) // dpN Quattro normal - { - x3f_dpq_interpolate_af(32,8,2); - } - else if(imgdata.sizes.raw_width == 5888 && imgdata.sizes.raw_height == 3776) // sd Quattro normal raw - { - x3f_dpq_interpolate_af_sd(216,464,imgdata.sizes.raw_width-1,3312,16,32,2); - } - else if(imgdata.sizes.raw_width == 6656 && imgdata.sizes.raw_height == 4480) // sd Quattro H normal raw - { - x3f_dpq_interpolate_af_sd(232,592,imgdata.sizes.raw_width-1,3888,16,32,2); - } - else if(imgdata.sizes.raw_width == 3328 && imgdata.sizes.raw_height == 2240) // sd Quattro H half size - { - x3f_dpq_interpolate_af_sd(116,296,imgdata.sizes.raw_width-1,2200,8,16,1); - } - else if(imgdata.sizes.raw_width == 5504 && imgdata.sizes.raw_height == 3680) // sd Quattro H APS-C raw - { - x3f_dpq_interpolate_af_sd(8,192,imgdata.sizes.raw_width-1,3185,16,32,2); - } - else if(imgdata.sizes.raw_width == 2752 && imgdata.sizes.raw_height == 1840) // sd Quattro H APS-C half size - { - x3f_dpq_interpolate_af_sd(4, 96,imgdata.sizes.raw_width-1,1800,8,16,1); - } - else if(imgdata.sizes.raw_width == 2944 && imgdata.sizes.raw_height == 1836) // dpN Quattro small raw - { - x3f_dpq_interpolate_af(16,4,1); - } - else if(imgdata.sizes.raw_width == 2944 && imgdata.sizes.raw_height == 1888) // sd Quattro small - { - x3f_dpq_interpolate_af_sd(108,232,imgdata.sizes.raw_width-1,1656,8,16,1); - } - } + if (TRU && Q && (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_DP2Q_INTERPOLATEAF)) + { + if (imgdata.sizes.raw_width == 5888 && imgdata.sizes.raw_height == 3672) // dpN Quattro normal + { + x3f_dpq_interpolate_af(32, 8, 2); + } + else if (imgdata.sizes.raw_width == 5888 && imgdata.sizes.raw_height == 3776) // sd Quattro normal raw + { + x3f_dpq_interpolate_af_sd(216, 464, imgdata.sizes.raw_width - 1, 3312, 16, 32, 2); + } + else if (imgdata.sizes.raw_width == 6656 && imgdata.sizes.raw_height == 4480) // sd Quattro H normal raw + { + x3f_dpq_interpolate_af_sd(232, 592, imgdata.sizes.raw_width - 1, 3920, 16, 32, 2); + } + else if (imgdata.sizes.raw_width == 3328 && imgdata.sizes.raw_height == 2240) // sd Quattro H half size + { + x3f_dpq_interpolate_af_sd(116, 296, imgdata.sizes.raw_width - 1, 2200, 8, 16, 1); + } + else if (imgdata.sizes.raw_width == 5504 && imgdata.sizes.raw_height == 3680) // sd Quattro H APS-C raw + { + x3f_dpq_interpolate_af_sd(8, 192, imgdata.sizes.raw_width - 1, 3185, 16, 32, 2); + } + else if (imgdata.sizes.raw_width == 2752 && imgdata.sizes.raw_height == 1840) // sd Quattro H APS-C half size + { + x3f_dpq_interpolate_af_sd(4, 96, imgdata.sizes.raw_width - 1, 1800, 8, 16, 1); + } + else if (imgdata.sizes.raw_width == 2944 && imgdata.sizes.raw_height == 1836) // dpN Quattro small raw + { + x3f_dpq_interpolate_af(16, 4, 1); + } + else if (imgdata.sizes.raw_width == 2944 && imgdata.sizes.raw_height == 1888) // sd Quattro small + { + x3f_dpq_interpolate_af_sd(108, 232, imgdata.sizes.raw_width - 1, 1656, 8, 16, 1); + } + } #endif - if(TRU && Q && Q->quattro_layout && (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_DP2Q_INTERPOLATERG) ) - x3f_dpq_interpolate_rg(); - + if (TRU && Q && Q->quattro_layout && (imgdata.params.raw_processing_options & LIBRAW_PROCESSING_DP2Q_INTERPOLATERG)) + x3f_dpq_interpolate_rg(); } else raise_error = 1; end: - if(raise_error) + if (raise_error) throw LIBRAW_EXCEPTION_IO_CORRUPT; } - diff --git a/core/libs/rawengine/libraw/src/libraw_datastream.cpp b/core/libs/rawengine/libraw/src/libraw_datastream.cpp index 4b137443af..bd9cf5ee55 100644 --- a/core/libs/rawengine/libraw/src/libraw_datastream.cpp +++ b/core/libs/rawengine/libraw/src/libraw_datastream.cpp @@ -1,701 +1,745 @@ /* -*- C++ -*- * File: libraw_datastream.cpp - * Copyright 2008-2017 LibRaw LLC (info@libraw.org) + * Copyright 2008-2018 LibRaw LLC (info@libraw.org) * * LibRaw C++ interface (implementation) LibRaw is free software; you can redistribute it and/or modify it under the terms of the one of two licenses as you choose: 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). */ #ifdef WIN32 #ifdef __MINGW32__ - #define _WIN32_WINNT 0x0500 - #include +#define _WIN32_WINNT 0x0500 +#include #endif #endif #define LIBRAW_LIBRARY_BUILD #include "libraw/libraw_types.h" #include "libraw/libraw.h" #include "libraw/libraw_datastream.h" #include #ifdef USE_JASPER -#include /* Decode RED camera movies */ +#include /* Decode RED camera movies */ #else #define NO_JASPER #endif #ifdef USE_JPEG #include #else #define NO_JPEG #endif -int LibRaw_abstract_datastream::tempbuffer_open(void *buf, size_t size) +int LibRaw_abstract_datastream::tempbuffer_open(void *buf, size_t size) { - if(substream) return EBUSY; - substream = new LibRaw_buffer_datastream(buf,size); - return substream?0:EINVAL; + if (substream) + return EBUSY; + substream = new LibRaw_buffer_datastream(buf, size); + return substream ? 0 : EINVAL; } - -void LibRaw_abstract_datastream::tempbuffer_close() +void LibRaw_abstract_datastream::tempbuffer_close() { - if(substream) delete substream; - substream = NULL; + if (substream) + delete substream; + substream = NULL; } // == LibRaw_file_datastream == LibRaw_file_datastream::~LibRaw_file_datastream() { - if(jas_file) fclose(jas_file); + if (jas_file) + fclose(jas_file); } LibRaw_file_datastream::LibRaw_file_datastream(const char *fname) - :filename(fname) - ,_fsize(0) + : filename(fname), _fsize(0) #ifdef WIN32 - ,wfilename() + , + wfilename() #endif - ,jas_file(NULL) + , + jas_file(NULL) { - if (filename.size()>0) - { + if (filename.size() > 0) + { #ifndef WIN32 - struct stat st; - if(!stat(filename.c_str(),&st)) - _fsize = st.st_size; + struct stat st; + if (!stat(filename.c_str(), &st)) + _fsize = st.st_size; #else - struct _stati64 st; - if(!_stati64(filename.c_str(),&st)) - _fsize = st.st_size; -#endif - - std::auto_ptr buf(new std::filebuf()); - buf->open(filename.c_str(), std::ios_base::in | std::ios_base::binary); - if (buf->is_open()) { - f = buf; - } + struct _stati64 st; + if (!_stati64(filename.c_str(), &st)) + _fsize = st.st_size; +#endif + + std::auto_ptr buf(new std::filebuf()); + buf->open(filename.c_str(), std::ios_base::in | std::ios_base::binary); + if (buf->is_open()) + { + f = buf; } + } } #if defined(_WIN32) && !defined(__MINGW32__) && defined(_MSC_VER) && (_MSC_VER > 1310) -LibRaw_file_datastream::LibRaw_file_datastream(const wchar_t *fname) : filename(),wfilename(fname),jas_file(NULL),_fsize(0) +LibRaw_file_datastream::LibRaw_file_datastream(const wchar_t *fname) + : filename(), wfilename(fname), jas_file(NULL), _fsize(0) { - if (wfilename.size()>0) + if (wfilename.size() > 0) + { + struct _stati64 st; + if (!_wstati64(wfilename.c_str(), &st)) + _fsize = st.st_size; + std::auto_ptr buf(new std::filebuf()); + buf->open(wfilename.c_str(), std::ios_base::in | std::ios_base::binary); + if (buf->is_open()) { - struct _stati64 st; - if(!_wstati64(wfilename.c_str(),&st)) - _fsize = st.st_size; - std::auto_ptr buf(new std::filebuf()); - buf->open(wfilename.c_str(), std::ios_base::in | std::ios_base::binary); - if (buf->is_open()) { - f = buf; - } + f = buf; } + } } -const wchar_t *LibRaw_file_datastream::wfname() -{ - return wfilename.size()>0?wfilename.c_str():NULL; -} +const wchar_t *LibRaw_file_datastream::wfname() { return wfilename.size() > 0 ? wfilename.c_str() : NULL; } #endif - int LibRaw_file_datastream::valid() -{ - return f.get() ? 1 : 0; -} +int LibRaw_file_datastream::valid() { return f.get() ? 1 : 0; } -#define LR_STREAM_CHK() do {if(!f.get()) throw LIBRAW_EXCEPTION_IO_EOF;}while(0) +#define LR_STREAM_CHK() \ + do \ + { \ + if (!f.get()) \ + throw LIBRAW_EXCEPTION_IO_EOF; \ + } while (0) -int LibRaw_file_datastream::read(void * ptr,size_t size, size_t nmemb) +int LibRaw_file_datastream::read(void *ptr, size_t size, size_t nmemb) { - if(substream) return substream->read(ptr,size,nmemb); - + if (substream) + return substream->read(ptr, size, nmemb); + /* Visual Studio 2008 marks sgetn as insecure, but VS2010 does not. */ #if defined(WIN32SECURECALLS) && (_MSC_VER < 1600) - LR_STREAM_CHK(); return int(f->_Sgetn_s(static_cast(ptr), nmemb * size,nmemb * size) / (size>0?size:1)); + LR_STREAM_CHK(); + return int(f->_Sgetn_s(static_cast(ptr), nmemb * size, nmemb * size) / (size > 0 ? size : 1)); #else - LR_STREAM_CHK(); return int(f->sgetn(static_cast(ptr), std::streamsize(nmemb * size)) / (size>0?size:1)); -#endif -} - -int LibRaw_file_datastream::eof() -{ - if(substream) return substream->eof(); - LR_STREAM_CHK(); return f->sgetc() == EOF; -} - -int LibRaw_file_datastream::seek(INT64 o, int whence) -{ - if(substream) return substream->seek(o,whence); - LR_STREAM_CHK(); - std::ios_base::seekdir dir; - switch (whence) - { - case SEEK_SET: dir = std::ios_base::beg; break; - case SEEK_CUR: dir = std::ios_base::cur; break; - case SEEK_END: dir = std::ios_base::end; break; - default: dir = std::ios_base::beg; - } - return f->pubseekoff((long)o, dir) < 0; -} - -INT64 LibRaw_file_datastream::tell() -{ - if(substream) return substream->tell(); - LR_STREAM_CHK(); return f->pubseekoff(0, std::ios_base::cur); -} - -char* LibRaw_file_datastream::gets(char *str, int sz) -{ - if(substream) return substream->gets(str,sz); - LR_STREAM_CHK(); - std::istream is(f.get()); - is.getline(str, sz); - if (is.fail()) return 0; - return str; -} - -int LibRaw_file_datastream::scanf_one(const char *fmt, void*val) -{ - if(substream) return substream->scanf_one(fmt,val); - LR_STREAM_CHK(); - - std::istream is(f.get()); - - /* HUGE ASSUMPTION: *fmt is either "%d" or "%f" */ - if (strcmp(fmt, "%d") == 0) { - int d; - is >> d; - if (is.fail()) return EOF; - *(static_cast(val)) = d; - } else { - float f; - is >> f; - if (is.fail()) return EOF; - *(static_cast(val)) = f; - } - - return 1; + LR_STREAM_CHK(); + return int(f->sgetn(static_cast(ptr), std::streamsize(nmemb * size)) / (size > 0 ? size : 1)); +#endif } -const char* LibRaw_file_datastream::fname() -{ - return filename.size()>0?filename.c_str():NULL; +int LibRaw_file_datastream::eof() +{ + if (substream) + return substream->eof(); + LR_STREAM_CHK(); + return f->sgetc() == EOF; } - + +int LibRaw_file_datastream::seek(INT64 o, int whence) +{ + if (substream) + return substream->seek(o, whence); + LR_STREAM_CHK(); + std::ios_base::seekdir dir; + switch (whence) + { + case SEEK_SET: + dir = std::ios_base::beg; + break; + case SEEK_CUR: + dir = std::ios_base::cur; + break; + case SEEK_END: + dir = std::ios_base::end; + break; + default: + dir = std::ios_base::beg; + } + return f->pubseekoff((long)o, dir) < 0; +} + +INT64 LibRaw_file_datastream::tell() +{ + if (substream) + return substream->tell(); + LR_STREAM_CHK(); + return f->pubseekoff(0, std::ios_base::cur); +} + +char *LibRaw_file_datastream::gets(char *str, int sz) +{ + if (substream) + return substream->gets(str, sz); + LR_STREAM_CHK(); + std::istream is(f.get()); + is.getline(str, sz); + if (is.fail()) + return 0; + return str; +} + +int LibRaw_file_datastream::scanf_one(const char *fmt, void *val) +{ + if (substream) + return substream->scanf_one(fmt, val); + LR_STREAM_CHK(); + + std::istream is(f.get()); + + /* HUGE ASSUMPTION: *fmt is either "%d" or "%f" */ + if (strcmp(fmt, "%d") == 0) + { + int d; + is >> d; + if (is.fail()) + return EOF; + *(static_cast(val)) = d; + } + else + { + float f; + is >> f; + if (is.fail()) + return EOF; + *(static_cast(val)) = f; + } + + return 1; +} + +const char *LibRaw_file_datastream::fname() { return filename.size() > 0 ? filename.c_str() : NULL; } + /* You can't have a "subfile" and a "tempfile" at the same time. */ int LibRaw_file_datastream::subfile_open(const char *fn) { - LR_STREAM_CHK(); - if (saved_f.get()) return EBUSY; - saved_f = f; - std::auto_ptr buf(new std::filebuf()); - - buf->open(fn, std::ios_base::in | std::ios_base::binary); - if (!buf->is_open()) { - f = saved_f; - return ENOENT; - } else { - f = buf; - } - - return 0; + LR_STREAM_CHK(); + if (saved_f.get()) + return EBUSY; + saved_f = f; + std::auto_ptr buf(new std::filebuf()); + + buf->open(fn, std::ios_base::in | std::ios_base::binary); + if (!buf->is_open()) + { + f = saved_f; + return ENOENT; + } + else + { + f = buf; + } + + return 0; } #if defined(_WIN32) && !defined(__MINGW32__) && defined(_MSC_VER) && (_MSC_VER > 1310) int LibRaw_file_datastream::subfile_open(const wchar_t *fn) { - LR_STREAM_CHK(); - if (saved_f.get()) return EBUSY; - saved_f = f; - std::auto_ptr buf(new std::filebuf()); - - buf->open(fn, std::ios_base::in | std::ios_base::binary); - if (!buf->is_open()) { - f = saved_f; - return ENOENT; - } else { - f = buf; - } + LR_STREAM_CHK(); + if (saved_f.get()) + return EBUSY; + saved_f = f; + std::auto_ptr buf(new std::filebuf()); + + buf->open(fn, std::ios_base::in | std::ios_base::binary); + if (!buf->is_open()) + { + f = saved_f; + return ENOENT; + } + else + { + f = buf; + } - return 0; + return 0; } #endif - void LibRaw_file_datastream::subfile_close() -{ - if (!saved_f.get()) return; - f = saved_f; +{ + if (!saved_f.get()) + return; + f = saved_f; } #undef LR_STREAM_CHK -void * LibRaw_file_datastream::make_jas_stream() +void *LibRaw_file_datastream::make_jas_stream() { #ifdef NO_JASPER - return NULL; + return NULL; #else #if defined(_WIN32) && !defined(__MINGW32__) && defined(_MSC_VER) && (_MSC_VER > 1310) - if(wfname()) - { - jas_file = _wfopen(wfname(),L"rb"); - return jas_stream_fdopen(fileno(jas_file),"rb"); - } - else + if (wfname()) + { + jas_file = _wfopen(wfname(), L"rb"); + return jas_stream_fdopen(fileno(jas_file), "rb"); + } + else #endif - { - return jas_stream_fopen(fname(),"rb"); - } + { + return jas_stream_fopen(fname(), "rb"); + } #endif } int LibRaw_file_datastream::jpeg_src(void *jpegdata) { #ifdef NO_JPEG return -1; // not supported #else - if(jas_file) { fclose(jas_file); jas_file = NULL;} + if (jas_file) + { + fclose(jas_file); + jas_file = NULL; + } #if defined(_WIN32) && !defined(__MINGW32__) && defined(_MSC_VER) && (_MSC_VER > 1310) - if(wfname()) - { - jas_file = _wfopen(wfname(),L"rb"); - } + if (wfname()) + { + jas_file = _wfopen(wfname(), L"rb"); + } else #endif - { - jas_file = fopen(fname(),"rb"); - } - if(jas_file) - { - fseek(jas_file,tell(),SEEK_SET); - j_decompress_ptr cinfo = (j_decompress_ptr) jpegdata; - jpeg_stdio_src(cinfo,jas_file); - return 0; // OK - } + { + jas_file = fopen(fname(), "rb"); + } + if (jas_file) + { + fseek(jas_file, tell(), SEEK_SET); + j_decompress_ptr cinfo = (j_decompress_ptr)jpegdata; + jpeg_stdio_src(cinfo, jas_file); + return 0; // OK + } return -1; #endif } - // == LibRaw_buffer_datastream LibRaw_buffer_datastream::LibRaw_buffer_datastream(void *buffer, size_t bsize) -{ - buf = (unsigned char*)buffer; streampos = 0; streamsize = bsize; +{ + buf = (unsigned char *)buffer; + streampos = 0; + streamsize = bsize; } -LibRaw_buffer_datastream::~LibRaw_buffer_datastream(){} +LibRaw_buffer_datastream::~LibRaw_buffer_datastream() {} -int LibRaw_buffer_datastream::read(void * ptr,size_t sz, size_t nmemb) -{ - if(substream) return substream->read(ptr,sz,nmemb); - size_t to_read = sz*nmemb; - if(to_read > streamsize - streampos) - to_read = streamsize-streampos; - if(to_read<1) - return 0; - memmove(ptr,buf+streampos,to_read); - streampos+=to_read; - return int((to_read+sz-1)/(sz>0?sz:1)); +int LibRaw_buffer_datastream::read(void *ptr, size_t sz, size_t nmemb) +{ + if (substream) + return substream->read(ptr, sz, nmemb); + size_t to_read = sz * nmemb; + if (to_read > streamsize - streampos) + to_read = streamsize - streampos; + if (to_read < 1) + return 0; + memmove(ptr, buf + streampos, to_read); + streampos += to_read; + return int((to_read + sz - 1) / (sz > 0 ? sz : 1)); } int LibRaw_buffer_datastream::seek(INT64 o, int whence) -{ - if(substream) return substream->seek(o,whence); - switch(whence) - { - case SEEK_SET: - if(o<0) - streampos = 0; - else if (size_t(o) > streamsize) - streampos = streamsize; - else - streampos = size_t(o); - return 0; - case SEEK_CUR: - if(o<0) - { - if(size_t(-o) >= streampos) - streampos = 0; - else - streampos += (size_t)o; - } - else if (o>0) - { - if(o+streampos> streamsize) - streampos = streamsize; - else - streampos += (size_t)o; - } - return 0; - case SEEK_END: - if(o>0) - streampos = streamsize; - else if ( size_t(-o) > streamsize) - streampos = 0; - else - streampos = streamsize+(size_t)o; - return 0; - default: - return 0; - } +{ + if (substream) + return substream->seek(o, whence); + switch (whence) + { + case SEEK_SET: + if (o < 0) + streampos = 0; + else if (size_t(o) > streamsize) + streampos = streamsize; + else + streampos = size_t(o); + return 0; + case SEEK_CUR: + if (o < 0) + { + if (size_t(-o) >= streampos) + streampos = 0; + else + streampos += (size_t)o; + } + else if (o > 0) + { + if (o + streampos > streamsize) + streampos = streamsize; + else + streampos += (size_t)o; + } + return 0; + case SEEK_END: + if (o > 0) + streampos = streamsize; + else if (size_t(-o) > streamsize) + streampos = 0; + else + streampos = streamsize + (size_t)o; + return 0; + default: + return 0; + } } INT64 LibRaw_buffer_datastream::tell() -{ - if(substream) return substream->tell(); - return INT64(streampos); -} - -char* LibRaw_buffer_datastream::gets(char *s, int sz) -{ - if (substream) return substream->gets(s,sz); - unsigned char *psrc,*pdest,*str; - str = (unsigned char *)s; - psrc = buf+streampos; - pdest = str; - while ( (size_t(psrc - buf) < streamsize) - && - ((pdest-str)scanf_one(fmt,val); - int scanf_res; - if(streampos>streamsize) return 0; +{ + if (substream) + return substream->tell(); + return INT64(streampos); +} + +char *LibRaw_buffer_datastream::gets(char *s, int sz) +{ + if (substream) + return substream->gets(s, sz); + unsigned char *psrc, *pdest, *str; + str = (unsigned char *)s; + psrc = buf + streampos; + pdest = str; + while ((size_t(psrc - buf) < streamsize) && ((pdest - str) < sz)) + { + *pdest = *psrc; + if (*psrc == '\n') + break; + psrc++; + pdest++; + } + if (size_t(psrc - buf) < streamsize) + psrc++; + if ((pdest - str) < sz) + *(++pdest) = 0; + streampos = psrc - buf; + return s; +} + +int LibRaw_buffer_datastream::scanf_one(const char *fmt, void *val) +{ + if (substream) + return substream->scanf_one(fmt, val); + int scanf_res; + if (streampos > streamsize) + return 0; #ifndef WIN32SECURECALLS - scanf_res = sscanf((char*)(buf+streampos),fmt,val); + scanf_res = sscanf((char *)(buf + streampos), fmt, val); #else - scanf_res = sscanf_s((char*)(buf+streampos),fmt,val); -#endif - if(scanf_res>0) - { - int xcnt=0; - while(streampos24) - break; - } - } - return scanf_res; + scanf_res = sscanf_s((char *)(buf + streampos), fmt, val); +#endif + if (scanf_res > 0) + { + int xcnt = 0; + while (streampos < streamsize) + { + streampos++; + xcnt++; + if (buf[streampos] == 0 || buf[streampos] == ' ' || buf[streampos] == '\t' || buf[streampos] == '\n' || xcnt > 24) + break; + } + } + return scanf_res; } int LibRaw_buffer_datastream::eof() -{ - if(substream) return substream->eof(); - return streampos >= streamsize; -} - int LibRaw_buffer_datastream::valid() -{ - return buf?1:0; +{ + if (substream) + return substream->eof(); + return streampos >= streamsize; } +int LibRaw_buffer_datastream::valid() { return buf ? 1 : 0; } - -void * LibRaw_buffer_datastream::make_jas_stream() +void *LibRaw_buffer_datastream::make_jas_stream() { #ifdef NO_JASPER - return NULL; + return NULL; #else - return jas_stream_memopen((char*)buf+streampos,streamsize-streampos); + return jas_stream_memopen((char *)buf + streampos, streamsize - streampos); #endif } int LibRaw_buffer_datastream::jpeg_src(void *jpegdata) { -#if defined(NO_JPEG) || !defined (USE_JPEG) +#if defined(NO_JPEG) || !defined(USE_JPEG) return -1; #else - j_decompress_ptr cinfo = (j_decompress_ptr) jpegdata; - jpeg_mem_src(cinfo,(unsigned char*)buf+streampos,streamsize-streampos); + j_decompress_ptr cinfo = (j_decompress_ptr)jpegdata; + jpeg_mem_src(cinfo, (unsigned char *)buf + streampos, streamsize - streampos); return 0; #endif } - -//int LibRaw_buffer_datastream - +// int LibRaw_buffer_datastream // == LibRaw_bigfile_datastream -LibRaw_bigfile_datastream::LibRaw_bigfile_datastream(const char *fname): filename(fname) +LibRaw_bigfile_datastream::LibRaw_bigfile_datastream(const char *fname) + : filename(fname) #ifdef WIN32 - ,wfilename() + , + wfilename() #endif -{ - if(filename.size()>0) - { +{ + if (filename.size() > 0) + { #ifndef WIN32 - struct stat st; - if(!stat(filename.c_str(),&st)) - _fsize = st.st_size; + struct stat st; + if (!stat(filename.c_str(), &st)) + _fsize = st.st_size; #else - struct _stati64 st; - if(!_stati64(filename.c_str(),&st)) - _fsize = st.st_size; + struct _stati64 st; + if (!_stati64(filename.c_str(), &st)) + _fsize = st.st_size; #endif #ifndef WIN32SECURECALLS - f = fopen(fname,"rb"); + f = fopen(fname, "rb"); #else - if(fopen_s(&f,fname,"rb")) - f = 0; + if (fopen_s(&f, fname, "rb")) + f = 0; #endif - } - else - {filename=std::string();f=0;} - sav=0; + } + else + { + filename = std::string(); + f = 0; + } + sav = 0; } #if defined(_WIN32) && !defined(__MINGW32__) && defined(_MSC_VER) && (_MSC_VER > 1310) -LibRaw_bigfile_datastream::LibRaw_bigfile_datastream(const wchar_t *fname) : filename(),wfilename(fname) -{ - if(wfilename.size()>0) - { - struct _stati64 st; - if(!_wstati64(wfilename.c_str(),&st)) - _fsize = st.st_size; +LibRaw_bigfile_datastream::LibRaw_bigfile_datastream(const wchar_t *fname) : filename(), wfilename(fname) +{ + if (wfilename.size() > 0) + { + struct _stati64 st; + if (!_wstati64(wfilename.c_str(), &st)) + _fsize = st.st_size; #ifndef WIN32SECURECALLS - f = _wfopen(wfilename.c_str(),L"rb"); + f = _wfopen(wfilename.c_str(), L"rb"); #else - if(_wfopen_s(&f,fname,L"rb")) - f = 0; + if (_wfopen_s(&f, fname, L"rb")) + f = 0; #endif - } - else - { - wfilename=std::wstring(); - f=0; - } - sav=0; -} -const wchar_t *LibRaw_bigfile_datastream::wfname() -{ - return wfilename.size()>0?wfilename.c_str():NULL; + } + else + { + wfilename = std::wstring(); + f = 0; + } + sav = 0; } +const wchar_t *LibRaw_bigfile_datastream::wfname() { return wfilename.size() > 0 ? wfilename.c_str() : NULL; } #endif -LibRaw_bigfile_datastream::~LibRaw_bigfile_datastream() {if(f)fclose(f); if(sav)fclose(sav);} -int LibRaw_bigfile_datastream::valid() { return f?1:0;} +LibRaw_bigfile_datastream::~LibRaw_bigfile_datastream() +{ + if (f) + fclose(f); + if (sav) + fclose(sav); +} +int LibRaw_bigfile_datastream::valid() { return f ? 1 : 0; } -#define LR_BF_CHK() do {if(!f) throw LIBRAW_EXCEPTION_IO_EOF;}while(0) +#define LR_BF_CHK() \ + do \ + { \ + if (!f) \ + throw LIBRAW_EXCEPTION_IO_EOF; \ + } while (0) -int LibRaw_bigfile_datastream::read(void * ptr,size_t size, size_t nmemb) -{ - LR_BF_CHK(); - return substream?substream->read(ptr,size,nmemb):int(fread(ptr,size,nmemb,f)); +int LibRaw_bigfile_datastream::read(void *ptr, size_t size, size_t nmemb) +{ + LR_BF_CHK(); + return substream ? substream->read(ptr, size, nmemb) : int(fread(ptr, size, nmemb, f)); } int LibRaw_bigfile_datastream::eof() -{ - LR_BF_CHK(); - return substream?substream->eof():feof(f); +{ + LR_BF_CHK(); + return substream ? substream->eof() : feof(f); } -int LibRaw_bigfile_datastream:: seek(INT64 o, int whence) -{ - LR_BF_CHK(); -#if defined (WIN32) +int LibRaw_bigfile_datastream::seek(INT64 o, int whence) +{ + LR_BF_CHK(); +#if defined(WIN32) #ifdef WIN32SECURECALLS - return substream?substream->seek(o,whence):_fseeki64(f,o,whence); + return substream ? substream->seek(o, whence) : _fseeki64(f, o, whence); #else - return substream?substream->seek(o,whence):fseek(f,(long)o,whence); + return substream ? substream->seek(o, whence) : fseek(f, (long)o, whence); #endif #else - return substream?substream->seek(o,whence):fseeko(f,o,whence); + return substream ? substream->seek(o, whence) : fseeko(f, o, whence); #endif } INT64 LibRaw_bigfile_datastream::tell() -{ - LR_BF_CHK(); -#if defined (WIN32) +{ + LR_BF_CHK(); +#if defined(WIN32) #ifdef WIN32SECURECALLS - return substream?substream->tell():_ftelli64(f); + return substream ? substream->tell() : _ftelli64(f); #else - return substream?substream->tell():ftell(f); + return substream ? substream->tell() : ftell(f); #endif #else - return substream?substream->tell():ftello(f); + return substream ? substream->tell() : ftello(f); #endif } -char* LibRaw_bigfile_datastream::gets(char *str, int sz) -{ - LR_BF_CHK(); - return substream?substream->gets(str,sz):fgets(str,sz,f); +char *LibRaw_bigfile_datastream::gets(char *str, int sz) +{ + LR_BF_CHK(); + return substream ? substream->gets(str, sz) : fgets(str, sz, f); } -int LibRaw_bigfile_datastream::scanf_one(const char *fmt, void*val) -{ - LR_BF_CHK(); - return substream?substream->scanf_one(fmt,val): -#ifndef WIN32SECURECALLS - fscanf(f,fmt,val) +int LibRaw_bigfile_datastream::scanf_one(const char *fmt, void *val) +{ + LR_BF_CHK(); + return substream ? substream->scanf_one(fmt, val) : +#ifndef WIN32SECURECALLS + fscanf(f, fmt, val) #else - fscanf_s(f,fmt,val) + fscanf_s(f, fmt, val) #endif - ; + ; } -const char *LibRaw_bigfile_datastream::fname() -{ - return filename.size()>0?filename.c_str():NULL; -} +const char *LibRaw_bigfile_datastream::fname() { return filename.size() > 0 ? filename.c_str() : NULL; } int LibRaw_bigfile_datastream::subfile_open(const char *fn) { - if(sav) return EBUSY; - sav = f; + if (sav) + return EBUSY; + sav = f; #ifndef WIN32SECURECALLS - f = fopen(fn,"rb"); + f = fopen(fn, "rb"); #else - fopen_s(&f,fn,"rb"); -#endif - if(!f) - { - f = sav; - sav = NULL; - return ENOENT; - } - else - return 0; + fopen_s(&f, fn, "rb"); +#endif + if (!f) + { + f = sav; + sav = NULL; + return ENOENT; + } + else + return 0; } #if defined(_WIN32) && !defined(__MINGW32__) && defined(_MSC_VER) && (_MSC_VER > 1310) int LibRaw_bigfile_datastream::subfile_open(const wchar_t *fn) { - if(sav) return EBUSY; - sav = f; + if (sav) + return EBUSY; + sav = f; #ifndef WIN32SECURECALLS - f = _wfopen(fn,L"rb"); + f = _wfopen(fn, L"rb"); #else - _wfopen_s(&f,fn,L"rb"); + _wfopen_s(&f, fn, L"rb"); #endif - if(!f) - { - f = sav; - sav = NULL; - return ENOENT; - } - else - return 0; + if (!f) + { + f = sav; + sav = NULL; + return ENOENT; + } + else + return 0; } #endif - void LibRaw_bigfile_datastream::subfile_close() { - if(!sav) return; - fclose(f); - f = sav; - sav = 0; + if (!sav) + return; + fclose(f); + f = sav; + sav = 0; } - void *LibRaw_bigfile_datastream::make_jas_stream() { #ifdef NO_JASPER - return NULL; + return NULL; #else - return jas_stream_fdopen(fileno(f),"rb"); + return jas_stream_fdopen(fileno(f), "rb"); #endif } int LibRaw_bigfile_datastream::jpeg_src(void *jpegdata) { #ifdef NO_JPEG return -1; #else - if(!f) return -1; - j_decompress_ptr cinfo = (j_decompress_ptr) jpegdata; - jpeg_stdio_src(cinfo,f); + if (!f) + return -1; + j_decompress_ptr cinfo = (j_decompress_ptr)jpegdata; + jpeg_stdio_src(cinfo, f); return 0; // OK #endif } - // == LibRaw_windows_datastream #ifdef WIN32 -LibRaw_windows_datastream::LibRaw_windows_datastream(const TCHAR* sFile) - : LibRaw_buffer_datastream(NULL, 0) - , hMap_(0) - , pView_(NULL) +LibRaw_windows_datastream::LibRaw_windows_datastream(const TCHAR *sFile) + : LibRaw_buffer_datastream(NULL, 0), hMap_(0), pView_(NULL) { - HANDLE hFile = CreateFile(sFile, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); - if (hFile == INVALID_HANDLE_VALUE) - throw std::runtime_error("failed to open the file"); - - try { Open(hFile); } catch(...) { CloseHandle(hFile); throw; } - - CloseHandle(hFile); // windows will defer the actual closing of this handle until the hMap_ is closed - reconstruct_base(); + HANDLE hFile = CreateFile(sFile, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (hFile == INVALID_HANDLE_VALUE) + throw std::runtime_error("failed to open the file"); + + try + { + Open(hFile); + } + catch (...) + { + CloseHandle(hFile); + throw; + } + + CloseHandle(hFile); // windows will defer the actual closing of this handle until the hMap_ is closed + reconstruct_base(); } - // ctor: construct with a file handle - caller is responsible for closing the file handle +// ctor: construct with a file handle - caller is responsible for closing the file handle LibRaw_windows_datastream::LibRaw_windows_datastream(HANDLE hFile) - : LibRaw_buffer_datastream(NULL, 0) - , hMap_(0) - , pView_(NULL) + : LibRaw_buffer_datastream(NULL, 0), hMap_(0), pView_(NULL) { - Open(hFile); - reconstruct_base(); + Open(hFile); + reconstruct_base(); } // dtor: unmap and close the mapping handle LibRaw_windows_datastream::~LibRaw_windows_datastream() { - if (pView_ != NULL) - ::UnmapViewOfFile(pView_); - - if (hMap_ != 0) - ::CloseHandle(hMap_); + if (pView_ != NULL) + ::UnmapViewOfFile(pView_); + + if (hMap_ != 0) + ::CloseHandle(hMap_); } void LibRaw_windows_datastream::Open(HANDLE hFile) { - // create a file mapping handle on the file handle - hMap_ = ::CreateFileMapping(hFile, 0, PAGE_READONLY, 0, 0, 0); - if (hMap_ == NULL) throw std::runtime_error("failed to create file mapping"); - - // now map the whole file base view - if (!::GetFileSizeEx(hFile, (PLARGE_INTEGER)&cbView_)) - throw std::runtime_error("failed to get the file size"); - - pView_ = ::MapViewOfFile(hMap_, FILE_MAP_READ, 0, 0, (size_t)cbView_); - if (pView_ == NULL) - throw std::runtime_error("failed to map the file"); -} - + // create a file mapping handle on the file handle + hMap_ = ::CreateFileMapping(hFile, 0, PAGE_READONLY, 0, 0, 0); + if (hMap_ == NULL) + throw std::runtime_error("failed to create file mapping"); -#endif + // now map the whole file base view + if (!::GetFileSizeEx(hFile, (PLARGE_INTEGER)&cbView_)) + throw std::runtime_error("failed to get the file size"); + pView_ = ::MapViewOfFile(hMap_, FILE_MAP_READ, 0, 0, (size_t)cbView_); + if (pView_ == NULL) + throw std::runtime_error("failed to map the file"); +} - +#endif diff --git a/core/libs/rawengine/libraw/src/libraw_xtrans_compressed.cpp b/core/libs/rawengine/libraw/src/libraw_xtrans_compressed.cpp deleted file mode 100644 index 2230305513..0000000000 --- a/core/libs/rawengine/libraw/src/libraw_xtrans_compressed.cpp +++ /dev/null @@ -1,812 +0,0 @@ -/* -*- C++ -*- - * File: libraw_xtrans_compressed.cpp - * Copyright (C) 2016 Alexey Danilchenko - * - * Adopted to LibRaw by Alex Tutubalin, lexa@lexa.ru - * LibRaw Fujifilm/compressed decoder - -LibRaw is free software; you can redistribute it and/or modify -it under the terms of the one of two licenses as you choose: - -1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 - (See file LICENSE.LGPL provided in LibRaw distribution archive for details). - -2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 - (See file LICENSE.CDDL provided in LibRaw distribution archive for details). - - */ - -// This file is #included in libraw_cxx - -#ifdef _abs -#undef _abs -#undef _min -#endif -#define _abs(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31)) -#define _min(a,b) ((a) < (b) ? (a) : (b)) - -struct int_pair { - int value1; - int value2; -}; - -enum _xt_lines -{ - _R0=0,_R1,_R2,_R3,_R4, - _G0,_G1,_G2,_G3,_G4,_G5,_G6,_G7, - _B0,_B1,_B2,_B3,_B4, - _ltotal -}; - - -struct xtrans_block { - int cur_bit; // current bit being read (from left to right) - int cur_pos; // current position in a buffer - INT64 cur_buf_offset; // offset of this buffer in a file - unsigned max_read_size; // Amount of data to be read - int cur_buf_size; // buffer size - uchar *cur_buf; // currently read block - bool lastlast; - LibRaw_abstract_datastream *input; - struct int_pair grad_even[3][41]; // tables of gradients - struct int_pair grad_odd[3][41]; - ushort *linealloc; - ushort *linebuf[_ltotal]; -}; - -static unsigned sgetn(int n, uchar *s) -{ - unsigned result = 0; - while (n-- > 0) - result = (result<<8) | (*s++); - return result; -} - -void LibRaw::init_xtrans(struct xtrans_params* info) -{ - int cur_val, i; - char *qt; - - if (libraw_internal_data.unpacker_data.fuji_block_width % 3) - derror(); - - info->q_table = (char *) malloc(32768); - merror(info->q_table, "init_xtrans()"); - - info->line_width = (libraw_internal_data.unpacker_data.fuji_block_width*2)/3; - - info->q_point[0] = 0; - info->q_point[1] = 0x12; - info->q_point[2] = 0x43; - info->q_point[3] = 0x114; - info->q_point[4] = (1 << libraw_internal_data.unpacker_data.fuji_bits) - 1; - info->min_value = 0x40; - - cur_val = -info->q_point[4]; - for (qt = info->q_table; cur_val<=info->q_point[4]; ++qt, ++cur_val) - { - if (cur_val<= -info->q_point[3]) - *qt = -4; - else if (cur_val<= -info->q_point[2]) - *qt = -3; - else if (cur_val<= -info->q_point[1]) - *qt = -2; - else if (cur_val< 0) - *qt = -1; - else if (cur_val== 0) - *qt = 0; - else if (cur_val< info->q_point[1]) - *qt = 1; - else if (cur_val< info->q_point[2]) - *qt = 2; - else if (cur_val< info->q_point[3]) - *qt = 3; - else - *qt = 4; - } - - // populting gradients - if (info->q_point[4] == 0x3FFF) - { - info->total_values = 0x4000; - info->raw_bits = 14; - info->max_bits = 56; - info->maxDiff = 256; - } - else if (info->q_point[4] == 0xFFF) - { - info->total_values = 4096; - info->raw_bits = 12; - info->max_bits = 48; - info->maxDiff = 64; - } - else - derror(); -} - -#define XTRANS_BUF_SIZE 0x10000 - -static inline void fuji_fill_buffer(struct xtrans_block *info) -{ - if (info->cur_pos >= info->cur_buf_size) - { - info->cur_pos = 0; - info->cur_buf_offset += info->cur_buf_size; -#ifdef LIBRAW_USE_OPENMP -#pragma omp critical -#endif - { -#ifndef LIBRAW_USE_OPENMP - info->input->lock(); -#endif - info->input->seek(info->cur_buf_offset, SEEK_SET); - info->cur_buf_size=info->input->read(info->cur_buf, 1, _min(info->max_read_size,XTRANS_BUF_SIZE)); -#ifndef LIBRAW_USE_OPENMP - info->input->unlock(); -#endif - if(info->cur_buf_size<1 && !info->lastlast) // nothing read - throw LIBRAW_EXCEPTION_IO_EOF; - info->max_read_size -= info->cur_buf_size; - - } - } -} - -void LibRaw::init_xtrans_block(struct xtrans_block* info, const struct xtrans_params *params, INT64 raw_offset, unsigned dsize) -{ - info->linealloc = (ushort*)calloc(sizeof(ushort),_ltotal*(params->line_width+2)); - merror(info->linealloc, "init_xtrans_block()"); - - INT64 fsize = libraw_internal_data.internal_data.input->size(); - info->max_read_size = _min(unsigned(fsize-raw_offset),dsize+16); // Data size may be incorrect? - info->lastlast = false; - - info->input = libraw_internal_data.internal_data.input; - info->linebuf[_R0] = info->linealloc; - for(int i = _R1; i<=_B4;i++) - info->linebuf[i] = info->linebuf[i-1] + params->line_width + 2; - - // init buffer - info->cur_buf = (uchar*)malloc(XTRANS_BUF_SIZE); - merror(info->cur_buf, "init_xtrans_block()"); - info->cur_bit = 0; - info->cur_pos = 0; - info->cur_buf_offset = raw_offset; - for(int j=0; j < 3; j++) - for (int i=0; i<41; i++) - { - info->grad_even[j][i].value1 = params->maxDiff; - info->grad_even[j][i].value2 = 1; - info->grad_odd[j][i].value1 = params->maxDiff; - info->grad_odd[j][i].value2 = 1; - } - - info->cur_buf_size = 0; - fuji_fill_buffer(info); -} - -void LibRaw::copy_line_to_xtrans(struct xtrans_block* info, int cur_line, int cur_block, int cur_block_width) -{ - ushort *lineBufB[3]; - ushort *lineBufG[6]; - ushort *lineBufR[3]; - unsigned pixel_count; - ushort* line_buf; - int index; - - int offset =libraw_internal_data.unpacker_data.fuji_block_width*cur_block + 6 * imgdata.sizes.raw_width * cur_line; - ushort* raw_block_data = imgdata.rawdata.raw_image + offset; - int row_count = 0; - - for(int i = 0; i<3; i++) - { - lineBufR[i] = info->linebuf[_R2+i] + 1; - lineBufB[i] = info->linebuf[_B2+i] + 1; - } - for(int i = 0; i<6; i++) - lineBufG[i] = info->linebuf[_G2+i] + 1; - - while (row_count < 6) - { - pixel_count = 0; - while (pixel_count < cur_block_width) - { - switch (imgdata.idata.xtrans_abs[row_count][(pixel_count % 6)]) - { - case 0: // red - line_buf = lineBufR[row_count >> 1]; - break; - case 1: // green - default: // to make static analyzer happy - line_buf = lineBufG[row_count]; - break; - case 2: // blue - line_buf = lineBufB[row_count >> 1]; - break; - } - - index = (((pixel_count*2/3) & 0x7FFFFFFE) | ((pixel_count % 3) & 1)) + ((pixel_count % 3) >> 1); - raw_block_data[pixel_count] = line_buf[index]; - - ++pixel_count; - } - ++row_count; - raw_block_data += imgdata.sizes.raw_width; - } -} - -#define fuji_quant_gradient(i,v1,v2) (9*i->q_table[i->q_point[4]+(v1)] + i->q_table[i->q_point[4]+(v2)]) - - -static inline void fuji_zerobits(struct xtrans_block* info, int *count) -{ - uchar zero = 0; - *count = 0; - while (zero == 0) - { - zero = (info->cur_buf[info->cur_pos] >> (7 - info->cur_bit)) & 1; - info->cur_bit++; - info->cur_bit &= 7; - if (!info->cur_bit) - { - ++info->cur_pos; - fuji_fill_buffer(info); - } - if (zero) - break; - ++*count; - } -} - -static inline void fuji_read_code(struct xtrans_block* info, int *data, int bits_to_read) -{ - uchar bits_left = bits_to_read; - uchar bits_left_in_byte = 8 - (info->cur_bit & 7); - *data = 0; - if (!bits_to_read) - return; - if (bits_to_read >= bits_left_in_byte) - { - do - { - *data <<= bits_left_in_byte; - bits_left -= bits_left_in_byte; - *data |= info->cur_buf[info->cur_pos] & ((1 << bits_left_in_byte) - 1); - ++info->cur_pos; - fuji_fill_buffer(info); - bits_left_in_byte = 8; - } - while (bits_left >= 8); - } - if (!bits_left) - { - info->cur_bit = (8 - (bits_left_in_byte & 7)) & 7; - return; - } - *data <<= bits_left; - bits_left_in_byte -= bits_left; - *data |= ((1 << bits_left) - 1) & ((unsigned)info->cur_buf[info->cur_pos] >> bits_left_in_byte); - info->cur_bit = (8 - (bits_left_in_byte & 7)) & 7; -} - -static inline int bitDiff(int value1, int value2) -{ - int decBits = 0; - if ( value2 < value1 ) - while (decBits <= 12 && - (value2 << ++decBits) - < value1) - ; - return decBits; -} - -static inline int fuji_decode_sample_even(struct xtrans_block* info, const struct xtrans_params * params, ushort* line_buf, int pos, struct int_pair* grads) -{ - int interp_val = 0; - //ushort decBits; - int errcnt=0; - - int sample=0, code=0; - ushort* line_buf_cur = line_buf + pos; - int Rb = line_buf_cur[-2 - params->line_width]; - int Rc = line_buf_cur[-3 - params->line_width]; - int Rd = line_buf_cur[-1 - params->line_width]; - int Rf = line_buf_cur[-4 - 2*params->line_width]; - - int grad, gradient, diffRcRb, diffRfRb, diffRdRb; - - grad = fuji_quant_gradient(params, Rb - Rf, Rc - Rb); - gradient = _abs(grad); - diffRcRb = _abs(Rc - Rb); - diffRfRb = _abs(Rf - Rb); - diffRdRb = _abs(Rd - Rb); - - if ( diffRcRb > diffRfRb && diffRcRb > diffRdRb ) - interp_val = Rf + Rd + 2 * Rb; - else if ( diffRdRb > diffRcRb && diffRdRb > diffRfRb ) - interp_val = Rf + Rc + 2 * Rb; - else - interp_val = Rd + Rc + 2 * Rb; - - - fuji_zerobits(info, &sample); - - if (sample < params->max_bits - params->raw_bits - 1) - { - int decBits = bitDiff(grads[gradient].value1, grads[gradient].value2); - fuji_read_code(info, &code, decBits); - code += sample << decBits; - } - else - { - fuji_read_code(info, &code, params->raw_bits); - code++; - } - - if (code < 0 || code >= params->total_values) - errcnt++; - - if (code & 1) - code = -1 - code/2; - else - code /= 2; - - grads[gradient].value1 += _abs(code); - if (grads[gradient].value2 == params->min_value ) - { - grads[gradient].value1 >>= 1; - grads[gradient].value2 >>= 1; - } - grads[gradient].value2++; - if (grad < 0) - interp_val = (interp_val >> 2) - code; - else - interp_val = (interp_val >> 2) + code; - if ( interp_val < 0 ) - interp_val += params->total_values; - else if (interp_val > params->q_point[4]) - interp_val -= params->total_values; - - if ( interp_val >= 0 ) - line_buf_cur[0] = _min(interp_val, params->q_point[4]); - else - line_buf_cur[0] = 0; - return errcnt; -} - -static inline int fuji_decode_sample_odd(struct xtrans_block* info, const struct xtrans_params * params, ushort* line_buf, int pos, struct int_pair* grads) -{ - int interp_val = 0; - int errcnt = 0; - - int sample=0, code=0; - ushort* line_buf_cur = line_buf + pos; - int Ra = line_buf_cur[-1]; - int Rb = line_buf_cur[-2 - params->line_width]; - int Rc = line_buf_cur[-3 - params->line_width]; - int Rd = line_buf_cur[-1 - params->line_width]; - int Rg = line_buf_cur[1]; - - int grad, gradient; - - grad = fuji_quant_gradient(params, Rb - Rc, Rc - Ra); - gradient = _abs(grad); - - if ((Rb > Rc && Rb > Rd) || (Rb < Rc && Rb < Rd)) - interp_val = (Rg + Ra + 2 * Rb) >> 2; - else - interp_val = (Ra + Rg) >> 1; - - fuji_zerobits(info, &sample); - - if (sample < params->max_bits - params->raw_bits - 1) - { - int decBits = bitDiff(grads[gradient].value1, grads[gradient].value2); - fuji_read_code(info, &code, decBits); - code += sample << decBits; - } - else - { - fuji_read_code(info, &code, params->raw_bits); - code++; - } - - if (code < 0 || code >= params->total_values) - errcnt++; - - if (code & 1) - code = -1 - code/2; - else - code /= 2; - - grads[gradient].value1 += _abs(code); - if (grads[gradient].value2 == params->min_value) - { - grads[gradient].value1 >>= 1; - grads[gradient].value2 >>= 1; - } - grads[gradient].value2++; - if (grad < 0) - interp_val -= code; - else - interp_val += code; - if ( interp_val < 0 ) - interp_val += params->total_values; - else if (interp_val > params->q_point[4]) - interp_val -= params->total_values; - - if ( interp_val >= 0 ) - line_buf_cur[0] = _min(interp_val, params->q_point[4]); - else - line_buf_cur[0] = 0; - return errcnt; -} - -static void fuji_decode_interpolation_even(int line_width, ushort* line_buf, int pos) -{ - ushort* line_buf_cur = line_buf + pos; - int Rb = line_buf_cur[-2 - line_width]; - int Rc = line_buf_cur[-3 - line_width]; - int Rd = line_buf_cur[-1 - line_width]; - int Rf = line_buf_cur[-4 - 2*line_width]; - int diffRcRb = _abs(Rc - Rb); - int diffRfRb = _abs(Rf - Rb); - int diffRdRb = _abs(Rd - Rb); - if ( diffRcRb > diffRfRb && diffRcRb > diffRdRb ) - *line_buf_cur = (Rf + Rd + 2 * Rb) >> 2; - else if ( diffRdRb > diffRcRb && diffRdRb > diffRfRb ) - *line_buf_cur = (Rf + Rc + 2 * Rb) >> 2; - else - *line_buf_cur = (Rd + Rc + 2 * Rb) >> 2; -} - -static void xtrans_extend_generic(ushort *linebuf[_ltotal], int line_width, int start, int end) -{ - for(int i = start; i<= end; i++) - { - linebuf[i][0] = linebuf[i-1][1]; - linebuf[i][line_width + 1] = linebuf[i-1][line_width]; - } -} - -static void xtrans_extend_red(ushort *linebuf[_ltotal], int line_width) -{ - xtrans_extend_generic(linebuf,line_width,_R2,_R4); -} - -static void xtrans_extend_green(ushort *linebuf[_ltotal], int line_width) -{ - xtrans_extend_generic(linebuf,line_width,_G2,_G7); -} - -static void xtrans_extend_blue(ushort *linebuf[_ltotal], int line_width) -{ - xtrans_extend_generic(linebuf,line_width,_B2,_B4); -} - -void LibRaw::xtrans_decode_block(struct xtrans_block* info, const struct xtrans_params *params, int cur_line) -{ - int r_even_pos = 0, r_odd_pos = 1; - int g_even_pos = 0, g_odd_pos = 1; - int b_even_pos = 0, b_odd_pos = 1; - - int errcnt = 0; - - const int line_width = params->line_width; - - while (g_even_pos < line_width || g_odd_pos < line_width) - { - if (g_even_pos < line_width) - { - fuji_decode_interpolation_even(line_width, info->linebuf[_R2] + 1, r_even_pos); - r_even_pos += 2; - errcnt+=fuji_decode_sample_even(info, params, info->linebuf[_G2] + 1, g_even_pos, info->grad_even[0]); - g_even_pos += 2; - } - if (g_even_pos > 8) - { - errcnt+=fuji_decode_sample_odd(info, params, info->linebuf[_R2] + 1, r_odd_pos, info->grad_odd[0]); - r_odd_pos += 2; - errcnt+=fuji_decode_sample_odd(info, params, info->linebuf[_G2] + 1, g_odd_pos, info->grad_odd[0]); - g_odd_pos += 2; - } - } - - xtrans_extend_red(info->linebuf,line_width); - xtrans_extend_green(info->linebuf,line_width); - - g_even_pos = 0, g_odd_pos = 1; - - while (g_even_pos < line_width || g_odd_pos < line_width) - { - if (g_even_pos < line_width) - { - errcnt+=fuji_decode_sample_even(info, params, info->linebuf[_G3] + 1, g_even_pos, info->grad_even[1]); - g_even_pos += 2; - fuji_decode_interpolation_even(line_width,info->linebuf[_B2] + 1, b_even_pos); - b_even_pos += 2; - } - if (g_even_pos > 8) - { - errcnt+=fuji_decode_sample_odd(info,params, info->linebuf[_G3] + 1, g_odd_pos, info->grad_odd[1]); - g_odd_pos += 2; - errcnt+=fuji_decode_sample_odd(info,params, info->linebuf[_B2] + 1, b_odd_pos, info->grad_odd[1]); - b_odd_pos += 2; - } - } - - xtrans_extend_green(info->linebuf,line_width); - xtrans_extend_blue(info->linebuf,line_width); - - r_even_pos = 0, r_odd_pos = 1; - g_even_pos = 0, g_odd_pos = 1; - - while (g_even_pos < line_width || g_odd_pos < line_width) - { - if (g_even_pos < line_width) - { - if (r_even_pos & 3) - errcnt+=fuji_decode_sample_even(info, params, info->linebuf[_R3] + 1, r_even_pos, info->grad_even[2]); - else - fuji_decode_interpolation_even(line_width, info->linebuf[_R3] + 1, r_even_pos); - r_even_pos += 2; - fuji_decode_interpolation_even(line_width, info->linebuf[_G4] + 1, g_even_pos); - g_even_pos += 2; - } - if (g_even_pos > 8) - { - errcnt+=fuji_decode_sample_odd(info, params,info->linebuf[_R3] + 1, r_odd_pos, info->grad_odd[2]); - r_odd_pos += 2; - errcnt+=fuji_decode_sample_odd(info,params, info->linebuf[_G4] + 1, g_odd_pos, info->grad_odd[2]); - g_odd_pos += 2; - } - } - - xtrans_extend_red(info->linebuf,line_width); - xtrans_extend_green(info->linebuf,line_width); - - g_even_pos = 0, g_odd_pos = 1; - b_even_pos = 0, b_odd_pos = 1; - - while (g_even_pos < line_width || g_odd_pos < line_width) - { - if (g_even_pos < line_width) - { - errcnt+=fuji_decode_sample_even(info,params, info->linebuf[_G5] + 1, g_even_pos, info->grad_even[0]); - g_even_pos += 2; - if ((b_even_pos & 3) == 2) - fuji_decode_interpolation_even(line_width, info->linebuf[_B3] + 1, b_even_pos); - else - errcnt+=fuji_decode_sample_even(info, params,info->linebuf[_B3] + 1, b_even_pos, info->grad_even[0]); - b_even_pos += 2; - } - if (g_even_pos > 8) - { - errcnt+=fuji_decode_sample_odd(info, params,info->linebuf[_G5] + 1, g_odd_pos, info->grad_odd[0]); - g_odd_pos += 2; - errcnt+=fuji_decode_sample_odd(info, params,info->linebuf[_B3] + 1, b_odd_pos, info->grad_odd[0]); - b_odd_pos += 2; - } - } - - xtrans_extend_green(info->linebuf,line_width); - xtrans_extend_blue(info->linebuf,line_width); - - r_even_pos = 0, r_odd_pos = 1; - g_even_pos = 0, g_odd_pos = 1; - - while (g_even_pos < line_width || g_odd_pos < line_width) - { - if (g_even_pos < line_width) - { - if ((r_even_pos & 3) == 2) - fuji_decode_interpolation_even(line_width, info->linebuf[_R4] + 1, r_even_pos); - else - errcnt+=fuji_decode_sample_even(info,params, info->linebuf[_R4] + 1, r_even_pos, info->grad_even[1]); - r_even_pos += 2; - errcnt+=fuji_decode_sample_even(info,params, info->linebuf[_G6] + 1, g_even_pos, info->grad_even[1]); - g_even_pos += 2; - } - if (g_even_pos > 8) - { - errcnt+=fuji_decode_sample_odd(info,params, info->linebuf[_R4] + 1, r_odd_pos, info->grad_odd[1]); - r_odd_pos += 2; - errcnt+=fuji_decode_sample_odd(info,params, info->linebuf[_G6] + 1, g_odd_pos, info->grad_odd[1]); - g_odd_pos += 2; - } - } - - xtrans_extend_red(info->linebuf,line_width); - xtrans_extend_green(info->linebuf,line_width); - - g_even_pos = 0, g_odd_pos = 1; - b_even_pos = 0, b_odd_pos = 1; - - while (g_even_pos < line_width || g_odd_pos < line_width) - { - if (g_even_pos < line_width) - { - fuji_decode_interpolation_even(line_width, info->linebuf[_G7] + 1, g_even_pos); - g_even_pos += 2; - if (b_even_pos & 3) - errcnt+=fuji_decode_sample_even(info,params, info->linebuf[_B4] + 1, b_even_pos, info->grad_even[2]); - else - fuji_decode_interpolation_even(line_width, info->linebuf[_B4] + 1, b_even_pos); - b_even_pos += 2; - } - if (g_even_pos > 8) - { - errcnt+=fuji_decode_sample_odd(info, params,info->linebuf[_G7] + 1, g_odd_pos, info->grad_odd[2]); - g_odd_pos += 2; - errcnt+=fuji_decode_sample_odd(info, params,info->linebuf[_B4] + 1, b_odd_pos, info->grad_odd[2]); - b_odd_pos += 2; - } - } - - xtrans_extend_green(info->linebuf,line_width); - xtrans_extend_blue(info->linebuf,line_width); - - if(errcnt) - derror(); -} - -void LibRaw::xtrans_decode_strip(const struct xtrans_params* info_common, int cur_block, INT64 raw_offset, unsigned dsize) -{ - int cur_block_width, cur_line; - unsigned line_size; - struct xtrans_block info; - - init_xtrans_block(&info, info_common, raw_offset,dsize); - line_size = sizeof(ushort)*(info_common->line_width+2); - - cur_block_width = libraw_internal_data.unpacker_data.fuji_block_width; - if (cur_block+1 == libraw_internal_data.unpacker_data.fuji_total_blocks) - cur_block_width = imgdata.sizes.raw_width % libraw_internal_data.unpacker_data.fuji_block_width; - - struct i_pair - { - int a,b; - }; - const i_pair mtable[6] = { {_R0,_R3},{_R1,_R4},{_G0,_G6},{_G1,_G7},{_B0,_B3},{_B1,_B4}}, - ztable[3]= {{_R2,3},{_G2,6},{_B2,3}}; - for (cur_line = 0; cur_line < libraw_internal_data.unpacker_data.fuji_total_lines; cur_line++) - { - info.lastlast = (cur_block == libraw_internal_data.unpacker_data.fuji_total_blocks-1) && (cur_line ==libraw_internal_data.unpacker_data.fuji_total_lines-1); - xtrans_decode_block(&info, info_common, cur_line); - - // copy data from line buffers and advance - for(int i=0; i < 6; i++) - memcpy(info.linebuf[mtable[i].a], info.linebuf[mtable[i].b], line_size); - - copy_line_to_xtrans(&info, cur_line, cur_block, cur_block_width); - - for(int i=0; i < 3; i++) - { - memset(info.linebuf[ztable[i].a], 0, ztable[i].b*line_size); - info.linebuf[ztable[i].a][0] = info.linebuf[ztable[i].a-1][1]; - info.linebuf[ztable[i].a][info_common->line_width + 1] = info.linebuf[ztable[i].a-1][info_common->line_width]; - } - } - - // release data - free(info.linealloc); - free(info.cur_buf); -} - -void LibRaw::xtrans_compressed_load_raw() -{ - struct xtrans_params common_info; - int cur_block; - unsigned line_size, *block_sizes; - INT64 raw_offset, *raw_block_offsets; - //struct xtrans_block info; - - init_xtrans(&common_info); - line_size = sizeof(ushort)*(common_info.line_width+2); - - // read block sizes - block_sizes = (unsigned*) malloc(sizeof(unsigned)* libraw_internal_data.unpacker_data.fuji_total_blocks); - merror(block_sizes, "xtrans_load_raw()"); - raw_block_offsets = (INT64*) malloc(sizeof(INT64)*libraw_internal_data.unpacker_data.fuji_total_blocks); - merror(raw_block_offsets, "xtrans_load_raw()"); - - raw_offset = sizeof(unsigned)*libraw_internal_data.unpacker_data.fuji_total_blocks; - if (raw_offset & 0xC) - raw_offset += 0x10 - (raw_offset & 0xC); - - raw_offset += libraw_internal_data.unpacker_data.data_offset; - - libraw_internal_data.internal_data.input->seek (libraw_internal_data.unpacker_data.data_offset, SEEK_SET); - libraw_internal_data.internal_data.input->read (block_sizes, 1, sizeof(unsigned)*libraw_internal_data.unpacker_data.fuji_total_blocks); - - raw_block_offsets[0] = raw_offset; - // calculating raw block offsets - for (cur_block = 0; cur_block < libraw_internal_data.unpacker_data.fuji_total_blocks; cur_block++) - { - unsigned bsize = sgetn(4, (uchar *)(block_sizes+cur_block)); - block_sizes[cur_block] = bsize; - } - - for (cur_block = 1; cur_block < libraw_internal_data.unpacker_data.fuji_total_blocks; cur_block++) - raw_block_offsets[cur_block] = raw_block_offsets[cur_block-1] + block_sizes[cur_block-1] ; - - xtrans_decode_loop(&common_info,libraw_internal_data.unpacker_data.fuji_total_blocks,raw_block_offsets,block_sizes); - - free(block_sizes); - free(raw_block_offsets); - free(common_info.q_table); -} - -void LibRaw::xtrans_decode_loop(const struct xtrans_params* common_info, int count, INT64* raw_block_offsets, unsigned *block_sizes) -{ - int cur_block; -#ifdef LIBRAW_USE_OPENMP -#pragma omp parallel for private(cur_block) -#endif - for (cur_block = 0; cur_block < count ; cur_block++) - { - xtrans_decode_strip(common_info, cur_block, raw_block_offsets[cur_block], block_sizes[cur_block]); - } -} - -void LibRaw::parse_xtrans_header() -{ - unsigned signature, version, h_raw_type, h_raw_bits, - h_raw_height, h_raw_rounded_width, h_raw_width, - h_block_size, h_blocks_in_row, h_total_lines; - - uchar header[16]; - - libraw_internal_data.internal_data.input->seek(libraw_internal_data.unpacker_data.data_offset,SEEK_SET); - libraw_internal_data.internal_data.input->read(header, 1, sizeof(header)); - - // read all header - signature = sgetn(2, header); - version = header[2]; - h_raw_type = header[3]; - h_raw_bits = header[4]; - h_raw_height = sgetn(2, header+5); - h_raw_rounded_width = sgetn(2, header+7); - h_raw_width = sgetn(2, header+9); - h_block_size = sgetn(2, header+11); - h_blocks_in_row = header[13]; - h_total_lines = sgetn(2, header+14); - - // general validation - if (signature != 0x4953 - || version != 1 - || h_raw_height > 0x3000 - || h_raw_height < 6 - || h_raw_height % 6 - || h_raw_width > 0x3000 - || h_raw_width < 0x300 - || h_raw_width % 24 - || h_raw_rounded_width > 0x3000 - || h_raw_rounded_width < h_block_size - || h_raw_rounded_width % h_block_size - || h_raw_rounded_width - h_raw_width >= h_block_size - || h_block_size != 0x300 - || h_blocks_in_row > 0x10 - || h_blocks_in_row == 0 - || h_blocks_in_row != h_raw_rounded_width / h_block_size - || h_total_lines > 0x800 - || h_total_lines == 0 - || h_total_lines != h_raw_height / 6 - || (h_raw_bits != 12 && h_raw_bits != 14) - || h_raw_type != 16) - return; - - // modify data - libraw_internal_data.unpacker_data.fuji_total_lines = h_total_lines; - libraw_internal_data.unpacker_data.fuji_total_blocks = h_blocks_in_row; - libraw_internal_data.unpacker_data.fuji_block_width = h_block_size; - libraw_internal_data.unpacker_data.fuji_bits = h_raw_bits; - imgdata.sizes.raw_width = h_raw_width; - imgdata.sizes.raw_height = h_raw_height; - libraw_internal_data.unpacker_data.data_offset += 16; - load_raw = &LibRaw::xtrans_compressed_load_raw; -} - - -#undef _abs -#undef _min diff --git a/core/libs/widgets/CMakeLists.txt b/core/libs/widgets/CMakeLists.txt index 40dab76920..6ddfd57501 100644 --- a/core/libs/widgets/CMakeLists.txt +++ b/core/libs/widgets/CMakeLists.txt @@ -1,174 +1,173 @@ # # Copyright (c) 2010-2018 by Gilles Caulier, # Copyright (c) 2015 by Veaceslav Munteanu, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. if (POLICY CMP0063) cmake_policy(SET CMP0063 NEW) endif (POLICY CMP0063) set(libcommonwidgets_SRCS common/abstractitemdragdrophandler.cpp common/dactivelabel.cpp common/dragdropimplementations.cpp common/modelcompleter.cpp common/searchtextbar.cpp ) set(liblayouttools_SRCS layout/dexpanderbox.cpp layout/statesavingobject.cpp layout/dlayoutbox.cpp ) set(librangetools_SRCS range/dsliderspinbox.cpp range/dnuminput.cpp range/drangebox.cpp ) set(libcombotools_SRCS combo/comboboxutilities.cpp combo/dcombobox.cpp combo/squeezedcombobox.cpp ) set(libcolorstools_SRCS colors/dcolorvalueselector.cpp colors/dhuesaturationselect.cpp colors/dcolorchoosermode.cpp colors/dcolorselector.cpp colors/colorgradientwidget.cpp colors/dgradientslider.cpp ) set(libfontstools_SRCS fonts/dfontproperties.cpp fonts/dfontselect.cpp ) set(libfilestools_SRCS files/filesaveoptionsbox.cpp files/filesaveconflictbox.cpp files/dfiledialog.cpp files/dfileselector.cpp files/dbinarysearch.cpp files/dbinaryiface.cpp - files/drawdecoderwidget.cpp ) set(libmainview_SRCS mainview/dxmlguiwindow.cpp mainview/daboutdata.cpp mainview/dzoombar.cpp mainview/dcursortracker.cpp mainview/thumbbardock.cpp mainview/thememanager.cpp mainview/schememanager.cpp mainview/sidebar.cpp mainview/fullscreensettings.cpp ../../app/utils/digikam_globals.cpp ) set(libitemview_SRCS itemview/dcategorizedview.cpp itemview/dcategorizedsortfilterproxymodel.cpp itemview/ditemdelegate.cpp itemview/ditemtooltip.cpp itemview/dcategorydrawer.cpp itemview/imagedelegateoverlay.cpp itemview/itemviewhoverbutton.cpp itemview/itemviewimagedelegate.cpp itemview/itemviewtooltip.cpp itemview/itemviewcategorized.cpp itemview/actioncategorizedview.cpp ) set(libgraphicsviewwidgets_SRCS graphicsview/clickdragreleaseitem.cpp graphicsview/dimgchilditem.cpp graphicsview/dimgpreviewitem.cpp graphicsview/regionframeitem.cpp graphicsview/graphicsdimgitem.cpp graphicsview/graphicsdimgview.cpp graphicsview/imagezoomsettings.cpp graphicsview/previewlayout.cpp graphicsview/paniconwidget.cpp graphicsview/itemvisibilitycontroller.cpp ) set(libmetadatawidgets_SRCS metadata/mdkeylistviewitem.cpp metadata/metadatalistview.cpp metadata/metadatalistviewitem.cpp metadata/metadatawidget.cpp metadata/metadataselector.cpp metadata/metadatapanel.cpp metadata/iptcwidget.cpp metadata/exifwidget.cpp metadata/makernotewidget.cpp metadata/xmpwidget.cpp metadata/ratingwidget.cpp metadata/colorlabelwidget.cpp metadata/picklabelwidget.cpp metadata/altlangstredit.cpp metadata/colorlabelwidget.cpp metadata/countryselector.cpp metadata/subjectwidget.cpp ) set(libiccprofileswidgets_SRCS iccprofiles/iccpreviewwidget.cpp iccprofiles/iccprofilewidget.cpp iccprofiles/cietonguewidget.cpp iccprofiles/iccprofilescombobox.cpp ) include_directories( $ $ $ $ $ $ $ $ ) if(KF5NotifyConfig_FOUND) include_directories($) endif() if(Gphoto2_FOUND) include_directories(${GPHOTO2_INCLUDE_DIRS}) endif() add_library(digikamwidgetscore_src OBJECT ${libmainview_SRCS} ${libcommonwidgets_SRCS} ${libgraphicsviewwidgets_SRCS} ${libiccprofileswidgets_SRCS} ${libitemview_SRCS} ${libmetadatawidgets_SRCS} ${libcolorstools_SRCS} ${libfontstools_SRCS} ${libfilestools_SRCS} ${libcombotools_SRCS} ${librangetools_SRCS} ${liblayouttools_SRCS} ) #############################################################" set(libimagehistory_SRCS imagehistory/filtershistorywidget.cpp imagehistory/imagefiltershistoryitemdelegate.cpp imagehistory/imagefiltershistorymodel.cpp imagehistory/imagefiltershistorytreeitem.cpp imagehistory/versionswidget.cpp ) add_library(imagehistorywidgets_src OBJECT ${libimagehistory_SRCS}) diff --git a/core/libs/widgets/combo/dcombobox.cpp b/core/libs/widgets/combo/dcombobox.cpp index a661bac44c..3c443d8252 100644 --- a/core/libs/widgets/combo/dcombobox.cpp +++ b/core/libs/widgets/combo/dcombobox.cpp @@ -1,152 +1,152 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2008-08-16 * Description : a combo box widget re-implemented with a * reset button to switch to a default item * * Copyright (C) 2008-2018 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "dcombobox.h" // Qt includes #include #include #include #include #include // KDE includes #include namespace Digikam { class Q_DECL_HIDDEN DComboBox::Private { public: explicit Private() { defaultIndex = 0; resetButton = 0; combo = 0; } int defaultIndex; QToolButton* resetButton; QComboBox* combo; }; DComboBox::DComboBox(QWidget* const parent) : QWidget(parent), d(new Private) { QHBoxLayout* const hlay = new QHBoxLayout(this); d->combo = new QComboBox(this); d->resetButton = new QToolButton(this); d->resetButton->setAutoRaise(true); d->resetButton->setFocusPolicy(Qt::NoFocus); d->resetButton->setIcon(QIcon::fromTheme(QLatin1String("document-revert"))); d->resetButton->setToolTip(i18nc("@info:tooltip", "Reset to default value")); hlay->addWidget(d->combo); hlay->addWidget(d->resetButton); hlay->setStretchFactor(d->combo, 10); hlay->setContentsMargins(QMargins()); hlay->setSpacing(QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing)); // ------------------------------------------------------------- connect(d->resetButton, &QToolButton::clicked, this, &DComboBox::slotReset); connect(d->combo, static_cast(&QComboBox::activated), this, &DComboBox::slotItemActivated); connect(d->combo, static_cast(&QComboBox::currentIndexChanged), this, &DComboBox::slotCurrentIndexChanged); } DComboBox::~DComboBox() { delete d; } QComboBox* DComboBox::combo() const { return d->combo; } void DComboBox::addItem(const QString& t, int index) { d->combo->addItem(t, index); } -void DComboBox::insertItem(int index, const QString& t) +void DComboBox::insertItem(int index, const QString& t, const QVariant& data) { - d->combo->insertItem(index, t); + d->combo->insertItem(index, t, data); } int DComboBox::currentIndex() const { return d->combo->currentIndex(); } void DComboBox::setCurrentIndex(int v) { d->combo->setCurrentIndex(v); } int DComboBox::defaultIndex() const { return d->defaultIndex; } void DComboBox::setDefaultIndex(int v) { d->defaultIndex = v; d->combo->setCurrentIndex(d->defaultIndex); slotItemActivated(v); } void DComboBox::slotReset() { d->combo->setCurrentIndex(d->defaultIndex); d->resetButton->setEnabled(false); slotItemActivated(d->defaultIndex); emit reset(); } void DComboBox::slotItemActivated(int v) { d->resetButton->setEnabled(v != d->defaultIndex); emit activated(v); } void DComboBox::slotCurrentIndexChanged(int v) { d->resetButton->setEnabled(v != d->defaultIndex); emit currentIndexChanged(v); } } // namespace Digikam diff --git a/core/libs/widgets/combo/dcombobox.h b/core/libs/widgets/combo/dcombobox.h index ce33be6632..1ad30935e7 100644 --- a/core/libs/widgets/combo/dcombobox.h +++ b/core/libs/widgets/combo/dcombobox.h @@ -1,84 +1,85 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2008-08-16 * Description : a combo box widget re-implemented with a * reset button to switch to a default item * * Copyright (C) 2008-2018 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_DCOMBO_BOX_H #define DIGIKAM_DCOMBO_BOX_H // Qt includes #include #include +#include // Local includes #include "digikam_export.h" namespace Digikam { class DIGIKAM_EXPORT DComboBox : public QWidget { Q_OBJECT public: explicit DComboBox(QWidget* const parent=0); ~DComboBox(); void setCurrentIndex(int d); int currentIndex() const; void setDefaultIndex(int d); int defaultIndex() const; QComboBox* combo() const; void addItem(const QString& t, int index = -1); - void insertItem(int index, const QString& t); + void insertItem(int index, const QString& t, const QVariant& data = QVariant()); Q_SIGNALS: void reset(); void activated(int); void currentIndexChanged(int); public Q_SLOTS: void slotReset(); private Q_SLOTS: void slotItemActivated(int); void slotCurrentIndexChanged(int); private: class Private; Private* const d; }; } // namespace Digikam #endif // DIGIKAM_DCOMBO_BOX_H diff --git a/core/tests/dimg/dimgfilteractiontest.cpp b/core/tests/dimg/dimgfilteractiontest.cpp index 50f69685aa..b77ecce992 100644 --- a/core/tests/dimg/dimgfilteractiontest.cpp +++ b/core/tests/dimg/dimgfilteractiontest.cpp @@ -1,166 +1,166 @@ /* ============================================================ * * This file is a part of digiKam project * http://www.digikam.org * * Date : 2010-11-13 * Description : a test for applying FilterActions * * Copyright (C) 2010 by Marcel Wiesweg * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "dimgfilteractiontest.h" // Qt includes #include #include #include #include #include #include // Local includes #include "metaengine.h" #include "dimagehistory.h" #include "drawdecoding.h" #include "filteractionfilter.h" QTEST_MAIN(DImgFilterActionTest) void DImgFilterActionTest::testDRawDecoding() { DRawDecoding params; params.rawPrm.sixteenBitsImage = true; params.rawPrm.autoBrightness = true; params.rawPrm.whiteBalance = DRawDecoderSettings::AERA; params.rawPrm.RGBInterpolate4Colors = true; - params.rawPrm.RAWQuality = DRawDecoderSettings::AMAZE; + params.rawPrm.RAWQuality = DRawDecoderSettings::DHT; params.rawPrm.NRType = DRawDecoderSettings::WAVELETSNR; params.rawPrm.outputColorSpace = DRawDecoderSettings::ADOBERGB; FilterAction action; params.writeToFilterAction(action); qDebug() << action.parameters(); DRawDecoding params2 = DRawDecoding::fromFilterAction(action); QVERIFY(params == params2); } /** * The data for this test had to be regenerated because the test was failing * The regeneration was performed like this: * 1. Create a folder in digikam and add the DSC00636.JPG * 2. Go to image editor and choose auto-levels * 3. Apply first option and then Save As New Version -> Save in new Format: PNG * 4. Repeat the operation until you get multiple versions of this file */ void DImgFilterActionTest::testActions() { QStringList files = imageDir().entryList(QDir::Files); files.removeOne(originalImage()); DImg original(imageDir().filePath(originalImage())); QVERIFY(!original.isNull()); foreach(const QString& fileName, files) { DImg ref(imageDir().filePath(fileName)); QVERIFY(!ref.isNull()); DImageHistory history = ref.getImageHistory(); FilterActionFilter filter; filter.setFilterActions(history.allActions()); QVERIFY(filter.isReproducible() || filter.isComplexAction()); filter.setupFilter(original.copy()); filter.startFilterDirectly(); qDebug() << filter.filterActions().size(); DImg img = filter.getTargetImage(); QVERIFY(ref.size() == img.size()); bool isEqual = true; DImg diff(ref.width(), ref.height(), ref.sixteenBit()); diff.fill(DColor(Qt::black)); for (uint x=0; x # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. if (POLICY CMP0063) cmake_policy(SET CMP0063 NEW) endif (POLICY CMP0063) include_directories( $ $ ) set(raw2png_SRCS raw2png.cpp) add_executable(raw2png ${raw2png_SRCS}) target_link_libraries(raw2png digikamcore Qt5::Gui Qt5::Core ) set(libinfo_SRCS libinfo.cpp) add_executable(libinfo ${libinfo_SRCS}) target_link_libraries(libinfo digikamcore Qt5::Gui Qt5::Core ) # -- LibRaw CLI Samples Compilation -------------------------------------------------------------------------------- # A small macro so that this is a bit cleaner macro(LIBRAW_BUILD_SAMPLES) set(_filename ${ARGV0}) string(REPLACE "." ";" _temp ${_filename}) list(GET _temp 0 _target) set(${_target}_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/../../libs/rawengine/libraw/samples/${_filename}) set_source_files_properties(${${_target}_SRCS} PROPERTIES COMPILE_FLAGS -w) add_executable(${_target} ${${_target}_SRCS}) target_link_libraries(${_target} ${OPENMP_LDFLAGS} ${CMAKE_THREAD_LIBS_INIT} digikamcore libraw libdng ) if(WIN32) target_link_libraries(${_target} ws2_32) endif() endmacro() LIBRAW_BUILD_SAMPLES(simple_dcraw.cpp) LIBRAW_BUILD_SAMPLES(mem_image.cpp) LIBRAW_BUILD_SAMPLES(dcraw_emu.cpp) LIBRAW_BUILD_SAMPLES(4channels.cpp) LIBRAW_BUILD_SAMPLES(unprocessed_raw.cpp) LIBRAW_BUILD_SAMPLES(raw-identify.cpp) LIBRAW_BUILD_SAMPLES(multirender_test.cpp) +LIBRAW_BUILD_SAMPLES(openbayer_sample.cpp) LIBRAW_BUILD_SAMPLES(postprocessing_benchmark.cpp) # C sample files which must be compiled only if LCMS v2 is detected, to prevent broken compilation if(LCMS2_FOUND) if(MSVC) LIBRAW_BUILD_SAMPLES(half_mt_win32.c) else() LIBRAW_BUILD_SAMPLES(dcraw_half.c) LIBRAW_BUILD_SAMPLES(half_mt.c) endif() endif()