Merge branch 'dev' of https://github.com/Beep6581/RawTherapee into defish
19
.github/workflows/appimage.yml
vendored
@ -30,7 +30,21 @@ jobs:
|
||||
echo "Running apt update."
|
||||
sudo apt update
|
||||
echo "Installing dependencies with apt."
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt install -y cmake libgtk-3-dev libgtkmm-3.0-dev liblensfun-dev librsvg2-dev liblcms2-dev libfftw3-dev libiptcdata0-dev libtiff5-dev libcanberra-gtk3-dev liblensfun-bin
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt install -y cmake libgtk-3-dev libgtkmm-3.0-dev liblensfun-dev librsvg2-dev liblcms2-dev libfftw3-dev libiptcdata0-dev libtiff5-dev libcanberra-gtk3-dev liblensfun-bin libexpat1-dev libbrotli-dev zlib1g-dev libinih-dev
|
||||
|
||||
- name: Install Exiv2
|
||||
run: |
|
||||
EXIV2_VERSION='v0.28.0'
|
||||
echo "Cloning Exiv2 $EXIV2_VERSION."
|
||||
git clone --depth 1 --branch "$EXIV2_VERSION" https://github.com/Exiv2/exiv2.git ext/exiv2
|
||||
|
||||
echo "Configuring build."
|
||||
mkdir ext/exiv2/build
|
||||
cd ext/exiv2/build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DEXIV2_ENABLE_BMFF=ON ..
|
||||
|
||||
echo "Building and installing."
|
||||
sudo make -j$(nproc) install
|
||||
|
||||
- name: Configure build
|
||||
run: |
|
||||
@ -113,6 +127,9 @@ jobs:
|
||||
- name: Package AppImage
|
||||
working-directory: ./build
|
||||
run: |
|
||||
echo "LD_LIBRARY_PATH is '$LD_LIBRARY_PATH'. Adding /usr/local/lib."
|
||||
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib"
|
||||
|
||||
echo "Creating artifact name."
|
||||
if [ '${{github.ref_type}}' == 'tag' ]; then
|
||||
ARTIFACT_NAME="RawTherapee_${REF_NAME_FILTERED}_${{matrix.build_type}}"
|
||||
|
2
.github/workflows/codeql.yml
vendored
@ -35,7 +35,7 @@ jobs:
|
||||
echo "Running apt update."
|
||||
sudo apt update
|
||||
echo "Installing dependencies with apt."
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt install -y cmake libgtk-3-dev libgtkmm-3.0-dev liblensfun-dev librsvg2-dev liblcms2-dev libfftw3-dev libiptcdata0-dev libtiff5-dev libcanberra-gtk3-dev liblensfun-bin
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt install -y cmake libgtk-3-dev libgtkmm-3.0-dev liblensfun-dev librsvg2-dev liblcms2-dev libfftw3-dev libiptcdata0-dev libtiff5-dev libcanberra-gtk3-dev liblensfun-bin libexiv2-dev
|
||||
|
||||
- name: Configure build
|
||||
run: |
|
||||
|
2
.github/workflows/macos.yml
vendored
@ -21,7 +21,7 @@ jobs:
|
||||
mkdir build
|
||||
date +%s > build/stamp
|
||||
brew uninstall --ignore-dependencies libtiff
|
||||
brew install libtiff gtk+3 gtkmm3 gtk-mac-integration adwaita-icon-theme libsigc++@2 little-cms2 libiptcdata fftw lensfun expat pkgconfig llvm shared-mime-info | tee -a depslog
|
||||
brew install libtiff gtk+3 gtkmm3 gtk-mac-integration adwaita-icon-theme libsigc++@2 little-cms2 libiptcdata fftw lensfun expat pkgconfig llvm shared-mime-info exiv2 | tee -a depslog
|
||||
date -u
|
||||
echo "----====Pourage====----"
|
||||
cat depslog | grep Pouring
|
||||
|
1
.github/workflows/windows.yml
vendored
@ -47,6 +47,7 @@ jobs:
|
||||
mingw-w64-x86_64-fftw
|
||||
mingw-w64-x86_64-lensfun
|
||||
mingw-w64-x86_64-libiptcdata
|
||||
mingw-w64-x86_64-exiv2
|
||||
|
||||
- name: Configure build
|
||||
run: |
|
||||
|
1
.gitignore
vendored
@ -25,7 +25,6 @@ Release
|
||||
|
||||
rtdata/rawtherapee.desktop
|
||||
rtengine/librtengine.a
|
||||
rtexif/librtexif.a
|
||||
rtgui/config.h
|
||||
rtgui/version.h
|
||||
rtgui/rawtherapee
|
||||
|
@ -497,6 +497,31 @@ pkg_check_modules(SIGC REQUIRED sigc++-2.0>=2.3.1)
|
||||
pkg_check_modules(LENSFUN REQUIRED lensfun>=0.2)
|
||||
pkg_check_modules(RSVG REQUIRED librsvg-2.0>=2.40)
|
||||
|
||||
# Require exiv2 >= 0.24 to make sure everything we need is available
|
||||
#find_package(Exiv2 0.24 REQUIRED)
|
||||
pkg_check_modules(EXIV2 REQUIRED exiv2>=0.24)
|
||||
#include_directories(SYSTEM ${Exiv2_INCLUDE_DIRS})
|
||||
#list(APPEND LIBS ${EXIV2_LIBRARIES})
|
||||
add_definitions(${EXIV2_DEFINITIONS})
|
||||
set(_exiv2_libs ${EXIV2_LIBRARIES})
|
||||
set(EXIV2_LIBRARIES "")
|
||||
foreach(l ${_exiv2_libs})
|
||||
set(_el "_el-NOTFOUND")
|
||||
if(EXIV2_LIBRARY_DIRS)
|
||||
message(STATUS "searching for library ${l} in ${EXIV2_LIBRARY_DIRS}")
|
||||
find_library(_el ${l} PATHS ${EXIV2_LIBRARY_DIRS} NO_DEFAULT_PATH)
|
||||
if(NOT _el)
|
||||
message(STATUS " NOT FOUND, searching again in default path")
|
||||
find_library(_el ${l})
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "searching for library ${l}")
|
||||
find_library(_el ${l})# PATHS ${EXIV2_LIBRARY_DIRS})
|
||||
endif()
|
||||
message(STATUS " result: ${_el}")
|
||||
set(EXIV2_LIBRARIES ${EXIV2_LIBRARIES} ${_el})
|
||||
endforeach()
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-DWIN32)
|
||||
add_definitions(-D_WIN32)
|
||||
@ -606,6 +631,7 @@ if(OPENMP_FOUND)
|
||||
set(CMAKE_REQUIRED_INCLUDES ${FFTW3F_INCLUDE_DIRS})
|
||||
set(CMAKE_REQUIRED_LIBRARIES)
|
||||
foreach(l ${FFTW3F_LIBRARIES})
|
||||
set(_f "_f-NOTFOUND")
|
||||
find_library(_f ${l} PATHS ${FFTW3F_LIBRARY_DIRS})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${_f})
|
||||
endforeach()
|
||||
@ -790,13 +816,18 @@ foreach(l ${LENSFUN_LIBRARIES})
|
||||
# the NO_DEFAULT_PATH is to make sure we find the lensfun version we
|
||||
# want, and not the system's one (e.g. if we have a custom version
|
||||
# installed in a non-standard location)
|
||||
set(_l "_l-NOTFOUND")
|
||||
message(STATUS "searching for library ${l} in ${LENSFUN_LIBRARY_DIRS}")
|
||||
find_library(_l ${l} PATHS ${LENSFUN_LIBRARY_DIRS} NO_DEFAULT_PATH)
|
||||
else()
|
||||
# LENSFUN_LIBRARY_DIRS can be empty if lensfun is installed in the
|
||||
# default path. In this case, adding NO_DEFAULT_PATH would make
|
||||
# find_library fail...
|
||||
set(_l "_l-NOTFOUND")
|
||||
message(STATUS "searching for library ${l}")
|
||||
find_library(_l ${l})
|
||||
endif()
|
||||
message(STATUS " result: ${_l}")
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${_l})
|
||||
endforeach()
|
||||
check_cxx_source_compiles(
|
||||
@ -838,7 +869,6 @@ else()
|
||||
CACHE INTERNAL "" FORCE)
|
||||
endif()
|
||||
|
||||
add_subdirectory(rtexif)
|
||||
add_subdirectory(rtengine)
|
||||
add_subdirectory(rtgui)
|
||||
add_subdirectory(rtdata)
|
||||
|
@ -4,24 +4,19 @@ del .\install_manifest.txt
|
||||
|
||||
rmdir /s /q .\CMakeFiles
|
||||
rmdir /s /q .\rtengine\CMakeFiles
|
||||
rmdir /s /q .\rtexif\CMakeFiles
|
||||
rmdir /s /q .\rtgui\CMakeFiles
|
||||
rmdir /s /q .\rtdata\CMakeFiles
|
||||
|
||||
del .\cmake_*
|
||||
del .\rtengine\cmake_*
|
||||
del .\rtexif\cmake_*
|
||||
del .\rtgui\cmake_*
|
||||
del .\rtdata\cmake_*
|
||||
|
||||
del .\Makefile
|
||||
del .\rtengine\Makefile
|
||||
del .\rtexif\Makefile
|
||||
del .\rtgui\Makefile
|
||||
del .\rtdata\Makefile
|
||||
|
||||
del .\rtengine\librtengine.so
|
||||
del .\rtengine\librtengine.a
|
||||
del .\rtgui\rawtherapee
|
||||
del .\rtexif\librtexif.so
|
||||
del .\rtexif\librtexif.a
|
||||
|
@ -17,7 +17,7 @@
|
||||
inkscape:export-filename="/tmp/template.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:version="0.92.2 2405546, 2018-03-11"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="add.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
@ -26,16 +26,16 @@
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:zoom="11.313708"
|
||||
inkscape:cx="20.683456"
|
||||
inkscape:cy="15.839861"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1019"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:pagecheckerboard="false"
|
||||
@ -70,7 +70,7 @@
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:title />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Maciej Dworak</dc:title>
|
||||
@ -120,8 +120,8 @@
|
||||
style="opacity:0.7;fill:none;fill-opacity:0.53333285;fill-rule:nonzero;stroke:#2a7fff;stroke-width:1.99999988;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||
<path
|
||||
id="path4951"
|
||||
style="opacity:0.7;fill:none;fill-rule:evenodd;stroke:#2a7fff;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 12,3 V 21 M 3,12 h 18"
|
||||
style="opacity:0.7;fill:none;fill-rule:evenodd;stroke:#2a7fff;stroke-width:3.33607316;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 12.447464,4.4346736 0,15.1306544 M 5,12 19.89493,12"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
</g>
|
||||
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
110
rtdata/images/svg/box.svg
Normal file
@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="24px"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
inkscape:export-filename="/tmp/template.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="box.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#E0E1E2"
|
||||
bordercolor="#666768"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="44.944444"
|
||||
inkscape:cx="12"
|
||||
inkscape:cy="12"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:pagecheckerboard="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-others="false"
|
||||
inkscape:object-nodes="false"
|
||||
inkscape:snap-grids="true"
|
||||
inkscape:snap-bbox-midpoints="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid1374"
|
||||
originx="1"
|
||||
originy="1"
|
||||
empspacing="11"
|
||||
dotted="false" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs815" />
|
||||
<metadata
|
||||
id="metadata818">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Maciej Dworak</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<dc:description>RawTherapee icon.</dc:description>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1">
|
||||
<rect
|
||||
style="opacity:0.7;fill:#ffffff;fill-opacity:0;fill-rule:nonzero;stroke:#2a7fff;stroke-width:2.34782624;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect3335"
|
||||
width="15.652174"
|
||||
height="15.652174"
|
||||
x="4.173913"
|
||||
y="4.173913" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.4 KiB |
128
rtdata/images/svg/edit-small.svg
Normal file
@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
inkscape:export-filename="/tmp/template.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="edit-small.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#E0E1E2"
|
||||
bordercolor="#666768"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1.04"
|
||||
inkscape:cx="8"
|
||||
inkscape:cy="7.5803253"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:pagecheckerboard="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-others="false"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-grids="true"
|
||||
inkscape:snap-bbox-midpoints="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid1374"
|
||||
originx="1"
|
||||
originy="1"
|
||||
empspacing="7"
|
||||
dotted="false" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs815" />
|
||||
<metadata
|
||||
id="metadata818">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Maciej Dworak</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<dc:description>RawTherapee icon.</dc:description>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1"
|
||||
transform="translate(0,-8)">
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 55,16 H 65 M 60,11 V 21"
|
||||
style="opacity:0.7;fill:none;fill-rule:evenodd;stroke:#2a7fff;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4977" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 24,16 H 34 M 29,11 V 21"
|
||||
style="opacity:0.7;fill:none;fill-rule:evenodd;stroke:#2a7fff;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4981" />
|
||||
<path
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 39,16 H 49 M 44,11 V 21"
|
||||
style="opacity:0.7;fill:none;fill-rule:evenodd;stroke:#2a7fff;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4983" />
|
||||
<path
|
||||
style="opacity:0.7;fill:#2a7fff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.00157475;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 11.413246,9.78023 c 0.784726,0 2.23775,1.576711 2.23775,2.428236 0,0.851523 -1.091559,1.184475 -1.091559,1.184475 l -2.237749,-2.428235 c 0,0 0.306833,-1.184476 1.091558,-1.184476 z M 9.762249,11.571765 12,14 6.405626,20.070587 4.1678762,17.642352 Z m -6.1538101,6.677647 2.237749,2.428235 -0.027314,0.02964 -3.9160622,1.821176 1.6783123,-4.249412 z"
|
||||
id="path1658"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="zzcczccccccccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.8 KiB |
136
rtdata/images/svg/edit.svg
Normal file
@ -0,0 +1,136 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="24px"
|
||||
height="24px"
|
||||
viewBox="0 0 24 24"
|
||||
version="1.1"
|
||||
id="SVGRoot"
|
||||
inkscape:export-filename="/tmp/template.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="edit.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#E0E1E2"
|
||||
bordercolor="#666768"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="34.25"
|
||||
inkscape:cx="12"
|
||||
inkscape:cy="12"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:pagecheckerboard="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-others="false"
|
||||
inkscape:object-nodes="false"
|
||||
inkscape:snap-grids="true"
|
||||
inkscape:snap-bbox-midpoints="false">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid1374"
|
||||
originx="1"
|
||||
originy="1"
|
||||
empspacing="11"
|
||||
dotted="false" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs815" />
|
||||
<metadata
|
||||
id="metadata818">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Maciej Dworak</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title />
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<dc:description>RawTherapee icon.</dc:description>
|
||||
<cc:license
|
||||
rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
|
||||
</cc:Work>
|
||||
<cc:License
|
||||
rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Reproduction" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#Distribution" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Notice" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#Attribution" />
|
||||
<cc:permits
|
||||
rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
|
||||
<cc:requires
|
||||
rdf:resource="http://creativecommons.org/ns#ShareAlike" />
|
||||
</cc:License>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Layer 1">
|
||||
<path
|
||||
style="opacity:0.7;fill:#2a7fff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.00157475;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 17.761905,2 C 18.897428,2 21,4.1025723 21,5.238095 c 0,1.1355228 -1.57952,1.57952 -1.57952,1.57952 L 16.182385,3.57952 c 0,0 0.443997,-1.57952 1.57952,-1.57952 z M 15.372861,4.3890438 18.610956,7.6271387 10.515719,15.722376 7.277624,12.484281 Z M 6.4681002,13.293805 9.7061953,16.5319 9.6666663,16.571429 4,19 6.4285712,13.333334 Z"
|
||||
id="path1658"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="zzcczccccccccccc" />
|
||||
<path
|
||||
style="opacity:0.7;fill:#2a7fff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.00157475;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m -34.951172,1.048828 c -1.402705,0 -4,2.5972953 -4,4 0,1.4027047 1.951172,1.9511719 1.951172,1.9511719 l 4,-4 c 0,0 -0.548467,-1.9511719 -1.951172,-1.9511719 z M -32,3.9999999 l -4,4 L -26,18 -22,14 Z M -21,15 l -4,4 0.04883,0.04883 7,3 -3,-7 z"
|
||||
id="path1658-3"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="zzcczccccccccccc" />
|
||||
<path
|
||||
style="fill:#2a7fff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M -34,6.9999999 -25,16 l -1,1 -9,-9.0000001 z"
|
||||
id="path1682"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#2a7fff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -24,19 5,2 -4,-3 z"
|
||||
id="path1686"
|
||||
inkscape:connector-curvature="0" />
|
||||
<circle
|
||||
style="opacity:0.7;fill:#2a7fff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00157475;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||
id="path1690"
|
||||
cx="-35"
|
||||
cy="19"
|
||||
r="3" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.7;fill:#2a7fff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.00157475;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
|
||||
d="M -36.898437,16.679688 A 3,3 0 0 0 -38,19 a 3,3 0 0 0 3,3 3,3 0 0 0 2.322266,-1.101562 A 3.5,3.5 0 0 1 -33.5,21 3.5,3.5 0 0 1 -37,17.5 a 3.5,3.5 0 0 1 0.101563,-0.820312 z"
|
||||
id="circle1692" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.6 KiB |
@ -17,8 +17,8 @@
|
||||
inkscape:export-filename="/tmp/template.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
inkscape:version="0.92.2 2405546, 2018-03-11"
|
||||
sodipodi:docname="tick-large.svg">
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="tick.svg">
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#E0E1E2"
|
||||
@ -33,9 +33,9 @@
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1019"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:pagecheckerboard="false"
|
||||
@ -63,7 +63,7 @@
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
<dc:title />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Maciej Dworak</dc:title>
|
||||
@ -103,7 +103,7 @@
|
||||
sodipodi:nodetypes="ccccccc"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2996-6"
|
||||
d="M 4.6666624,10.166665 8.3333305,13.833335 19.333336,2.833329 23.000006,6.4999972 8.3333305,21.166671 0.99999442,13.833335 Z"
|
||||
d="M 6.0000005,10.299997 9.0000007,13.533332 18.000004,3.833329 21.000006,7.066663 9.0000007,20 3,13.533332 Z"
|
||||
style="opacity:0.7;fill:#2a7fff;fill-opacity:1;stroke:none;stroke-width:2.30911016" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
@ -52,6 +52,7 @@ DYNPROFILEEDITOR_PROFILE;Processing Profile
|
||||
EDITWINDOW_TITLE;Image Edit
|
||||
EDIT_OBJECT_TOOLTIP;Displays a widget on the preview window which lets you adjust this tool.
|
||||
EDIT_PIPETTE_TOOLTIP;To add an adjustment point to the curve, hold the Ctrl key while left-clicking the desired spot in the image preview.\nTo adjust the point, hold the Ctrl key while left-clicking the corresponding area in the preview, then let go of Ctrl (unless you desire fine control) and while still holding the left mouse button move the mouse up or down to move that point up or down in the curve.
|
||||
ERROR_MSG_METADATA_VALUE;Metadata: error setting %1 to %2
|
||||
EXIFFILTER_APERTURE;Aperture
|
||||
EXIFFILTER_CAMERA;Camera
|
||||
EXIFFILTER_EXPOSURECOMPENSATION;Exposure compensation (EV)
|
||||
@ -63,6 +64,8 @@ EXIFFILTER_LENS;Lens
|
||||
EXIFFILTER_METADATAFILTER;Enable metadata filters
|
||||
EXIFFILTER_PATH;File path
|
||||
EXIFFILTER_SHUTTER;Shutter
|
||||
EXIFPANEL_ACTIVATE_ALL_HINT;Select all tags
|
||||
EXIFPANEL_ACTIVATE_NONE_HINT;Unselect all tags
|
||||
EXIFPANEL_ADDEDIT;Add/Edit
|
||||
EXIFPANEL_ADDEDITHINT;Add new tag or edit tag.
|
||||
EXIFPANEL_ADDTAGDLG_ENTERVALUE;Enter value
|
||||
@ -76,8 +79,8 @@ EXIFPANEL_RESET;Reset
|
||||
EXIFPANEL_RESETALL;Reset All
|
||||
EXIFPANEL_RESETALLHINT;Reset all tags to their original values.
|
||||
EXIFPANEL_RESETHINT;Reset the selected tags to their original values.
|
||||
EXIFPANEL_SHOWALL;Show all
|
||||
EXIFPANEL_SUBDIRECTORY;Subdirectory
|
||||
EXIFPANEL_BASIC_GROUP;Basic
|
||||
EXIFPANEL_VALUE_NOT_SHOWN;Not shown
|
||||
EXPORT_BYPASS;Processing steps to bypass
|
||||
EXPORT_BYPASS_ALL;Select / Unselect All
|
||||
EXPORT_BYPASS_DEFRINGE;Bypass Defringe
|
||||
@ -1948,7 +1951,10 @@ PREFERENCES_INTENT_SATURATION;Saturation
|
||||
PREFERENCES_INTERNALTHUMBIFUNTOUCHED;Show embedded JPEG thumbnail if raw is unedited
|
||||
PREFERENCES_LANG;Language
|
||||
PREFERENCES_LANGAUTODETECT;Use system language
|
||||
PREFERENCES_LENSFUNDBDIR;Lensfun database directory
|
||||
PREFERENCES_LENSFUNDBDIR_TOOLTIP;Directory containing the Lensfun database. Leave empty to use the default directories.
|
||||
PREFERENCES_LENSPROFILESDIR;Lens profiles directory
|
||||
PREFERENCES_LENSPROFILESDIR_TOOLTIP;Directory containing Adobe Lens Correction Profiles (LCPs)
|
||||
PREFERENCES_MAXRECENTFOLDERS;Maximum number of recent folders
|
||||
PREFERENCES_MENUGROUPEXTPROGS;Group 'Open with'
|
||||
PREFERENCES_MENUGROUPFILEOPERATIONS;Group 'File operations'
|
||||
@ -1956,6 +1962,11 @@ PREFERENCES_MENUGROUPLABEL;Group 'Color label'
|
||||
PREFERENCES_MENUGROUPPROFILEOPERATIONS;Group 'Processing profile operations'
|
||||
PREFERENCES_MENUGROUPRANK;Group 'Rank'
|
||||
PREFERENCES_MENUOPTIONS;Context Menu Options
|
||||
PREFERENCES_METADATA;Metadata
|
||||
PREFERENCES_METADATA_SYNC;Metadata synchronization with XMP sidecars
|
||||
PREFERENCES_METADATA_SYNC_NONE;Off
|
||||
PREFERENCES_METADATA_SYNC_READ;Read only
|
||||
PREFERENCES_METADATA_SYNC_READWRITE;Bidirectional
|
||||
PREFERENCES_MONINTENT;Default rendering intent
|
||||
PREFERENCES_MONITOR;Monitor
|
||||
PREFERENCES_MONPROFILE;Default color profile
|
||||
@ -2038,6 +2049,9 @@ PREFERENCES_TP_LABEL;Tool panel:
|
||||
PREFERENCES_TP_VSCROLLBAR;Hide vertical scrollbar
|
||||
PREFERENCES_USEBUNDLEDPROFILES;Use bundled profiles
|
||||
PREFERENCES_WORKFLOW;Layout
|
||||
PREFERENCES_XMP_SIDECAR_MODE;XMP sidecar style
|
||||
PREFERENCES_XMP_SIDECAR_MODE_STD;Standard (FILENAME.xmp for FILENAME.ext)
|
||||
PREFERENCES_XMP_SIDECAR_MODE_EXT;darktable-like (FILENAME.ext.xmp for FILENAME.ext)
|
||||
PREFERENCES_ZOOMONSCROLL;Zoom images by scrolling
|
||||
PROFILEPANEL_COPYPPASTE;Parameters to copy
|
||||
PROFILEPANEL_GLOBALPROFILES;Bundled profiles
|
||||
|
@ -227,6 +227,8 @@ menu separator {
|
||||
}
|
||||
|
||||
#PlacesPaned .view.separator {
|
||||
min-height: 0.16666666666666666em;
|
||||
color: #363636;
|
||||
}
|
||||
|
||||
#MetaPanelNotebook separator {
|
||||
|
@ -44,7 +44,7 @@ textview.view, treeview.view {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.view, .textview, textview, textview.view {
|
||||
.view, .textview, textview, textview.view, treeview > entry {
|
||||
background-color: #262626;
|
||||
}
|
||||
/* The headers of these panels */
|
||||
@ -207,6 +207,8 @@ menu separator {
|
||||
}
|
||||
|
||||
#PlacesPaned .view.separator {
|
||||
min-height: 0.16666666666666666em;
|
||||
color: #363636;
|
||||
}
|
||||
|
||||
#MetaPanelNotebook separator {
|
||||
|
@ -42,8 +42,11 @@ if(NOT WITH_SYSTEM_KLT)
|
||||
else()
|
||||
include_directories("${KLT_INCLUDE_DIRS}")
|
||||
endif()
|
||||
if(EXIV2_INCLUDE_DIRS)
|
||||
include_directories("${EXIV2_INCLUDE_DIRS}")
|
||||
endif()
|
||||
|
||||
link_directories("${PROJECT_SOURCE_DIR}/rtexif"
|
||||
link_directories(
|
||||
"${EXPAT_LIBRARY_DIRS}"
|
||||
"${EXTRA_LIBDIR}"
|
||||
"${FFTW3F_LIBRARY_DIRS}"
|
||||
@ -143,6 +146,7 @@ set(RTENGINESOURCEFILES
|
||||
lcp.cc
|
||||
lmmse_demosaic.cc
|
||||
loadinitial.cc
|
||||
metadata.cc
|
||||
munselllch.cc
|
||||
myfile.cc
|
||||
panasonic_decoders.cc
|
||||
@ -223,7 +227,7 @@ endif()
|
||||
|
||||
set_target_properties(rtengine PROPERTIES COMPILE_FLAGS "${RTENGINE_CXX_FLAGS}")
|
||||
|
||||
target_link_libraries(rtengine rtexif
|
||||
target_link_libraries(rtengine
|
||||
${EXPAT_LIBRARIES}
|
||||
${EXTRA_LIB}
|
||||
${FFTW3F_LIBRARIES}
|
||||
@ -240,7 +244,8 @@ target_link_libraries(rtengine rtexif
|
||||
${LENSFUN_LIBRARIES}
|
||||
${RSVG_LIBRARIES}
|
||||
${KLT_LIBRARIES}
|
||||
)
|
||||
${EXIV2_LIBRARIES}
|
||||
)
|
||||
|
||||
if(OpenMP_FOUND)
|
||||
target_link_libraries(rtengine ${OpenMP_CXX_LIBRARIES})
|
||||
|
@ -103,6 +103,9 @@ using namespace std;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// RT: BEGIN COMMENT
|
||||
#ifdef near
|
||||
# undef near
|
||||
#endif
|
||||
#if 0
|
||||
DT_MODULE_INTROSPECTION(4, dt_iop_ashift_params_t)
|
||||
|
||||
|
@ -57,7 +57,7 @@ bool loadFile(
|
||||
rtengine::procparams::ColorManagementParams icm;
|
||||
icm.workingProfile = working_color_space;
|
||||
|
||||
img_src.getImage(curr_wb, TR_NONE, img_float.get(), pp, rtengine::procparams::ToneCurveParams(), rtengine::procparams::RAWParams(), 0);
|
||||
img_src.getImage(curr_wb, TR_NONE, img_float.get(), pp, rtengine::procparams::ToneCurveParams(), rtengine::procparams::RAWParams());
|
||||
|
||||
if (!working_color_space.empty()) {
|
||||
img_src.convertColorSpace(img_float.get(), icm, curr_wb);
|
||||
|
537
rtengine/dcp.cc
@ -24,6 +24,7 @@
|
||||
#include <glib/gstdio.h>
|
||||
#include <glibmm/fileutils.h>
|
||||
#include <glibmm/miscutils.h>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "dcp.h"
|
||||
|
||||
@ -35,11 +36,9 @@
|
||||
#include "rawimagesource.h"
|
||||
#include "rt_math.h"
|
||||
#include "utils.h"
|
||||
#include "../rtexif/rtexif.h"
|
||||
#include "../rtgui/options.h"
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtexif;
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -440,7 +439,381 @@ std::string casefold_collate_key(const Glib::ustring &str)
|
||||
return str.casefold().raw();
|
||||
}
|
||||
|
||||
}
|
||||
class DCPMetadata
|
||||
{
|
||||
private:
|
||||
enum TagType {
|
||||
INVALID = 0,
|
||||
BYTE = 1,
|
||||
ASCII = 2,
|
||||
SHORT = 3,
|
||||
LONG = 4,
|
||||
RATIONAL = 5,
|
||||
SBYTE = 6,
|
||||
UNDEFINED = 7,
|
||||
SSHORT = 8,
|
||||
SLONG = 9,
|
||||
SRATIONAL = 10,
|
||||
FLOAT = 11,
|
||||
DOUBLE = 12
|
||||
};
|
||||
|
||||
enum ByteOrder {
|
||||
UNKNOWN = 0,
|
||||
INTEL = 0x4949,
|
||||
MOTOROLA = 0x4D4D
|
||||
};
|
||||
|
||||
public:
|
||||
explicit DCPMetadata(FILE *file) :
|
||||
file_(file),
|
||||
order_(UNKNOWN)
|
||||
{
|
||||
}
|
||||
|
||||
bool parse()
|
||||
{
|
||||
if (!file_) {
|
||||
#ifndef NDEBUG
|
||||
std::cerr << "ERROR: No file opened." << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
setlocale(LC_NUMERIC, "C"); // to set decimal point in sscanf
|
||||
|
||||
// read tiff header
|
||||
std::fseek(file_, 0, SEEK_SET);
|
||||
std::uint16_t bo;
|
||||
std::fread(&bo, 1, 2, file_);
|
||||
order_ = ByteOrder(bo);
|
||||
|
||||
get2(); // Skip
|
||||
|
||||
// Seek to IFD
|
||||
const std::size_t offset = get4();
|
||||
std::fseek(file_, offset, SEEK_SET);
|
||||
|
||||
// First read the IFD directory
|
||||
const std::uint16_t numtags = get2();
|
||||
|
||||
if (numtags > 1000) { // KodakIfd has lots of tags, thus 1000 as the limit
|
||||
return false;
|
||||
}
|
||||
|
||||
for (std::uint16_t i = 0; i < numtags; ++i) {
|
||||
Tag tag;
|
||||
if (parseTag(tag)) {
|
||||
tags_[tag.id] = std::move(tag);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool find(int id) const
|
||||
{
|
||||
return tags_.find(id) != tags_.end();
|
||||
}
|
||||
|
||||
std::string toString(int id) const
|
||||
{
|
||||
const Tags::const_iterator tag = tags_.find(id);
|
||||
if (tag != tags_.end()) {
|
||||
if (tag->second.type == ASCII) {
|
||||
return std::string(tag->second.value.begin(), tag->second.value.end()).c_str();
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::int32_t toInt(int id, std::size_t offset = 0, TagType as_type = INVALID) const
|
||||
{
|
||||
const Tags::const_iterator tag = tags_.find(id);
|
||||
if (tag == tags_.end()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (as_type == INVALID) {
|
||||
as_type = tag->second.type;
|
||||
}
|
||||
|
||||
switch (as_type) {
|
||||
case SBYTE: {
|
||||
if (offset < tag->second.value.size()) {
|
||||
return static_cast<signed char>(tag->second.value[offset]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case BYTE: {
|
||||
if (offset < tag->second.value.size()) {
|
||||
return tag->second.value[offset];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case SSHORT: {
|
||||
if (offset + 1 < tag->second.value.size()) {
|
||||
return static_cast<std::int16_t>(sget2(tag->second.value.data() + offset));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case SHORT: {
|
||||
if (offset + 1 < tag->second.value.size()) {
|
||||
return sget2(tag->second.value.data() + offset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case SLONG:
|
||||
case LONG: {
|
||||
if (offset + 3 < tag->second.value.size()) {
|
||||
return sget4(tag->second.value.data() + offset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case SRATIONAL:
|
||||
case RATIONAL: {
|
||||
if (offset + 7 < tag->second.value.size()) {
|
||||
const std::uint32_t denominator = sget4(tag->second.value.data() + offset + 4);
|
||||
return
|
||||
denominator == 0
|
||||
? 0
|
||||
: static_cast<std::int32_t>(sget4(tag->second.value.data() + offset)) / denominator;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case FLOAT: {
|
||||
return toDouble(id, offset);
|
||||
}
|
||||
|
||||
default: {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int toShort(int id, std::size_t offset = 0) const
|
||||
{
|
||||
return toInt(id, offset, SHORT);
|
||||
}
|
||||
|
||||
double toDouble(int id, std::size_t offset = 0) const
|
||||
{
|
||||
const Tags::const_iterator tag = tags_.find(id);
|
||||
if (tag == tags_.end()) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
switch (tag->second.type) {
|
||||
case SBYTE: {
|
||||
if (offset < tag->second.value.size()) {
|
||||
return static_cast<signed char>(tag->second.value[offset]);
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
case BYTE: {
|
||||
if (offset < tag->second.value.size()) {
|
||||
return tag->second.value[offset];
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
case SSHORT: {
|
||||
if (offset + 1 < tag->second.value.size()) {
|
||||
return static_cast<std::int16_t>(sget2(tag->second.value.data() + offset));
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
case SHORT: {
|
||||
if (offset + 1 < tag->second.value.size()) {
|
||||
return sget2(tag->second.value.data() + offset);
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
case SLONG:
|
||||
case LONG: {
|
||||
if (offset + 3 < tag->second.value.size()) {
|
||||
return sget4(tag->second.value.data() + offset);
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
case SRATIONAL:
|
||||
case RATIONAL: {
|
||||
if (offset + 7 < tag->second.value.size()) {
|
||||
const std::int32_t numerator = sget4(tag->second.value.data() + offset);
|
||||
const std::int32_t denominator = sget4(tag->second.value.data() + offset + 4);
|
||||
return
|
||||
denominator == 0
|
||||
? 0.0
|
||||
: static_cast<double>(numerator) / static_cast<double>(denominator);
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
case FLOAT: {
|
||||
if (offset + 3 < tag->second.value.size()) {
|
||||
union IntFloat {
|
||||
std::uint32_t i;
|
||||
float f;
|
||||
} conv;
|
||||
|
||||
conv.i = sget4(tag->second.value.data() + offset);
|
||||
return conv.f; // IEEE FLOATs are already C format, they just need a recast
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
default: {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int getCount(int id) const
|
||||
{
|
||||
const Tags::const_iterator tag = tags_.find(id);
|
||||
if (tag != tags_.end()) {
|
||||
return tag->second.count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
struct Tag {
|
||||
int id;
|
||||
std::vector<unsigned char> value;
|
||||
TagType type;
|
||||
unsigned int count;
|
||||
};
|
||||
|
||||
using Tags = std::unordered_map<int, Tag>;
|
||||
|
||||
std::uint16_t sget2(const std::uint8_t* s) const
|
||||
{
|
||||
if (order_ == INTEL) {
|
||||
return s[0] | s[1] << 8;
|
||||
} else {
|
||||
return s[0] << 8 | s[1];
|
||||
}
|
||||
}
|
||||
|
||||
std::uint32_t sget4(const std::uint8_t* s) const
|
||||
{
|
||||
if (order_ == INTEL) {
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
std::uint16_t get2()
|
||||
{
|
||||
std::uint16_t res = std::numeric_limits<std::uint16_t>::max();
|
||||
std::fread(&res, 1, 2, file_);
|
||||
return sget2(reinterpret_cast<const std::uint8_t*>(&res));
|
||||
}
|
||||
|
||||
std::uint32_t get4()
|
||||
{
|
||||
std::uint32_t res = std::numeric_limits<std::uint32_t>::max();
|
||||
std::fread(&res, 1, 4, file_);
|
||||
return sget4(reinterpret_cast<const std::uint8_t*>(&res));
|
||||
}
|
||||
|
||||
static int getTypeSize(TagType type)
|
||||
{
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
case BYTE:
|
||||
case ASCII:
|
||||
case SBYTE:
|
||||
case UNDEFINED: {
|
||||
return 1;
|
||||
}
|
||||
|
||||
case SHORT:
|
||||
case SSHORT: {
|
||||
return 2;
|
||||
}
|
||||
|
||||
case LONG:
|
||||
case SLONG:
|
||||
case FLOAT: {
|
||||
return 4;
|
||||
}
|
||||
|
||||
case RATIONAL:
|
||||
case SRATIONAL:
|
||||
case DOUBLE: {
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool parseTag(Tag& tag)
|
||||
{
|
||||
tag.id = get2();
|
||||
tag.type = TagType(get2());
|
||||
tag.count = std::max(1U, get4());
|
||||
|
||||
// Filter out invalid tags
|
||||
// Note: The large count is to be able to pass LeafData ASCII tag which can be up to almost 10 megabytes,
|
||||
// (only a small part of it will actually be parsed though)
|
||||
if (
|
||||
tag.type == INVALID
|
||||
|| tag.type > DOUBLE
|
||||
|| tag.count > 10 * 1024 * 1024
|
||||
) {
|
||||
tag.type = INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store next Tag's position in file
|
||||
const std::size_t saved_position = std::ftell(file_) + 4;
|
||||
|
||||
// Load value field (possibly seek before)
|
||||
const std::size_t value_size = static_cast<std::size_t>(tag.count) * getTypeSize(tag.type);
|
||||
|
||||
if (value_size > 4) {
|
||||
if (std::fseek(file_, get4(), SEEK_SET) == -1) {
|
||||
tag.type = INVALID;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Read value
|
||||
tag.value.resize(value_size + 1);
|
||||
const std::size_t read = std::fread(tag.value.data(), 1, value_size, file_);
|
||||
if (read != value_size) {
|
||||
tag.type = INVALID;
|
||||
return false;
|
||||
}
|
||||
tag.value[read] = '\0';
|
||||
|
||||
// Seek back to the saved position
|
||||
std::fseek(file_, saved_position, SEEK_SET);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FILE* const file_;
|
||||
|
||||
Tags tags_;
|
||||
ByteOrder order_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
struct DCPProfileApplyState::Data {
|
||||
float pro_photo[3][3];
|
||||
@ -472,23 +845,23 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) :
|
||||
delta_info.hue_step = delta_info.val_step = look_info.hue_step = look_info.val_step = 0;
|
||||
constexpr int tiff_float_size = 4;
|
||||
|
||||
enum class TagKey : int {
|
||||
COLOR_MATRIX_1 = 50721,
|
||||
COLOR_MATRIX_2 = 50722,
|
||||
PROFILE_HUE_SAT_MAP_DIMS = 50937,
|
||||
PROFILE_HUE_SAT_MAP_DATA_1 = 50938,
|
||||
PROFILE_HUE_SAT_MAP_DATA_2 = 50939,
|
||||
PROFILE_TONE_CURVE = 50940,
|
||||
PROFILE_TONE_COPYRIGHT = 50942,
|
||||
CALIBRATION_ILLUMINANT_1 = 50778,
|
||||
CALIBRATION_ILLUMINANT_2 = 50779,
|
||||
FORWARD_MATRIX_1 = 50964,
|
||||
FORWARD_MATRIX_2 = 50965,
|
||||
PROFILE_LOOK_TABLE_DIMS = 50981, // ProfileLookup is the low quality variant
|
||||
PROFILE_LOOK_TABLE_DATA = 50982,
|
||||
PROFILE_HUE_SAT_MAP_ENCODING = 51107,
|
||||
PROFILE_LOOK_TABLE_ENCODING = 51108,
|
||||
BASELINE_EXPOSURE_OFFSET = 51109
|
||||
enum TagKey {
|
||||
TAG_KEY_COLOR_MATRIX_1 = 50721,
|
||||
TAG_KEY_COLOR_MATRIX_2 = 50722,
|
||||
TAG_KEY_PROFILE_HUE_SAT_MAP_DIMS = 50937,
|
||||
TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_1 = 50938,
|
||||
TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_2 = 50939,
|
||||
TAG_KEY_PROFILE_TONE_CURVE = 50940,
|
||||
TAG_KEY_PROFILE_TONE_COPYRIGHT = 50942,
|
||||
TAG_KEY_CALIBRATION_ILLUMINANT_1 = 50778,
|
||||
TAG_KEY_CALIBRATION_ILLUMINANT_2 = 50779,
|
||||
TAG_KEY_FORWARD_MATRIX_1 = 50964,
|
||||
TAG_KEY_FORWARD_MATRIX_2 = 50965,
|
||||
TAG_KEY_PROFILE_LOOK_TABLE_DIMS = 50981, // ProfileLookup is the low quality variant
|
||||
TAG_KEY_PROFILE_LOOK_TABLE_DATA = 50982,
|
||||
TAG_KEY_PROFILE_HUE_SAT_MAP_ENCODING = 51107,
|
||||
TAG_KEY_PROFILE_LOOK_TABLE_ENCODING = 51108,
|
||||
TAG_KEY_BASELINE_EXPOSURE_OFFSET = 51109
|
||||
};
|
||||
|
||||
static const float adobe_camera_raw_default_curve[] = {
|
||||
@ -758,54 +1131,48 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) :
|
||||
return;
|
||||
}
|
||||
|
||||
ExifManager exifManager(file, nullptr, true);
|
||||
exifManager.parseTIFF(false);
|
||||
std::unique_ptr<TagDirectory> tagDir(exifManager.roots.at(0));
|
||||
DCPMetadata md(file);
|
||||
if (!md.parse()) {
|
||||
printf ("Unable to load DCP profile '%s'.", filename.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
Tag* tag = tagDir->getTag(toUnderlying(TagKey::CALIBRATION_ILLUMINANT_1));
|
||||
light_source_1 =
|
||||
tag
|
||||
? tag->toInt(0, rtexif::SHORT)
|
||||
md.find(TAG_KEY_CALIBRATION_ILLUMINANT_1)
|
||||
? md.toShort(TAG_KEY_CALIBRATION_ILLUMINANT_1)
|
||||
: -1;
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::CALIBRATION_ILLUMINANT_2));
|
||||
light_source_2 =
|
||||
tag
|
||||
? tag->toInt(0, rtexif::SHORT)
|
||||
md.find(TAG_KEY_CALIBRATION_ILLUMINANT_2)
|
||||
? md.toShort(TAG_KEY_CALIBRATION_ILLUMINANT_2)
|
||||
: -1;
|
||||
temperature_1 = calibrationIlluminantToTemperature(light_source_1);
|
||||
temperature_2 = calibrationIlluminantToTemperature(light_source_2);
|
||||
|
||||
const bool has_second_hue_sat = tagDir->getTag(toUnderlying(TagKey::PROFILE_HUE_SAT_MAP_DATA_2)); // Some profiles have two matrices, but just one huesat
|
||||
const bool has_second_hue_sat = md.find(TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_2); // Some profiles have two matrices, but just one huesat
|
||||
|
||||
// Fetch Forward Matrices, if any
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::FORWARD_MATRIX_1));
|
||||
|
||||
if (tag) {
|
||||
has_forward_matrix_1 = true;
|
||||
has_forward_matrix_1 = md.find(TAG_KEY_FORWARD_MATRIX_1);
|
||||
|
||||
if (has_forward_matrix_1) {
|
||||
for (int row = 0; row < 3; ++row) {
|
||||
for (int col = 0; col < 3; ++col) {
|
||||
forward_matrix_1[row][col] = tag->toDouble((col + row * 3) * 8);
|
||||
forward_matrix_1[row][col] = md.toDouble(TAG_KEY_FORWARD_MATRIX_1, (col + row * 3) * 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::FORWARD_MATRIX_2));
|
||||
|
||||
if (tag) {
|
||||
has_forward_matrix_2 = true;
|
||||
has_forward_matrix_2 = md.find(TAG_KEY_FORWARD_MATRIX_2);
|
||||
|
||||
if (has_forward_matrix_2) {
|
||||
for (int row = 0; row < 3; ++row) {
|
||||
for (int col = 0; col < 3; ++col) {
|
||||
forward_matrix_2[row][col] = tag->toDouble((col + row * 3) * 8);
|
||||
forward_matrix_2[row][col] = md.toDouble(TAG_KEY_FORWARD_MATRIX_2, (col + row * 3) * 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Color Matrix (one is always there)
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::COLOR_MATRIX_1));
|
||||
|
||||
if (!tag) {
|
||||
if (!md.find(TAG_KEY_COLOR_MATRIX_1)) {
|
||||
std::cerr << "DCP '" << filename << "' is missing 'ColorMatrix1'. Skipped." << std::endl;
|
||||
fclose(file);
|
||||
return;
|
||||
@ -815,29 +1182,24 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) :
|
||||
|
||||
for (int row = 0; row < 3; ++row) {
|
||||
for (int col = 0; col < 3; ++col) {
|
||||
color_matrix_1[row][col] = tag->toDouble((col + row * 3) * 8);
|
||||
color_matrix_1[row][col] = md.toDouble(TAG_KEY_COLOR_MATRIX_1, (col + row * 3) * 8);
|
||||
}
|
||||
}
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_LOOK_TABLE_DIMS));
|
||||
if (md.find(TAG_KEY_PROFILE_LOOK_TABLE_DIMS)) {
|
||||
look_info.hue_divisions = md.toInt(TAG_KEY_PROFILE_LOOK_TABLE_DIMS, 0);
|
||||
look_info.sat_divisions = md.toInt(TAG_KEY_PROFILE_LOOK_TABLE_DIMS, 4);
|
||||
look_info.val_divisions = md.toInt(TAG_KEY_PROFILE_LOOK_TABLE_DIMS, 8);
|
||||
|
||||
if (tag) {
|
||||
look_info.hue_divisions = tag->toInt(0);
|
||||
look_info.sat_divisions = tag->toInt(4);
|
||||
look_info.val_divisions = tag->toInt(8);
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_LOOK_TABLE_ENCODING));
|
||||
look_info.srgb_gamma = tag && tag->toInt(0);
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_LOOK_TABLE_DATA));
|
||||
look_info.array_count = tag->getCount() / 3;
|
||||
look_info.srgb_gamma = md.find(TAG_KEY_PROFILE_LOOK_TABLE_ENCODING) && md.toInt(TAG_KEY_PROFILE_LOOK_TABLE_ENCODING);
|
||||
|
||||
look_info.array_count = md.getCount(TAG_KEY_PROFILE_LOOK_TABLE_DATA) / 3;
|
||||
look_table.resize(look_info.array_count);
|
||||
|
||||
for (unsigned int i = 0; i < look_info.array_count; i++) {
|
||||
look_table[i].hue_shift = tag->toDouble((i * 3) * tiff_float_size);
|
||||
look_table[i].sat_scale = tag->toDouble((i * 3 + 1) * tiff_float_size);
|
||||
look_table[i].val_scale = tag->toDouble((i * 3 + 2) * tiff_float_size);
|
||||
look_table[i].hue_shift = md.toDouble(TAG_KEY_PROFILE_LOOK_TABLE_DATA, (i * 3) * tiff_float_size);
|
||||
look_table[i].sat_scale = md.toDouble(TAG_KEY_PROFILE_LOOK_TABLE_DATA, (i * 3 + 1) * tiff_float_size);
|
||||
look_table[i].val_scale = md.toDouble(TAG_KEY_PROFILE_LOOK_TABLE_DATA, (i * 3 + 2) * tiff_float_size);
|
||||
}
|
||||
|
||||
// Precalculated constants for table application
|
||||
@ -854,25 +1216,20 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) :
|
||||
look_info.pc.val_step = look_info.hue_divisions * look_info.pc.hue_step;
|
||||
}
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_HUE_SAT_MAP_DIMS));
|
||||
if (md.find(TAG_KEY_PROFILE_HUE_SAT_MAP_DIMS)) {
|
||||
delta_info.hue_divisions = md.toInt(TAG_KEY_PROFILE_HUE_SAT_MAP_DIMS, 0);
|
||||
delta_info.sat_divisions = md.toInt(TAG_KEY_PROFILE_HUE_SAT_MAP_DIMS, 4);
|
||||
delta_info.val_divisions = md.toInt(TAG_KEY_PROFILE_HUE_SAT_MAP_DIMS, 8);
|
||||
|
||||
if (tag) {
|
||||
delta_info.hue_divisions = tag->toInt(0);
|
||||
delta_info.sat_divisions = tag->toInt(4);
|
||||
delta_info.val_divisions = tag->toInt(8);
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_HUE_SAT_MAP_ENCODING));
|
||||
delta_info.srgb_gamma = tag && tag->toInt(0);
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_HUE_SAT_MAP_DATA_1));
|
||||
delta_info.array_count = tag->getCount() / 3;
|
||||
delta_info.srgb_gamma = md.find(TAG_KEY_PROFILE_HUE_SAT_MAP_ENCODING) && md.toInt(TAG_KEY_PROFILE_HUE_SAT_MAP_ENCODING);
|
||||
|
||||
delta_info.array_count = md.getCount(TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_1) / 3;
|
||||
deltas_1.resize(delta_info.array_count);
|
||||
|
||||
for (unsigned int i = 0; i < delta_info.array_count; ++i) {
|
||||
deltas_1[i].hue_shift = tag->toDouble((i * 3) * tiff_float_size);
|
||||
deltas_1[i].sat_scale = tag->toDouble((i * 3 + 1) * tiff_float_size);
|
||||
deltas_1[i].val_scale = tag->toDouble((i * 3 + 2) * tiff_float_size);
|
||||
deltas_1[i].hue_shift = md.toDouble(TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_1, (i * 3) * tiff_float_size);
|
||||
deltas_1[i].sat_scale = md.toDouble(TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_1, (i * 3 + 1) * tiff_float_size);
|
||||
deltas_1[i].val_scale = md.toDouble(TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_1, (i * 3 + 2) * tiff_float_size);
|
||||
}
|
||||
|
||||
delta_info.pc.h_scale =
|
||||
@ -892,13 +1249,13 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) :
|
||||
// Second matrix
|
||||
has_color_matrix_2 = true;
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::COLOR_MATRIX_2));
|
||||
const bool cm2 = md.find(TAG_KEY_COLOR_MATRIX_2);
|
||||
|
||||
for (int row = 0; row < 3; ++row) {
|
||||
for (int col = 0; col < 3; ++col) {
|
||||
color_matrix_2[row][col] =
|
||||
tag
|
||||
? tag->toDouble((col + row * 3) * 8)
|
||||
cm2
|
||||
? md.toDouble(TAG_KEY_COLOR_MATRIX_2, (col + row * 3) * 8)
|
||||
: color_matrix_1[row][col];
|
||||
}
|
||||
}
|
||||
@ -908,27 +1265,21 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) :
|
||||
deltas_2.resize(delta_info.array_count);
|
||||
|
||||
// Saturation maps. Need to be unwinded.
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_HUE_SAT_MAP_DATA_2));
|
||||
|
||||
for (unsigned int i = 0; i < delta_info.array_count; ++i) {
|
||||
deltas_2[i].hue_shift = tag->toDouble((i * 3) * tiff_float_size);
|
||||
deltas_2[i].sat_scale = tag->toDouble((i * 3 + 1) * tiff_float_size);
|
||||
deltas_2[i].val_scale = tag->toDouble((i * 3 + 2) * tiff_float_size);
|
||||
deltas_2[i].hue_shift = md.toDouble(TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_2, (i * 3) * tiff_float_size);
|
||||
deltas_2[i].sat_scale = md.toDouble(TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_2, (i * 3 + 1) * tiff_float_size);
|
||||
deltas_2[i].val_scale = md.toDouble(TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_2, (i * 3 + 2) * tiff_float_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::BASELINE_EXPOSURE_OFFSET));
|
||||
|
||||
if (tag) {
|
||||
has_baseline_exposure_offset = true;
|
||||
baseline_exposure_offset = tag->toDouble();
|
||||
has_baseline_exposure_offset = md.find(TAG_KEY_BASELINE_EXPOSURE_OFFSET);
|
||||
if (has_baseline_exposure_offset) {
|
||||
baseline_exposure_offset = md.toDouble(TAG_KEY_BASELINE_EXPOSURE_OFFSET);
|
||||
}
|
||||
|
||||
// Read tone curve points, if any, but disable to RTs own profiles
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_TONE_CURVE));
|
||||
|
||||
if (tag) {
|
||||
if (md.find(TAG_KEY_PROFILE_TONE_CURVE)) {
|
||||
std::vector<double> curve_points = {
|
||||
static_cast<double>(DCT_Spline) // The first value is the curve type
|
||||
};
|
||||
@ -936,9 +1287,9 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) :
|
||||
// Push back each X/Y coordinates in a loop
|
||||
bool curve_is_linear = true;
|
||||
|
||||
for (int i = 0; i < tag->getCount(); i += 2) {
|
||||
const double x = tag->toDouble((i + 0) * tiff_float_size);
|
||||
const double y = tag->toDouble((i + 1) * tiff_float_size);
|
||||
for (unsigned int i = 0, n = md.getCount(TAG_KEY_PROFILE_TONE_CURVE); i < n; i += 2) {
|
||||
const double x = md.toDouble(TAG_KEY_PROFILE_TONE_CURVE, (i + 0) * tiff_float_size);
|
||||
const double y = md.toDouble(TAG_KEY_PROFILE_TONE_CURVE, (i + 1) * tiff_float_size);
|
||||
|
||||
if (x != y) {
|
||||
curve_is_linear = false;
|
||||
@ -954,9 +1305,7 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) :
|
||||
tone_curve.Set(DiagonalCurve(curve_points, CURVES_MIN_POLY_POINTS));
|
||||
}
|
||||
} else {
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_TONE_COPYRIGHT));
|
||||
|
||||
if (tag && tag->valueToString().find("Adobe Systems") != std::string::npos) {
|
||||
if (md.find(TAG_KEY_PROFILE_TONE_COPYRIGHT) && md.toString(TAG_KEY_PROFILE_TONE_COPYRIGHT).find("Adobe Systems") != std::string::npos) {
|
||||
// An Adobe profile without tone curve is expected to have the Adobe Default Curve, we add that
|
||||
std::vector<double> curve_points = {
|
||||
static_cast<double>(DCT_Spline)
|
||||
|
@ -231,18 +231,18 @@ void Crop::update(int todo)
|
||||
if (settings->leveldnautsimpl == 1) {
|
||||
if (params.dirpyrDenoise.Cmethod == "MAN" || params.dirpyrDenoise.Cmethod == "PON") {
|
||||
PreviewProps pp(trafx, trafy, trafw * skip, trafh * skip, skip);
|
||||
parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw, 0);
|
||||
parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw);
|
||||
}
|
||||
} else {
|
||||
if (params.dirpyrDenoise.C2method == "MANU") {
|
||||
PreviewProps pp(trafx, trafy, trafw * skip, trafh * skip, skip);
|
||||
parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw, 0);
|
||||
parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw);
|
||||
}
|
||||
}
|
||||
|
||||
if ((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "PRE") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "PREV")) {
|
||||
PreviewProps pp(trafx, trafy, trafw * skip, trafh * skip, skip);
|
||||
parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw, 0);
|
||||
parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw);
|
||||
|
||||
if ((!isDetailWindow) && parent->adnListener && skip == 1 && params.dirpyrDenoise.enabled) {
|
||||
float lowdenoise = 1.f;
|
||||
@ -454,7 +454,7 @@ void Crop::update(int todo)
|
||||
for (int wcr = 0; wcr <= 2; wcr++) {
|
||||
for (int hcr = 0; hcr <= 2; hcr++) {
|
||||
PreviewProps ppP(coordW[wcr], coordH[hcr], crW, crH, 1);
|
||||
parent->imgsrc->getImage(parent->currWB, tr, origCropPart, ppP, params.toneCurve, params.raw, 0);
|
||||
parent->imgsrc->getImage(parent->currWB, tr, origCropPart, ppP, params.toneCurve, params.raw);
|
||||
|
||||
// we only need image reduced to 1/4 here
|
||||
for (int ii = 0; ii < crH; ii += 2) {
|
||||
@ -615,7 +615,7 @@ void Crop::update(int todo)
|
||||
// if (params.dirpyrDenoise.Cmethod=="AUT" || params.dirpyrDenoise.Cmethod=="PON") {//reinit origCrop after Auto
|
||||
if ((settings->leveldnautsimpl == 1 && params.dirpyrDenoise.Cmethod == "AUT") || (settings->leveldnautsimpl == 0 && params.dirpyrDenoise.C2method == "AUTO")) { //reinit origCrop after Auto
|
||||
PreviewProps pp(trafx, trafy, trafw * skip, trafh * skip, skip);
|
||||
parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw, 0);
|
||||
parent->imgsrc->getImage(parent->currWB, tr, origCrop, pp, params.toneCurve, params.raw);
|
||||
}
|
||||
|
||||
if ((todo & M_SPOT) && params.spot.enabled && !params.spot.entries.empty()) {
|
||||
@ -751,7 +751,7 @@ void Crop::update(int todo)
|
||||
fattalCrop.reset(f);
|
||||
PreviewProps pp(0, 0, parent->fw, parent->fh, skip);
|
||||
int tr = getCoarseBitMask(params.coarse);
|
||||
parent->imgsrc->getImage(parent->currWB, tr, f, pp, params.toneCurve, params.raw, 0);
|
||||
parent->imgsrc->getImage(parent->currWB, tr, f, pp, params.toneCurve, params.raw);
|
||||
parent->imgsrc->convertColorSpace(f, params.icm, parent->currWB);
|
||||
|
||||
if (params.dirpyrDenoise.enabled || params.filmNegative.enabled || params.spot.enabled) {
|
||||
|
@ -569,7 +569,7 @@ dfInfo* rtengine::DFManager::Implementation::addFileInfo(const Glib::ustring& fi
|
||||
return &(iter->second);
|
||||
}
|
||||
|
||||
FramesData idata(filename, std::unique_ptr<RawMetaDataLocation>(new RawMetaDataLocation(ri.get_exifBase(), ri.get_ciffBase(), ri.get_ciffLen())), true);
|
||||
FramesData idata(filename);
|
||||
/* Files are added in the map, divided by same maker/model,ISO and shutter*/
|
||||
std::string key(dfInfo::key(toUppercase(idata.getMake()), toUppercase(idata.getModel()), idata.getISOSpeed(), idata.getShutterSpeed()));
|
||||
auto iter = dfList.find(key);
|
||||
|
@ -88,7 +88,7 @@ bool DynamicProfileRule::matches (const rtengine::FramesMetaData *im, const Gli
|
||||
&& camera (im->getCamera())
|
||||
&& lens (im->getLens())
|
||||
&& path (filename)
|
||||
&& imagetype(im->getImageType(0)));
|
||||
&& imagetype(im->getImageType()));
|
||||
}
|
||||
|
||||
namespace
|
||||
|
@ -342,7 +342,7 @@ ffInfo* FFManager::addFileInfo (const Glib::ustring& filename, bool pool)
|
||||
return &(iter->second);
|
||||
}
|
||||
|
||||
FramesData idata(filename, std::unique_ptr<RawMetaDataLocation>(new RawMetaDataLocation(ri.get_exifBase(), ri.get_ciffBase(), ri.get_ciffLen())), true);
|
||||
FramesData idata(filename);
|
||||
/* Files are added in the map, divided by same maker/model,lens and aperture*/
|
||||
std::string key(ffInfo::key(idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber()));
|
||||
iter = ffList.find(key);
|
||||
|
@ -84,7 +84,7 @@ void getSpotAvgMax(ImageSource *imgsrc, ColorTemp currWB, const std::unique_ptr<
|
||||
}
|
||||
|
||||
rtengine::Imagefloat spotImg(spotSize, spotSize);
|
||||
imgsrc->getImage(currWB, tr, &spotImg, pp, params->toneCurve, params->raw, 0);
|
||||
imgsrc->getImage(currWB, tr, &spotImg, pp, params->toneCurve, params->raw);
|
||||
|
||||
auto avgMax = [spotSize, &spotImg](RGB & avg, RGB & max) -> void {
|
||||
avg = {};
|
||||
|
@ -1176,27 +1176,27 @@ void RawImageSource::HLRecovery_inpaint(float** red, float** green, float** blue
|
||||
{2.0f, 3.0f, 0.001f}
|
||||
};
|
||||
|
||||
const float rad1 = vals[blur][0];
|
||||
const float rad2 = vals[blur][1];
|
||||
const float radius1 = vals[blur][0];
|
||||
const float radius2 = vals[blur][1];
|
||||
const float th = vals[blur][2];
|
||||
|
||||
guidedFilter(guide, mask, mask, rad1, th, true, 1);
|
||||
guidedFilter(guide, mask, mask, radius1, th, true, 1);
|
||||
if (plistener) {
|
||||
progress += 0.03;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
if (blur > 0) { //no use of 2nd guidedFilter if Blur = 0 (slider to 1)..speed-up and very small differences.
|
||||
guidedFilter(guide, rbuf, rbuf, rad2, 0.01f * 65535.f, true, 1);
|
||||
guidedFilter(guide, rbuf, rbuf, radius2, 0.01f * 65535.f, true, 1);
|
||||
if (plistener) {
|
||||
progress += 0.03;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
guidedFilter(guide, gbuf, gbuf, rad2, 0.01f * 65535.f, true, 1);
|
||||
guidedFilter(guide, gbuf, gbuf, radius2, 0.01f * 65535.f, true, 1);
|
||||
if (plistener) {
|
||||
progress += 0.03;
|
||||
plistener->setProgress(progress);
|
||||
}
|
||||
guidedFilter(guide, bbuf, bbuf, rad2, 0.01f * 65535.f, true, 1);
|
||||
guidedFilter(guide, bbuf, bbuf, radius2, 0.01f * 65535.f, true, 1);
|
||||
if (plistener) {
|
||||
progress += 0.03;
|
||||
plistener->setProgress(progress);
|
||||
|
@ -277,10 +277,9 @@ void RawImageSource::getAutoMatchedToneCurve(const ColorManagementParams &cp, St
|
||||
|
||||
std::unique_ptr<IImage8> source;
|
||||
{
|
||||
RawMetaDataLocation rml;
|
||||
eSensorType sensor_type;
|
||||
int w = 0, h = 0;
|
||||
std::unique_ptr<Thumbnail> thumb(Thumbnail::loadQuickFromRaw(getFileName(), rml, sensor_type, w, h, 1, false, true, true));
|
||||
const std::unique_ptr<Thumbnail> thumb(Thumbnail::loadQuickFromRaw(getFileName(), sensor_type, w, h, 1, false, true, true));
|
||||
if (!thumb) {
|
||||
if (settings->verbose) {
|
||||
std::cout << "histogram matching: no thumbnail found, generating a neutral curve" << std::endl;
|
||||
@ -309,11 +308,10 @@ void RawImageSource::getAutoMatchedToneCurve(const ColorManagementParams &cp, St
|
||||
|
||||
std::unique_ptr<IImage8> target;
|
||||
{
|
||||
RawMetaDataLocation rml;
|
||||
eSensorType sensor_type;
|
||||
double scale;
|
||||
int w = fw / skip, h = fh / skip;
|
||||
std::unique_ptr<Thumbnail> thumb(Thumbnail::loadFromRaw(getFileName(), rml, sensor_type, w, h, 1, false, observer, false, true));
|
||||
const std::unique_ptr<Thumbnail> thumb(Thumbnail::loadFromRaw(getFileName(), sensor_type, w, h, 1, false, observer, false, true));
|
||||
if (!thumb) {
|
||||
if (settings->verbose) {
|
||||
std::cout << "histogram matching: raw decoding failed, generating a neutral curve" << std::endl;
|
||||
|
@ -21,12 +21,9 @@
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
#include <libiptcdata/iptc-data.h>
|
||||
|
||||
#include "imageio.h"
|
||||
#include "metadata.h"
|
||||
|
||||
namespace Glib
|
||||
{
|
||||
@ -35,22 +32,16 @@ class ustring;
|
||||
|
||||
}
|
||||
|
||||
namespace rtexif
|
||||
{
|
||||
|
||||
class TagDirectory;
|
||||
}
|
||||
|
||||
namespace rtengine
|
||||
{
|
||||
|
||||
class FrameData final
|
||||
class FramesData final :
|
||||
public FramesMetaData
|
||||
{
|
||||
|
||||
protected:
|
||||
rtexif::TagDirectory* frameRootDir;
|
||||
IptcData* iptc;
|
||||
|
||||
private:
|
||||
bool ok_;
|
||||
Glib::ustring fname_;
|
||||
unsigned int dcrawFrameCount;
|
||||
struct tm time;
|
||||
time_t timeStamp;
|
||||
int iso_speed;
|
||||
@ -64,87 +55,44 @@ protected:
|
||||
int rating;
|
||||
std::string lens;
|
||||
IIOSampleFormat sampleFormat;
|
||||
|
||||
// each frame has the knowledge of "being an"
|
||||
// or "being part of an" HDR or PS image
|
||||
bool isPixelShift;
|
||||
bool isHDR;
|
||||
|
||||
public:
|
||||
|
||||
FrameData (rtexif::TagDirectory* frameRootDir, rtexif::TagDirectory* rootDir, rtexif::TagDirectory* firstRootDir, time_t ts = 0);
|
||||
virtual ~FrameData ();
|
||||
|
||||
bool getPixelShift () const;
|
||||
bool getHDR () const;
|
||||
std::string getImageType () const;
|
||||
IIOSampleFormat getSampleFormat () const;
|
||||
rtexif::TagDirectory* getExifData () const;
|
||||
procparams::IPTCPairs getIPTCData () const;
|
||||
static procparams::IPTCPairs getIPTCData (IptcData* iptc_);
|
||||
bool hasExif () const;
|
||||
bool hasIPTC () const;
|
||||
tm getDateTime () const;
|
||||
time_t getDateTimeAsTS () const;
|
||||
int getISOSpeed () const;
|
||||
double getFNumber () const;
|
||||
double getFocalLen () const;
|
||||
double getFocalLen35mm () const;
|
||||
float getFocusDist () const;
|
||||
double getShutterSpeed () const;
|
||||
double getExpComp () const;
|
||||
std::string getMake () const;
|
||||
std::string getModel () const;
|
||||
std::string getLens () const;
|
||||
std::string getSerialNumber () const;
|
||||
std::string getOrientation () const;
|
||||
int getRating () const;
|
||||
};
|
||||
|
||||
class FramesData final : public FramesMetaData {
|
||||
private:
|
||||
// frame's root IFD, can be a file root IFD or a SUB-IFD
|
||||
std::vector<std::unique_ptr<FrameData>> frames;
|
||||
// root IFD in the file
|
||||
std::vector<rtexif::TagDirectory*> roots;
|
||||
IptcData* iptc;
|
||||
unsigned int dcrawFrameCount;
|
||||
struct tm modTime;
|
||||
time_t modTimeStamp;
|
||||
bool isPixelShift;
|
||||
bool isHDR;
|
||||
int w_;
|
||||
int h_;
|
||||
|
||||
public:
|
||||
explicit FramesData (const Glib::ustring& fname, std::unique_ptr<RawMetaDataLocation> rml = nullptr, bool firstFrameOnly = false);
|
||||
~FramesData () override;
|
||||
explicit FramesData(const Glib::ustring& fname, time_t ts = 0);
|
||||
|
||||
void setDCRawFrameCount (unsigned int frameCount);
|
||||
unsigned int getRootCount () const override;
|
||||
unsigned int getFrameCount () const override;
|
||||
bool getPixelShift () const override;
|
||||
bool getHDR (unsigned int frame = 0) const override;
|
||||
std::string getImageType (unsigned int frame) const override;
|
||||
IIOSampleFormat getSampleFormat (unsigned int frame = 0) const override;
|
||||
rtexif::TagDirectory* getFrameExifData (unsigned int frame = 0) const override;
|
||||
rtexif::TagDirectory* getRootExifData (unsigned int root = 0) const override;
|
||||
rtexif::TagDirectory* getBestExifData (ImageSource *imgSource, procparams::RAWParams *rawParams) const override;
|
||||
procparams::IPTCPairs getIPTCData (unsigned int frame = 0) const override;
|
||||
bool hasExif (unsigned int frame = 0) const override;
|
||||
bool hasIPTC (unsigned int frame = 0) const override;
|
||||
tm getDateTime (unsigned int frame = 0) const override;
|
||||
time_t getDateTimeAsTS (unsigned int frame = 0) const override;
|
||||
int getISOSpeed (unsigned int frame = 0) const override;
|
||||
double getFNumber (unsigned int frame = 0) const override;
|
||||
double getFocalLen (unsigned int frame = 0) const override;
|
||||
double getFocalLen35mm (unsigned int frame = 0) const override;
|
||||
float getFocusDist (unsigned int frame = 0) const override;
|
||||
double getShutterSpeed (unsigned int frame = 0) const override;
|
||||
double getExpComp (unsigned int frame = 0) const override;
|
||||
std::string getMake (unsigned int frame = 0) const override;
|
||||
std::string getModel (unsigned int frame = 0) const override;
|
||||
std::string getLens (unsigned int frame = 0) const override;
|
||||
std::string getSerialNumber (unsigned int frame = 0) const;
|
||||
std::string getOrientation (unsigned int frame = 0) const override;
|
||||
int getRating (unsigned int frame = 0) const override;
|
||||
void setDCRawFrameCount(unsigned int frameCount);
|
||||
unsigned int getFrameCount() const override;
|
||||
bool getPixelShift() const override;
|
||||
bool getHDR() const override;
|
||||
std::string getImageType() const override;
|
||||
IIOSampleFormat getSampleFormat() const override;
|
||||
bool hasExif() const override;
|
||||
tm getDateTime() const override;
|
||||
time_t getDateTimeAsTS() const override;
|
||||
int getISOSpeed() const override;
|
||||
double getFNumber() const override;
|
||||
double getFocalLen() const override;
|
||||
double getFocalLen35mm() const override;
|
||||
float getFocusDist() const override;
|
||||
double getShutterSpeed() const override;
|
||||
double getExpComp() const override;
|
||||
std::string getMake() const override;
|
||||
std::string getModel() const override;
|
||||
std::string getLens() const override;
|
||||
std::string getSerialNumber() const;
|
||||
std::string getOrientation() const override;
|
||||
Glib::ustring getFileName() const override;
|
||||
int getRating() const override;
|
||||
void getDimensions(int &w, int &h) const override;
|
||||
|
||||
void fillBasicTags(Exiv2::ExifData &exif) const;
|
||||
|
||||
void setDimensions(int w, int h);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
*/
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@ -26,7 +27,6 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <libiptcdata/iptc-jpeg.h>
|
||||
#include <png.h>
|
||||
#include <tiff.h>
|
||||
#include <tiffio.h>
|
||||
@ -39,23 +39,24 @@
|
||||
|
||||
#include "color.h"
|
||||
#include "iccjpeg.h"
|
||||
#include "imagedata.h"
|
||||
#include "imageio.h"
|
||||
#include "iptcpairs.h"
|
||||
#include "jpeg.h"
|
||||
#include "procparams.h"
|
||||
#include "rt_math.h"
|
||||
#include "settings.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "../rtgui/options.h"
|
||||
#include "../rtgui/version.h"
|
||||
|
||||
#include "../rtexif/rtexif.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
namespace rtengine { extern const Settings *settings; }
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
@ -85,126 +86,37 @@ FILE* g_fopen_withBinaryAndLock(const Glib::ustring& fname)
|
||||
return f;
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Integer = std::size_t>
|
||||
auto to_long(const Iterator &iter, Integer n = Integer{0}) -> decltype(
|
||||
#if EXIV2_TEST_VERSION(0,28,0)
|
||||
iter->toInt64()
|
||||
) {
|
||||
return iter->toInt64(n);
|
||||
#else
|
||||
iter->toLong()
|
||||
) {
|
||||
return iter->toLong(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
Glib::ustring ImageIO::errorMsg[6] = {"Success", "Cannot read file.", "Invalid header.", "Error while reading header.", "File reading error", "Image format not supported."};
|
||||
|
||||
// For only copying the raw input data
|
||||
void ImageIO::setMetadata (const rtexif::TagDirectory* eroot)
|
||||
{
|
||||
if (exifRoot != nullptr) {
|
||||
delete exifRoot;
|
||||
exifRoot = nullptr;
|
||||
}
|
||||
|
||||
if (eroot) {
|
||||
rtexif::TagDirectory* td = eroot->clone (nullptr);
|
||||
|
||||
// make IPTC and XMP pass through
|
||||
td->keepTag(0x83bb); // IPTC
|
||||
td->keepTag(0x02bc); // XMP
|
||||
|
||||
exifRoot = td;
|
||||
}
|
||||
}
|
||||
|
||||
// For merging with RT specific data
|
||||
void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::procparams::ExifPairs& exif, const rtengine::procparams::IPTCPairs& iptcc)
|
||||
void ImageIO::setMetadata(Exiv2Metadata info)
|
||||
{
|
||||
|
||||
// store exif info
|
||||
exifChange->clear();
|
||||
*exifChange = exif;
|
||||
|
||||
if (exifRoot != nullptr) {
|
||||
delete exifRoot;
|
||||
exifRoot = nullptr;
|
||||
}
|
||||
|
||||
if (eroot) {
|
||||
exifRoot = eroot->clone (nullptr);
|
||||
}
|
||||
|
||||
if (iptc != nullptr) {
|
||||
iptc_data_free (iptc);
|
||||
iptc = nullptr;
|
||||
}
|
||||
|
||||
// build iptc structures for libiptcdata
|
||||
if (iptcc.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
iptc = iptc_data_new ();
|
||||
|
||||
const unsigned char utf8Esc[] = {0x1B, '%', 'G'};
|
||||
IptcDataSet * ds = iptc_dataset_new ();
|
||||
iptc_dataset_set_tag (ds, IPTC_RECORD_OBJECT_ENV, IPTC_TAG_CHARACTER_SET);
|
||||
iptc_dataset_set_data (ds, utf8Esc, 3, IPTC_DONT_VALIDATE);
|
||||
iptc_data_add_dataset (iptc, ds);
|
||||
iptc_dataset_unref (ds);
|
||||
|
||||
for (rtengine::procparams::IPTCPairs::const_iterator i = iptcc.begin(); i != iptcc.end(); ++i) {
|
||||
if (i->first == "Keywords" && !(i->second.empty())) {
|
||||
for (unsigned int j = 0; j < i->second.size(); j++) {
|
||||
IptcDataSet * ds = iptc_dataset_new ();
|
||||
iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, IPTC_TAG_KEYWORDS);
|
||||
iptc_dataset_set_data (ds, (const unsigned char*)i->second.at(j).c_str(), min(static_cast<size_t>(64), i->second.at(j).bytes()), IPTC_DONT_VALIDATE);
|
||||
iptc_data_add_dataset (iptc, ds);
|
||||
iptc_dataset_unref (ds);
|
||||
}
|
||||
|
||||
continue;
|
||||
} else if (i->first == "SupplementalCategories" && !(i->second.empty())) {
|
||||
for (unsigned int j = 0; j < i->second.size(); j++) {
|
||||
IptcDataSet * ds = iptc_dataset_new ();
|
||||
iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, IPTC_TAG_SUPPL_CATEGORY);
|
||||
iptc_dataset_set_data (ds, (const unsigned char*)i->second.at(j).c_str(), min(static_cast<size_t>(32), i->second.at(j).bytes()), IPTC_DONT_VALIDATE);
|
||||
iptc_data_add_dataset (iptc, ds);
|
||||
iptc_dataset_unref (ds);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < 16; j++)
|
||||
if (i->first == strTags[j].field && !(i->second.empty())) {
|
||||
IptcDataSet * ds = iptc_dataset_new ();
|
||||
iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, strTags[j].tag);
|
||||
iptc_dataset_set_data (ds, (const unsigned char*)i->second.at(0).c_str(), min(strTags[j].size, i->second.at(0).bytes()), IPTC_DONT_VALIDATE);
|
||||
iptc_data_add_dataset (iptc, ds);
|
||||
iptc_dataset_unref (ds);
|
||||
}
|
||||
}
|
||||
|
||||
iptc_data_sort (iptc);
|
||||
metadataInfo = std::move(info);
|
||||
}
|
||||
|
||||
void ImageIO::setOutputProfile (const char* pdata, int plen)
|
||||
void ImageIO::setOutputProfile(const std::string& pdata)
|
||||
{
|
||||
|
||||
delete [] profileData;
|
||||
|
||||
if (pdata) {
|
||||
profileData = new char [plen];
|
||||
memcpy (profileData, pdata, plen);
|
||||
} else {
|
||||
profileData = nullptr;
|
||||
}
|
||||
|
||||
profileLength = plen;
|
||||
profileData = pdata;
|
||||
}
|
||||
|
||||
ImageIO::ImageIO() :
|
||||
pl(nullptr),
|
||||
embProfile(nullptr),
|
||||
profileData(nullptr),
|
||||
profileLength(0),
|
||||
loadedProfileData(nullptr),
|
||||
loadedProfileLength(0),
|
||||
exifChange(new procparams::ExifPairs),
|
||||
iptc(nullptr),
|
||||
exifRoot(nullptr),
|
||||
sampleFormat(IIOSF_UNKNOWN),
|
||||
sampleArrangement(IIOSA_UNKNOWN)
|
||||
{
|
||||
@ -218,8 +130,6 @@ ImageIO::~ImageIO ()
|
||||
}
|
||||
|
||||
deleteLoadedProfileData();
|
||||
delete exifRoot;
|
||||
delete [] profileData;
|
||||
}
|
||||
|
||||
void png_read_data(png_struct_def *png_ptr, unsigned char *data, size_t length);
|
||||
@ -935,76 +845,6 @@ int ImageIO::loadPPMFromMemory(const char* buffer, int width, int height, bool s
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
// Taken from Darktable -- src/imageio/format/png.c
|
||||
//
|
||||
/* Write EXIF data to PNG file.
|
||||
* Code copied from DigiKam's libs/dimg/loaders/pngloader.cpp.
|
||||
* The EXIF embedding is defined by ImageMagicK.
|
||||
* It is documented in the ExifTool page:
|
||||
* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PNG.html
|
||||
*
|
||||
* ..and in turn copied from ufraw. thanks to udi and colleagues
|
||||
* for making useful code much more readable and discoverable ;)
|
||||
*/
|
||||
|
||||
void PNGwriteRawProfile(png_struct *ping, png_info *ping_info, const char *profile_type, guint8 *profile_data, png_uint_32 length)
|
||||
{
|
||||
png_textp text;
|
||||
long i;
|
||||
guint8 *sp;
|
||||
png_charp dp;
|
||||
png_uint_32 allocated_length, description_length;
|
||||
|
||||
const guint8 hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||
text = static_cast<png_textp>(png_malloc(ping, sizeof(png_text)));
|
||||
description_length = strlen(profile_type);
|
||||
allocated_length = length * 2 + (length >> 5) + 20 + description_length;
|
||||
|
||||
text[0].text = static_cast<png_charp>(png_malloc(ping, allocated_length));
|
||||
text[0].key = static_cast<png_charp>(png_malloc(ping, 80));
|
||||
text[0].key[0] = '\0';
|
||||
|
||||
g_strlcat(text[0].key, "Raw profile type ", 80);
|
||||
g_strlcat(text[0].key, profile_type, 80);
|
||||
|
||||
sp = profile_data;
|
||||
dp = text[0].text;
|
||||
*dp++ = '\n';
|
||||
|
||||
g_strlcpy(dp, profile_type, allocated_length);
|
||||
|
||||
dp += description_length;
|
||||
*dp++ = '\n';
|
||||
*dp = '\0';
|
||||
|
||||
g_snprintf(dp, allocated_length - strlen(text[0].text), "%8lu ", static_cast<unsigned long int>(length));
|
||||
|
||||
dp += 8;
|
||||
|
||||
for(i = 0; i < long(length); i++)
|
||||
{
|
||||
if(i % 36 == 0) *dp++ = '\n';
|
||||
|
||||
*(dp++) = hex[((*sp >> 4) & 0x0f)];
|
||||
*(dp++) = hex[((*sp++) & 0x0f)];
|
||||
}
|
||||
|
||||
*dp++ = '\n';
|
||||
*dp = '\0';
|
||||
text[0].text_length = (dp - text[0].text);
|
||||
text[0].compression = -1;
|
||||
|
||||
if(text[0].text_length <= allocated_length) png_set_text(ping, ping_info, text, 1);
|
||||
|
||||
png_free(ping, text[0].text);
|
||||
png_free(ping, text[0].key);
|
||||
png_free(ping, text);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int ImageIO::savePNG (const Glib::ustring &fname, int bps) const
|
||||
{
|
||||
if (getWidth() < 1 || getHeight() < 1) {
|
||||
@ -1067,39 +907,15 @@ int ImageIO::savePNG (const Glib::ustring &fname, int bps) const
|
||||
png_set_IHDR(png, info, width, height, bps, PNG_COLOR_TYPE_RGB,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_BASE);
|
||||
|
||||
if (profileData) {
|
||||
if (!profileData.empty()) {
|
||||
#if PNG_LIBPNG_VER < 10500
|
||||
png_charp profdata = reinterpret_cast<png_charp>(profileData);
|
||||
png_const_charp profdata = reinterpret_cast<png_const_charp>(profileData.data());
|
||||
#else
|
||||
png_bytep profdata = reinterpret_cast<png_bytep>(profileData);
|
||||
png_const_bytep profdata = reinterpret_cast<png_const_bytep>(profileData.data());
|
||||
#endif
|
||||
png_set_iCCP(png, info, const_cast<png_charp>("icc"), 0, profdata, profileLength);
|
||||
png_set_iCCP(png, info, "icc", 0, profdata, profileData.size());
|
||||
}
|
||||
|
||||
{
|
||||
// buffer for the exif and iptc
|
||||
unsigned int bufferSize;
|
||||
unsigned char* buffer = nullptr; // buffer will be allocated in createTIFFHeader
|
||||
unsigned char* iptcdata = nullptr;
|
||||
unsigned int iptclen = 0;
|
||||
|
||||
if (iptc && iptc_data_save (iptc, &iptcdata, &iptclen) && iptcdata) {
|
||||
iptc_data_free_buf (iptc, iptcdata);
|
||||
iptcdata = nullptr;
|
||||
}
|
||||
|
||||
int size = rtexif::ExifManager::createPNGMarker(exifRoot, *exifChange, width, height, bps, (char*)iptcdata, iptclen, buffer, bufferSize);
|
||||
|
||||
if (iptcdata) {
|
||||
iptc_data_free_buf (iptc, iptcdata);
|
||||
}
|
||||
if (buffer && size) {
|
||||
PNGwriteRawProfile(png, info, "exif", buffer, size);
|
||||
delete[] buffer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int rowlen = width * 3 * bps / 8;
|
||||
unsigned char *row = new unsigned char [rowlen];
|
||||
|
||||
@ -1133,6 +949,11 @@ int ImageIO::savePNG (const Glib::ustring &fname, int bps) const
|
||||
delete [] row;
|
||||
fclose (file);
|
||||
|
||||
if (!saveMetadata(fname)) {
|
||||
g_remove(fname.c_str());
|
||||
return IMIO_CANNOTWRITEFILE;
|
||||
}
|
||||
|
||||
if (pl) {
|
||||
pl->setProgressStr ("PROGRESSBAR_READY");
|
||||
pl->setProgress (1.0);
|
||||
@ -1232,61 +1053,9 @@ int ImageIO::saveJPEG (const Glib::ustring &fname, int quality, int subSamp) con
|
||||
|
||||
jpeg_start_compress(&cinfo, TRUE);
|
||||
|
||||
// buffer for exif marker
|
||||
unsigned char* exifBuffer = nullptr;
|
||||
unsigned int exifBufferSize = 0;
|
||||
|
||||
// assemble and write exif marker
|
||||
if (exifRoot) {
|
||||
rtexif::ExifManager::createJPEGMarker (exifRoot, *exifChange, cinfo.image_width, cinfo.image_height, exifBuffer, exifBufferSize);
|
||||
|
||||
if (exifBufferSize > 0 && exifBufferSize < 65530) {
|
||||
jpeg_write_marker(&cinfo, JPEG_APP0 + 1, exifBuffer, exifBufferSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (exifBuffer != nullptr) {
|
||||
delete [] exifBuffer;
|
||||
}
|
||||
|
||||
// buffer for iptc marker
|
||||
unsigned char* iptcBuffer = new unsigned char[65535];
|
||||
|
||||
// assemble and write iptc marker
|
||||
if (iptc) {
|
||||
unsigned char* iptcdata;
|
||||
unsigned int iptcSize;
|
||||
bool error = false;
|
||||
|
||||
if (iptc_data_save (iptc, &iptcdata, &iptcSize)) {
|
||||
if (iptcdata) {
|
||||
iptc_data_free_buf (iptc, iptcdata);
|
||||
}
|
||||
|
||||
error = true;
|
||||
}
|
||||
|
||||
int bytes = 0;
|
||||
|
||||
if (!error && (bytes = iptc_jpeg_ps3_save_iptc (nullptr, 0, iptcdata, iptcSize, iptcBuffer, 65532)) < 0) {
|
||||
error = true;
|
||||
}
|
||||
|
||||
if (iptcdata) {
|
||||
iptc_data_free_buf (iptc, iptcdata);
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
jpeg_write_marker(&cinfo, JPEG_APP0 + 13, iptcBuffer, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
delete [] iptcBuffer;
|
||||
|
||||
// write icc profile to the output
|
||||
if (profileData) {
|
||||
write_icc_profile (&cinfo, (JOCTET*)profileData, profileLength);
|
||||
if (!profileData.empty()) {
|
||||
write_icc_profile (&cinfo, reinterpret_cast<const JOCTET*>(profileData.data()), profileData.size());
|
||||
}
|
||||
|
||||
// write image data
|
||||
@ -1335,6 +1104,11 @@ int ImageIO::saveJPEG (const Glib::ustring &fname, int quality, int subSamp) con
|
||||
|
||||
fclose (file);
|
||||
|
||||
if (!saveMetadata(fname)) {
|
||||
g_remove(fname.c_str());
|
||||
return IMIO_CANNOTWRITEFILE;
|
||||
}
|
||||
|
||||
if (pl) {
|
||||
pl->setProgressStr ("PROGRESSBAR_READY");
|
||||
pl->setProgress (1.0);
|
||||
@ -1343,6 +1117,7 @@ int ImageIO::saveJPEG (const Glib::ustring &fname, int quality, int subSamp) con
|
||||
return IMIO_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int ImageIO::saveTIFF (
|
||||
const Glib::ustring &fname,
|
||||
int bps,
|
||||
@ -1368,15 +1143,6 @@ int ImageIO::saveTIFF (
|
||||
|
||||
std::string mode = "w";
|
||||
|
||||
// little hack to get libTiff to use proper byte order (see TIFFClienOpen()):
|
||||
if (exifRoot) {
|
||||
if (exifRoot->getOrder() == rtexif::INTEL) {
|
||||
mode += 'l';
|
||||
} else {
|
||||
mode += 'b';
|
||||
}
|
||||
}
|
||||
|
||||
if (big) {
|
||||
mode += '8';
|
||||
}
|
||||
@ -1388,7 +1154,7 @@ int ImageIO::saveTIFF (
|
||||
TIFF* out = TIFFFdOpen (osfileno, fname.c_str(), mode.c_str());
|
||||
#else
|
||||
TIFF* out = TIFFOpen(fname.c_str(), mode.c_str());
|
||||
int fileno = TIFFFileno (out);
|
||||
// int fileno = TIFFFileno (out);
|
||||
#endif
|
||||
|
||||
if (!out) {
|
||||
@ -1400,109 +1166,7 @@ int ImageIO::saveTIFF (
|
||||
pl->setProgress (0.0);
|
||||
}
|
||||
|
||||
bool applyExifPatch = false;
|
||||
|
||||
if (exifRoot && !big) {
|
||||
rtexif::TagDirectory* cl = (const_cast<rtexif::TagDirectory*> (exifRoot))->clone (nullptr);
|
||||
|
||||
// ------------------ remove some unknown top level tags which produce warnings when opening a tiff (might be useless) -----------------
|
||||
|
||||
rtexif::Tag *removeTag = cl->getTag (0x9003);
|
||||
|
||||
if (removeTag) {
|
||||
removeTag->setKeep (false);
|
||||
}
|
||||
|
||||
removeTag = cl->getTag (0x9211);
|
||||
|
||||
if (removeTag) {
|
||||
removeTag->setKeep (false);
|
||||
}
|
||||
|
||||
// ------------------ Apply list of change -----------------
|
||||
|
||||
for (auto currExifChange : *exifChange) {
|
||||
cl->applyChange (currExifChange.first, currExifChange.second);
|
||||
}
|
||||
|
||||
rtexif::Tag *tag = cl->getTag (TIFFTAG_EXIFIFD);
|
||||
|
||||
if (tag && tag->isDirectory()) {
|
||||
rtexif::TagDirectory *exif = tag->getDirectory();
|
||||
|
||||
if (exif) {
|
||||
int exif_size = exif->calculateSize();
|
||||
// TIFFOpen writes out the header and sets file pointer at position 8
|
||||
const uint64_t file_offset = 8; // must be 64-bit, because TIFFTAG_EXIFIFD is
|
||||
unsigned char *buffer = new unsigned char[exif_size + file_offset];
|
||||
|
||||
exif->write (file_offset, buffer);
|
||||
|
||||
write (fileno, buffer + file_offset, exif_size);
|
||||
|
||||
delete [] buffer;
|
||||
// let libtiff know that scanlines or any other following stuff should go
|
||||
// at a different offset:
|
||||
TIFFSetWriteOffset (out, exif_size + file_offset);
|
||||
TIFFSetField (out, TIFFTAG_EXIFIFD, file_offset);
|
||||
applyExifPatch = true;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO Even though we are saving EXIF IFD - MakerNote still comes out screwed.
|
||||
|
||||
if ((tag = cl->getTag (TIFFTAG_MODEL)) != nullptr) {
|
||||
TIFFSetField (out, TIFFTAG_MODEL, tag->getValue());
|
||||
}
|
||||
|
||||
if ((tag = cl->getTag (TIFFTAG_MAKE)) != nullptr) {
|
||||
TIFFSetField (out, TIFFTAG_MAKE, tag->getValue());
|
||||
}
|
||||
|
||||
if ((tag = cl->getTag (TIFFTAG_DATETIME)) != nullptr) {
|
||||
TIFFSetField (out, TIFFTAG_DATETIME, tag->getValue());
|
||||
}
|
||||
|
||||
if ((tag = cl->getTag (TIFFTAG_ARTIST)) != nullptr) {
|
||||
TIFFSetField (out, TIFFTAG_ARTIST, tag->getValue());
|
||||
}
|
||||
|
||||
if ((tag = cl->getTag (TIFFTAG_COPYRIGHT)) != nullptr) {
|
||||
TIFFSetField (out, TIFFTAG_COPYRIGHT, tag->getValue());
|
||||
}
|
||||
|
||||
delete cl;
|
||||
}
|
||||
|
||||
unsigned char* iptcdata = nullptr;
|
||||
unsigned int iptclen = 0;
|
||||
|
||||
if (iptc && iptc_data_save (iptc, &iptcdata, &iptclen)) {
|
||||
if (iptcdata) {
|
||||
iptc_data_free_buf (iptc, iptcdata);
|
||||
iptcdata = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
|
||||
bool needsReverse = exifRoot && exifRoot->getOrder() == rtexif::MOTOROLA;
|
||||
#else
|
||||
bool needsReverse = exifRoot && exifRoot->getOrder() == rtexif::INTEL;
|
||||
#endif
|
||||
|
||||
if (iptcdata) {
|
||||
rtexif::Tag iptcTag(nullptr, rtexif::lookupAttrib (rtexif::ifdAttribs, "IPTCData"));
|
||||
iptcTag.initLongArray((char*)iptcdata, iptclen);
|
||||
if (needsReverse) {
|
||||
unsigned char *ptr = iptcTag.getValue();
|
||||
for (int a = 0; a < iptcTag.getCount(); ++a, ptr += 4) {
|
||||
std::swap(ptr[0], ptr[3]);
|
||||
std::swap(ptr[1], ptr[2]);
|
||||
}
|
||||
}
|
||||
TIFFSetField (out, TIFFTAG_RICHTIFFIPTC, iptcTag.getCount(), (long*)iptcTag.getValue());
|
||||
iptc_data_free_buf (iptc, iptcdata);
|
||||
}
|
||||
bool needsReverse = false;
|
||||
|
||||
TIFFSetField (out, TIFFTAG_SOFTWARE, "RawTherapee " RTVERSION);
|
||||
TIFFSetField (out, TIFFTAG_IMAGEWIDTH, width);
|
||||
@ -1516,24 +1180,36 @@ int ImageIO::saveTIFF (
|
||||
TIFFSetField (out, TIFFTAG_COMPRESSION, uncompressed ? COMPRESSION_NONE : COMPRESSION_ADOBE_DEFLATE);
|
||||
TIFFSetField (out, TIFFTAG_SAMPLEFORMAT, (bps == 16 || bps == 32) && isFloat ? SAMPLEFORMAT_IEEEFP : SAMPLEFORMAT_UINT);
|
||||
|
||||
[out]()
|
||||
{
|
||||
const std::vector<rtexif::Tag*> default_tags = rtexif::ExifManager::getDefaultTIFFTags(nullptr);
|
||||
|
||||
TIFFSetField (out, TIFFTAG_XRESOLUTION, default_tags[2]->toDouble());
|
||||
TIFFSetField (out, TIFFTAG_YRESOLUTION, default_tags[3]->toDouble());
|
||||
TIFFSetField (out, TIFFTAG_RESOLUTIONUNIT, default_tags[4]->toInt());
|
||||
|
||||
for (auto default_tag : default_tags) {
|
||||
delete default_tag;
|
||||
// somehow Exiv2 (tested with 0.27.3) doesn't seem to be able to update
|
||||
// XResolution and YResolution, so we do it ourselves here....
|
||||
constexpr float default_resolution = 300.f;
|
||||
float x_res = default_resolution;
|
||||
float y_res = default_resolution;
|
||||
int res_unit = RESUNIT_INCH;
|
||||
if (!metadataInfo.filename().empty()) {
|
||||
auto exif = metadataInfo.getOutputExifData();
|
||||
auto it = exif.findKey(Exiv2::ExifKey("Exif.Image.XResolution"));
|
||||
if (it != exif.end()) {
|
||||
x_res = it->toFloat();
|
||||
}
|
||||
}();
|
||||
it = exif.findKey(Exiv2::ExifKey("Exif.Image.YResolution"));
|
||||
if (it != exif.end()) {
|
||||
y_res = it->toFloat();
|
||||
}
|
||||
it = exif.findKey(Exiv2::ExifKey("Exif.Image.ResolutionUnit"));
|
||||
if (it != exif.end()) {
|
||||
res_unit = to_long(it);
|
||||
}
|
||||
}
|
||||
TIFFSetField(out, TIFFTAG_XRESOLUTION, x_res);
|
||||
TIFFSetField(out, TIFFTAG_YRESOLUTION, y_res);
|
||||
TIFFSetField(out, TIFFTAG_RESOLUTIONUNIT, res_unit);
|
||||
|
||||
if (!uncompressed) {
|
||||
TIFFSetField (out, TIFFTAG_PREDICTOR, (bps == 16 || bps == 32) && isFloat ? PREDICTOR_FLOATINGPOINT : PREDICTOR_HORIZONTAL);
|
||||
}
|
||||
if (profileData) {
|
||||
TIFFSetField (out, TIFFTAG_ICCPROFILE, profileLength, profileData);
|
||||
if (!profileData.empty()) {
|
||||
TIFFSetField (out, TIFFTAG_ICCPROFILE, profileData.size(), profileData.data());
|
||||
}
|
||||
|
||||
for (int row = 0; row < height; row++) {
|
||||
@ -1568,43 +1244,15 @@ int ImageIO::saveTIFF (
|
||||
writeOk = false;
|
||||
}
|
||||
|
||||
/************************************************************************************************************
|
||||
*
|
||||
* Hombre: This is a dirty hack to update the Exif tag data type to 0x0004 so that Windows can understand it.
|
||||
* libtiff will set this data type to 0x000d and doesn't provide any mechanism to update it before
|
||||
* dumping to the file.
|
||||
*
|
||||
*/
|
||||
if (applyExifPatch) {
|
||||
unsigned char b[10];
|
||||
uint16 tagCount = 0;
|
||||
lseek(fileno, 4, SEEK_SET);
|
||||
read(fileno, b, 4);
|
||||
uint32 ifd0Offset = rtexif::sget4(b, exifRoot->getOrder());
|
||||
lseek(fileno, ifd0Offset, SEEK_SET);
|
||||
read(fileno, b, 2);
|
||||
tagCount = rtexif::sget2(b, exifRoot->getOrder());
|
||||
for (size_t i = 0; i < tagCount ; ++i) {
|
||||
uint16 tagID = 0;
|
||||
read(fileno, b, 2);
|
||||
tagID = rtexif::sget2(b, exifRoot->getOrder());
|
||||
if (tagID == 0x8769) {
|
||||
rtexif::sset2(4, b, exifRoot->getOrder());
|
||||
write(fileno, b, 2);
|
||||
break;
|
||||
} else {
|
||||
read(fileno, b, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
/************************************************************************************************************/
|
||||
|
||||
|
||||
TIFFClose (out);
|
||||
#ifdef WIN32
|
||||
fclose (file);
|
||||
#endif
|
||||
|
||||
if (!saveMetadata(fname)) {
|
||||
writeOk = false;
|
||||
}
|
||||
|
||||
if (pl) {
|
||||
pl->setProgressStr ("PROGRESSBAR_READY");
|
||||
pl->setProgress (1.0);
|
||||
@ -1731,3 +1379,57 @@ void ImageIO::deleteLoadedProfileData( )
|
||||
|
||||
loadedProfileData = nullptr;
|
||||
}
|
||||
|
||||
bool ImageIO::saveMetadata(const Glib::ustring &fname) const
|
||||
{
|
||||
if (metadataInfo.filename().empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool has_meta = true;
|
||||
try {
|
||||
metadataInfo.load();
|
||||
} catch (const std::exception& exc) {
|
||||
if (settings->verbose) {
|
||||
std::cout << "EXIF LOAD ERROR: " << exc.what() << std::endl;
|
||||
}
|
||||
has_meta = false;
|
||||
}
|
||||
|
||||
if (has_meta) {
|
||||
try {
|
||||
metadataInfo.saveToImage(fname, false);
|
||||
// auto src = open_exiv2(metadataInfo.filename());
|
||||
// auto dst = open_exiv2(fname);
|
||||
// src->readMetadata();
|
||||
// dst->setMetadata(*src);
|
||||
// dst->exifData()["Exif.Image.Software"] = "RawTherapee " RTVERSION;
|
||||
// for (const auto& p : metadataInfo.exif()) {
|
||||
// try {
|
||||
// dst->exifData()[p.first] = p.second;
|
||||
// } catch (const Exiv2::AnyError& exc) {
|
||||
// }
|
||||
// }
|
||||
// for (const auto& p : metadataInfo.iptc()) {
|
||||
// try {
|
||||
// auto& v = p.second;
|
||||
// if (!v.empty()) {
|
||||
// dst->iptcData()[p.first] = v[0];
|
||||
// for (size_t j = 1; j < v.size(); ++j) {
|
||||
// Exiv2::Iptcdatum d(Exiv2::IptcKey(p.first));
|
||||
// d.setValue(v[j]);
|
||||
// dst->iptcData().add(d);
|
||||
// }
|
||||
// }
|
||||
// } catch (const Exiv2::AnyError& exc) {
|
||||
// }
|
||||
// }
|
||||
// dst->writeMetadata();
|
||||
} catch (const std::exception& exc) {
|
||||
std::cout << "EXIF ERROR: " << exc.what() << std::endl;
|
||||
//return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -19,14 +19,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <glibmm/ustring.h>
|
||||
|
||||
#include <libiptcdata/iptc-data.h>
|
||||
|
||||
#include "iimage.h"
|
||||
#include "imagedimensions.h"
|
||||
#include "imageformat.h"
|
||||
#include "metadata.h"
|
||||
#include "rtengine.h"
|
||||
|
||||
enum {
|
||||
@ -40,50 +38,40 @@ enum {
|
||||
IMIO_CANNOTWRITEFILE
|
||||
};
|
||||
|
||||
namespace rtexif
|
||||
{
|
||||
|
||||
class TagDirectory;
|
||||
|
||||
}
|
||||
|
||||
namespace rtengine
|
||||
{
|
||||
|
||||
class ColorTemp;
|
||||
class ProgressListener;
|
||||
class Imagefloat;
|
||||
|
||||
namespace procparams
|
||||
{
|
||||
|
||||
class ExifPairs;
|
||||
class IPTCPairs;
|
||||
|
||||
}
|
||||
|
||||
class ColorTemp;
|
||||
class ProgressListener;
|
||||
class Imagefloat;
|
||||
|
||||
class ImageIO : virtual public ImageDatas
|
||||
{
|
||||
|
||||
protected:
|
||||
ProgressListener* pl;
|
||||
cmsHPROFILE embProfile;
|
||||
char* profileData;
|
||||
std::string profileData;
|
||||
int profileLength;
|
||||
char* loadedProfileData;
|
||||
int loadedProfileLength;
|
||||
const std::unique_ptr<procparams::ExifPairs> exifChange;
|
||||
IptcData* iptc;
|
||||
const rtexif::TagDirectory* exifRoot;
|
||||
MyMutex imutex;
|
||||
IIOSampleFormat sampleFormat;
|
||||
IIOSampleArrangement sampleArrangement;
|
||||
Exiv2Metadata metadataInfo;
|
||||
|
||||
private:
|
||||
void deleteLoadedProfileData( );
|
||||
|
||||
public:
|
||||
static Glib::ustring errorMsg[6];
|
||||
|
||||
ImageIO();
|
||||
~ImageIO() override;
|
||||
|
||||
@ -124,9 +112,10 @@ public:
|
||||
cmsHPROFILE getEmbeddedProfile () const;
|
||||
void getEmbeddedProfileData (int& length, unsigned char*& pdata) const;
|
||||
|
||||
void setMetadata (const rtexif::TagDirectory* eroot);
|
||||
void setMetadata (const rtexif::TagDirectory* eroot, const rtengine::procparams::ExifPairs& exif, const rtengine::procparams::IPTCPairs& iptcc);
|
||||
void setOutputProfile (const char* pdata, int plen);
|
||||
void setMetadata(Exiv2Metadata info);
|
||||
void setOutputProfile(const std::string& pdata);
|
||||
|
||||
bool saveMetadata(const Glib::ustring &fname) const;
|
||||
|
||||
MyMutex& mutex ();
|
||||
};
|
||||
|
@ -109,7 +109,7 @@ public:
|
||||
virtual void getWBMults (const ColorTemp &ctemp, const procparams::RAWParams &raw, std::array<float, 4>& scale_mul, float &autoGainComp, float &rm, float &gm, float &bm) const = 0;
|
||||
|
||||
// use right after demosaicing image, add coarse transformation and put the result in the provided Imagefloat*
|
||||
virtual void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hlp, const procparams::RAWParams &raw, int opposed) = 0;
|
||||
virtual void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hlp, const procparams::RAWParams &raw) = 0;
|
||||
virtual eSensorType getSensorType () const = 0;
|
||||
virtual bool isMono () const = 0;
|
||||
// true is ready to provide the AutoWB, i.e. when the image has been demosaiced for RawImageSource
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "image8.h"
|
||||
#include "imagefloat.h"
|
||||
#include "improcfun.h"
|
||||
#include "metadata.h"
|
||||
#include "labimage.h"
|
||||
#include "lcp.h"
|
||||
#include "procparams.h"
|
||||
@ -406,6 +407,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
|
||||
Color HLR alters rgb output of demosaic, so re-demosaic is needed when Color HLR is being turned off;
|
||||
if HLR is enabled and changing method *from* Color to any other method
|
||||
OR HLR gets disabled when Color method was selected
|
||||
If white balance changed with inpaint opposed, because inpaint opposed depends on the white balance
|
||||
*/
|
||||
// If high detail (=100%) is newly selected, do a demosaic update, since the last was just with FAST
|
||||
|
||||
@ -413,7 +415,10 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
|
||||
imageTypeListener->imageTypeChanged(imgsrc->isRAW(), imgsrc->getSensorType() == ST_BAYER, imgsrc->getSensorType() == ST_FUJI_XTRANS, imgsrc->isMono(), imgsrc->isGainMapSupported());
|
||||
}
|
||||
|
||||
bool iscolor = (params->toneCurve.method == "Color");// || params->toneCurve.method == "Coloropp");
|
||||
bool iscolor = (params->toneCurve.method == "Color" || params->toneCurve.method == "Coloropp");
|
||||
if ((todo & M_WB) && params->toneCurve.hrenabled && params->toneCurve.method == "Coloropp") {
|
||||
todo |= DEMOSAIC;
|
||||
}
|
||||
|
||||
if ((todo & M_RAW)
|
||||
|| (!highDetailRawComputed && highDetailNeeded)
|
||||
@ -871,8 +876,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
|
||||
PreviewProps pp(0, 0, fw, fh, scale);
|
||||
// Tells to the ImProcFunctions' tools what is the preview scale, which may lead to some simplifications
|
||||
ipf.setScale(scale);
|
||||
int inpaintopposed = 1;//force getimage to use inpaint-opposed if enable, only once
|
||||
imgsrc->getImage(currWB, tr, orig_prev, pp, params->toneCurve, params->raw, inpaintopposed);
|
||||
imgsrc->getImage(currWB, tr, orig_prev, pp, params->toneCurve, params->raw);
|
||||
|
||||
if ((todo & M_SPOT) && params->spot.enabled && !params->spot.entries.empty()) {
|
||||
spotsDone = true;
|
||||
@ -2177,20 +2181,10 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
|
||||
customColCurve1, customColCurve2, customColCurve3, 1);
|
||||
|
||||
const FramesMetaData* metaData = imgsrc->getMetaData();
|
||||
int imgNum = 0;
|
||||
|
||||
if (imgsrc->isRAW()) {
|
||||
if (imgsrc->getSensorType() == ST_BAYER) {
|
||||
imgNum = rtengine::LIM<unsigned int>(params->raw.bayersensor.imageNum, 0, metaData->getFrameCount() - 1);
|
||||
} else if (imgsrc->getSensorType() == ST_FUJI_XTRANS) {
|
||||
//imgNum = rtengine::LIM<unsigned int>(params->raw.xtranssensor.imageNum, 0, metaData->getFrameCount() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
float fnum = metaData->getFNumber(imgNum); // F number
|
||||
float fiso = metaData->getISOSpeed(imgNum) ; // ISO
|
||||
float fspeed = metaData->getShutterSpeed(imgNum) ; // Speed
|
||||
double fcomp = metaData->getExpComp(imgNum); // Compensation +/-
|
||||
float fnum = metaData->getFNumber(); // F number
|
||||
float fiso = metaData->getISOSpeed() ; // ISO
|
||||
float fspeed = metaData->getShutterSpeed() ; // Speed
|
||||
double fcomp = metaData->getExpComp(); // Compensation +/-
|
||||
double adap;
|
||||
|
||||
if (fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { //if no exif data or wrong
|
||||
@ -2976,7 +2970,7 @@ void ImProcCoordinator::saveInputICCReference(const Glib::ustring& fname, bool a
|
||||
currWB = ColorTemp(); // = no white balance
|
||||
}
|
||||
|
||||
imgsrc->getImage(currWB, tr, im, pp, ppar.toneCurve, ppar.raw, 0);
|
||||
imgsrc->getImage(currWB, tr, im, pp, ppar.toneCurve, ppar.raw);
|
||||
ImProcFunctions ipf(&ppar, true);
|
||||
|
||||
if (ipf.needsTransform(fW, fH, imgsrc->getRotateDegree(), imgsrc->getMetaData())) {
|
||||
@ -3032,7 +3026,7 @@ void ImProcCoordinator::saveInputICCReference(const Glib::ustring& fname, bool a
|
||||
im = tempImage;
|
||||
}
|
||||
|
||||
im->setMetadata(imgsrc->getMetaData()->getRootExifData());
|
||||
im->setMetadata(Exiv2Metadata(imgsrc->getFileName(), false));
|
||||
|
||||
im->saveTIFF(fname, 16, false, true);
|
||||
delete im;
|
||||
@ -3153,7 +3147,7 @@ void ImProcCoordinator::process()
|
||||
paramsUpdateMutex.unlock();
|
||||
|
||||
// M_VOID means no update, and is a bit higher that the rest
|
||||
if (change & (M_VOID - 1)) {
|
||||
if (change & (~M_VOID)) {
|
||||
updatePreviewImage(change, panningRelatedChange);
|
||||
}
|
||||
|
||||
|
@ -5634,18 +5634,18 @@ void ImProcFunctions::getAutoExp(const LUTu &histogram, int histcompr, double cl
|
||||
double ImProcFunctions::getAutoDistor(const Glib::ustring &fname, int thumb_size)
|
||||
{
|
||||
if (!fname.empty()) {
|
||||
rtengine::RawMetaDataLocation ri;
|
||||
// TODO: std::unique_ptr<> to the rescue
|
||||
int w_raw = -1, h_raw = thumb_size;
|
||||
int w_thumb = -1, h_thumb = thumb_size;
|
||||
|
||||
eSensorType sensorType = rtengine::ST_NONE;
|
||||
Thumbnail* thumb = rtengine::Thumbnail::loadQuickFromRaw(fname, ri, sensorType, w_thumb, h_thumb, 1, FALSE);
|
||||
Thumbnail* thumb = rtengine::Thumbnail::loadQuickFromRaw(fname, sensorType, w_thumb, h_thumb, 1, FALSE);
|
||||
|
||||
if (!thumb) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
Thumbnail* raw = rtengine::Thumbnail::loadFromRaw(fname, ri, sensorType, w_raw, h_raw, 1, 1.0, ColorTemp::DEFAULT_OBSERVER, FALSE);
|
||||
Thumbnail* raw = rtengine::Thumbnail::loadFromRaw(fname, sensorType, w_raw, h_raw, 1, 1.0, ColorTemp::DEFAULT_OBSERVER, FALSE);
|
||||
|
||||
if (!raw) {
|
||||
delete thumb;
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "profilestore.h"
|
||||
#include "../rtgui/threadutils.h"
|
||||
#include "rtlensfun.h"
|
||||
#include "metadata.h"
|
||||
#include "procparams.h"
|
||||
|
||||
namespace rtengine
|
||||
@ -114,6 +115,8 @@ int init (const Settings* s, const Glib::ustring& baseDir, const Glib::ustring&
|
||||
}
|
||||
|
||||
Color::init ();
|
||||
Exiv2Metadata::init();
|
||||
|
||||
delete lcmsMutex;
|
||||
lcmsMutex = new MyMutex;
|
||||
fftwMutex = new MyMutex;
|
||||
@ -122,6 +125,7 @@ int init (const Settings* s, const Glib::ustring& baseDir, const Glib::ustring&
|
||||
|
||||
void cleanup ()
|
||||
{
|
||||
Exiv2Metadata::cleanup();
|
||||
ProcParams::cleanup ();
|
||||
Color::cleanup ();
|
||||
RawImageSource::cleanup ();
|
||||
|
@ -2130,7 +2130,7 @@ void ImProcFunctions::getAutoLogloc(int sp, ImageSource *imgsrc, float *sourceg,
|
||||
Imagefloat img(int(fw / SCALE + 0.5), int(fh / SCALE + 0.5));
|
||||
const ProcParams neutral;
|
||||
|
||||
imgsrc->getImage(imgsrc->getWB(), TR_NONE, &img, pp, params->toneCurve, neutral.raw, 0);
|
||||
imgsrc->getImage(imgsrc->getWB(), TR_NONE, &img, pp, params->toneCurve, neutral.raw);
|
||||
imgsrc->convertColorSpace(&img, params->icm, imgsrc->getWB());
|
||||
float minVal = RT_INFINITY;
|
||||
float maxVal = -RT_INFINITY;
|
||||
@ -2237,20 +2237,11 @@ void ImProcFunctions::getAutoLogloc(int sp, ImageSource *imgsrc, float *sourceg,
|
||||
//calculate La - Absolute luminance shooting
|
||||
|
||||
const FramesMetaData* metaData = imgsrc->getMetaData();
|
||||
int imgNum = 0;
|
||||
|
||||
if (imgsrc->isRAW()) {
|
||||
if (imgsrc->getSensorType() == ST_BAYER) {
|
||||
imgNum = rtengine::LIM<unsigned int>(params->raw.bayersensor.imageNum, 0, metaData->getFrameCount() - 1);
|
||||
} else if (imgsrc->getSensorType() == ST_FUJI_XTRANS) {
|
||||
//imgNum = rtengine::LIM<unsigned int>(params->raw.xtranssensor.imageNum, 0, metaData->getFrameCount() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
float fnum = metaData->getFNumber(imgNum); // F number
|
||||
float fiso = metaData->getISOSpeed(imgNum) ; // ISO
|
||||
float fspeed = metaData->getShutterSpeed(imgNum) ; // Speed
|
||||
double fcomp = metaData->getExpComp(imgNum); // Compensation +/-
|
||||
float fnum = metaData->getFNumber(); // F number
|
||||
float fiso = metaData->getISOSpeed() ; // ISO
|
||||
float fspeed = metaData->getShutterSpeed() ; // Speed
|
||||
double fcomp = metaData->getExpComp(); // Compensation +/-
|
||||
double adap;
|
||||
|
||||
if (fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { //if no exif data or wrong
|
||||
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee 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.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
struct IptcPair {
|
||||
IptcTag tag;
|
||||
size_t size;
|
||||
Glib::ustring field;
|
||||
};
|
||||
|
||||
const IptcPair strTags[] = {
|
||||
{IPTC_TAG_CAPTION, 2000, "Caption"},
|
||||
{IPTC_TAG_WRITER_EDITOR, 32, "CaptionWriter"},
|
||||
{IPTC_TAG_HEADLINE, 256, "Headline"},
|
||||
{IPTC_TAG_SPECIAL_INSTRUCTIONS, 256, "Instructions"},
|
||||
{IPTC_TAG_CATEGORY, 3, "Category"},
|
||||
{IPTC_TAG_BYLINE, 32, "Creator"},
|
||||
{IPTC_TAG_BYLINE_TITLE, 32, "CreatorJobTitle"},
|
||||
{IPTC_TAG_CREDIT, 32, "Credit"},
|
||||
{IPTC_TAG_SOURCE, 32, "Source"},
|
||||
{IPTC_TAG_COPYRIGHT_NOTICE, 128, "Copyright"},
|
||||
{IPTC_TAG_CITY, 32, "City"},
|
||||
{IPTC_TAG_STATE, 32, "Province"},
|
||||
{IPTC_TAG_COUNTRY_NAME, 64, "Country"},
|
||||
{IPTC_TAG_OBJECT_NAME, 64, "Title"},
|
||||
{IPTC_TAG_ORIG_TRANS_REF, 32, "TransReference"},
|
||||
{IPTC_TAG_DATE_CREATED, 8, "DateCreated"}
|
||||
};
|
624
rtengine/metadata.cc
Normal file
@ -0,0 +1,624 @@
|
||||
/* -*- C++ -*-
|
||||
*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2019 Alberto Griggio <alberto.griggio@gmail.com>
|
||||
*
|
||||
* RawTherapee 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.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <iostream>
|
||||
#include <giomm.h>
|
||||
#include <set>
|
||||
|
||||
#include "metadata.h"
|
||||
#include "settings.h"
|
||||
#include "imagedata.h"
|
||||
#include "../rtgui/version.h"
|
||||
#include "../rtgui/pathutils.h"
|
||||
|
||||
|
||||
#if EXIV2_TEST_VERSION(0,28,0)
|
||||
using Exiv2Error = Exiv2::Error;
|
||||
#else
|
||||
using Exiv2Error = Exiv2::AnyError;
|
||||
#endif
|
||||
|
||||
|
||||
namespace rtengine {
|
||||
|
||||
extern const Settings *settings;
|
||||
|
||||
std::unique_ptr<Exiv2Metadata::ImageCache> Exiv2Metadata::cache_(nullptr);
|
||||
|
||||
namespace {
|
||||
|
||||
class Error: public Exiv2Error {
|
||||
public:
|
||||
Error(const std::string &msg):
|
||||
#if EXIV2_TEST_VERSION(0,28,0)
|
||||
Exiv2Error(Exiv2::ErrorCode::kerGeneralError),
|
||||
#endif
|
||||
msg_(msg) {}
|
||||
const char *what() const throw() { return msg_.c_str(); }
|
||||
int code() const throw() { return 0; }
|
||||
|
||||
private:
|
||||
std::string msg_;
|
||||
};
|
||||
|
||||
|
||||
constexpr size_t IMAGE_CACHE_SIZE = 200;
|
||||
|
||||
std::unique_ptr<Exiv2::Image> open_exiv2(const Glib::ustring& fname,
|
||||
bool check_exif)
|
||||
{
|
||||
#ifdef EXV_UNICODE_PATH
|
||||
glong ws_size = 0;
|
||||
gunichar2* const ws = g_utf8_to_utf16(fname.c_str(), -1, nullptr, &ws_size, nullptr);
|
||||
std::wstring wfname;
|
||||
wfname.reserve(ws_size);
|
||||
for (glong i = 0; i < ws_size; ++i) {
|
||||
wfname.push_back(ws[i]);
|
||||
}
|
||||
g_free(ws);
|
||||
auto image = Exiv2::ImageFactory::open(wfname);
|
||||
#else
|
||||
auto image = Exiv2::ImageFactory::open(Glib::filename_from_utf8(fname));
|
||||
#endif
|
||||
image->readMetadata();
|
||||
if (!image->good() || (check_exif && image->exifData().empty())) {
|
||||
#if EXIV2_TEST_VERSION(0,27,0)
|
||||
auto error_code = Exiv2::ErrorCode::kerErrorMessage;
|
||||
#else
|
||||
auto error_code = 1;
|
||||
#endif
|
||||
throw Exiv2::Error(error_code, "exiv2: invalid image");
|
||||
}
|
||||
std::unique_ptr<Exiv2::Image> ret(image.release());
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
template <class Data, class Key>
|
||||
void clear_metadata_key(Data &data, const Key &key)
|
||||
{
|
||||
while (true) {
|
||||
auto it = data.findKey(key);
|
||||
if (it == data.end()) {
|
||||
break;
|
||||
} else {
|
||||
data.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Iterator, typename Integer = std::size_t>
|
||||
auto to_long(const Iterator &iter, Integer n = Integer{0}) -> decltype(
|
||||
#if EXIV2_TEST_VERSION(0,28,0)
|
||||
iter->toInt64()
|
||||
) {
|
||||
return iter->toInt64(n);
|
||||
#else
|
||||
iter->toLong()
|
||||
) {
|
||||
return iter->toLong(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
Exiv2Metadata::Exiv2Metadata():
|
||||
src_(""),
|
||||
merge_xmp_(false),
|
||||
image_(nullptr),
|
||||
exif_(new rtengine::procparams::ExifPairs),
|
||||
iptc_(new rtengine::procparams::IPTCPairs)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Exiv2Metadata::Exiv2Metadata(const Glib::ustring &path):
|
||||
src_(path),
|
||||
merge_xmp_(settings->metadata_xmp_sync != Settings::MetadataXmpSync::NONE),
|
||||
image_(nullptr),
|
||||
exif_(new rtengine::procparams::ExifPairs),
|
||||
iptc_(new rtengine::procparams::IPTCPairs)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Exiv2Metadata::Exiv2Metadata(const Glib::ustring &path, bool merge_xmp_sidecar):
|
||||
src_(path),
|
||||
merge_xmp_(merge_xmp_sidecar),
|
||||
image_(nullptr),
|
||||
exif_(new rtengine::procparams::ExifPairs),
|
||||
iptc_(new rtengine::procparams::IPTCPairs)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void Exiv2Metadata::load() const
|
||||
{
|
||||
if (!src_.empty() && !image_.get() && Glib::file_test(src_.c_str(), Glib::FILE_TEST_EXISTS)) {
|
||||
CacheVal val;
|
||||
auto finfo = Gio::File::create_for_path(src_)->query_info(G_FILE_ATTRIBUTE_TIME_MODIFIED);
|
||||
Glib::TimeVal xmp_mtime(0, 0);
|
||||
if (merge_xmp_) {
|
||||
auto xmpname = xmpSidecarPath(src_);
|
||||
if (Glib::file_test(xmpname.c_str(), Glib::FILE_TEST_EXISTS)) {
|
||||
xmp_mtime = Gio::File::create_for_path(xmpname)->query_info(G_FILE_ATTRIBUTE_TIME_MODIFIED)->modification_time();
|
||||
}
|
||||
}
|
||||
|
||||
if (cache_ && cache_->get(src_, val) && val.image_mtime >= finfo->modification_time() && val.use_xmp == merge_xmp_ && val.xmp_mtime >= xmp_mtime) {
|
||||
image_ = val.image;
|
||||
} else {
|
||||
auto img = open_exiv2(src_, true);
|
||||
image_.reset(img.release());
|
||||
if (merge_xmp_) {
|
||||
do_merge_xmp(image_.get(), false);
|
||||
}
|
||||
if (cache_) {
|
||||
val.image = image_;
|
||||
val.image_mtime = finfo->modification_time();
|
||||
val.xmp_mtime = xmp_mtime;
|
||||
val.use_xmp = merge_xmp_;
|
||||
cache_->set(src_, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Exiv2::ExifData& Exiv2Metadata::exifData()
|
||||
{
|
||||
return image_.get() ? image_->exifData() : exif_data_;
|
||||
}
|
||||
|
||||
const Exiv2::ExifData& Exiv2Metadata::exifData() const
|
||||
{
|
||||
return const_cast<Exiv2Metadata *>(this)->exifData();
|
||||
}
|
||||
|
||||
Exiv2::IptcData& Exiv2Metadata::iptcData()
|
||||
{
|
||||
return image_.get() ? image_->iptcData() : iptc_data_;
|
||||
}
|
||||
|
||||
const Exiv2::IptcData& Exiv2Metadata::iptcData() const
|
||||
{
|
||||
return const_cast<Exiv2Metadata *>(this)->iptcData();
|
||||
}
|
||||
|
||||
Exiv2::XmpData& Exiv2Metadata::xmpData()
|
||||
{
|
||||
return image_.get() ? image_->xmpData() : xmp_data_;
|
||||
}
|
||||
|
||||
const Exiv2::XmpData& Exiv2Metadata::xmpData() const
|
||||
{
|
||||
return const_cast<Exiv2Metadata *>(this)->xmpData();
|
||||
}
|
||||
|
||||
const Glib::ustring& Exiv2Metadata::filename() const
|
||||
{
|
||||
return src_;
|
||||
}
|
||||
|
||||
const rtengine::procparams::ExifPairs& Exiv2Metadata::exif() const
|
||||
{
|
||||
return *exif_;
|
||||
}
|
||||
|
||||
const rtengine::procparams::IPTCPairs& Exiv2Metadata::iptc() const
|
||||
{
|
||||
return *iptc_;
|
||||
}
|
||||
|
||||
void Exiv2Metadata::setExif(const rtengine::procparams::ExifPairs &exif)
|
||||
{
|
||||
*exif_ = exif;
|
||||
}
|
||||
|
||||
void Exiv2Metadata::setIptc(const rtengine::procparams::IPTCPairs &iptc)
|
||||
{
|
||||
*iptc_ = iptc;
|
||||
}
|
||||
|
||||
void Exiv2Metadata::do_merge_xmp(Exiv2::Image *dst, bool keep_all) const
|
||||
{
|
||||
try {
|
||||
auto xmp = getXmpSidecar(src_);
|
||||
Exiv2::ExifData exif;
|
||||
Exiv2::IptcData iptc;
|
||||
Exiv2::copyXmpToIptc(xmp, iptc);
|
||||
Exiv2::moveXmpToExif(xmp, exif);
|
||||
std::unordered_map<std::string, std::unordered_set<std::string>> seen;
|
||||
|
||||
if (!keep_all) {
|
||||
remove_unwanted(exif);
|
||||
}
|
||||
|
||||
for (auto &datum : exif) {
|
||||
dst->exifData()[datum.key()] = datum;
|
||||
}
|
||||
for (auto &datum : iptc) {
|
||||
auto &s = seen[datum.key()];
|
||||
if (s.empty()) {
|
||||
clear_metadata_key(dst->iptcData(), Exiv2::IptcKey(datum.key()));
|
||||
dst->iptcData()[datum.key()] = datum;
|
||||
s.insert(datum.toString());
|
||||
} else if (s.insert(datum.toString()).second) {
|
||||
dst->iptcData().add(datum);
|
||||
}
|
||||
}
|
||||
seen.clear();
|
||||
for (auto &datum : xmp) {
|
||||
auto &s = seen[datum.key()];
|
||||
if (s.empty()) {
|
||||
clear_metadata_key(dst->xmpData(), Exiv2::XmpKey(datum.key()));
|
||||
dst->xmpData()[datum.key()] = datum;
|
||||
s.insert(datum.toString());
|
||||
} else if (s.insert(datum.toString()).second) {
|
||||
dst->xmpData().add(datum);
|
||||
}
|
||||
}
|
||||
} catch (std::exception &exc) {
|
||||
if (settings->verbose) {
|
||||
std::cerr << "Error loading metadata from XMP sidecar: "
|
||||
<< exc.what() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Exiv2Metadata::saveToImage(const Glib::ustring &path, bool preserve_all_tags) const
|
||||
{
|
||||
auto dst = open_exiv2(path, false);
|
||||
if (image_.get()) {
|
||||
dst->setIptcData(image_->iptcData());
|
||||
dst->setXmpData(image_->xmpData());
|
||||
if (merge_xmp_) {
|
||||
do_merge_xmp(dst.get(), preserve_all_tags);
|
||||
}
|
||||
auto srcexif = image_->exifData();
|
||||
if (!preserve_all_tags) {
|
||||
remove_unwanted(srcexif);
|
||||
}
|
||||
//dst->setExifData(srcexif);
|
||||
for (auto &tag : srcexif) {
|
||||
if (tag.count() > 0) {
|
||||
dst->exifData()[tag.key()] = tag;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dst->setExifData(exif_data_);
|
||||
dst->setIptcData(iptc_data_);
|
||||
dst->setXmpData(xmp_data_);
|
||||
}
|
||||
|
||||
dst->exifData()["Exif.Image.Software"] = "RawTherapee " RTVERSION;
|
||||
import_exif_pairs(dst->exifData());
|
||||
import_iptc_pairs(dst->iptcData());
|
||||
bool xmp_tried = false;
|
||||
bool iptc_tried = false;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
try {
|
||||
dst->writeMetadata();
|
||||
return;
|
||||
} catch (Exiv2::Error &exc) {
|
||||
if (exc.code() == Exiv2::ErrorCode::kerTooLargeJpegSegment) {
|
||||
std::string msg = exc.what();
|
||||
if (msg.find("XMP") != std::string::npos &&
|
||||
!dst->xmpData().empty()) {
|
||||
dst->xmpData().clear();
|
||||
if (!xmp_tried && merge_xmp_) {
|
||||
do_merge_xmp(dst.get(), preserve_all_tags);
|
||||
xmp_tried = true;
|
||||
}
|
||||
} else if (msg.find("IPTC") != std::string::npos &&
|
||||
!dst->iptcData().empty()) {
|
||||
dst->iptcData().clear();
|
||||
if (!iptc_tried) {
|
||||
import_iptc_pairs(dst->iptcData());
|
||||
iptc_tried = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw exc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Exiv2Metadata::remove_unwanted(Exiv2::ExifData &dst) const
|
||||
{
|
||||
Exiv2::ExifThumb thumb(dst);
|
||||
thumb.erase();
|
||||
|
||||
static const std::set<std::string> badtags = {
|
||||
"Exif.Image.Orientation",
|
||||
"Exif.Image2.JPEGInterchangeFormat",
|
||||
"Exif.Image2.JPEGInterchangeFormatLength",
|
||||
"Exif.Image.NewSubfileType",
|
||||
"Exif.Image.SubfileType",
|
||||
"Exif.Image.ImageWidth",
|
||||
"Exif.Image.ImageLength",
|
||||
"Exif.Image.BitsPerSample",
|
||||
"Exif.Image.Compression",
|
||||
"Exif.Image.PhotometricInterpretation",
|
||||
"Exif.Image.Thresholding",
|
||||
"Exif.Image.CellWidth",
|
||||
"Exif.Image.CellLength",
|
||||
"Exif.Image.FillOrder",
|
||||
"Exif.Image.StripOffsets",
|
||||
"Exif.Image.Orientation",
|
||||
"Exif.Image.SamplesPerPixel",
|
||||
"Exif.Image.RowsPerStrip",
|
||||
"Exif.Image.StripByteCounts",
|
||||
"Exif.Image.XResolution",
|
||||
"Exif.Image.YResolution",
|
||||
"Exif.Image.PlanarConfiguration",
|
||||
"Exif.Image.GrayResponseUnit",
|
||||
"Exif.Image.GrayResponseCurve",
|
||||
"Exif.Image.T4Options",
|
||||
"Exif.Image.T6Options",
|
||||
"Exif.Image.ResolutionUnit",
|
||||
"Exif.Image.PageNumber",
|
||||
"Exif.Image.Predictor",
|
||||
"Exif.Image.TileWidth",
|
||||
"Exif.Image.TileLength",
|
||||
"Exif.Image.TileOffsets",
|
||||
"Exif.Image.TileByteCounts",
|
||||
"Exif.Image.SubIFDs",
|
||||
"Exif.Image.ExtraSamples",
|
||||
"Exif.Image.SampleFormat",
|
||||
"Exif.Image.SMinSampleValue",
|
||||
"Exif.Image.SMaxSampleValue",
|
||||
"Exif.Image.Indexed",
|
||||
"Exif.Image.JPEGTables",
|
||||
"Exif.Image.OPIProxy",
|
||||
"Exif.Image.JPEGProc",
|
||||
"Exif.Image.JPEGInterchangeFormat",
|
||||
"Exif.Image.JPEGInterchangeFormatLength",
|
||||
"Exif.Image.JPEGRestartInterval",
|
||||
"Exif.Image.JPEGLosslessPredictors",
|
||||
"Exif.Image.JPEGPointTransforms",
|
||||
"Exif.Image.JPEGQTables",
|
||||
"Exif.Image.JPEGDCTables",
|
||||
"Exif.Image.JPEGACTables",
|
||||
"Exif.Image.TIFFEPStandardID",
|
||||
"Exif.Image.DNGVersion",
|
||||
"Exif.Image.DNGBackwardVersion",
|
||||
"Exif.Image.DNGPrivateData",
|
||||
"Exif.Image.OriginalRawFileData",
|
||||
"Exif.Image.SubTileBlockSize",
|
||||
"Exif.Image.RowInterleaveFactor",
|
||||
"Exif.Photo.ComponentsConfiguration",
|
||||
"Exif.Photo.CompressedBitsPerPixel"
|
||||
};
|
||||
|
||||
static const std::vector<std::string> badpatterns = {
|
||||
"Exif.SubImage"
|
||||
};
|
||||
|
||||
if (exif_keys_ && !src_.empty()) {
|
||||
try {
|
||||
FramesData fd(src_);
|
||||
fd.fillBasicTags(dst);
|
||||
} catch (std::exception &exc) {
|
||||
std::cout << "Error reading metadata from " << src_
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = dst.begin(); it != dst.end(); ) {
|
||||
int relevant = exif_keys_ ? (exif_keys_->find(it->key()) != exif_keys_->end() ? 1 : 0) : -1;
|
||||
if (badtags.find(it->key()) != badtags.end() && relevant != 1) {
|
||||
it = dst.erase(it);
|
||||
} else if (relevant == 0) {
|
||||
it = dst.erase(it);
|
||||
} else {
|
||||
bool found = false;
|
||||
for (auto &p : badpatterns) {
|
||||
if (it->key().find(p) == 0) {
|
||||
it = dst.erase(it);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Exiv2Metadata::import_exif_pairs(Exiv2::ExifData &out) const
|
||||
{
|
||||
for (auto &p : *exif_) {
|
||||
try {
|
||||
out[p.first] = p.second;
|
||||
} catch (std::exception &exc) {
|
||||
if (settings->verbose) {
|
||||
std::cout << "Error setting " << p.first << " to " << p.second
|
||||
<< ": " << exc.what() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Exiv2Metadata::import_iptc_pairs(Exiv2::IptcData &out) const
|
||||
{
|
||||
for (auto &p : *iptc_) {
|
||||
try {
|
||||
auto &v = p.second;
|
||||
if (v.size() >= 1) {
|
||||
clear_metadata_key(out, Exiv2::IptcKey(p.first));
|
||||
Exiv2::Iptcdatum d(Exiv2::IptcKey(p.first));
|
||||
d.setValue(v[0]);
|
||||
out[p.first] = d;
|
||||
for (size_t j = 1; j < v.size(); ++j) {
|
||||
d.setValue(v[j]);
|
||||
out.add(d);
|
||||
}
|
||||
}
|
||||
} catch (std::exception &exc) {
|
||||
if (settings->verbose) {
|
||||
std::cout << "Error setting " << p.first
|
||||
<< ": " << exc.what() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Exiv2Metadata::saveToXmp(const Glib::ustring &path) const
|
||||
{
|
||||
Exiv2::XmpData xmp;
|
||||
Exiv2::copyExifToXmp(exifData(), xmp);
|
||||
Exiv2::copyIptcToXmp(iptcData(), xmp);
|
||||
for (auto &datum : xmpData()) {
|
||||
xmp[datum.key()] = datum;
|
||||
}
|
||||
Exiv2::ExifData exif;
|
||||
Exiv2::IptcData iptc;
|
||||
import_exif_pairs(exif);
|
||||
import_iptc_pairs(iptc);
|
||||
Exiv2::copyExifToXmp(exif, xmp);
|
||||
Exiv2::copyIptcToXmp(iptc, xmp);
|
||||
|
||||
std::string data;
|
||||
bool err = false;
|
||||
if (Exiv2::XmpParser::encode(data, xmp, Exiv2::XmpParser::omitPacketWrapper|Exiv2::XmpParser::useCompactFormat) != 0) {
|
||||
err = true;
|
||||
} else {
|
||||
FILE *out = g_fopen(path.c_str(), "wb");
|
||||
if (!out || fputs(data.c_str(), out) == EOF) {
|
||||
err = true;
|
||||
}
|
||||
if (out) {
|
||||
fclose(out);
|
||||
}
|
||||
}
|
||||
|
||||
if (err) {
|
||||
throw Error("error saving XMP sidecar " + path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Exiv2Metadata::setExifKeys(const std::vector<std::string> *keys)
|
||||
{
|
||||
exif_keys_.reset();
|
||||
if (keys) {
|
||||
exif_keys_ = std::make_shared<std::unordered_set<std::string>>();
|
||||
exif_keys_->insert(keys->begin(), keys->end());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Exiv2Metadata::getDimensions(int &w, int &h) const
|
||||
{
|
||||
if (image_) {
|
||||
if (dynamic_cast<const Exiv2::XmpSidecar *>(image_.get())) {
|
||||
auto &exif = image_->exifData();
|
||||
auto itw = exif.findKey(Exiv2::ExifKey("Exif.Image.ImageWidth"));
|
||||
auto ith = exif.findKey(Exiv2::ExifKey("Exif.Image.ImageLength"));
|
||||
if (itw != exif.end() && ith != exif.end()) {
|
||||
w = to_long(itw);
|
||||
h = to_long(ith);
|
||||
} else {
|
||||
w = h = -1;
|
||||
}
|
||||
} else {
|
||||
w = image_->pixelWidth();
|
||||
h = image_->pixelHeight();
|
||||
}
|
||||
} else {
|
||||
w = h = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Glib::ustring Exiv2Metadata::xmpSidecarPath(const Glib::ustring &path)
|
||||
{
|
||||
Glib::ustring fn = path;
|
||||
if (settings->xmp_sidecar_style == Settings::XmpSidecarStyle::STD) {
|
||||
fn = removeExtension(fn);
|
||||
}
|
||||
return fn + ".xmp";
|
||||
}
|
||||
|
||||
|
||||
Exiv2::XmpData Exiv2Metadata::getXmpSidecar(const Glib::ustring &path)
|
||||
{
|
||||
Exiv2::XmpData ret;
|
||||
auto fname = xmpSidecarPath(path);
|
||||
if (Glib::file_test(fname, Glib::FILE_TEST_EXISTS)) {
|
||||
auto image = open_exiv2(fname, false);
|
||||
ret = image->xmpData();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void Exiv2Metadata::init()
|
||||
{
|
||||
cache_.reset(new ImageCache(IMAGE_CACHE_SIZE));
|
||||
Exiv2::XmpParser::initialize();
|
||||
#ifdef EXV_ENABLE_BMFF
|
||||
Exiv2::enableBMFF(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void Exiv2Metadata::cleanup()
|
||||
{
|
||||
Exiv2::XmpParser::terminate();
|
||||
}
|
||||
|
||||
|
||||
Exiv2::ExifData Exiv2Metadata::getOutputExifData() const
|
||||
{
|
||||
Exiv2::ExifData exif = exifData();
|
||||
try {
|
||||
auto xmp = getXmpSidecar(src_);
|
||||
Exiv2::moveXmpToExif(xmp, exif);
|
||||
} catch (std::exception &exc) {
|
||||
if (settings->verbose) {
|
||||
std::cerr << "Error loading metadata from XMP sidecar: "
|
||||
<< exc.what() << std::endl;
|
||||
}
|
||||
}
|
||||
remove_unwanted(exif);
|
||||
import_exif_pairs(exif);
|
||||
for (auto it = exif.begin(); it != exif.end(); ) {
|
||||
if (it->count() > 0) {
|
||||
++it;
|
||||
} else {
|
||||
it = exif.erase(it);
|
||||
}
|
||||
}
|
||||
return exif;
|
||||
}
|
||||
|
||||
|
||||
} // namespace rtengine
|
100
rtengine/metadata.h
Normal file
@ -0,0 +1,100 @@
|
||||
/* -*- C++ -*-
|
||||
*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2019 Alberto Griggio <alberto.griggio@gmail.com>
|
||||
*
|
||||
* RawTherapee 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.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glibmm.h>
|
||||
#include <exiv2/exiv2.hpp>
|
||||
#include <memory>
|
||||
#include <unordered_set>
|
||||
#include "procparams.h"
|
||||
#include "cache.h"
|
||||
|
||||
namespace rtengine {
|
||||
|
||||
class Exiv2Metadata final
|
||||
{
|
||||
public:
|
||||
Exiv2Metadata();
|
||||
explicit Exiv2Metadata(const Glib::ustring& path);
|
||||
Exiv2Metadata(const Glib::ustring& path, bool merge_xmp_sidecar);
|
||||
|
||||
void load() const;
|
||||
|
||||
Exiv2::ExifData& exifData();
|
||||
const Exiv2::ExifData& exifData() const;
|
||||
|
||||
Exiv2::IptcData& iptcData();
|
||||
const Exiv2::IptcData& iptcData() const;
|
||||
|
||||
Exiv2::XmpData& xmpData();
|
||||
const Exiv2::XmpData& xmpData() const;
|
||||
|
||||
const Glib::ustring& filename() const;
|
||||
const rtengine::procparams::ExifPairs& exif() const;
|
||||
const rtengine::procparams::IPTCPairs& iptc() const;
|
||||
void setExif(const rtengine::procparams::ExifPairs& exif);
|
||||
void setIptc(const rtengine::procparams::IPTCPairs& iptc);
|
||||
|
||||
void saveToImage(const Glib::ustring& path, bool preserve_all_tags) const;
|
||||
void saveToXmp(const Glib::ustring& path) const;
|
||||
|
||||
void setExifKeys(const std::vector<std::string> *keys);
|
||||
|
||||
void getDimensions(int &w, int &h) const;
|
||||
|
||||
Exiv2::ExifData getOutputExifData() const;
|
||||
|
||||
static Glib::ustring xmpSidecarPath(const Glib::ustring& path);
|
||||
static Exiv2::XmpData getXmpSidecar(const Glib::ustring& path);
|
||||
|
||||
static void init();
|
||||
static void cleanup();
|
||||
|
||||
private:
|
||||
void do_merge_xmp(Exiv2::Image* dst, bool keep_all) const;
|
||||
void import_exif_pairs(Exiv2::ExifData& out) const;
|
||||
void import_iptc_pairs(Exiv2::IptcData& out) const;
|
||||
void remove_unwanted(Exiv2::ExifData& dst) const;
|
||||
|
||||
Glib::ustring src_;
|
||||
bool merge_xmp_;
|
||||
mutable std::shared_ptr<Exiv2::Image> image_;
|
||||
std::unique_ptr<rtengine::procparams::ExifPairs> exif_;
|
||||
std::unique_ptr<rtengine::procparams::IPTCPairs> iptc_;
|
||||
Exiv2::ExifData exif_data_;
|
||||
Exiv2::IptcData iptc_data_;
|
||||
Exiv2::XmpData xmp_data_;
|
||||
|
||||
std::shared_ptr<std::unordered_set<std::string>> exif_keys_;
|
||||
|
||||
struct CacheVal {
|
||||
std::shared_ptr<Exiv2::Image> image;
|
||||
Glib::TimeVal image_mtime;
|
||||
Glib::TimeVal xmp_mtime;
|
||||
bool use_xmp;
|
||||
CacheVal(): image(nullptr), image_mtime(), xmp_mtime(), use_xmp(false) {}
|
||||
};
|
||||
//typedef std::pair<std::shared_ptr<Exiv2::Image>, Glib::TimeVal> CacheVal;
|
||||
typedef Cache<Glib::ustring, CacheVal> ImageCache;
|
||||
static std::unique_ptr<ImageCache> cache_;
|
||||
};
|
||||
|
||||
} // namespace rtengine
|
@ -297,7 +297,7 @@ PerspectiveCorrection::Params PerspectiveCorrection::autocompute(ImageSource *sr
|
||||
neutral.raw.bayersensor.method = RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::FAST);
|
||||
neutral.raw.xtranssensor.method = RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::FAST);
|
||||
neutral.icm.outputProfile = ColorManagementParams::NoICMString;
|
||||
src->getImage(src->getWB(), tr, img.get(), pp, neutral.toneCurve, neutral.raw, 0);
|
||||
src->getImage(src->getWB(), tr, img.get(), pp, neutral.toneCurve, neutral.raw);
|
||||
src->convertColorSpace(img.get(), pparams->icm, src->getWB());
|
||||
|
||||
neutral.commonTrans.autofill = false; // Ensures crop factor is correct.
|
||||
|
@ -61,9 +61,8 @@ PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext
|
||||
data = tpp->getImage8Data();
|
||||
}
|
||||
} else {
|
||||
rtengine::RawMetaDataLocation ri;
|
||||
eSensorType sensorType = rtengine::ST_NONE;
|
||||
tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, sensorType, width, height, 1, true, true);
|
||||
tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, sensorType, width, height, 1, true, true);
|
||||
|
||||
if (tpp) {
|
||||
data = tpp->getImage8Data();
|
||||
@ -121,7 +120,7 @@ PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext
|
||||
double contrastThresholdDummy = 0.0;
|
||||
rawImage.demosaic(params.raw, false, contrastThresholdDummy);
|
||||
Imagefloat image(fw, fh);
|
||||
rawImage.getImage (wb, TR_NONE, &image, pp, params.toneCurve, params.raw, 0);
|
||||
rawImage.getImage (wb, TR_NONE, &image, pp, params.toneCurve, params.raw);
|
||||
rtengine::Image8 output(fw, fh);
|
||||
rawImage.convertColorSpace(&image, params.icm, wb);
|
||||
#ifdef _OPENMP
|
||||
|
@ -232,6 +232,17 @@ void getFromKeyfile(
|
||||
}
|
||||
}
|
||||
|
||||
void getFromKeyfile(
|
||||
const Glib::KeyFile& keyfile,
|
||||
const Glib::ustring& group_name,
|
||||
const Glib::ustring& key,
|
||||
std::vector<std::string>& value
|
||||
)
|
||||
{
|
||||
auto tmpval = keyfile.get_string_list(group_name, key);
|
||||
value.assign(tmpval.begin(), tmpval.end());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool assignFromKeyfile(
|
||||
const Glib::KeyFile& keyfile,
|
||||
@ -360,6 +371,17 @@ void putToKeyfile(
|
||||
keyfile.set_double_list(group_name, key, list);
|
||||
}
|
||||
|
||||
void putToKeyfile(
|
||||
const Glib::ustring& group_name,
|
||||
const Glib::ustring& key,
|
||||
const std::vector<std::string>& value,
|
||||
Glib::KeyFile& keyfile
|
||||
)
|
||||
{
|
||||
const Glib::ArrayHandle<Glib::ustring> list = value;
|
||||
keyfile.set_string_list(group_name, key, list);
|
||||
}
|
||||
|
||||
void putToKeyfile(
|
||||
const Glib::ustring& group_name,
|
||||
const Glib::ustring& key,
|
||||
@ -411,7 +433,8 @@ bool saveToKeyfile(
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace rtengine
|
||||
{
|
||||
@ -5799,21 +5822,6 @@ Glib::ustring RAWParams::getFlatFieldBlurTypeString(FlatFieldBlurType type)
|
||||
}
|
||||
|
||||
|
||||
MetaDataParams::MetaDataParams():
|
||||
mode(MetaDataParams::TUNNEL)
|
||||
{
|
||||
}
|
||||
|
||||
bool MetaDataParams::operator==(const MetaDataParams &other) const
|
||||
{
|
||||
return mode == other.mode;
|
||||
}
|
||||
|
||||
bool MetaDataParams::operator!=(const MetaDataParams &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
FilmNegativeParams::FilmNegativeParams() :
|
||||
enabled(false),
|
||||
redRatio(1.36),
|
||||
@ -5866,6 +5874,96 @@ bool FilmNegativeParams::operator !=(const FilmNegativeParams& other) const
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
const std::map<std::string, std::string> exif_keys = {
|
||||
{"Copyright", "Exif.Image.Copyright"},
|
||||
{"Artist", "Exif.Image.Artist"},
|
||||
{"ImageDescription", "Exif.Image.ImageDescription"},
|
||||
{"Exif.UserComment", "Exif.Photo.UserComment"},
|
||||
{"ISOSpeed", "Exif.Photo.ISOSpeedRatings"},
|
||||
{"FNumber", "Exif.Photo.FNumber"},
|
||||
{"ShutterSpeed", "Exif.Photo.ExposureTime"},
|
||||
{"FocalLength", "Exif.Photo.FocalLength"},
|
||||
{"ExpComp", "Exif.Photo.ExposureBiasValue"},
|
||||
{"Flash", "Exif.Photo.Flash"},
|
||||
{"Make", "Exif.Image.Make"},
|
||||
{"Model", "Exif.Image.Model"},
|
||||
{"Lens", "Exif.Photo.LensModel"},
|
||||
{"DateTime", "Exif.Photo.DateTimeOriginal"},
|
||||
{"XResolution", "Exif.Image.XResolution"},
|
||||
{"YResolution", "Exif.Image.YResolution"}
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> iptc_keys = {
|
||||
{"Title", "Iptc.Application2.ObjectName"},
|
||||
{"Category", "Iptc.Application2.Category"},
|
||||
{"SupplementalCategories", "Iptc.Application2.SuppCategory"},
|
||||
{"Keywords", "Iptc.Application2.Keywords"},
|
||||
{"Instructions", "Iptc.Application2.SpecialInstructions"},
|
||||
{"DateCreated", "Iptc.Application2.DateCreated"},
|
||||
{"Creator", "Iptc.Application2.Byline"},
|
||||
{"CreatorJobTitle", "Iptc.Application2.BylineTitle"},
|
||||
{"City", "Iptc.Application2.City"},
|
||||
{"Province", "Iptc.Application2.ProvinceState"},
|
||||
{"Country", "Iptc.Application2.CountryName"},
|
||||
{"TransReference", "Iptc.Application2.TransmissionReference"},
|
||||
{"Headline", "Iptc.Application2.Headline"},
|
||||
{"Credit", "Iptc.Application2.Credit"},
|
||||
{"Source", "Iptc.Application2.Source"},
|
||||
{"Copyright", "Iptc.Application2.Copyright"},
|
||||
{"Caption", "Iptc.Application2.Caption"},
|
||||
{"CaptionWriter", "Iptc.Application2.Writer"}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
std::vector<std::string> MetaDataParams::basicExifKeys = {
|
||||
"Exif.Image.Copyright",
|
||||
"Exif.Image.Artist",
|
||||
"Exif.Image.ImageDescription",
|
||||
"Exif.Photo.UserComment",
|
||||
"Exif.Image.Make",
|
||||
"Exif.Image.Model",
|
||||
"Exif.Photo.LensModel",
|
||||
"Exif.Photo.FNumber",
|
||||
"Exif.Photo.ExposureTime",
|
||||
"Exif.Photo.FocalLength",
|
||||
"Exif.Photo.ISOSpeedRatings",
|
||||
"Exif.Photo.ExposureBiasValue",
|
||||
"Exif.Photo.Flash",
|
||||
"Exif.Photo.DateTimeOriginal",
|
||||
"Exif.Image.XResolution",
|
||||
"Exif.Image.YResolution"
|
||||
};
|
||||
|
||||
|
||||
MetaDataParams::MetaDataParams():
|
||||
mode(MetaDataParams::EDIT),
|
||||
exifKeys{},
|
||||
exif{},
|
||||
iptc{}
|
||||
{
|
||||
exifKeys = basicExifKeys;
|
||||
}
|
||||
|
||||
|
||||
bool MetaDataParams::operator==(const MetaDataParams &other) const
|
||||
{
|
||||
return mode == other.mode
|
||||
&& exifKeys == other.exifKeys
|
||||
&& exif == other.exif
|
||||
&& iptc == other.iptc;
|
||||
}
|
||||
|
||||
bool MetaDataParams::operator!=(const MetaDataParams &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
|
||||
ProcParams::ProcParams()
|
||||
{
|
||||
setDefaults();
|
||||
@ -5966,8 +6064,8 @@ void ProcParams::setDefaults()
|
||||
raw = {};
|
||||
|
||||
metadata = {};
|
||||
exif.clear();
|
||||
iptc.clear();
|
||||
//exif.clear();
|
||||
//iptc.clear();
|
||||
|
||||
// -1 means that there's no pp3 data with rank yet. In this case, the
|
||||
// embedded Rating metadata should take precedence. -1 should never be
|
||||
@ -5994,7 +6092,9 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
|
||||
keyFile.set_string("Version", "AppVersion", RTVERSION);
|
||||
keyFile.set_integer("Version", "Version", PPVERSION);
|
||||
|
||||
if (rank >= 0) {
|
||||
saveToKeyfile(!pedited || pedited->general.rank, "General", "Rank", rank, keyFile);
|
||||
}
|
||||
saveToKeyfile(!pedited || pedited->general.colorlabel, "General", "ColorLabel", colorlabel, keyFile);
|
||||
saveToKeyfile(!pedited || pedited->general.intrash, "General", "InTrash", inTrash, keyFile);
|
||||
|
||||
@ -7669,6 +7769,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
|
||||
|
||||
// MetaData
|
||||
saveToKeyfile(!pedited || pedited->metadata.mode, "MetaData", "Mode", metadata.mode, keyFile);
|
||||
saveToKeyfile(!pedited || pedited->metadata.exifKeys, "MetaData", "ExifKeys", metadata.exifKeys, keyFile);
|
||||
|
||||
// Film negative
|
||||
saveToKeyfile(!pedited || pedited->filmNegative.enabled, "Film Negative", "Enabled", filmNegative.enabled, keyFile);
|
||||
@ -7696,16 +7797,30 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
|
||||
|
||||
// EXIF change list
|
||||
if (!pedited || pedited->exif) {
|
||||
for (ExifPairs::const_iterator i = exif.begin(); i != exif.end(); ++i) {
|
||||
keyFile.set_string("Exif", i->first, i->second);
|
||||
std::map<Glib::ustring, Glib::ustring> m;
|
||||
for (auto &p : exif_keys) {
|
||||
m[p.second] = p.first;
|
||||
}
|
||||
for (auto &p : metadata.exif) {
|
||||
auto it = m.find(p.first);
|
||||
if (it != m.end()) {
|
||||
keyFile.set_string("Exif", it->second, p.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IPTC change list
|
||||
if (!pedited || pedited->iptc) {
|
||||
for (IPTCPairs::const_iterator i = iptc.begin(); i != iptc.end(); ++i) {
|
||||
Glib::ArrayHandle<Glib::ustring> values = i->second;
|
||||
keyFile.set_string_list("IPTC", i->first, values);
|
||||
std::map<std::string, std::string> m;
|
||||
for (auto &p : iptc_keys) {
|
||||
m[p.second] = p.first;
|
||||
}
|
||||
for (auto &p : metadata.iptc) {
|
||||
auto it = m.find(p.first);
|
||||
if (it != m.end()) {
|
||||
Glib::ArrayHandle<Glib::ustring> values = p.second;
|
||||
keyFile.set_string_list("IPTC", it->second, values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10562,23 +10677,28 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
|
||||
}
|
||||
|
||||
if (keyFile.has_group("MetaData")) {
|
||||
int mode = int(MetaDataParams::TUNNEL);
|
||||
int mode = int(MetaDataParams::EDIT);
|
||||
assignFromKeyfile(keyFile, "MetaData", "Mode", pedited, mode, pedited->metadata.mode);
|
||||
|
||||
if (mode >= int(MetaDataParams::TUNNEL) && mode <= int(MetaDataParams::STRIP)) {
|
||||
metadata.mode = static_cast<MetaDataParams::Mode>(mode);
|
||||
}
|
||||
|
||||
assignFromKeyfile(keyFile, "MetaData", "ExifKeys", pedited, metadata.exifKeys, pedited->metadata.exifKeys);
|
||||
}
|
||||
|
||||
if (keyFile.has_group("Exif")) {
|
||||
for (const auto& key : keyFile.get_keys("Exif")) {
|
||||
exif[key] = keyFile.get_string("Exif", key);
|
||||
auto it = exif_keys.find(key);
|
||||
if (it != exif_keys.end()) {
|
||||
metadata.exif[it->second] = keyFile.get_string("Exif", key);
|
||||
|
||||
if (pedited) {
|
||||
pedited->exif = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Load iptc change settings
|
||||
@ -10595,16 +10715,22 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
|
||||
if (keyFile.has_group("IPTC")) {
|
||||
for (const auto& key : keyFile.get_keys("IPTC")) {
|
||||
// does this key already exist?
|
||||
const IPTCPairs::iterator element = iptc.find(key);
|
||||
auto it = iptc_keys.find(key);
|
||||
if (it == iptc_keys.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element != iptc.end()) {
|
||||
auto kk = it->second;
|
||||
const IPTCPairs::iterator element = metadata.iptc.find(kk);
|
||||
|
||||
if (element != metadata.iptc.end()) {
|
||||
// it already exist so we cleanup the values
|
||||
element->second.clear();
|
||||
}
|
||||
|
||||
// TODO: look out if merging Keywords and SupplementalCategories from the procparams chain would be interesting
|
||||
for (const auto& currLoadedTagValue : keyFile.get_string_list("IPTC", key)) {
|
||||
iptc[key].push_back(currLoadedTagValue);
|
||||
metadata.iptc[kk].push_back(currLoadedTagValue);
|
||||
}
|
||||
|
||||
if (pedited) {
|
||||
@ -10684,8 +10810,6 @@ bool ProcParams::operator ==(const ProcParams& other) const
|
||||
&& rgbCurves == other.rgbCurves
|
||||
&& colorToning == other.colorToning
|
||||
&& metadata == other.metadata
|
||||
&& exif == other.exif
|
||||
&& iptc == other.iptc
|
||||
&& dehaze == other.dehaze
|
||||
&& filmNegative == other.filmNegative;
|
||||
}
|
||||
|
@ -1993,31 +1993,22 @@ struct ColorManagementParams {
|
||||
bool operator !=(const ColorManagementParams& other) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parameters for metadata handling
|
||||
*/
|
||||
struct MetaDataParams {
|
||||
enum Mode {
|
||||
TUNNEL,
|
||||
EDIT,
|
||||
STRIP
|
||||
};
|
||||
Mode mode;
|
||||
|
||||
MetaDataParams();
|
||||
|
||||
bool operator ==(const MetaDataParams &other) const;
|
||||
bool operator !=(const MetaDataParams &other) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Minimal wrapper allowing forward declaration for representing a key/value for the exif metadata information
|
||||
*/
|
||||
class ExifPairs final
|
||||
{
|
||||
private:
|
||||
using Pairs = std::map<Glib::ustring, Glib::ustring>;
|
||||
|
||||
public:
|
||||
using const_iterator = std::map<Glib::ustring, Glib::ustring>::const_iterator;
|
||||
using const_iterator = Pairs::const_iterator;
|
||||
using size_type = Pairs::size_type;
|
||||
|
||||
const_iterator find(const Glib::ustring& key) const
|
||||
{
|
||||
return pairs.find(key);
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
@ -2034,6 +2025,16 @@ public:
|
||||
pairs.clear();
|
||||
}
|
||||
|
||||
size_type erase(const Glib::ustring& key)
|
||||
{
|
||||
return pairs.erase(key);
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
{
|
||||
return pairs.empty();
|
||||
}
|
||||
|
||||
Glib::ustring& operator[](const Glib::ustring& key)
|
||||
{
|
||||
return pairs[key];
|
||||
@ -2045,7 +2046,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<Glib::ustring, Glib::ustring> pairs;
|
||||
Pairs pairs;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -2077,6 +2078,11 @@ public:
|
||||
return pairs.empty();
|
||||
}
|
||||
|
||||
iterator erase(const const_iterator& key)
|
||||
{
|
||||
return pairs.erase(key);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
pairs.clear();
|
||||
@ -2096,6 +2102,29 @@ private:
|
||||
std::map<Glib::ustring, std::vector<Glib::ustring>> pairs;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parameters for metadata handling
|
||||
*/
|
||||
struct MetaDataParams {
|
||||
enum Mode {
|
||||
TUNNEL,
|
||||
EDIT,
|
||||
STRIP
|
||||
};
|
||||
Mode mode;
|
||||
std::vector<std::string> exifKeys;
|
||||
ExifPairs exif;
|
||||
IPTCPairs iptc;
|
||||
|
||||
MetaDataParams();
|
||||
|
||||
bool operator ==(const MetaDataParams &other) const;
|
||||
bool operator !=(const MetaDataParams &other) const;
|
||||
|
||||
static std::vector<std::string> basicExifKeys;
|
||||
};
|
||||
|
||||
|
||||
struct WaveletParams {
|
||||
std::vector<double> ccwcurve;
|
||||
std::vector<double> wavdenoise;
|
||||
@ -2614,8 +2643,8 @@ public:
|
||||
int ppVersion; ///< Version of the PP file from which the parameters have been read
|
||||
|
||||
MetaDataParams metadata; ///< Metadata parameters
|
||||
ExifPairs exif; ///< List of modifications appplied on the exif tags of the input image
|
||||
IPTCPairs iptc; ///< The IPTC tags and values to be saved to the output image
|
||||
// ExifPairs exif; ///< List of modifications appplied on the exif tags of the input image
|
||||
// IPTCPairs iptc; ///< The IPTC tags and values to be saved to the output image
|
||||
|
||||
/**
|
||||
* The constructor only sets the hand-wired defaults.
|
||||
|
@ -741,11 +741,11 @@ void RawImageSource::getWBMults(const ColorTemp &ctemp, const RAWParams &raw, st
|
||||
autoGainComp = camInitialGain / initialGain;
|
||||
}
|
||||
|
||||
void RawImageSource::getImage(const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const RAWParams &raw, int opposed)
|
||||
void RawImageSource::getImage(const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const RAWParams &raw)
|
||||
{
|
||||
// added int opposed to force getimage to use inpaint-opposed if enable, only once
|
||||
MyMutex::MyLock lock(getImageMutex);
|
||||
tran = defTransform(tran);
|
||||
|
||||
tran = defTransform(ri, tran);
|
||||
|
||||
// compute channel multipliers
|
||||
double r, g, b;
|
||||
@ -849,10 +849,6 @@ void RawImageSource::getImage(const ColorTemp &ctemp, int tran, Imagefloat* imag
|
||||
bool doHr = (hrp.hrenabled && !iscolor);
|
||||
|
||||
if (hrp.hrenabled && iscolor) {
|
||||
if(hrp.method == "Coloropp" && opposed == 1) {//force Inpaint opposed if WB change, and opposed limited the number to 1
|
||||
rgbSourceModified = false;
|
||||
}
|
||||
|
||||
if (!rgbSourceModified) {
|
||||
if (hrp.method == "Color") {
|
||||
if (settings->verbose) {
|
||||
@ -1101,8 +1097,22 @@ void RawImageSource::convertColorSpace(Imagefloat* image, const ColorManagementP
|
||||
|
||||
void RawImageSource::getFullSize(int& w, int& h, int tr)
|
||||
{
|
||||
computeFullSize(ri, tr, w, h, border);
|
||||
}
|
||||
|
||||
tr = defTransform(tr);
|
||||
|
||||
void RawImageSource::computeFullSize(const RawImage *ri, int tr, int &w, int &h, int border)
|
||||
{
|
||||
tr = defTransform(ri, tr);
|
||||
|
||||
const int W = ri->get_width();
|
||||
const int H = ri->get_height();
|
||||
const bool fuji = ri->get_FujiWidth() != 0;
|
||||
const bool d1x = !ri->get_model().compare("D1X");
|
||||
const int b =
|
||||
border >= 0 ? border :
|
||||
(ri->getSensorType() == ST_BAYER ? 4 :
|
||||
(ri->getSensorType() == ST_FUJI_XTRANS ? 7 : 0));
|
||||
|
||||
if (fuji) {
|
||||
w = ri->get_FujiWidth() * 2 + 1;
|
||||
@ -1121,8 +1131,8 @@ void RawImageSource::getFullSize(int& w, int& h, int tr)
|
||||
h = tmp;
|
||||
}
|
||||
|
||||
w -= 2 * border;
|
||||
h -= 2 * border;
|
||||
w -= 2 * b;
|
||||
h -= 2 * b;
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
@ -1353,9 +1363,13 @@ int RawImageSource::load(const Glib::ustring &fname, bool firstFrameOnly)
|
||||
|
||||
|
||||
// Load complete Exif information
|
||||
std::unique_ptr<RawMetaDataLocation> rml(new RawMetaDataLocation(ri->get_exifBase(), ri->get_ciffBase(), ri->get_ciffLen()));
|
||||
idata = new FramesData(fname, std::move(rml));
|
||||
idata = new FramesData(fname); // TODO: std::unique_ptr<>
|
||||
idata->setDCRawFrameCount(numFrames);
|
||||
{
|
||||
int ww, hh;
|
||||
getFullSize(ww, hh);
|
||||
idata->setDimensions(ww, hh);
|
||||
}
|
||||
|
||||
green(W, H);
|
||||
red(W, H);
|
||||
@ -2847,7 +2861,7 @@ void RawImageSource::scaleColors(int winx, int winy, int winw, int winh, const R
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
int RawImageSource::defTransform(int tran)
|
||||
int RawImageSource::defTransform(const RawImage *ri, int tran)
|
||||
{
|
||||
|
||||
int deg = ri->get_rotateDegree();
|
||||
@ -8125,7 +8139,7 @@ ColorTemp RawImageSource::getSpotWB(std::vector<Coord2D> &red, std::vector<Coord
|
||||
void RawImageSource::transformPosition(int x, int y, int tran, int& ttx, int& tty)
|
||||
{
|
||||
|
||||
tran = defTransform(tran);
|
||||
tran = defTransform(ri, tran);
|
||||
|
||||
x += border;
|
||||
y += border;
|
||||
|
@ -47,7 +47,7 @@ private:
|
||||
static LUTf invGrad; // for fast_demosaic
|
||||
static LUTf initInvGrad ();
|
||||
static void colorSpaceConversion_ (Imagefloat* im, const procparams::ColorManagementParams& cmp, const ColorTemp &wb, double pre_mul[3], cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], const std::string &camName);
|
||||
int defTransform (int tran);
|
||||
static int defTransform (const RawImage *ri, int tran);
|
||||
|
||||
protected:
|
||||
MyMutex getImageMutex; // locks getImage
|
||||
@ -146,7 +146,7 @@ public:
|
||||
void getrgbloc(int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, const procparams::WBParams & wbpar) override;
|
||||
|
||||
void getWBMults (const ColorTemp &ctemp, const procparams::RAWParams &raw, std::array<float, 4>& scale_mul, float &autoGainComp, float &rm, float &gm, float &bm) const override;
|
||||
void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hrp, const procparams::RAWParams &raw, int opposed) override;
|
||||
void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hrp, const procparams::RAWParams &raw) override;
|
||||
eSensorType getSensorType () const override;
|
||||
bool isMono () const override;
|
||||
ColorTemp getWB () const override
|
||||
@ -232,6 +232,8 @@ public:
|
||||
virtual float operator()(int row) const { return 1.f; }
|
||||
};
|
||||
|
||||
static void computeFullSize(const RawImage *ri, int tr, int &w, int &h, int border=-1);
|
||||
|
||||
protected:
|
||||
typedef unsigned short ushort;
|
||||
void processFalseColorCorrection(Imagefloat* i, const int steps);
|
||||
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee 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.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace rtengine
|
||||
{
|
||||
|
||||
class RawMetaDataLocation {
|
||||
|
||||
public:
|
||||
int exifBase;
|
||||
int ciffBase;
|
||||
int ciffLength;
|
||||
|
||||
RawMetaDataLocation () : exifBase(-1), ciffBase(-1), ciffLength(-1) {}
|
||||
explicit RawMetaDataLocation (int exifBase) : exifBase(exifBase), ciffBase(-1), ciffLength(-1) {}
|
||||
RawMetaDataLocation (int ciffBase, int ciffLength) : exifBase(-1), ciffBase(ciffBase), ciffLength(ciffLength) {}
|
||||
RawMetaDataLocation (int exifBase, int ciffBase, int ciffLength) : exifBase(exifBase), ciffBase(ciffBase), ciffLength(ciffLength) {}
|
||||
};
|
||||
|
||||
}
|
@ -64,9 +64,9 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
|
||||
DARKFRAME, // EvLCPUseVign,
|
||||
HDR, // EvLCPUseCA,
|
||||
M_VOID, // EvFixedExp
|
||||
ALLNORAW, // EvWBMethod,
|
||||
ALLNORAW, // EvWBTemp,
|
||||
ALLNORAW, // EvWBGreen,
|
||||
WB, // EvWBMethod,
|
||||
WB, // EvWBTemp,
|
||||
WB, // EvWBGreen,
|
||||
AUTOEXP, // EvToneCurveMode1,
|
||||
AUTOEXP, // EvToneCurve2,
|
||||
AUTOEXP, // EvToneCurveMode2,
|
||||
@ -234,7 +234,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
|
||||
LUMINANCECURVE, // EvCATbadpix
|
||||
LUMINANCECURVE, // EvCATAutoadap
|
||||
DEFRINGE, // EvPFCurve
|
||||
ALLNORAW, // EvWBequal
|
||||
WB, // EvWBequal
|
||||
0, // EvWBequalbo : obsolete
|
||||
HDR, // EvGradientDegree
|
||||
HDR, // EvGradientEnabled
|
||||
@ -470,7 +470,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
|
||||
RETINEX, // EvRetinexgaintransmission
|
||||
RETINEX, // EvLskal
|
||||
OUTPUTPROFILE, // EvOBPCompens
|
||||
ALLNORAW, // EvWBtempBias
|
||||
WB, // EvWBtempBias
|
||||
DARKFRAME, // EvRawImageNum
|
||||
0, // unused
|
||||
0, // unused
|
||||
@ -517,7 +517,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
|
||||
ALLNORAW, // EvTMFattalEnabled
|
||||
HDR, // EvTMFattalThreshold
|
||||
HDR, // EvTMFattalAmount
|
||||
ALLNORAW, // EvWBEnabled
|
||||
WB, // EvWBEnabled
|
||||
AUTOEXP, // EvRGBEnabled
|
||||
LUMINANCECURVE, // EvLEnabled
|
||||
DEMOSAIC, // EvPdShrEnabled
|
||||
|
@ -23,17 +23,18 @@
|
||||
#include "procevents.h"
|
||||
|
||||
// Use M_VOID if you wish to update the proc params without updating the preview at all !
|
||||
#define M_VOID (1<<17)
|
||||
#define M_VOID (1<<20)
|
||||
// Use M_MINUPDATE if you wish to update the preview without modifying the image (think about it like a "refreshPreview")
|
||||
// Must NOT be used with other event (i.e. will be used for MINUPDATE only)
|
||||
#define M_MINUPDATE (1<<16)
|
||||
#define M_MINUPDATE (1<<19)
|
||||
// Force high quality
|
||||
#define M_HIGHQUAL (1<<15)
|
||||
#define M_HIGHQUAL (1<<18)
|
||||
|
||||
// Elementary functions that can be done to
|
||||
// the preview image when an event occurs
|
||||
#define M_SPOT (1<<19)
|
||||
#define M_CSHARP (1<<18)
|
||||
#define M_WB (1<<17)
|
||||
#define M_SPOT (1<<16)
|
||||
#define M_CSHARP (1<<15)
|
||||
#define M_MONITOR (1<<14)
|
||||
#define M_RETINEX (1<<13)
|
||||
#define M_CROP (1<<12)
|
||||
@ -57,6 +58,7 @@
|
||||
#define DARKFRAME (M_PREPROC|M_RAW|M_INIT|M_SPOT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
|
||||
#define FLATFIELD (M_PREPROC|M_RAW|M_INIT|M_SPOT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
|
||||
#define DEMOSAIC (M_RAW|M_INIT|M_SPOT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
|
||||
#define WB (M_WB|M_INIT|M_SPOT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
|
||||
#define ALLNORAW (M_INIT|M_SPOT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
|
||||
#define CAPTURESHARPEN (M_INIT|M_SPOT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR|M_CSHARP)
|
||||
#define HDR (M_SPOT|M_LINDENOISE|M_HDR|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
/* -*- C++ -*-
|
||||
*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
@ -30,7 +31,6 @@
|
||||
#include "iimage.h"
|
||||
#include "imageformat.h"
|
||||
#include "procevents.h"
|
||||
#include "rawmetadatalocation.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include "../rtgui/threadutils.h"
|
||||
@ -51,12 +51,6 @@ class LUT;
|
||||
using LUTu = LUT<uint32_t>;
|
||||
|
||||
class EditDataProvider;
|
||||
namespace rtexif
|
||||
{
|
||||
|
||||
class TagDirectory;
|
||||
|
||||
}
|
||||
|
||||
namespace rtengine
|
||||
{
|
||||
@ -91,78 +85,56 @@ class FramesMetaData
|
||||
{
|
||||
|
||||
public:
|
||||
/** @return Returns the number of root Metadata */
|
||||
virtual unsigned int getRootCount () const = 0;
|
||||
/** @return Returns the number of frame contained in the file based on Metadata */
|
||||
virtual unsigned int getFrameCount () const = 0;
|
||||
virtual unsigned int getFrameCount() const = 0;
|
||||
|
||||
/** Checks the availability of exif metadata tags.
|
||||
* @return Returns true if image contains exif metadata tags */
|
||||
virtual bool hasExif (unsigned int frame = 0) const = 0;
|
||||
/** Returns the directory of exif metadata tags.
|
||||
* @param root root number in the metadata tree
|
||||
* @return The directory of exif metadata tags */
|
||||
virtual rtexif::TagDirectory* getRootExifData (unsigned int root = 0) const = 0;
|
||||
/** Returns the directory of exif metadata tags.
|
||||
* @param frame frame number in the metadata tree
|
||||
* @return The directory of exif metadata tags */
|
||||
virtual rtexif::TagDirectory* getFrameExifData (unsigned int frame = 0) const = 0;
|
||||
/** Returns the directory of exif metadata tags containing at least the 'Make' tag for the requested frame.
|
||||
* If no usable metadata exist in the frame, send back the best TagDirectory describing the frame content.
|
||||
* @param imgSource rawimage that we want the metadata from
|
||||
* @param rawParams RawParams to select the frame number
|
||||
* @return The directory of exif metadata tags containing at least the 'Make' tag */
|
||||
virtual rtexif::TagDirectory* getBestExifData (ImageSource *imgSource, procparams::RAWParams *rawParams) const = 0;
|
||||
/** Checks the availability of IPTC tags.
|
||||
* @return Returns true if image contains IPTC tags */
|
||||
virtual bool hasIPTC (unsigned int frame = 0) const = 0;
|
||||
/** Returns the directory of IPTC tags.
|
||||
* @return The directory of IPTC tags */
|
||||
virtual procparams::IPTCPairs getIPTCData (unsigned int frame = 0) const = 0;
|
||||
virtual bool hasExif() const = 0;
|
||||
/** @return a struct containing the date and time of the image */
|
||||
virtual tm getDateTime (unsigned int frame = 0) const = 0;
|
||||
virtual tm getDateTime() const = 0;
|
||||
/** @return a timestamp containing the date and time of the image */
|
||||
virtual time_t getDateTimeAsTS(unsigned int frame = 0) const = 0;
|
||||
virtual time_t getDateTimeAsTS() const = 0;
|
||||
/** @return the ISO of the image */
|
||||
virtual int getISOSpeed (unsigned int frame = 0) const = 0;
|
||||
virtual int getISOSpeed() const = 0;
|
||||
/** @return the F number of the image */
|
||||
virtual double getFNumber (unsigned int frame = 0) const = 0;
|
||||
virtual double getFNumber() const = 0;
|
||||
/** @return the focal length used at the exposure */
|
||||
virtual double getFocalLen (unsigned int frame = 0) const = 0;
|
||||
virtual double getFocalLen() const = 0;
|
||||
/** @return the focal length in 35mm used at the exposure */
|
||||
virtual double getFocalLen35mm (unsigned int frame = 0) const = 0;
|
||||
virtual double getFocalLen35mm() const = 0;
|
||||
/** @return the focus distance in meters, 0=unknown, 10000=infinity */
|
||||
virtual float getFocusDist (unsigned int frame = 0) const = 0;
|
||||
virtual float getFocusDist() const = 0;
|
||||
/** @return the shutter speed */
|
||||
virtual double getShutterSpeed (unsigned int frame = 0) const = 0;
|
||||
virtual double getShutterSpeed() const = 0;
|
||||
/** @return the exposure compensation */
|
||||
virtual double getExpComp (unsigned int frame = 0) const = 0;
|
||||
virtual double getExpComp() const = 0;
|
||||
/** @return the maker of the camera */
|
||||
virtual std::string getMake (unsigned int frame = 0) const = 0;
|
||||
virtual std::string getMake() const = 0;
|
||||
/** @return the model of the camera */
|
||||
virtual std::string getModel (unsigned int frame = 0) const = 0;
|
||||
virtual std::string getModel() const = 0;
|
||||
|
||||
std::string getCamera (unsigned int frame = 0) const
|
||||
std::string getCamera() const
|
||||
{
|
||||
return getMake(frame) + " " + getModel(frame);
|
||||
return getMake() + " " + getModel();
|
||||
}
|
||||
|
||||
/** @return the lens on the camera */
|
||||
virtual std::string getLens (unsigned int frame = 0) const = 0;
|
||||
virtual std::string getLens() const = 0;
|
||||
/** @return the orientation of the image */
|
||||
virtual std::string getOrientation (unsigned int frame = 0) const = 0;
|
||||
virtual std::string getOrientation() const = 0;
|
||||
/** @return the rating of the image */
|
||||
virtual int getRating (unsigned int frame = 0) const = 0;
|
||||
virtual int getRating() const = 0;
|
||||
|
||||
/** @return true if the file is a PixelShift shot (Pentax and Sony bodies) */
|
||||
virtual bool getPixelShift () const = 0;
|
||||
/** @return false: not an HDR file ; true: single or multi-frame HDR file (e.g. Pentax HDR raw file or 32 bit float DNG file or Log compressed) */
|
||||
virtual bool getHDR (unsigned int frame = 0) const = 0;
|
||||
virtual bool getHDR() const = 0;
|
||||
|
||||
/** @return false: not an HDR file ; true: single or multi-frame HDR file (e.g. Pentax HDR raw file or 32 bit float DNG file or Log compressed) */
|
||||
virtual std::string getImageType (unsigned int frame) const = 0;
|
||||
virtual std::string getImageType() const = 0;
|
||||
/** @return the sample format based on MetaData */
|
||||
virtual IIOSampleFormat getSampleFormat (unsigned int frame = 0) const = 0;
|
||||
virtual IIOSampleFormat getSampleFormat() const = 0;
|
||||
|
||||
/** Functions to convert between floating point and string representation of shutter and aperture */
|
||||
static std::string apertureToString (double aperture);
|
||||
@ -183,7 +155,10 @@ public:
|
||||
* Use it only for raw files. In caseof jpgs and tiffs pass a NULL pointer.
|
||||
* @param firstFrameOnly must be true to get the MetaData of the first frame only, e.g. for a PixelShift file.
|
||||
* @return The metadata */
|
||||
static FramesMetaData* fromFile (const Glib::ustring& fname, std::unique_ptr<RawMetaDataLocation> rml, bool firstFrameOnly = false);
|
||||
static FramesMetaData* fromFile(const Glib::ustring& fname);
|
||||
|
||||
virtual Glib::ustring getFileName() const = 0;
|
||||
virtual void getDimensions(int &w, int &h) const = 0;
|
||||
};
|
||||
|
||||
/** This listener interface is used to indicate the progress of time consuming operations */
|
||||
|
@ -324,7 +324,7 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h,
|
||||
|
||||
namespace {
|
||||
|
||||
Image8 *load_inspector_mode(const Glib::ustring &fname, RawMetaDataLocation &rml, eSensorType &sensorType, int &w, int &h)
|
||||
Image8 *load_inspector_mode(const Glib::ustring &fname, eSensorType &sensorType, int &w, int &h)
|
||||
{
|
||||
BENCHFUN
|
||||
|
||||
@ -350,7 +350,7 @@ Image8 *load_inspector_mode(const Glib::ustring &fname, RawMetaDataLocation &rml
|
||||
PreviewProps pp(0, 0, w, h, 1);
|
||||
|
||||
Imagefloat tmp(w, h);
|
||||
src.getImage(src.getWB(), TR_NONE, &tmp, pp, neutral.toneCurve, neutral.raw, 0);
|
||||
src.getImage(src.getWB(), TR_NONE, &tmp, pp, neutral.toneCurve, neutral.raw);
|
||||
src.convertColorSpace(&tmp, neutral.icm, src.getWB());
|
||||
|
||||
Image8 *img = new Image8(w, h);
|
||||
@ -380,7 +380,7 @@ Image8 *load_inspector_mode(const Glib::ustring &fname, RawMetaDataLocation &rml
|
||||
|
||||
} // namespace
|
||||
|
||||
Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, bool rotate, bool inspectorMode, bool forHistogramMatching)
|
||||
Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, eSensorType &sensorType, int &w, int &h, int fixwh, bool rotate, bool inspectorMode, bool forHistogramMatching)
|
||||
{
|
||||
Thumbnail* tpp = new Thumbnail ();
|
||||
tpp->isRaw = 1;
|
||||
@ -390,7 +390,7 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL
|
||||
tpp->colorMatrix[2][2] = 1.0;
|
||||
|
||||
if (inspectorMode && !forHistogramMatching && settings->thumbnail_inspector_mode == Settings::ThumbnailInspectorMode::RAW) {
|
||||
Image8 *img = load_inspector_mode(fname, rml, sensorType, w, h);
|
||||
Image8 *img = load_inspector_mode(fname, sensorType, w, h);
|
||||
if (!img) {
|
||||
delete tpp;
|
||||
return nullptr;
|
||||
@ -415,10 +415,6 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL
|
||||
|
||||
sensorType = ri->getSensorType();
|
||||
|
||||
rml.exifBase = ri->get_exifBase();
|
||||
rml.ciffBase = ri->get_ciffBase();
|
||||
rml.ciffLength = ri->get_ciffLen();
|
||||
|
||||
Image8* img = new Image8 ();
|
||||
// No sample format detection occurred earlier, so we set them here,
|
||||
// as they are mandatory for the setScanline method
|
||||
@ -459,7 +455,7 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL
|
||||
delete img;
|
||||
delete ri;
|
||||
|
||||
img = load_inspector_mode(fname, rml, sensorType, w, h);
|
||||
img = load_inspector_mode(fname, sensorType, w, h);
|
||||
if (!img) {
|
||||
delete tpp;
|
||||
return nullptr;
|
||||
@ -523,28 +519,7 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL
|
||||
#define FISGREEN(filter,row,col) \
|
||||
((filter >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==1 || !filter)
|
||||
|
||||
RawMetaDataLocation Thumbnail::loadMetaDataFromRaw (const Glib::ustring& fname)
|
||||
{
|
||||
RawMetaDataLocation rml;
|
||||
rml.exifBase = -1;
|
||||
rml.ciffBase = -1;
|
||||
rml.ciffLength = -1;
|
||||
|
||||
RawImage ri (fname);
|
||||
unsigned int imageNum = 0;
|
||||
|
||||
int r = ri.loadRaw (false, imageNum);
|
||||
|
||||
if ( !r ) {
|
||||
rml.exifBase = ri.get_exifBase();
|
||||
rml.ciffBase = ri.get_ciffBase();
|
||||
rml.ciffLength = ri.get_ciffLen();
|
||||
}
|
||||
|
||||
return rml;
|
||||
}
|
||||
|
||||
Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, StandardObserver wbObserver, bool rotate, bool forHistogramMatching)
|
||||
Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, StandardObserver wbObserver, bool rotate, bool forHistogramMatching)
|
||||
{
|
||||
RawImage *ri = new RawImage (fname);
|
||||
unsigned int tempImageNum = 0;
|
||||
@ -593,10 +568,6 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati
|
||||
|
||||
ri->pre_interpolate();
|
||||
|
||||
rml.exifBase = ri->get_exifBase();
|
||||
rml.ciffBase = ri->get_ciffBase();
|
||||
rml.ciffLength = ri->get_ciffLen();
|
||||
|
||||
tpp->camwbRed = tpp->redMultiplier / pre_mul[0]; //ri->get_pre_mul(0);
|
||||
tpp->camwbGreen = tpp->greenMultiplier / pre_mul[1]; //ri->get_pre_mul(1);
|
||||
tpp->camwbBlue = tpp->blueMultiplier / pre_mul[2]; //ri->get_pre_mul(2);
|
||||
@ -999,6 +970,9 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati
|
||||
}
|
||||
|
||||
tpp->init();
|
||||
|
||||
RawImageSource::computeFullSize(ri, TR_NONE, tpp->full_width, tpp->full_height);
|
||||
|
||||
delete ri;
|
||||
return tpp;
|
||||
}
|
||||
@ -1056,7 +1030,9 @@ Thumbnail::Thumbnail () :
|
||||
gammaCorrected (false),
|
||||
colorMatrix{},
|
||||
scaleGain (1.0),
|
||||
isRaw (true)
|
||||
isRaw (true),
|
||||
full_width(-1),
|
||||
full_height(-1)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1109,19 +1085,11 @@ IImage8* Thumbnail::quickProcessImage (const procparams::ProcParams& params, int
|
||||
// Full thumbnail processing, second stage if complete profile exists
|
||||
IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorType sensorType, int rheight, TypeInterpolation interp, const FramesMetaData *metadata, double& myscale, bool forMonitor, bool forHistogramMatching)
|
||||
{
|
||||
unsigned int imgNum = 0;
|
||||
if (isRaw) {
|
||||
if (sensorType == ST_BAYER) {
|
||||
imgNum = rtengine::LIM<unsigned int>(params.raw.bayersensor.imageNum, 0, metadata->getFrameCount() - 1);
|
||||
} else if (sensorType == ST_FUJI_XTRANS) {
|
||||
//imgNum = rtengine::LIM<unsigned int>(params.raw.xtranssensor.imageNum, 0, metadata->getFrameCount() - 1)
|
||||
}
|
||||
}
|
||||
std::string camName = metadata->getCamera(imgNum);
|
||||
float shutter = metadata->getShutterSpeed(imgNum);
|
||||
float fnumber = metadata->getFNumber(imgNum);
|
||||
float iso = metadata->getISOSpeed(imgNum);
|
||||
float fcomp = metadata->getExpComp(imgNum);
|
||||
const std::string camName = metadata->getCamera();
|
||||
const float shutter = metadata->getShutterSpeed();
|
||||
const float fnumber = metadata->getFNumber();
|
||||
const float iso = metadata->getISOSpeed();
|
||||
const float fcomp = metadata->getExpComp();
|
||||
|
||||
// check if the WB's equalizer, temperature bias, or observer value has changed
|
||||
if (wbEqual < (params.wb.equal - 5e-4) || wbEqual > (params.wb.equal + 5e-4) || wbTempBias < (params.wb.tempBias - 5e-4) || wbTempBias > (params.wb.tempBias + 5e-4) || wbObserver != params.wb.observer) {
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "image8.h"
|
||||
#include "imagefloat.h"
|
||||
#include "LUT.h"
|
||||
#include "rawmetadatalocation.h"
|
||||
|
||||
#include "../rtgui/threadutils.h"
|
||||
|
||||
@ -86,6 +85,8 @@ class Thumbnail
|
||||
public:
|
||||
|
||||
bool isRaw;
|
||||
int full_width;
|
||||
int full_height;
|
||||
|
||||
~Thumbnail ();
|
||||
Thumbnail ();
|
||||
@ -97,10 +98,9 @@ public:
|
||||
int getImageWidth (const procparams::ProcParams& pparams, int rheight, float &ratio);
|
||||
void getDimensions (int& w, int& h, double& scaleFac);
|
||||
|
||||
static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, bool rotate, bool inspectorMode = false, bool forHistogramMatching = false);
|
||||
static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, StandardObserver wbObserver, bool rotate, bool forHistogramMatching = false);
|
||||
static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, eSensorType &sensorType, int &w, int &h, int fixwh, bool rotate, bool inspectorMode = false, bool forHistogramMatching = false);
|
||||
static Thumbnail* loadFromRaw (const Glib::ustring& fname, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, StandardObserver wbObserver, bool rotate, bool forHistogramMatching=false);
|
||||
static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, StandardObserver wbObserver, bool inspectorMode = false);
|
||||
static RawMetaDataLocation loadMetaDataFromRaw (const Glib::ustring& fname);
|
||||
|
||||
void getCamWB (double& temp, double& green, StandardObserver observer);
|
||||
void getAutoWB (double& temp, double& green, double equal, double tempBias, StandardObserver observer);
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
/* -*- C++ -*-
|
||||
*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
@ -112,6 +113,19 @@ public:
|
||||
};
|
||||
ThumbnailInspectorMode thumbnail_inspector_mode;
|
||||
|
||||
enum class XmpSidecarStyle {
|
||||
STD, // FILENAME.xmp for FILENAME.ext
|
||||
EXT // FILENAME.ext.xmp for FILENAME.ext
|
||||
};
|
||||
XmpSidecarStyle xmp_sidecar_style;
|
||||
|
||||
enum class MetadataXmpSync {
|
||||
NONE,
|
||||
READ,
|
||||
READ_WRITE
|
||||
};
|
||||
MetadataXmpSync metadata_xmp_sync;
|
||||
|
||||
/** Creates a new instance of Settings.
|
||||
* @return a pointer to the new Settings instance. */
|
||||
static Settings* create();
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "imagesource.h"
|
||||
#include "improcfun.h"
|
||||
#include "labimage.h"
|
||||
#include "metadata.h"
|
||||
#include "mytime.h"
|
||||
#include "processingjob.h"
|
||||
#include "procparams.h"
|
||||
@ -372,7 +373,7 @@ private:
|
||||
int beg_tileW = wcr * tileWskip + tileWskip / 2.f - crW / 2.f;
|
||||
int beg_tileH = hcr * tileHskip + tileHskip / 2.f - crH / 2.f;
|
||||
PreviewProps ppP(beg_tileW, beg_tileH, crW, crH, skipP);
|
||||
imgsrc->getImage(currWB, tr, origCropPart, ppP, params.toneCurve, params.raw, 0);
|
||||
imgsrc->getImage(currWB, tr, origCropPart, ppP, params.toneCurve, params.raw);
|
||||
//baseImg->getStdImage(currWB, tr, origCropPart, ppP, true, params.toneCurve);
|
||||
|
||||
// we only need image reduced to 1/4 here
|
||||
@ -596,7 +597,7 @@ private:
|
||||
for (int wcr = 0; wcr <= 2; wcr++) {
|
||||
for (int hcr = 0; hcr <= 2; hcr++) {
|
||||
PreviewProps ppP(coordW[wcr], coordH[hcr], crW, crH, 1);
|
||||
imgsrc->getImage(currWB, tr, origCropPart, ppP, params.toneCurve, params.raw, 0);
|
||||
imgsrc->getImage(currWB, tr, origCropPart, ppP, params.toneCurve, params.raw);
|
||||
//baseImg->getStdImage(currWB, tr, origCropPart, ppP, true, params.toneCurve);
|
||||
|
||||
|
||||
@ -756,7 +757,7 @@ private:
|
||||
}
|
||||
|
||||
baseImg = new Imagefloat(fw, fh);
|
||||
imgsrc->getImage(currWB, tr, baseImg, pp, params.toneCurve, params.raw, 1);
|
||||
imgsrc->getImage(currWB, tr, baseImg, pp, params.toneCurve, params.raw);
|
||||
|
||||
if (pl) {
|
||||
pl->setProgress(0.50);
|
||||
@ -1688,18 +1689,11 @@ private:
|
||||
|
||||
if (params.colorappearance.enabled) {
|
||||
double adap;
|
||||
int imgNum = 0;
|
||||
|
||||
if (imgsrc->getSensorType() == ST_BAYER) {
|
||||
imgNum = params.raw.bayersensor.imageNum;
|
||||
} else if (imgsrc->getSensorType() == ST_FUJI_XTRANS) {
|
||||
//imgNum = params.raw.xtranssensor.imageNum;
|
||||
}
|
||||
|
||||
float fnum = imgsrc->getMetaData()->getFNumber(imgNum); // F number
|
||||
float fiso = imgsrc->getMetaData()->getISOSpeed(imgNum) ; // ISO
|
||||
float fspeed = imgsrc->getMetaData()->getShutterSpeed(imgNum) ; //speed
|
||||
float fcomp = imgsrc->getMetaData()->getExpComp(imgNum); //compensation + -
|
||||
const float fnum = imgsrc->getMetaData()->getFNumber(); // F number
|
||||
const float fiso = imgsrc->getMetaData()->getISOSpeed() ; // ISO
|
||||
const float fspeed = imgsrc->getMetaData()->getShutterSpeed() ; // Speed
|
||||
const float fcomp = imgsrc->getMetaData()->getExpComp(); // Compensation + -
|
||||
|
||||
if (fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) {
|
||||
adap = 2000.;
|
||||
@ -1832,18 +1826,19 @@ private:
|
||||
readyImg = tempImage;
|
||||
}
|
||||
|
||||
Exiv2Metadata info(imgsrc->getFileName());
|
||||
switch (params.metadata.mode) {
|
||||
case MetaDataParams::TUNNEL:
|
||||
// Sending back the whole first root, which won't necessarily be the selected frame number
|
||||
// and may contain subframe depending on initial raw's hierarchy
|
||||
readyImg->setMetadata(initialImage->getMetaData()->getRootExifData());
|
||||
readyImg->setMetadata(std::move(info));
|
||||
break;
|
||||
|
||||
case MetaDataParams::EDIT:
|
||||
// ask for the correct frame number, but may contain subframe depending on initial raw's hierarchy
|
||||
readyImg->setMetadata(initialImage->getMetaData()->getBestExifData(imgsrc, ¶ms.raw), params.exif, params.iptc);
|
||||
info.setExif(params.metadata.exif);
|
||||
info.setIptc(params.metadata.iptc);
|
||||
if (!(params.metadata.exifKeys.size() == 1 && params.metadata.exifKeys[0] == "*")) {
|
||||
info.setExifKeys(&(params.metadata.exifKeys));
|
||||
}
|
||||
readyImg->setMetadata(std::move(info));
|
||||
break;
|
||||
|
||||
default: // case MetaDataParams::STRIP
|
||||
// nothing to do
|
||||
break;
|
||||
@ -1868,11 +1863,11 @@ private:
|
||||
}
|
||||
|
||||
ProfileContent pc = ICCStore::getInstance()->getContent(params.icm.outputProfile);
|
||||
readyImg->setOutputProfile(pc.getData().c_str(), pc.getData().size());
|
||||
readyImg->setOutputProfile(pc.getData());
|
||||
}
|
||||
} else {
|
||||
// No ICM
|
||||
readyImg->setOutputProfile(nullptr, 0);
|
||||
readyImg->setOutputProfile({});
|
||||
}
|
||||
|
||||
// t2.set();
|
||||
|
@ -459,7 +459,7 @@ void ImProcFunctions::removeSpots (Imagefloat* img, ImageSource* imgsrc, const s
|
||||
}
|
||||
}
|
||||
|
||||
imgsrc->getImage(currWB, tr, srcSpotBox->getImage(), spp, params->toneCurve, params->raw, 0);
|
||||
imgsrc->getImage(currWB, tr, srcSpotBox->getImage(), spp, params->toneCurve, params->raw);
|
||||
if (cmp) {
|
||||
imgsrc->convertColorSpace(srcImage, *cmp, currWB);
|
||||
}
|
||||
@ -479,7 +479,7 @@ void ImProcFunctions::removeSpots (Imagefloat* img, ImageSource* imgsrc, const s
|
||||
dstImage->b(y, x) = 60000.f;
|
||||
}
|
||||
}
|
||||
imgsrc->getImage(currWB, tr, dstSpotBox->getImage(), spp, params->toneCurve, params->raw, 0);
|
||||
imgsrc->getImage(currWB, tr, dstSpotBox->getImage(), spp, params->toneCurve, params->raw);
|
||||
if (cmp) {
|
||||
imgsrc->convertColorSpace(dstImage, *cmp, currWB);
|
||||
}
|
||||
|
@ -193,7 +193,7 @@ int StdImageSource::load (const Glib::ustring &fname)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void StdImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const RAWParams &raw, int opposed)
|
||||
void StdImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const ToneCurveParams &hrp, const RAWParams &raw)
|
||||
{
|
||||
|
||||
// the code will use OpenMP as of now.
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
|
||||
int load (const Glib::ustring &fname) override;
|
||||
void getWBMults (const ColorTemp &ctemp, const procparams::RAWParams &raw, std::array<float, 4>& scale_mul, float &autoGainComp, float &rm, float &gm, float &bm) const override {};
|
||||
void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hrp, const procparams::RAWParams &raw, int opposed) override;
|
||||
void getImage (const ColorTemp &ctemp, int tran, Imagefloat* image, const PreviewProps &pp, const procparams::ToneCurveParams &hrp, const procparams::RAWParams &raw) override;
|
||||
void getrgbloc (int begx, int begy, int yEn, int xEn, int cx, int cy, int bf_h, int bf_w, const procparams::WBParams & wbpar) override {};
|
||||
ColorTemp getWB () const override
|
||||
{
|
||||
|
@ -1,29 +0,0 @@
|
||||
add_library(rtexif STATIC
|
||||
canonattribs.cc
|
||||
fujiattribs.cc
|
||||
kodakattribs.cc
|
||||
nikonattribs.cc
|
||||
olympusattribs.cc
|
||||
panasonicattribs.cc
|
||||
pentaxattribs.cc
|
||||
rtexif.cc
|
||||
sonyminoltaattribs.cc
|
||||
stdattribs.cc
|
||||
)
|
||||
|
||||
add_dependencies(rtexif UpdateInfo)
|
||||
|
||||
if(WIN32)
|
||||
include_directories(${EXTRA_INCDIR} ${GLIB2_INCLUDE_DIRS} ${GLIBMM_INCLUDE_DIRS} ${GTK_INCLUDE_DIRS} ${GTKMM_INCLUDE_DIRS} ${TIFF_INCLUDE_DIRS})
|
||||
link_directories(. "${PROJECT_SOURCE_DIR}/rtexif" ${EXTRA_LIBDIR} ${GLIB2_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS} ${GTK_LIBRARY_DIRS} ${GTKMM_LIBRARY_DIRS} ${LENSFUN_LIBRARY_DIRS} ${TIFF_LIBRARY_DIRS})
|
||||
else()
|
||||
set_target_properties(rtexif PROPERTIES COMPILE_FLAGS " -fPIC")
|
||||
include_directories(${EXTRA_INCDIR} ${GLIB2_INCLUDE_DIRS} ${GLIBMM_INCLUDE_DIRS} ${GTK_INCLUDE_DIRS} ${GTKMM_INCLUDE_DIRS} ${TIFF_INCLUDE_DIRS})
|
||||
link_directories(${EXTRA_LIBDIR} ${GLIB2_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS} ${GTK_LIBRARY_DIRS} ${GTKMM_LIBRARY_DIRS} ${LENSFUN_LIBRARY_DIRS} ${TIFF_LIBRARY_DIRS})
|
||||
endif()
|
||||
|
||||
include_directories(BEFORE "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
install(TARGETS rtexif DESTINATION "${LIBDIR}")
|
||||
endif()
|
@ -1,313 +0,0 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee 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.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "rtexif.h"
|
||||
|
||||
namespace rtexif
|
||||
{
|
||||
|
||||
class FAOnOffInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FAOnOffInterpreter ()
|
||||
{
|
||||
choices[0] = "Off";
|
||||
choices[1] = "On";
|
||||
}
|
||||
};
|
||||
FAOnOffInterpreter faOnOffInterpreter;
|
||||
|
||||
class FASharpnessInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FASharpnessInterpreter ()
|
||||
{
|
||||
choices[1] = "Soft";
|
||||
choices[2] = "Soft2";
|
||||
choices[3] = "Normal";
|
||||
choices[4] = "Hard";
|
||||
choices[5] = "Hard2";
|
||||
choices[0x82] = "Medium Soft";
|
||||
choices[0x84] = "Medium Hard";
|
||||
choices[0x8000] = "Film Simulation";
|
||||
choices[0xffff] = "n/a";
|
||||
}
|
||||
};
|
||||
FASharpnessInterpreter faSharpnessInterpreter;
|
||||
|
||||
class FAWhiteBalanceInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FAWhiteBalanceInterpreter ()
|
||||
{
|
||||
choices[0] = "Auto";
|
||||
choices[0x100] = "Daylight";
|
||||
choices[0x200] = "Cloudy";
|
||||
choices[0x300] = "Daylight Fluorescent";
|
||||
choices[0x301] = "Day White Fluorescent";
|
||||
choices[0x302] = "White Fluorescent";
|
||||
choices[0x303] = "Warm White Fluorescent";
|
||||
choices[0x304] = "Living Room Warm White Fluorescent";
|
||||
choices[0x400] = "Incandescent";
|
||||
choices[0x500] = "Flash";
|
||||
choices[0x600] = "Underwater";
|
||||
choices[0xf00] = "Custom";
|
||||
choices[0xf01] = "Custom2";
|
||||
choices[0xf02] = "Custom3";
|
||||
choices[0xf03] = "Custom4";
|
||||
choices[0xf04] = "Custom5";
|
||||
choices[0xff0] = "Kelvin";
|
||||
}
|
||||
};
|
||||
FAWhiteBalanceInterpreter faWhiteBalanceInterpreter;
|
||||
|
||||
class FASaturationInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FASaturationInterpreter ()
|
||||
{
|
||||
choices[0] = "Normal";
|
||||
choices[128] = "Medium High";
|
||||
choices[256] = "High";
|
||||
choices[384] = "Medium Low";
|
||||
choices[512] = "Low";
|
||||
choices[768] = "None (B&W)";
|
||||
choices[769] = "B&W Red Filter";
|
||||
choices[770] = "B&W Yellow Filter";
|
||||
choices[771] = "B&W Green Filter";
|
||||
choices[784] = "B&W Sepia";
|
||||
choices[1024] = "Low 2";
|
||||
choices[1280] = "Acros";
|
||||
choices[1281] = "Acros Red Filter";
|
||||
choices[1282] = "Acros Yellow Filter";
|
||||
choices[1283] = "Acros Green Filter";
|
||||
choices[32768] = "Film Simulation";
|
||||
}
|
||||
};
|
||||
FASaturationInterpreter faSaturationInterpreter;
|
||||
|
||||
class FAContrastInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FAContrastInterpreter ()
|
||||
{
|
||||
choices[0] = "Normal";
|
||||
choices[0x80] = "Medium High";
|
||||
choices[0x100] = "High";
|
||||
choices[0x180] = "Medium Low";
|
||||
choices[0x200] = "Low";
|
||||
choices[0x8000] = "Film Simulation";
|
||||
}
|
||||
};
|
||||
FAContrastInterpreter faContrastInterpreter;
|
||||
|
||||
class FAContrast2Interpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FAContrast2Interpreter ()
|
||||
{
|
||||
choices[0] = "Normal";
|
||||
choices[0x100] = "High";
|
||||
choices[0x300] = "Low";
|
||||
}
|
||||
};
|
||||
FAContrast2Interpreter faContrast2Interpreter;
|
||||
|
||||
class FANoiseReductionInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FANoiseReductionInterpreter ()
|
||||
{
|
||||
choices[0x40] = "Low";
|
||||
choices[0x80] = "Normal";
|
||||
choices[0x100] = "n/a";
|
||||
}
|
||||
};
|
||||
FANoiseReductionInterpreter faNoiseReductionInterpreter;
|
||||
|
||||
class FAFlashInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
// FujiFlashMode
|
||||
FAFlashInterpreter ()
|
||||
{
|
||||
choices[0] = "Auto";
|
||||
choices[1] = "On";
|
||||
choices[2] = "Off";
|
||||
choices[3] = "Red-eye reduction";
|
||||
choices[4] = "External";
|
||||
}
|
||||
};
|
||||
FAFlashInterpreter faFlashInterpreter;
|
||||
|
||||
class FAFocusModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FAFocusModeInterpreter ()
|
||||
{
|
||||
choices[0] = "Auto";
|
||||
choices[1] = "Manual";
|
||||
}
|
||||
};
|
||||
FAFocusModeInterpreter faFocusModeInterpreter;
|
||||
|
||||
class FAColorModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FAColorModeInterpreter ()
|
||||
{
|
||||
choices[0] = "Standard";
|
||||
choices[0x10] = "Chrome";
|
||||
choices[0x30] = "B & W";
|
||||
}
|
||||
};
|
||||
FAColorModeInterpreter faColorModeInterpreter;
|
||||
|
||||
class FADynamicRangeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FADynamicRangeInterpreter ()
|
||||
{
|
||||
choices[1] = "Standard";
|
||||
choices[3] = "Wide";
|
||||
}
|
||||
};
|
||||
FADynamicRangeInterpreter faDynamicRangeInterpreter;
|
||||
|
||||
class FAFilmModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FAFilmModeInterpreter ()
|
||||
{
|
||||
choices[0x0] = "F0/Standard (Provia)";
|
||||
choices[0x100] = "F1/Studio Portrait";
|
||||
choices[0x110] = "F1a/Studio Portrait Enhanced Saturation";
|
||||
choices[0x120] = "F1b/Studio Portrait Smooth Skin Tone (Astia)";
|
||||
choices[0x130] = "F1c/Studio Portrait Increased Sharpness";
|
||||
choices[0x200] = "F2/Fujichrome (Velvia)";
|
||||
choices[0x300] = "F3/Studio Portrait Ex";
|
||||
choices[0x400] = "F4/Velvia";
|
||||
choices[0x500] = "Pro Neg. Std";
|
||||
choices[0x501] = "Pro Neg. Hi";
|
||||
choices[0x600] = "Classic Chrome";
|
||||
}
|
||||
};
|
||||
FAFilmModeInterpreter faFilmModeInterpreter;
|
||||
|
||||
class FADRSettingInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
// DynamicRangeSetting
|
||||
FADRSettingInterpreter ()
|
||||
{
|
||||
choices[0x0] = "Auto (100-400%)";
|
||||
choices[0x1] = "Manual";
|
||||
choices[0x100] = "Standard (100%)";
|
||||
choices[0x200] = "Wide1 (230%)";
|
||||
choices[0x201] = "Wide2 (400%)";
|
||||
choices[0x8000] = "Film Simulation";
|
||||
}
|
||||
};
|
||||
FADRSettingInterpreter faDRSettingInterpreter;
|
||||
|
||||
class FAPictureModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FAPictureModeInterpreter ()
|
||||
{
|
||||
choices[0x0] = "Auto";
|
||||
choices[0x1] = "Portrait";
|
||||
choices[0x2] = "Landscape";
|
||||
choices[0x3] = "Macro";
|
||||
choices[0x4] = "Sports";
|
||||
choices[0x5] = "Night Scene";
|
||||
choices[0x6] = "Program AE";
|
||||
choices[0x7] = "Natural Light";
|
||||
choices[0x8] = "Anti-blur";
|
||||
choices[0x9] = "Beach & Snow";
|
||||
choices[0xa] = "Sunset";
|
||||
choices[0xb] = "Museum";
|
||||
choices[0xc] = "Party";
|
||||
choices[0xd] = "Flower";
|
||||
choices[0xe] = "Text";
|
||||
choices[0xf] = "Natural Light & Flash";
|
||||
choices[0x10] = "Beach";
|
||||
choices[0x11] = "Snow";
|
||||
choices[0x12] = "Fireworks";
|
||||
choices[0x13] = "Underwater";
|
||||
choices[0x14] = "Portrait with Skin Correction";
|
||||
choices[0x16] = "Panorama";
|
||||
choices[0x17] = "Night (tripod)";
|
||||
choices[0x18] = "Pro Low-light";
|
||||
choices[0x19] = "Pro Focus";
|
||||
choices[0x1a] = "Portrait 2";
|
||||
choices[0x1b] = "Dog Face Detection";
|
||||
choices[0x1c] = "Cat Face Detection";
|
||||
choices[0x40] = "Advanced Filter";
|
||||
choices[0x100] = "Aperture-priority AE";
|
||||
choices[0x200] = "Shutter speed priority AE";
|
||||
choices[0x300] = "Manual";
|
||||
}
|
||||
};
|
||||
FAPictureModeInterpreter faPictureModeInterpreter;
|
||||
|
||||
|
||||
|
||||
const TagAttrib fujiAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0000, AUTO, "Version", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0010, AUTO, "InternalSerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1000, AUTO, "Quality", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1001, AUTO, "Sharpness", &faSharpnessInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1002, AUTO, "WhiteBalance", &faWhiteBalanceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1003, AUTO, "Saturation", &faSaturationInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1004, AUTO, "Contrast", &faContrastInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1005, AUTO, "ColorTemperature", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1006, AUTO, "Contrast2", &faContrast2Interpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x100a, AUTO, "WhiteBalanceFineTune", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x100b, AUTO, "NoiseReduction", &faNoiseReductionInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1010, AUTO, "FujiFlashMode", &faFlashInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1011, AUTO, "FlashExposureComp", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1020, AUTO, "Macro", &faOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1021, AUTO, "FocusMode", &faFocusModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1023, AUTO, "FocusPixel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1030, AUTO, "SlowSync", &faOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1031, AUTO, "PictureMode", &faPictureModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1100, AUTO, "AutoBracketing", &faOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1101, AUTO, "SequenceNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1210, AUTO, "ColorMode", &faColorModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1300, AUTO, "BlurWarning", &faOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1301, AUTO, "FocusWarning", &faOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1302, AUTO, "ExposureWarning", &faOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1400, AUTO, "DynamicRange", &faDynamicRangeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1401, AUTO, "FilmMode", &faFilmModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1402, AUTO, "DynamicRangeSetting", &faDRSettingInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1403, AUTO, "DevelopmentDynamicRange", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1404, AUTO, "MinFocalLength", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1405, AUTO, "MaxFocalLength", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1406, AUTO, "MaxApertureAtMinFocal", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1407, AUTO, "MaxApertureAtMaxFocal", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x140b, AUTO, "AutoDynamicRange", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x4100, AUTO, "FacesDetected", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8000, AUTO, "FileSource", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8002, AUTO, "OrderNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8003, AUTO, "FrameNumber", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
}
|
||||
|
@ -1,162 +0,0 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "rtexif.h"
|
||||
|
||||
namespace rtexif
|
||||
{
|
||||
|
||||
|
||||
void parseKodakIfdTextualInfo (Tag *textualInfo, Tag* exif_)
|
||||
{
|
||||
// parse TextualInfo and copy values into corresponding standard Exif
|
||||
if (textualInfo->getType() != ASCII) {
|
||||
return;
|
||||
}
|
||||
|
||||
TagDirectory *exif = exif_->getDirectory();
|
||||
char *value = (char *)textualInfo->getValue();
|
||||
|
||||
char *p = value;
|
||||
char *pc, *plf;
|
||||
|
||||
while ((pc = strchr (p, ':')) != nullptr && (plf = strchr (pc, '\n')) != nullptr) {
|
||||
while (*p == ' ') {
|
||||
p++;
|
||||
}
|
||||
|
||||
size_t len = pc - p;
|
||||
|
||||
while (len > 1 && p[len - 1] == ' ') {
|
||||
len--;
|
||||
}
|
||||
|
||||
std::string key = std::string (p, len);
|
||||
++pc;
|
||||
|
||||
while (*pc == ' ') {
|
||||
pc++;
|
||||
}
|
||||
|
||||
len = plf - pc;
|
||||
|
||||
while (len > 1 && pc[len - 1] == ' ') {
|
||||
len--;
|
||||
}
|
||||
|
||||
std::string val = std::string (pc, len);
|
||||
p = ++plf;
|
||||
|
||||
// we pick out a few select tags here
|
||||
Tag *t;
|
||||
|
||||
if (key == "Lens") {
|
||||
// Proback645 may have "Lens" but not "Focal Length"
|
||||
float flen = atof (val.c_str());
|
||||
|
||||
if (flen != 0.f) {
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "FocalLength"));
|
||||
t->initRational (flen * 32, 32);
|
||||
exif->replaceTag (t);
|
||||
}
|
||||
} else if (key == "Focal Length") {
|
||||
float flen = atof (val.c_str());
|
||||
|
||||
if (flen != 0.f) {
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "FocalLength"));
|
||||
t->initRational (flen * 32, 32);
|
||||
exif->replaceTag (t);
|
||||
}
|
||||
} else if (key == "Aperture") {
|
||||
float aperture = atof (&val.c_str()[1]);
|
||||
|
||||
if (aperture != 0.f) {
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "FNumber"));
|
||||
t->initRational ((int) (aperture * 10), 10);
|
||||
exif->replaceTag (t);
|
||||
}
|
||||
} else if (key == "Exposure Bias" || key == "Compensation") {
|
||||
float bias = 0.0;
|
||||
|
||||
if (val != "Off") {
|
||||
bias = atof (val.c_str());
|
||||
}
|
||||
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "ExposureBiasValue"));
|
||||
t->initRational ((int) (bias * 1000), 1000);
|
||||
exif->replaceTag (t);
|
||||
} else if (key == "ISO Speed") {
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "ISOSpeedRatings"));
|
||||
t->initInt (atoi (val.c_str()), SHORT);
|
||||
exif->replaceTag (t);
|
||||
} else if (key == "Shutter") {
|
||||
const char *p1 = strchr (val.c_str(), '/');
|
||||
int a, b;
|
||||
|
||||
if (p1 == nullptr) {
|
||||
a = atoi (val.c_str());
|
||||
b = 1;
|
||||
} else {
|
||||
a = atoi (val.c_str());
|
||||
b = atoi (&p1[1]);
|
||||
}
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "ExposureTime"));
|
||||
t->initRational (a, b);
|
||||
exif->replaceTag (t);
|
||||
|
||||
const float ssv = -log2 ((float)a / std::max((float)b, 0.0001f)); // convert to APEX value, avoid division by zero
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "ShutterSpeedValue"));
|
||||
t->initRational (1000000 * ssv, 1000000);
|
||||
exif->replaceTag (t);
|
||||
} else if (key == "Flash Fired") {
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "Flash"));
|
||||
|
||||
if (val == "No") {
|
||||
t->initInt (0, SHORT);
|
||||
} else {
|
||||
// not sure if "Flash Fired" is only yes/no, only seen "No" in test pictures
|
||||
t->initInt (1, SHORT);
|
||||
}
|
||||
|
||||
exif->replaceTag (t);
|
||||
} else if (key == "White balance") { // yes should be small 'b' int 'balance'.
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "Flash"));
|
||||
t->initInt ((val == "Auto") ? 0 : 1, SHORT);
|
||||
exif->replaceTag (t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// table not complete, not all proprietary Kodak tags are known
|
||||
const TagAttrib kodakIfdAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0001, AUTO, "UnknownEV?", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0003, AUTO, "ExposureValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x03e9, AUTO, "OriginalFileName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x03eb, AUTO, "SensorLeftBorder", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x03ec, AUTO, "SensorTopBorder", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x03ed, AUTO, "SensorImageWidth", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x03ee, AUTO, "SensorImageHeight", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x03f1, AUTO, "TextualInfo", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x03fc, AUTO, "WhiteBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x03fd, AUTO, "Processing", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0401, AUTO, "Time", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0414, AUTO, "NCDFileInfo", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0846, AUTO, "ColorTemperature", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0852, AUTO, "WB_RGBMul0", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0853, AUTO, "WB_RGBMul1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0854, AUTO, "WB_RGBMul2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0855, AUTO, "WB_RGBMul3", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x085c, AUTO, "WB_RGBCoeffs0", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x085d, AUTO, "WB_RGBCoeffs1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x085e, AUTO, "WB_RGBCoeffs2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x085f, AUTO, "WB_RGBCoeffs3", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0ce5, AUTO, "FirmwareVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1391, AUTO, "ToneCurveFileName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1784, AUTO, "ISO", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr }
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,859 +0,0 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee 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.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
#include "rtexif.h"
|
||||
|
||||
namespace rtexif
|
||||
{
|
||||
|
||||
class OLOnOffInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
OLOnOffInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
if (t->toInt() == 0) {
|
||||
return "Off";
|
||||
} else {
|
||||
return "On";
|
||||
}
|
||||
}
|
||||
};
|
||||
OLOnOffInterpreter olOnOffInterpreter;
|
||||
|
||||
class OLYesNoInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
OLYesNoInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
if (t->toInt() == 0) {
|
||||
return "No";
|
||||
} else {
|
||||
return "Yes";
|
||||
}
|
||||
}
|
||||
};
|
||||
OLYesNoInterpreter olYesNoInterpreter;
|
||||
|
||||
class OLApertureInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
OLApertureInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
std::ostringstream str;
|
||||
str.precision (2);
|
||||
str << pow (2, t->toInt() / 512.0);
|
||||
return str.str();
|
||||
}
|
||||
};
|
||||
OLApertureInterpreter olApertureInterpreter;
|
||||
|
||||
class OLLensTypeInterpreter : public Interpreter
|
||||
{
|
||||
std::map<std::string, std::string> lenses;
|
||||
public:
|
||||
OLLensTypeInterpreter ()
|
||||
{
|
||||
lenses["00 01 00"] = "Olympus Zuiko Digital ED 50mm f/2.0 Macro";
|
||||
lenses["00 01 01"] = "Olympus Zuiko Digital 40-150mm f/3.5-4.5";
|
||||
lenses["00 01 10"] = "Olympus M.Zuiko Digital ED 14-42mm f/3.5-5.6";
|
||||
lenses["00 02 00"] = "Olympus Zuiko Digital ED 150mm f/2.0";
|
||||
lenses["00 02 10"] = "Olympus M.Zuiko Digital 17mm f/2.8 Pancake";
|
||||
lenses["00 03 00"] = "Olympus Zuiko Digital ED 300mm f/2.8";
|
||||
lenses["00 03 10"] = "Olympus M.Zuiko Digital ED 14-150mm f/4.0-5.6 [II]";
|
||||
lenses["00 04 10"] = "Olympus M.Zuiko Digital ED 9-18mm f/4.0-5.6";
|
||||
lenses["00 05 00"] = "Olympus Zuiko Digital 14-54mm f/2.8-3.5";
|
||||
lenses["00 05 01"] = "Olympus Zuiko Digital Pro ED 90-250mm f/2.8";
|
||||
lenses["00 05 10"] = "Olympus M.Zuiko Digital ED 14-42mm f/3.5-5.6 L";
|
||||
lenses["00 06 00"] = "Olympus Zuiko Digital ED 50-200mm f/2.8-3.5";
|
||||
lenses["00 06 01"] = "Olympus Zuiko Digital ED 8mm f/3.5 Fisheye";
|
||||
lenses["00 06 10"] = "Olympus M.Zuiko Digital ED 40-150mm f/4.0-5.6";
|
||||
lenses["00 07 00"] = "Olympus Zuiko Digital 11-22mm f/2.8-3.5";
|
||||
lenses["00 07 01"] = "Olympus Zuiko Digital 18-180mm f/3.5-6.3";
|
||||
lenses["00 07 10"] = "Olympus M.Zuiko Digital ED 12mm f/2.0";
|
||||
lenses["00 08 01"] = "Olympus Zuiko Digital 70-300mm f/4.0-5.6";
|
||||
lenses["00 08 10"] = "Olympus M.Zuiko Digital ED 75-300mm f/4.8-6.7";
|
||||
lenses["00 09 10"] = "Olympus M.Zuiko Digital 14-42mm f/3.5-5.6 II";
|
||||
lenses["00 10 01"] = "Kenko Tokina Reflex 300mm f/6.3 MF Macro";
|
||||
lenses["00 10 10"] = "Olympus M.Zuiko Digital ED 12-50mm f/3.5-6.3 EZ";
|
||||
lenses["00 11 10"] = "Olympus M.Zuiko Digital 45mm f/1.8";
|
||||
lenses["00 12 10"] = "Olympus M.Zuiko Digital ED 60mm f/2.8 Macro";
|
||||
lenses["00 13 10"] = "Olympus M.Zuiko Digital 14-42mm f/3.5-5.6 II R";
|
||||
lenses["00 14 10"] = "Olympus M.Zuiko Digital ED 40-150mm f/4.0-5.6 R";
|
||||
lenses["00 15 00"] = "Olympus Zuiko Digital ED 7-14mm f/4.0";
|
||||
lenses["00 15 10"] = "Olympus M.Zuiko Digital ED 75mm f/1.8";
|
||||
lenses["00 16 10"] = "Olympus M.Zuiko Digital 17mm f/1.8";
|
||||
lenses["00 17 00"] = "Olympus Zuiko Digital Pro ED 35-100mm f/2.0";
|
||||
lenses["00 18 00"] = "Olympus Zuiko Digital 14-45mm f/3.5-5.6";
|
||||
lenses["00 18 10"] = "Olympus M.Zuiko Digital ED 75-300mm f/4.8-6.7 II";
|
||||
lenses["00 19 10"] = "Olympus M.Zuiko Digital ED 12-40mm f/2.8 Pro";
|
||||
lenses["00 20 00"] = "Olympus Zuiko Digital 35mm f/3.5 Macro";
|
||||
lenses["00 20 10"] = "Olympus M.Zuiko Digital ED 40-150mm f/2.8 Pro";
|
||||
lenses["00 21 10"] = "Olympus M.Zuiko Digital ED 14-42mm f/3.5-5.6 EZ";
|
||||
lenses["00 22 00"] = "Olympus Zuiko Digital 17.5-45mm f/3.5-5.6";
|
||||
lenses["00 22 10"] = "Olympus M.Zuiko Digital 25mm f/1.8";
|
||||
lenses["00 23 00"] = "Olympus Zuiko Digital ED 14-42mm f/3.5-5.6";
|
||||
lenses["00 23 10"] = "Olympus M.Zuiko Digital ED 7-14mm f/2.8 Pro";
|
||||
lenses["00 24 00"] = "Olympus Zuiko Digital ED 40-150mm f/4.0-5.6";
|
||||
lenses["00 24 10"] = "Olympus M.Zuiko Digital ED 300mm f/4.0 IS Pro";
|
||||
lenses["00 25 10"] = "Olympus M.Zuiko Digital ED 8mm f/1.8 Fisheye Pro";
|
||||
lenses["00 26 10"] = "Olympus M.Zuiko Digital ED 12-100mm f/4.0 IS Pro";
|
||||
lenses["00 27 10"] = "Olympus M.Zuiko Digital ED 30mm f/3.5 Macro";
|
||||
lenses["00 28 10"] = "Olympus M.Zuiko Digital ED 25mm f/1.2 Pro";
|
||||
lenses["00 29 10"] = "Olympus M.Zuiko Digital ED 17mm f/1.2 Pro";
|
||||
lenses["00 30 00"] = "Olympus Zuiko Digital ED 50-200mm f/2.8-3.5 SWD";
|
||||
lenses["00 30 10"] = "Olympus M.Zuiko Digital ED 45mm f/1.2 Pro";
|
||||
lenses["00 31 00"] = "Olympus Zuiko Digital ED 12-60mm f/2.8-4.0 SWD";
|
||||
lenses["00 32 00"] = "Olympus Zuiko Digital ED 14-35mm f/2.0 SWD";
|
||||
lenses["00 32 10"] = "Olympus M.Zuiko Digital ED 12-200mm f/3.5-6.3";
|
||||
lenses["00 33 00"] = "Olympus Zuiko Digital 25mm f/2.8";
|
||||
lenses["00 33 10"] = "Olympus M.Zuiko Digital 150-400mm f/4.5 TC1.25x IS Pro";
|
||||
lenses["00 34 00"] = "Olympus Zuiko Digital ED 9-18mm f/4.0-5.6";
|
||||
lenses["00 34 10"] = "Olympus M.Zuiko Digital ED 12-45mm f/4.0 Pro";
|
||||
lenses["00 35 00"] = "Olympus Zuiko Digital 14-54mm f/2.8-3.5 II";
|
||||
lenses["00 35 10"] = "Olympus M.Zuiko 100-400mm f/5.0-6.3";
|
||||
lenses["00 36 10"] = "Olympus M.Zuiko Digital ED 8-25mm f/4 Pro";
|
||||
lenses["01 01 00"] = "Sigma 18-50mm f/3.5-5.6 DC";
|
||||
lenses["01 01 10"] = "Sigma 30mm f/2.8 EX DN";
|
||||
lenses["01 02 00"] = "Sigma 55-200mm f/4.0-5.6 DC";
|
||||
lenses["01 02 10"] = "Sigma 19mm f/2.8 EX DN";
|
||||
lenses["01 03 00"] = "Sigma 18-125mm f/3.5-5.6 DC";
|
||||
lenses["01 03 10"] = "Sigma 30mm f/2.8 DN | A";
|
||||
lenses["01 04 00"] = "Sigma 18-125mm f/3.5-5.6 DC";
|
||||
lenses["01 04 10"] = "Sigma 19mm f/2.8 DN | A";
|
||||
lenses["01 05 00"] = "Sigma 30mm f/1.4 EX DC HSM";
|
||||
lenses["01 05 10"] = "Sigma 60mm f/2.8 DN | A";
|
||||
lenses["01 06 00"] = "Sigma APO 50-500mm f/4.0-6.3 EX DG HSM";
|
||||
lenses["01 06 10"] = "Sigma 30mm f/1.4 DC DN | C";
|
||||
lenses["01 07 00"] = "Sigma Macro 105mm f/2.8 EX DG";
|
||||
lenses["01 07 10"] = "Sigma 16mm f/1.4 DC DN | C (017)";
|
||||
lenses["01 08 00"] = "Sigma APO Macro 150mm f/2.8 EX DG HSM";
|
||||
lenses["01 09 00"] = "Sigma 18-50mm f/2.8 EX DC Macro";
|
||||
lenses["01 10 00"] = "Sigma 24mm f/1.8 EX DG Aspherical Macro";
|
||||
lenses["01 11 00"] = "Sigma APO 135-400mm f/4.5-5.6 DG";
|
||||
lenses["01 12 00"] = "Sigma APO 300-800mm f/5.6 EX DG HSM";
|
||||
lenses["01 13 00"] = "Sigma 30mm f/1.4 EX DC HSM";
|
||||
lenses["01 14 00"] = "Sigma APO 50-500mm f/4.0-6.3 EX DG HSM";
|
||||
lenses["01 15 00"] = "Sigma 10-20mm f/4.0-5.6 EX DC HSM";
|
||||
lenses["01 16 00"] = "Sigma APO 70-200mm f/2.8 II EX DG Macro HSM";
|
||||
lenses["01 17 00"] = "Sigma 50mm f/1.4 EX DG HSM";
|
||||
lenses["02 01 00"] = "Leica D Vario Elmarit 14-50mm f/2.8-3.5 Asph.";
|
||||
lenses["02 01 10"] = "Lumix G Vario 14-45mm f/3.5-5.6 Asph. Mega OIS";
|
||||
lenses["02 02 00"] = "Leica D Summilux 25mm f/1.4 Asph.";
|
||||
lenses["02 02 10"] = "Lumix G Vario 45-200mm f/4.0-5.6 Mega OIS";
|
||||
lenses["02 03 00"] = "Leica D Vario Elmar 14-50mm f/3.8-5.6 Asph. Mega OIS";
|
||||
lenses["02 03 01"] = "Leica D Vario Elmar 14-50mm f/3.8-5.6 Asph.";
|
||||
lenses["02 03 10"] = "Lumix G Vario HD 14-140mm f/4.0-5.8 Asph. Mega OIS";
|
||||
lenses["02 04 00"] = "Leica D Vario Elmar 14-150mm f/3.5-5.6";
|
||||
lenses["02 04 10"] = "Lumix G Vario 7-14mm f/4.0 Asph.";
|
||||
lenses["02 05 10"] = "Lumix G 20mm f/1.7 Asph.";
|
||||
lenses["02 06 10"] = "Leica DG Macro-Elmarit 45mm f/2.8 Asph. Mega OIS";
|
||||
lenses["02 07 10"] = "Lumix G Vario 14-42mm f/3.5-5.6 Asph. Mega OIS";
|
||||
lenses["02 08 10"] = "Lumix G Fisheye 8mm f/3.5";
|
||||
lenses["02 09 10"] = "Lumix G Vario 100-300mm f/4.0-5.6 Mega OIS";
|
||||
lenses["02 10 10"] = "Lumix G 14mm f/2.5 Asph.";
|
||||
lenses["02 11 10"] = "Lumix G 12.5mm f/12 3D";
|
||||
lenses["02 12 10"] = "Leica DG Summilux 25mm f/1.4 Asph.";
|
||||
lenses["02 13 10"] = "Lumix G X Vario PZ 45-175mm f/4.0-5.6 Asph. Power OIS";
|
||||
lenses["02 14 10"] = "Lumix G X Vario PZ 14-42mm f/3.5-5.6 Asph. Power OIS";
|
||||
lenses["02 15 10"] = "Lumix G X Vario 12-35mm f/2.8 Asph. Power OIS";
|
||||
lenses["02 16 10"] = "Lumix G Vario 45-150mm f/4.0-5.6 Asph. Mega OIS";
|
||||
lenses["02 17 10"] = "Lumix G X Vario 35-100mm f/2.8 Power OIS";
|
||||
lenses["02 18 10"] = "Lumix G Vario 14-42mm f/3.5-5.6 II Asph. Mega OIS";
|
||||
lenses["02 19 10"] = "Lumix G Vario 14-140mm f/3.5-5.6 Asph. Power OIS";
|
||||
lenses["02 20 10"] = "Lumix G Vario 12-32mm f/3.5-5.6 Asph. Mega OIS";
|
||||
lenses["02 21 10"] = "Leica DG Nocticron 42.5mm f/1.2 Asph. Power OIS";
|
||||
lenses["02 22 10"] = "Leica DG Summilux 15mm f/1.7 Asph.";
|
||||
lenses["02 23 10"] = "Lumix G Vario 35-100mm f/4.0-5.6 Asph. Mega OIS";
|
||||
lenses["02 24 10"] = "Lumix G Macro 30mm f/2.8 Asph. Mega OIS";
|
||||
lenses["02 25 10"] = "Lumix G 42.5mm f/1.7 Asph. Power OIS";
|
||||
lenses["02 26 10"] = "Lumix G 25mm f/1.7 Asph.";
|
||||
lenses["02 27 10"] = "Leica DG Vario-Elmar 100-400mm f/4.0-6.3 Asph. Power OIS";
|
||||
lenses["02 28 10"] = "Lumix G Vario 12-60mm f/3.5-5.6 Asph. Power OIS";
|
||||
lenses["02 29 10"] = "Leica DG Summilux 12mm f/1.4 Asph.";
|
||||
lenses["02 30 10"] = "Leica DG Vario-Elmarit 12-60mm f/2.8-4 Asph. Power OIS";
|
||||
lenses["02 31 10"] = "Lumix G Vario 45-200mm f/4.0-5.6 II";
|
||||
lenses["02 32 10"] = "Lumix G Vario 100-300mm f/4.0-5.6 II";
|
||||
lenses["02 33 10"] = "Lumix G X Vario 12-35mm f/2.8 II Asph. Power OIS";
|
||||
lenses["02 34 10"] = "Lumix G Vario 35-100mm f/2.8 II";
|
||||
lenses["02 35 10"] = "Leica DG Vario-Elmarit 8-18mm f/2.8-4 Asph.";
|
||||
lenses["02 36 10"] = "Leica DG Elmarit 200mm f/2.8 Power OIS";
|
||||
lenses["02 37 10"] = "Leica DG Vario-Elmarit 50-200mm f/2.8-4 Asph. Power OIS";
|
||||
lenses["02 38 10"] = "Leica DG Vario-Summilux 10-25mm f/1.7 Asph.";
|
||||
lenses["02 40 10"] = "Leica DG Vario-Summilux 25-50mm f/1.7 Asph.";
|
||||
lenses["03 01 00"] = "Leica D Vario Elmarit 14-50mm f/2.8-3.5 Asph.";
|
||||
lenses["03 02 00"] = "Leica D Summilux 25mm f/1.4 Asph.";
|
||||
lenses["05 01 10"] = "Tamron 14-150mm f/3.5-5.8 Di III";
|
||||
lenses["024 01 10"] = "Venus Optics Laowa 50mm f/2.8 2x Macro";
|
||||
}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
std::ostringstream lid;
|
||||
lid.setf (std::ios_base::hex, std::ios_base::basefield);
|
||||
lid.setf (std::ios_base::uppercase);
|
||||
lid << std::setw (2) << std::setfill ('0') << t->toInt (0) << ' '; //maker
|
||||
lid << std::setw (2) << std::setfill ('0') << t->toInt (2) << ' '; //model
|
||||
lid << std::setw (2) << std::setfill ('0') << t->toInt (3); // submodel
|
||||
|
||||
std::map<std::string, std::string>::const_iterator r = lenses.find (lid.str());
|
||||
|
||||
if (r != lenses.end()) {
|
||||
return r->second;
|
||||
} else {
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
};
|
||||
OLLensTypeInterpreter olLensTypeInterpreter;
|
||||
|
||||
class OLFlashTypeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLFlashTypeInterpreter ()
|
||||
{
|
||||
choices[0] = "None";
|
||||
choices[2] = "Simple E-System";
|
||||
choices[3] = "E-System";
|
||||
}
|
||||
};
|
||||
OLFlashTypeInterpreter olFlashTypeInterpreter;
|
||||
|
||||
class OLExposureModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLExposureModeInterpreter ()
|
||||
{
|
||||
choices[1] = "Manual";
|
||||
choices[2] = "Program";
|
||||
choices[3] = "Aperture-priority AE";
|
||||
choices[4] = "Shutter speed priority AE";
|
||||
choices[5] = "Program-shift";
|
||||
}
|
||||
};
|
||||
OLExposureModeInterpreter olExposureModeInterpreter;
|
||||
|
||||
class OLMeteringModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLMeteringModeInterpreter ()
|
||||
{
|
||||
choices[2] = "Center-weighted average";
|
||||
choices[3] = "Spot";
|
||||
choices[5] = "ESP";
|
||||
choices[261] = "Pattern+AF";
|
||||
choices[515] = "Spot+Highlight control";
|
||||
choices[1027] = "Spot+Shadow control";
|
||||
}
|
||||
};
|
||||
OLMeteringModeInterpreter olMeteringModeInterpreter;
|
||||
|
||||
class OLFocusModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLFocusModeInterpreter ()
|
||||
{
|
||||
choices[0] = "Single AF";
|
||||
choices[1] = "Sequential shooting AF";
|
||||
choices[2] = "Continuous AF";
|
||||
choices[3] = "Multi AF";
|
||||
choices[4] = "Face detect";
|
||||
choices[10] = "MF";
|
||||
}
|
||||
};
|
||||
OLFocusModeInterpreter olFocusModeInterpreter;
|
||||
|
||||
class OLWhitebalance2Interpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLWhitebalance2Interpreter ()
|
||||
{
|
||||
choices[0] = "Auto";
|
||||
choices[1] = "Auto (Keep Warm Color Off)";
|
||||
choices[16] = "7500K (Fine Weather with Shade)";
|
||||
choices[17] = "6000K (Cloudy)";
|
||||
choices[18] = "5300K (Fine Weather)";
|
||||
choices[20] = "3000K (Tungsten light)";
|
||||
choices[21] = "3600K (Tungsten light-like)";
|
||||
choices[22] = "Auto Setup";
|
||||
choices[23] = "5500K (Flash)";
|
||||
choices[33] = "6600K (Daylight fluorescent)";
|
||||
choices[34] = "4500K (Neutral white fluorescent)";
|
||||
choices[35] = "4000K (Cool white fluorescent)";
|
||||
choices[36] = "White Fluorescent";
|
||||
choices[48] = "3600K (Tungsten light-like)";
|
||||
choices[67] = "Underwater";
|
||||
choices[256] = "One Touch WB 1";
|
||||
choices[257] = "One Touch WB 2";
|
||||
choices[258] = "One Touch WB 3";
|
||||
choices[259] = "One Touch WB 4";
|
||||
choices[512] = "Custom WB 1";
|
||||
choices[513] = "Custom WB 2";
|
||||
choices[514] = "Custom WB 3";
|
||||
choices[515] = "Custom WB 4";
|
||||
}
|
||||
};
|
||||
OLWhitebalance2Interpreter olWhitebalance2Interpreter;
|
||||
|
||||
class OLSceneModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLSceneModeInterpreter ()
|
||||
{
|
||||
choices[0] = "Standard";
|
||||
choices[6] = "Auto";
|
||||
choices[7] = "Sport";
|
||||
choices[8] = "Portrait";
|
||||
choices[9] = "Landscape+Portrait";
|
||||
choices[10] = "Landscape";
|
||||
choices[11] = "Night Scene";
|
||||
choices[12] = "Self Portrait";
|
||||
choices[13] = "Panorama";
|
||||
choices[14] = "2 in 1";
|
||||
choices[15] = "Movie";
|
||||
choices[16] = "Landscape+Portrait";
|
||||
choices[17] = "Night+Portrait";
|
||||
choices[18] = "Indoor";
|
||||
choices[19] = "Fireworks";
|
||||
choices[20] = "Sunset";
|
||||
choices[21] = "Beauty Skin";
|
||||
choices[22] = "Macro";
|
||||
choices[23] = "Super Macro";
|
||||
choices[24] = "Food";
|
||||
choices[25] = "Documents";
|
||||
choices[26] = "Museum";
|
||||
choices[27] = "Shoot & Select";
|
||||
choices[28] = "Beach & Snow";
|
||||
choices[29] = "Self Portrait+Timer";
|
||||
choices[30] = "Candle";
|
||||
choices[31] = "Available Light";
|
||||
choices[32] = "Behind Glass";
|
||||
choices[33] = "My Mode";
|
||||
choices[34] = "Pet";
|
||||
choices[35] = "Underwater Wide1";
|
||||
choices[36] = "Underwater Macro";
|
||||
choices[37] = "Shoot & Select1";
|
||||
choices[38] = "Shoot & Select2";
|
||||
choices[39] = "High Key";
|
||||
choices[40] = "Digital Image Stabilization";
|
||||
choices[41] = "Auction";
|
||||
choices[42] = "Beach";
|
||||
choices[43] = "Snow";
|
||||
choices[44] = "Underwater Wide2";
|
||||
choices[45] = "Low Key";
|
||||
choices[46] = "Children";
|
||||
choices[47] = "Vivid";
|
||||
choices[48] = "Nature Macro";
|
||||
choices[49] = "Underwater Snapshot";
|
||||
choices[50] = "Shooting Guide";
|
||||
choices[54] = "Face Portrait";
|
||||
choices[57] = "Bulb";
|
||||
choices[59] = "Smile Shot";
|
||||
choices[60] = "Quick Shutter";
|
||||
choices[63] = "Slow Shutter";
|
||||
choices[64] = "Bird Watching";
|
||||
choices[65] = "Multiple Exposure";
|
||||
choices[66] = "e-Portrait";
|
||||
choices[67] = "Soft Background Shot";
|
||||
choices[142] = "Hand-held Starlight";
|
||||
choices[154] = "HDR";
|
||||
}
|
||||
};
|
||||
OLSceneModeInterpreter olSceneModeInterpreter;
|
||||
|
||||
class OLPictureModeBWFilterInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLPictureModeBWFilterInterpreter ()
|
||||
{
|
||||
choices[0] = "n/a";
|
||||
choices[1] = "Neutral";
|
||||
choices[2] = "Yellow";
|
||||
choices[3] = "Orange";
|
||||
choices[4] = "Red";
|
||||
choices[5] = "Green";
|
||||
}
|
||||
};
|
||||
OLPictureModeBWFilterInterpreter olPictureModeBWFilterInterpreter;
|
||||
|
||||
class OLPictureModeToneInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLPictureModeToneInterpreter ()
|
||||
{
|
||||
choices[0] = "n/a";
|
||||
choices[1] = "Neutral";
|
||||
choices[2] = "Sepia";
|
||||
choices[3] = "Blue";
|
||||
choices[4] = "Purple";
|
||||
choices[5] = "Green";
|
||||
}
|
||||
};
|
||||
OLPictureModeToneInterpreter olPictureModeToneInterpreter;
|
||||
|
||||
class OLImageQuality2Interpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLImageQuality2Interpreter ()
|
||||
{
|
||||
choices[1] = "SQ";
|
||||
choices[2] = "HQ";
|
||||
choices[3] = "SHQ";
|
||||
choices[4] = "RAW";
|
||||
choices[5] = "SQ (5)";
|
||||
}
|
||||
};
|
||||
OLImageQuality2Interpreter olImageQuality2Interpreter;
|
||||
|
||||
class OLDevEngineInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
// RawDevEngine
|
||||
OLDevEngineInterpreter ()
|
||||
{
|
||||
choices[0] = "High Speed";
|
||||
choices[1] = "High Function";
|
||||
choices[2] = "Advanced High Speed";
|
||||
choices[3] = "Advanced High Function";
|
||||
}
|
||||
};
|
||||
OLDevEngineInterpreter olDevEngineInterpreter;
|
||||
|
||||
class OLPictureModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLPictureModeInterpreter ()
|
||||
{
|
||||
choices[1] = "Vivid";
|
||||
choices[2] = "Natural";
|
||||
choices[3] = "Muted";
|
||||
choices[4] = "Portrait";
|
||||
choices[5] = "i-Enhance";
|
||||
choices[7] = "Color Creator";
|
||||
choices[9] = "Color Profile 1";
|
||||
choices[10] = "Color Profile 2";
|
||||
choices[11] = "Color Profile 3";
|
||||
choices[12] = "Monochrome Profile 1";
|
||||
choices[13] = "Monochrome Profile 2";
|
||||
choices[14] = "Monochrome Profile 3";
|
||||
choices[256] = "Monotone";
|
||||
choices[512] = "Sepia";
|
||||
}
|
||||
};
|
||||
OLPictureModeInterpreter olPictureModeInterpreter;
|
||||
|
||||
class OLColorSpaceInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLColorSpaceInterpreter ()
|
||||
{
|
||||
choices[0] = "sRGB";
|
||||
choices[1] = "Adobe RGB";
|
||||
choices[2] = "Pro Photo RGB";
|
||||
}
|
||||
};
|
||||
OLColorSpaceInterpreter olColorSpaceInterpreter;
|
||||
|
||||
class OLNoiseFilterInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
OLNoiseFilterInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
int a = t->toInt (0);
|
||||
int b = t->toInt (2);
|
||||
int c = t->toInt (4);
|
||||
|
||||
if (a == -1 && b == -2 && c == 1) {
|
||||
return "Low";
|
||||
} else if (a == -2 && b == -2 && c == 1) {
|
||||
return "Off";
|
||||
} else if (a == 0 && b == -2 && c == 1) {
|
||||
return "Standard";
|
||||
} else if (a == 1 && b == -2 && c == 1) {
|
||||
return "High";
|
||||
} else {
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
};
|
||||
OLNoiseFilterInterpreter olNoiseFilterInterpreter;
|
||||
|
||||
class OLFlashModeInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
OLFlashModeInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
std::ostringstream str;
|
||||
int a = t->toInt ();
|
||||
str << "Flash Used = " << ((a & 1) ? "Yes" : "No") << std::endl;
|
||||
str << "Fill-in = " << ((a & 2) ? "On" : "Off") << std::endl;
|
||||
str << "Red-eye = " << ((a & 4) ? "On" : "Off") << std::endl;
|
||||
str << "Slow-sync = " << ((a & 8) ? "On" : "Off") << std::endl;
|
||||
str << "Forced On = " << ((a & 16) ? "On" : "Off") << std::endl;
|
||||
str << "2nd Curtain = " << ((a & 32) ? "On" : "Off");
|
||||
return str.str();
|
||||
}
|
||||
};
|
||||
OLFlashModeInterpreter olFlashModeInterpreter;
|
||||
|
||||
class OLNoiseReductionInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
OLNoiseReductionInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
std::ostringstream str;
|
||||
int a = t->toInt ();
|
||||
str << "Noise Reduction = " << ((a & 1) ? "On" : "Off") << std::endl;
|
||||
str << "Noise Filter = " << ((a & 2) ? "On" : "Off") << std::endl;
|
||||
str << "Noise Filter (ISO Boost) = " << ((a & 4) ? "On" : "Off") << std::endl;
|
||||
str << "Auto = " << ((a & 8) ? "On" : "Off");
|
||||
return str.str();
|
||||
}
|
||||
};
|
||||
OLNoiseReductionInterpreter olNoiseReductionInterpreter;
|
||||
|
||||
class OLFlashModelInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLFlashModelInterpreter ()
|
||||
{
|
||||
choices[0] = "None";
|
||||
choices[1] = "FL-20";
|
||||
choices[2] = "FL-50";
|
||||
choices[3] = "RF-11";
|
||||
choices[4] = "TF-22";
|
||||
choices[5] = "FL-36";
|
||||
choices[6] = "FL-50R";
|
||||
choices[7] = "FL-36R";
|
||||
choices[9] = "FL-14";
|
||||
choices[11] = "FL-600R";
|
||||
}
|
||||
};
|
||||
OLFlashModelInterpreter olFlashModelInterpreter;
|
||||
|
||||
const TagAttrib olyFocusInfoAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0000, AUTO, "FocusInfoVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0209, AUTO, "AutoFocus", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0210, AUTO, "SceneDetect", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0211, AUTO, "SceneArea", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0212, AUTO, "SceneDetectData", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0300, AUTO, "ZoomStepCount", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0301, AUTO, "FocusStepCount", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0303, AUTO, "FocusStepInfinity", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0304, AUTO, "FocusStepNear", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0305, AUTO, "FocusDistance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0308, AUTO, "AFPoint", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1201, AUTO, "ExternalFlash", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1203, AUTO, "ExternalFlashGuideNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1204, AUTO, "ExternalFlashBounce", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1205, AUTO, "ExternalFlashZoom", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1208, AUTO, "InternalFlash", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1209, AUTO, "ManualFlash", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1500, AUTO, "SensorTemperature", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1600, AUTO, "ImageStabilization", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
|
||||
const TagAttrib olyImageProcessingAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0000, AUTO, "ImageProcessingVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0100, AUTO, "WB_RBLevels", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0102, AUTO, "WB_RBLevels3000K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0103, AUTO, "WB_RBLevels3300K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0104, AUTO, "WB_RBLevels3600K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0105, AUTO, "WB_RBLevels3900K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0106, AUTO, "WB_RBLevels4000K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0107, AUTO, "WB_RBLevels4300K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0108, AUTO, "WB_RBLevels4500K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0109, AUTO, "WB_RBLevels4800K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010a, AUTO, "WB_RBLevels5300K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010b, AUTO, "WB_RBLevels6000K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010c, AUTO, "WB_RBLevels6600K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010d, AUTO, "WB_RBLevels7500K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010e, AUTO, "WB_RBLevelsCWB1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010f, AUTO, "WB_RBLevelsCWB2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0110, AUTO, "WB_RBLevelsCWB3", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0111, AUTO, "WB_RBLevelsCWB4", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0113, AUTO, "WB_GLevel3000K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0114, AUTO, "WB_GLevel3300K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0115, AUTO, "WB_GLevel3600K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0116, AUTO, "WB_GLevel3900K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0117, AUTO, "WB_GLevel4000K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0118, AUTO, "WB_GLevel4300K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0119, AUTO, "WB_GLevel4500K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x011a, AUTO, "WB_GLevel4800K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x011b, AUTO, "WB_GLevel5300K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x011c, AUTO, "WB_GLevel6000K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x011d, AUTO, "WB_GLevel6600K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x011e, AUTO, "WB_GLevel7500K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x011f, AUTO, "WB_GLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0200, AUTO, "ColorMatrix", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0300, AUTO, "Enhancer", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0301, AUTO, "EnhancerValues", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0310, AUTO, "CoringFilter", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0311, AUTO, "CoringValues", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0600, AUTO, "BlackLevel2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0610, AUTO, "GainBase", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0611, AUTO, "ValidBits", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0612, AUTO, "CropLeft", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0613, AUTO, "CropTop", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0614, AUTO, "CropWidth", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0615, AUTO, "CropHeight", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1010, AUTO, "NoiseReduction2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1011, AUTO, "DistortionCorrection2", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1012, AUTO, "ShadingCompensation2", &olOnOffInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x1103, AUTO, "UnknownBlock", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1200, AUTO, "FaceDetect", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1201, AUTO, "FaceDetectArea", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
|
||||
const TagAttrib olyRawDevelopmentAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0000, AUTO, "RawDevVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0100, AUTO, "RawDevExposureBiasValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0101, AUTO, "RawDevWhiteBalanceValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0102, AUTO, "RawDevWBFineAdjustment", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0103, AUTO, "RawDevGrayPoint", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0104, AUTO, "RawDevSaturationEmphasis", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0105, AUTO, "RawDevMemoryColorEmphasis", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0106, AUTO, "RawDevContrastValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0107, AUTO, "RawDevSharpnessValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0108, AUTO, "RawDevColorSpace", &olColorSpaceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0109, AUTO, "RawDevEngine", &olDevEngineInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010a, AUTO, "RawDevNoiseReduction", &olNoiseReductionInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010b, AUTO, "RawDevEditStatus", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010c, AUTO, "RawDevSettings", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
|
||||
const TagAttrib olyRawDevelopment2Attribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0000, AUTO, "RawDevVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0100, AUTO, "RawDevExposureBiasValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0101, AUTO, "RawDevWhiteBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0102, AUTO, "RawDevWhiteBalanceValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0103, AUTO, "RawDevWBFineAdjustment", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0104, AUTO, "RawDevGrayPoint", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0105, AUTO, "RawDevContrastValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0106, AUTO, "RawDevSharpnessValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0107, AUTO, "RawDevSaturationEmphasis", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0108, AUTO, "RawDevMemoryColorEmphasis", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0109, AUTO, "RawDevColorSpace", &olColorSpaceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010a, AUTO, "RawDevNoiseReduction", &olNoiseReductionInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010b, AUTO, "RawDevEngine", &olDevEngineInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010c, AUTO, "RawDevPictureMode", &olPictureModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010d, AUTO, "RawDevPMSaturation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010e, AUTO, "RawDevPMContrast", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010f, AUTO, "RawDevPMSharpness", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0110, AUTO, "RawDevPM_BWFilter", &olPictureModeBWFilterInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0111, AUTO, "RawDevPMPictureTone", &olPictureModeToneInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0112, AUTO, "RawDevGradation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0113, AUTO, "RawDevSaturation3", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0119, AUTO, "RawDevAutoGradation", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0120, AUTO, "RawDevPMNoiseFilter", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
|
||||
const TagAttrib olyCameraSettingsAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0000, AUTO, "CameraSettingsVersion", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x0100, AUTO, "PreviewImageValid", &olYesNoInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x0101, AUTO, "PreviewImageStart", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x0102, AUTO, "PreviewImageLength", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0200, AUTO, "ExposureMode", &olExposureModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0201, AUTO, "AELock", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0202, AUTO, "MeteringMode", &olMeteringModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0300, AUTO, "MacroMode", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0301, AUTO, "FocusMode", &olFocusModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0302, AUTO, "FocusProcess", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0303, AUTO, "AFSearch", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0304, AUTO, "AFAreas", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0400, AUTO, "FlashMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0401, AUTO, "FlashExposureComp", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0500, AUTO, "WhiteBalance2", &olWhitebalance2Interpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0501, AUTO, "WhiteBalanceTemperature", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0502, AUTO, "WhiteBalanceBracket", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0503, AUTO, "CustomSaturation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0504, AUTO, "ModifiedSaturation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0505, AUTO, "ContrastSetting", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0506, AUTO, "SharpnessSetting", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0507, AUTO, "ColorSpace", &olColorSpaceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0509, AUTO, "SceneMode", &olSceneModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x050a, AUTO, "NoiseReduction", &olNoiseReductionInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x050b, AUTO, "DistortionCorrection", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x050c, AUTO, "ShadingCompensation", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x050d, AUTO, "CompressionFactor", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x050f, AUTO, "Gradation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0520, AUTO, "PictureMode", &olPictureModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0521, AUTO, "PictureModeSaturation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0522, AUTO, "PictureModeHue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0523, AUTO, "PictureModeContrast", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0524, AUTO, "PictureModeSharpness", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0525, AUTO, "PictureModeBWFilter", &olPictureModeBWFilterInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0526, AUTO, "PictureModeTone", &olPictureModeToneInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0527, AUTO, "NoiseFilter", &olNoiseFilterInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0600, AUTO, "DriveMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0601, AUTO, "PanoramaMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0603, AUTO, "ImageQuality2", &olImageQuality2Interpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0900, AUTO, "ManometerPressure", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0901, AUTO, "ManometerReading", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0902, AUTO, "ExtendedWBDetect", &olOnOffInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
|
||||
const TagAttrib olyEquipmentAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0000, AUTO, "EquipmentVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0100, AUTO, "CameraType2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0101, AUTO, "SerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0102, AUTO, "InternalSerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0103, AUTO, "FocalPlaneDiagonal", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0104, AUTO, "BodyFirmwareVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0201, AUTO, "LensType", &olLensTypeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0202, AUTO, "LensSerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0204, AUTO, "LensFirmwareVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0205, AUTO, "MaxApertureAtMinFocal", &olApertureInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0206, AUTO, "MaxApertureAtMaxFocal", &olApertureInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0207, AUTO, "MinFocalLength", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0208, AUTO, "MaxFocalLength", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x020a, AUTO, "MaxApertureAtCurrentFocal", &olApertureInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x020b, AUTO, "LensProperties", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0301, AUTO, "Extender", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0302, AUTO, "ExtenderSerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0303, AUTO, "ExtenderModel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0304, AUTO, "ExtenderFirmwareVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1000, AUTO, "FlashType", &olFlashTypeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1001, AUTO, "FlashModel", &olFlashModelInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1002, AUTO, "FlashFirmwareVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1003, AUTO, "FlashSerialNumber", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
|
||||
const TagAttrib olympusAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0104, AUTO, "BodyFirmwareVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0200, AUTO, "SpecialMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0201, AUTO, "Quality", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0202, AUTO, "Macro", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0203, AUTO, "BWMode", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0204, AUTO, "DigitalZoom", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0205, AUTO, "FocalPlaneDiagonal", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0206, AUTO, "LensDistortionParams", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0207, AUTO, "CameraType", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x0208, AUTO, "TextInfo", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0209, AUTO, "CameraID", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x020b, AUTO, "EpsonImageWidth", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x020c, AUTO, "EpsonImageHeight", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x020d, AUTO, "EpsonSoftware", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0280, AUTO, "PreviewImage", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0300, AUTO, "PreCaptureFrames", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0301, AUTO, "WhiteBoard", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0302, AUTO, "OneTouchWB", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0303, AUTO, "WhiteBalanceBracket", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0304, AUTO, "WhiteBalanceBias", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0403, AUTO, "SceneMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0404, AUTO, "SerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0405, AUTO, "Firmware", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x0e00, AUTO, "PrintIM", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0f00, AUTO, "DataDump", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0f01, AUTO, "DataDump2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1000, AUTO, "ShutterSpeedValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1001, AUTO, "ISOValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1002, AUTO, "ApertureValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1003, AUTO, "BrightnessValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1004, AUTO, "FlashMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1005, AUTO, "FlashDevice", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1006, AUTO, "ExposureCompensation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1007, AUTO, "SensorTemperature", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1008, AUTO, "LensTemperature", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1009, AUTO, "LightCondition", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x100a, AUTO, "FocusRange", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x100b, AUTO, "FocusMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x100c, AUTO, "ManualFocusDistance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x100d, AUTO, "ZoomStepCount", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x100e, AUTO, "FocusStepCount", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x100f, AUTO, "Sharpness", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1010, AUTO, "FlashChargeLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1011, AUTO, "ColorMatrix", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1012, AUTO, "BlackLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1013, AUTO, "ColorTemperatureBG", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1014, AUTO, "ColorTemperatureRG", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1015, AUTO, "WBMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1017, AUTO, "RedBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1018, AUTO, "BlueBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1019, AUTO, "ColorMatrixNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x101a, AUTO, "SerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x101b, AUTO, "ExternalFlashAE1_0", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x101c, AUTO, "ExternalFlashAE2_0", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x101d, AUTO, "InternalFlashAE1_0", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x101e, AUTO, "InternalFlashAE2_0", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x101f, AUTO, "ExternalFlashAE1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1020, AUTO, "ExternalFlashAE2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1021, AUTO, "InternalFlashAE1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1022, AUTO, "InternalFlashAE2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1023, AUTO, "FlashExposureComp", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1024, AUTO, "InternalFlashTable", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1025, AUTO, "ExternalFlashGValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1026, AUTO, "ExternalFlashBounce", &olYesNoInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1027, AUTO, "ExternalFlashZoom", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1028, AUTO, "ExternalFlashMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1029, AUTO, "Contrast", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x102a, AUTO, "SharpnessFactor", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x102b, AUTO, "ColorControl", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x102c, AUTO, "ValidBits", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x102d, AUTO, "CoringFilter", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x102e, AUTO, "OlympusImageWidth", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x102f, AUTO, "OlympusImageHeight", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1030, AUTO, "SceneDetect", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1031, AUTO, "SceneArea", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1033, AUTO, "SceneDetectData", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1034, AUTO, "CompressionRatio", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x1035, AUTO, "PreviewImageValid", &olYesNoInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x1036, AUTO, "PreviewImageStart", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x1037, AUTO, "PreviewImageLength", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1038, AUTO, "AFResult", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1039, AUTO, "CCDScanMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x103a, AUTO, "NoiseReduction", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x103b, AUTO, "InfinityLensStep", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x103c, AUTO, "NearLensStep", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x103d, AUTO, "LightValueCenter", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x103e, AUTO, "LightValuePeriphery", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x103f, AUTO, "FieldCount", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, olyEquipmentAttribs, 0x2010, AUTO, "Equipment", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, olyCameraSettingsAttribs, 0x2020, AUTO, "CameraSettings", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, olyRawDevelopmentAttribs, 0x2030, AUTO, "RawDevelopment", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, olyRawDevelopment2Attribs, 0x2031, AUTO, "RawDev2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, olyImageProcessingAttribs, 0x2040, AUTO, "ImageProcessing", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, olyFocusInfoAttribs, 0x2050, AUTO, "FocusInfo", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x2100, AUTO, "Olympus2100", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x2300, AUTO, "Olympus2300", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x2400, AUTO, "Olympus2400", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x2500, AUTO, "Olympus2500", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x2600, AUTO, "Olympus2600", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x2700, AUTO, "Olympus2700", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x2800, AUTO, "Olympus2800", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x2900, AUTO, "Olympus2900", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x3000, AUTO, "RawInfo", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
}
|
@ -1,138 +0,0 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "rtexif.h"
|
||||
|
||||
namespace rtexif
|
||||
{
|
||||
|
||||
// TODO: write interpreters
|
||||
|
||||
const TagAttrib panasonicAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0001, AUTO, "Quality", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0002, AUTO, "FirmwareVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0003, AUTO, "WhiteBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0007, AUTO, "FocusMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x000f, AUTO, "AFMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x001a, AUTO, "ImageStabilization", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x001c, AUTO, "Macro", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x001f, AUTO, "ShootingMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0020, AUTO, "Audio", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0023, AUTO, "WhiteBalanceBias", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0024, AUTO, "FlashBias", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0025, AUTO, "InternalSerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0026, AUTO, "ExifVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0028, AUTO, "ColorEffect", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0029, AUTO, "TimeSincePowerOn", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x002a, AUTO, "BurstMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x002b, AUTO, "SequenceNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x002c, AUTO, "Contrast", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x002d, AUTO, "NoiseReduction", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x002e, AUTO, "SelfTimer", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0030, AUTO, "Rotation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0031, AUTO, "AFAssistLamp", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0032, AUTO, "ColorMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0033, AUTO, "BabyAge1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0034, AUTO, "OpticalZoomMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0035, AUTO, "ConversionLens", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0036, AUTO, "TravelDay", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0039, AUTO, "Contrast", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x003a, AUTO, "WorldTimeLocation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x003b, AUTO, "TextStamp1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x003c, AUTO, "ProgramISO", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x003d, AUTO, "AdvancedSceneType", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x003e, AUTO, "TextStamp2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x003f, AUTO, "FacesDetected", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0040, AUTO, "Saturation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0041, AUTO, "Sharpness", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0042, AUTO, "FilmMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0044, AUTO, "ColorTempKelvin", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0045, AUTO, "BracketSettings", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0046, AUTO, "WBAdjustAB", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0047, AUTO, "WBAdjustGM", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0048, AUTO, "FlashCurtain", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0049, AUTO, "LongShutterNoiseReduction", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x004b, AUTO, "ImageWidth", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x004c, AUTO, "ImageHeight", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x004d, AUTO, "AFPointPosition", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x004e, AUTO, "FaceDetInfo", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0051, AUTO, "LensType", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0052, AUTO, "LensSerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0053, AUTO, "AccessoryType", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0054, AUTO, "AccessorySerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0059, AUTO, "Transform1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x005d, AUTO, "IntelligentExposure", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0060, AUTO, "LensFirmwareVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0061, AUTO, "FaceRecInfo", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0062, AUTO, "FlashWarning", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0065, AUTO, "Title", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0066, AUTO, "BabyName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0067, AUTO, "Location", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0069, AUTO, "Country", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x006b, AUTO, "State", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x006d, AUTO, "City", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x006f, AUTO, "Landmark", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0070, AUTO, "IntelligentResolution", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0077, AUTO, "BurstSheed", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0079, AUTO, "IntelligentDRange", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x007c, AUTO, "ClearRetouch", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0080, AUTO, "City2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0086, AUTO, "ManometerPressure", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0089, AUTO, "PhotoStyle", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x008a, AUTO, "ShadingCompensation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x008c, AUTO, "AccelerometerZ", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x008d, AUTO, "AccelerometerX", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x008e, AUTO, "AccelerometerY", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x008f, AUTO, "CameraOrientation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0090, AUTO, "RollAngle", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0091, AUTO, "PitchAngle", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0093, AUTO, "SweepPanoramaDirection", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0094, AUTO, "PanoramaFieldOfView", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0096, AUTO, "TimerRecording", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x009d, AUTO, "InternalNDFilter", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x009e, AUTO, "HDR", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x009f, AUTO, "ShutterType", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x00a3, AUTO, "ClearRetouchValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x00ab, AUTO, "TouchAE", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0e00, AUTO, "PrintIM", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8000, AUTO, "MakerNoteVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8001, AUTO, "SceneMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8004, AUTO, "WBRedLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8005, AUTO, "WBGreenLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8006, AUTO, "WBBlueLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8007, AUTO, "FlashFired", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8008, AUTO, "TextStamp3", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8009, AUTO, "TextStamp4", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8010, AUTO, "BabyAge2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8012, AUTO, "Transform2", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr }
|
||||
};
|
||||
|
||||
const TagAttrib panasonicRawAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0001, AUTO, "Version", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0002, AUTO, "SensorWidth", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0003, AUTO, "SensorHeight", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0004, AUTO, "SensorTopBorder", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0005, AUTO, "SensorLeftBorder", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0006, AUTO, "ImageHeight", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0007, AUTO, "ImageWidth", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0011, AUTO, "RedBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0012, AUTO, "BlueBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0017, AUTO, "ISOSpeed", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0024, AUTO, "WBRedLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0025, AUTO, "WBGreenLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0026, AUTO, "WBBlueLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x002e, AUTO, "PreviewImage", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010f, AUTO, "Make", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0110, AUTO, "Model", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0111, AUTO, "StripOffsets", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0112, AUTO, "Orientation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0116, AUTO, "RowsPerStrip", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0117, AUTO, "StripByteCounts", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0118, AUTO, "RawDataOffset", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr }
|
||||
};
|
||||
|
||||
}
|
3557
rtexif/rtexif.cc
706
rtexif/rtexif.h
@ -1,706 +0,0 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee 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.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <iomanip>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <glibmm/ustring.h>
|
||||
|
||||
#include "../rtengine/noncopyable.h"
|
||||
#include "../rtengine/rawmetadatalocation.h"
|
||||
|
||||
namespace Glib
|
||||
{
|
||||
class KeyFile;
|
||||
}
|
||||
namespace rtengine
|
||||
{
|
||||
|
||||
namespace procparams
|
||||
{
|
||||
class ExifPairs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class CacheImageData;
|
||||
|
||||
namespace rtexif
|
||||
{
|
||||
|
||||
enum TagType {INVALID = 0, BYTE = 1, ASCII = 2, SHORT = 3, LONG = 4, RATIONAL = 5, SBYTE = 6, UNDEFINED = 7, SSHORT = 8, SLONG = 9, SRATIONAL = 10, FLOAT = 11, DOUBLE = 12, OLYUNDEF = 13, AUTO = 98, SUBDIR = 99};
|
||||
enum ActionCode {
|
||||
AC_DONTWRITE, // don't write it to the output
|
||||
AC_WRITE, // write it to the output
|
||||
AC_SYSTEM, // changed by RT (not editable/deletable) - don't write, don't show
|
||||
AC_NEW, // new addition - write, don't show
|
||||
|
||||
AC_INVALID = 100, // invalid state
|
||||
};
|
||||
enum ByteOrder {UNKNOWN = 0, INTEL = 0x4949, MOTOROLA = 0x4D4D};
|
||||
#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
|
||||
const ByteOrder HOSTORDER = INTEL;
|
||||
#else
|
||||
const enum ByteOrder HOSTORDER = MOTOROLA;
|
||||
#endif
|
||||
enum MNKind {NOMK, IFD, HEADERIFD, NIKON3, OLYMPUS2, FUJI, TABLESUBDIR};
|
||||
|
||||
bool extractLensInfo (const std::string &fullname, double &minFocal, double &maxFocal, double &maxApertureAtMinFocal, double &maxApertureAtMaxFocal);
|
||||
|
||||
unsigned short sget2 (unsigned char *s, ByteOrder order);
|
||||
int sget4 (unsigned char *s, ByteOrder order);
|
||||
unsigned short get2 (FILE* f, ByteOrder order);
|
||||
int get4 (FILE* f, ByteOrder order);
|
||||
void sset2 (unsigned short v, unsigned char *s, ByteOrder order);
|
||||
void sset4 (int v, unsigned char *s, ByteOrder order);
|
||||
float int_to_float (int i);
|
||||
short int int2_to_signed (short unsigned int i);
|
||||
|
||||
struct TIFFHeader {
|
||||
|
||||
unsigned short byteOrder;
|
||||
unsigned short fixed;
|
||||
unsigned int ifdOffset;
|
||||
};
|
||||
|
||||
class Tag;
|
||||
class Interpreter;
|
||||
|
||||
/// Structure of information describing an Exif tag
|
||||
struct TagAttrib {
|
||||
int ignore; // =0: never ignore, =1: always ignore, =2: ignore if the subdir type is reduced image, =-1: end of table
|
||||
ActionCode action;
|
||||
int editable;
|
||||
const TagAttrib* subdirAttribs; // !NULL if this tag points to a subdir
|
||||
/** Numeric identifier of tag (or index inside DirectoryTable)
|
||||
To avoid rewriting all the tables, and to address the problem of TagDirectoryTable with heterogeneous tag's type,
|
||||
this parameter is now an unsigned int, where the leftmost 2 bytes represent the tag's type, which by default will be aqual
|
||||
to 0 (INVALID). Only non null tag type will be used. See nikon attrib for an example
|
||||
*/
|
||||
unsigned short ID;
|
||||
TagType type;
|
||||
const char* name;
|
||||
Interpreter* interpreter; // Call back hook
|
||||
};
|
||||
|
||||
const TagAttrib* lookupAttrib (const TagAttrib* dir, const char* field);
|
||||
|
||||
/// A directory of tags
|
||||
class TagDirectory
|
||||
{
|
||||
|
||||
protected:
|
||||
std::vector<Tag*> tags; // tags in the directory
|
||||
const TagAttrib* attribs; // descriptor table to decode the tags
|
||||
ByteOrder order; // byte order
|
||||
TagDirectory* parent; // parent directory (NULL if root)
|
||||
bool parseJPEG;
|
||||
static Glib::ustring getDumpKey (int tagID, const Glib::ustring &tagName);
|
||||
|
||||
public:
|
||||
TagDirectory ();
|
||||
TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib* ta, ByteOrder border, bool skipIgnored = true, bool parseJpeg = true);
|
||||
TagDirectory (TagDirectory* p, const TagAttrib* ta, ByteOrder border);
|
||||
virtual ~TagDirectory ();
|
||||
|
||||
inline ByteOrder getOrder () const
|
||||
{
|
||||
return order;
|
||||
}
|
||||
TagDirectory* getParent ()
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
inline bool getParseJpeg() const
|
||||
{
|
||||
return parseJPEG;
|
||||
}
|
||||
TagDirectory* getRoot ();
|
||||
inline int getCount () const
|
||||
{
|
||||
return tags.size ();
|
||||
}
|
||||
const TagAttrib* getAttrib (int id) const;
|
||||
// Find a Tag by scanning the whole tag tree and stopping at the first occurrence
|
||||
const TagAttrib* getAttrib (const char* name);
|
||||
// Try to get the Tag at a given location. 'name' is a path relative to this directory (e.g. "LensInfo/FocalLength")
|
||||
const TagAttrib* getAttribP (const char* name);
|
||||
const TagAttrib* getAttribTable() const
|
||||
{
|
||||
return attribs;
|
||||
}
|
||||
// Find a Tag by scanning the whole tag tree and stopping at the first occurrence
|
||||
Tag* getTag (const char* name) const;
|
||||
// Try to get the Tag at a given location. 'name' is a path relative to this directory (e.g. "LensInfo/FocalLength")
|
||||
Tag* getTagP (const char* name) const;
|
||||
Tag* getTag (int ID) const;
|
||||
|
||||
// Try to get the Tag in the current directory and in subdirectories
|
||||
// if lookUpward = true, it will scan the parents TagDirectory up to the root one,
|
||||
// but w/o looking into their subdirs
|
||||
Tag* findTag (const char* name, bool lookUpward = false) const;
|
||||
// Find a all Tags with the given name by scanning the whole tag tree
|
||||
std::vector<const Tag*> findTags (const char* name);
|
||||
// Find a all Tags with the given ID by scanning the whole tag tree
|
||||
std::vector<const Tag*> findTags (int ID);
|
||||
// Try to get the Tag in the current directory and in parent directories
|
||||
// (won't look into subdirs)
|
||||
Tag* findTagUpward (const char* name) const;
|
||||
bool getXMPTagValue (const char* name, char* value) const;
|
||||
|
||||
void keepTag (int ID);
|
||||
void addTag (Tag* &a);
|
||||
void addTagFront (Tag* &a);
|
||||
void replaceTag (Tag* a);
|
||||
inline Tag* getTagByIndex (int ix)
|
||||
{
|
||||
return tags[ix];
|
||||
}
|
||||
inline void setOrder (ByteOrder bo)
|
||||
{
|
||||
order = bo;
|
||||
}
|
||||
|
||||
virtual int calculateSize ();
|
||||
virtual int write (int start, unsigned char* buffer);
|
||||
virtual TagDirectory* clone (TagDirectory* parent) const;
|
||||
void applyChange (const std::string &field, const Glib::ustring &value);
|
||||
|
||||
void printAll (unsigned int level = 0) const; // reentrant debug function, keep level=0 on first call !
|
||||
bool CPBDump (const Glib::ustring &commFName, const Glib::ustring &imageFName, const Glib::ustring &profileFName, const Glib::ustring &defaultPParams,
|
||||
const CacheImageData* cfs, const bool flagMode, Glib::KeyFile *keyFile = nullptr, Glib::ustring tagDirName = "") const;
|
||||
void sort ();
|
||||
};
|
||||
|
||||
// a table of tags: id are offset from beginning and not identifiers
|
||||
class TagDirectoryTable: public TagDirectory, public rtengine::NonCopyable
|
||||
{
|
||||
protected:
|
||||
unsigned char *values; // Tags values are saved internally here
|
||||
long zeroOffset; // Offset 0 (index 0) could be at an offset from values
|
||||
long valuesSize; // Size of allocated memory
|
||||
TagType defaultType; // Default type of all tags in this directory
|
||||
public:
|
||||
TagDirectoryTable();
|
||||
TagDirectoryTable (TagDirectory* p, unsigned char *v, int memsize, int offs, TagType type, const TagAttrib* ta, ByteOrder border);
|
||||
TagDirectoryTable (TagDirectory* p, FILE* f, int memsize, int offset, TagType type, const TagAttrib* ta, ByteOrder border);
|
||||
~TagDirectoryTable() override;
|
||||
int calculateSize () override;
|
||||
int write (int start, unsigned char* buffer) override;
|
||||
TagDirectory* clone (TagDirectory* parent) const override;
|
||||
};
|
||||
|
||||
// a class representing a single tag
|
||||
class Tag :
|
||||
public rtengine::NonCopyable
|
||||
{
|
||||
|
||||
protected:
|
||||
unsigned short tag;
|
||||
TagType type;
|
||||
unsigned int count;
|
||||
unsigned char* value;
|
||||
int valuesize;
|
||||
bool keep;
|
||||
bool allocOwnMemory;
|
||||
|
||||
const TagAttrib* attrib;
|
||||
TagDirectory* parent;
|
||||
TagDirectory** directory;
|
||||
MNKind makerNoteKind;
|
||||
bool parseMakerNote (FILE* f, int base, ByteOrder bom );
|
||||
|
||||
public:
|
||||
Tag (TagDirectory* parent, FILE* f, int base); // parse next tag from the file
|
||||
Tag (TagDirectory* parent, const TagAttrib* attr);
|
||||
Tag (TagDirectory* parent, const TagAttrib* attr, unsigned char *data, TagType t);
|
||||
Tag (TagDirectory* parent, const TagAttrib* attr, int data, TagType t); // create a new tag from array (used
|
||||
Tag (TagDirectory* parent, const TagAttrib* attr, const char* data); // create a new tag from array (used
|
||||
|
||||
~Tag ();
|
||||
void initType (unsigned char *data, TagType type);
|
||||
void initInt (int data, TagType t, int count = 1);
|
||||
void initUserComment (const Glib::ustring &text);
|
||||
void initString (const char* text);
|
||||
void initSubDir ();
|
||||
void initSubDir (TagDirectory* dir);
|
||||
void initMakerNote (MNKind mnk, const TagAttrib* ta);
|
||||
void initUndefArray (const char* data, int len);
|
||||
void initLongArray (const char* data, int len);
|
||||
void initRational (int num, int den);
|
||||
|
||||
static void swapByteOrder2 (unsigned char *buffer, int count);
|
||||
|
||||
// get basic tag properties
|
||||
int getID () const
|
||||
{
|
||||
return tag;
|
||||
}
|
||||
int getCount () const
|
||||
{
|
||||
return count;
|
||||
}
|
||||
TagType getType () const
|
||||
{
|
||||
return (attrib && attrib->type > INVALID && attrib->type < AUTO) ? attrib->type : type;
|
||||
}
|
||||
unsigned char* getValue () const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
signed char* getSignedValue () const
|
||||
{
|
||||
return reinterpret_cast<signed char*> (value);
|
||||
}
|
||||
const TagAttrib* getAttrib () const
|
||||
{
|
||||
return attrib;
|
||||
}
|
||||
inline ByteOrder getOrder () const
|
||||
{
|
||||
return parent ? parent->getOrder() : HOSTORDER;
|
||||
}
|
||||
inline TagDirectory* getParent () const
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
int getValueSize () const
|
||||
{
|
||||
return valuesize;
|
||||
}
|
||||
bool getOwnMemory () const
|
||||
{
|
||||
return allocOwnMemory;
|
||||
}
|
||||
|
||||
// read/write value
|
||||
int toInt (int ofs = 0, TagType astype = INVALID) const;
|
||||
void fromInt (int v);
|
||||
double toDouble (int ofs = 0) const;
|
||||
double* toDoubleArray (int ofs = 0) const;
|
||||
void toRational (int& num, int& denom, int ofs = 0) const;
|
||||
void toString (char* buffer, std::size_t size, int ofs = 0) const;
|
||||
void fromString (const char* v, int size = -1);
|
||||
void setInt (int v, int ofs = 0, TagType astype = LONG);
|
||||
int getDistanceFrom (const TagDirectory *root);
|
||||
|
||||
// additional getter/setter for more comfortable use
|
||||
std::string valueToString () const;
|
||||
std::string nameToString (int i = 0);
|
||||
void valueFromString (const std::string& value);
|
||||
void userCommentFromString (const Glib::ustring& text);
|
||||
|
||||
// functions for writing
|
||||
int calculateSize ();
|
||||
int write (int offs, int dataOffs, unsigned char* buffer);
|
||||
Tag* clone (TagDirectory* parent) const;
|
||||
|
||||
// to control if the tag shall be written
|
||||
bool getKeep () const
|
||||
{
|
||||
return keep;
|
||||
}
|
||||
void setKeep (bool k)
|
||||
{
|
||||
keep = k;
|
||||
}
|
||||
|
||||
// get subdirectory (there can be several, the last is NULL)
|
||||
bool isDirectory () const
|
||||
{
|
||||
return directory != nullptr;
|
||||
}
|
||||
TagDirectory* getDirectory (int i = 0)
|
||||
{
|
||||
return (directory) ? directory[i] : nullptr;
|
||||
}
|
||||
|
||||
MNKind getMakerNoteFormat () const
|
||||
{
|
||||
return makerNoteKind;
|
||||
}
|
||||
};
|
||||
|
||||
class ExifManager
|
||||
{
|
||||
|
||||
Tag* saveCIFFMNTag (TagDirectory* root, int len, const char* name);
|
||||
void parseCIFF (int length, TagDirectory* root);
|
||||
void parse (bool isRaw, bool skipIgnored = true, bool parseJpeg = true);
|
||||
|
||||
public:
|
||||
FILE* f;
|
||||
std::unique_ptr<rtengine::RawMetaDataLocation> rml;
|
||||
ByteOrder order;
|
||||
bool onlyFirst; // Only first IFD
|
||||
unsigned int IFDOffset;
|
||||
std::vector<TagDirectory*> roots;
|
||||
std::vector<TagDirectory*> frames;
|
||||
|
||||
ExifManager (FILE* fHandle, std::unique_ptr<rtengine::RawMetaDataLocation> _rml, bool onlyFirstIFD)
|
||||
: f(fHandle), rml(std::move(_rml)), order(UNKNOWN), onlyFirst(onlyFirstIFD),
|
||||
IFDOffset(0) {}
|
||||
|
||||
void setIFDOffset(unsigned int offset);
|
||||
|
||||
|
||||
void parseRaw (bool skipIgnored = true);
|
||||
void parseStd (bool skipIgnored = true);
|
||||
void parseJPEG (int offset = 0); // offset: to extract exif data from a embedded preview/thumbnail
|
||||
void parseTIFF (bool skipIgnored = true);
|
||||
void parseCIFF ();
|
||||
|
||||
/// @brief Get default tag for TIFF
|
||||
/// @param forthis The byte order will be taken from the given directory.
|
||||
/// @return The ownership of the return tags is passed to the caller.
|
||||
static std::vector<Tag*> getDefaultTIFFTags (TagDirectory* forthis);
|
||||
static void createJPEGMarker (const TagDirectory* root, const rtengine::procparams::ExifPairs& changeList, int W, int H, unsigned char *&buffer, unsigned &bufferSize);
|
||||
static int createTIFFHeader (const TagDirectory* root, const rtengine::procparams::ExifPairs& changeList, int W, int H, int bps, const char* profiledata, int profilelen, const char* iptcdata, int iptclen, unsigned char *&buffer, unsigned &bufferSize);
|
||||
static int createPNGMarker(const TagDirectory *root, const rtengine::procparams::ExifPairs &changeList, int W, int H, int bps, const char *iptcdata, int iptclen, unsigned char *&buffer, unsigned &bufferSize);
|
||||
};
|
||||
|
||||
class Interpreter
|
||||
{
|
||||
public:
|
||||
Interpreter () {}
|
||||
virtual ~Interpreter() {};
|
||||
virtual std::string toString (const Tag* t) const
|
||||
{
|
||||
char buffer[1024];
|
||||
t->toString (buffer, sizeof(buffer));
|
||||
std::string s (buffer);
|
||||
std::string::size_type p1 = s.find_first_not_of (' ');
|
||||
|
||||
if ( p1 == std::string::npos ) {
|
||||
return s;
|
||||
} else {
|
||||
return s.substr (p1, s.find_last_not_of (' ') - p1 + 1);
|
||||
}
|
||||
}
|
||||
virtual void fromString (Tag* t, const std::string& value)
|
||||
{
|
||||
if (t->getType() == SHORT || t->getType() == LONG) {
|
||||
t->fromInt (atoi (value.c_str()));
|
||||
} else {
|
||||
t->fromString (value.c_str());
|
||||
}
|
||||
}
|
||||
// Get the value as a double
|
||||
virtual double toDouble (const Tag* t, int ofs = 0)
|
||||
{
|
||||
|
||||
switch (t->getType()) {
|
||||
case SBYTE:
|
||||
return double (int (t->getSignedValue()[ofs]));
|
||||
|
||||
case BYTE:
|
||||
return (double) ((int)t->getValue()[ofs]);
|
||||
|
||||
case ASCII:
|
||||
return 0.0;
|
||||
|
||||
case SSHORT:
|
||||
return (double)int2_to_signed (sget2 (t->getValue() + ofs, t->getOrder()));
|
||||
|
||||
case SHORT:
|
||||
return (double) ((int)sget2 (t->getValue() + ofs, t->getOrder()));
|
||||
|
||||
case SLONG:
|
||||
case LONG:
|
||||
return (double) ((int)sget4 (t->getValue() + ofs, t->getOrder()));
|
||||
|
||||
case SRATIONAL: {
|
||||
const double dividend = (int)sget4 (t->getValue() + ofs, t->getOrder());
|
||||
const double divisor = (int)sget4 (t->getValue() + ofs + 4, t->getOrder());
|
||||
return divisor == 0. ? 0. : dividend / divisor;
|
||||
}
|
||||
|
||||
case RATIONAL: {
|
||||
const double dividend = (uint32_t)sget4 (t->getValue() + ofs, t->getOrder());
|
||||
const double divisor = (uint32_t)sget4 (t->getValue() + ofs + 4, t->getOrder());
|
||||
return divisor == 0. ? 0. : dividend / divisor;
|
||||
}
|
||||
|
||||
case FLOAT:
|
||||
return double (sget4 (t->getValue() + ofs, t->getOrder()));
|
||||
|
||||
case UNDEFINED:
|
||||
return 0.;
|
||||
|
||||
default:
|
||||
return 0.; // Quick fix for missing cases (INVALID, DOUBLE, OLYUNDEF, SUBDIR)
|
||||
}
|
||||
}
|
||||
// Get the value as an int
|
||||
virtual int toInt (const Tag* t, int ofs = 0, TagType astype = INVALID)
|
||||
{
|
||||
if (astype == INVALID || astype == AUTO) {
|
||||
astype = t->getType();
|
||||
}
|
||||
|
||||
switch (astype) {
|
||||
case SBYTE:
|
||||
return int (t->getSignedValue()[ofs]);
|
||||
|
||||
case BYTE:
|
||||
return t->getValue()[ofs];
|
||||
|
||||
case ASCII:
|
||||
return 0;
|
||||
|
||||
case SSHORT:
|
||||
return (int)int2_to_signed (sget2 (t->getValue() + ofs, t->getOrder()));
|
||||
|
||||
case SHORT:
|
||||
return (int)sget2 (t->getValue() + ofs, t->getOrder());
|
||||
|
||||
case SLONG:
|
||||
case LONG:
|
||||
return (int)sget4 (t->getValue() + ofs, t->getOrder());
|
||||
|
||||
case SRATIONAL: {
|
||||
int a = (int)sget4 (t->getValue() + ofs + 4, t->getOrder());
|
||||
return a == 0 ? 0 : (int)sget4 (t->getValue() + ofs, t->getOrder()) / a;
|
||||
}
|
||||
|
||||
case RATIONAL: {
|
||||
uint32_t a = (uint32_t)sget4 (t->getValue() + ofs + 4, t->getOrder());
|
||||
return a == 0 ? 0 : (uint32_t)sget4 (t->getValue() + ofs, t->getOrder()) / a;
|
||||
}
|
||||
|
||||
case FLOAT:
|
||||
return (int)toDouble (t, ofs);
|
||||
|
||||
case UNDEFINED:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return 0; // Quick fix for missing cases (INVALID, DOUBLE, OLYUNDEF, SUBDIR)
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
extern Interpreter stdInterpreter;
|
||||
|
||||
template<typename T = std::uint32_t>
|
||||
class ChoiceInterpreter : public Interpreter
|
||||
{
|
||||
protected:
|
||||
using Choices = std::map<T, std::string>;
|
||||
using ChoicesIterator = typename Choices::const_iterator;
|
||||
Choices choices;
|
||||
public:
|
||||
ChoiceInterpreter () {};
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
const typename std::map<T, std::string>::const_iterator r = choices.find(t->toInt());
|
||||
|
||||
if (r != choices.end()) {
|
||||
return r->second;
|
||||
} else {
|
||||
char buffer[1024];
|
||||
t->toString(buffer, sizeof(buffer));
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template< class T >
|
||||
class IntLensInterpreter : public Interpreter
|
||||
{
|
||||
protected:
|
||||
typedef std::multimap< T, std::string> container_t;
|
||||
typedef typename std::multimap< T, std::string>::const_iterator it_t;
|
||||
typedef std::pair< T, std::string> p_t;
|
||||
container_t choices;
|
||||
|
||||
virtual std::string guess (const T lensID, double focalLength, double maxApertureAtFocal, double *lensInfoArray) const
|
||||
{
|
||||
it_t r;
|
||||
size_t nFound = choices.count ( lensID );
|
||||
|
||||
switch ( nFound ) {
|
||||
case 0: { // lens Unknown
|
||||
std::ostringstream s;
|
||||
s << lensID;
|
||||
return s.str();
|
||||
}
|
||||
|
||||
case 1: // lens found
|
||||
r = choices.find ( lensID );
|
||||
return r->second;
|
||||
|
||||
default:
|
||||
// More than one hit: we must guess
|
||||
break;
|
||||
}
|
||||
|
||||
std::string bestMatch ("Unknown");
|
||||
double a1, a2, f1, f2;
|
||||
|
||||
/* FIRST TRY
|
||||
*
|
||||
* Get the lens info (min/man focal, min/max aperture) and compare them to the possible choice
|
||||
*/
|
||||
if (lensInfoArray) {
|
||||
for ( r = choices.lower_bound ( lensID ); r != choices.upper_bound (lensID); ++r ) {
|
||||
if ( !extractLensInfo ( r->second, f1, f2, a1, a2) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (f1 == lensInfoArray[0] && f2 == lensInfoArray[1] && a1 == lensInfoArray[2] && a2 == lensInfoArray[3])
|
||||
// can't match better! we take this entry as being the one
|
||||
{
|
||||
return r->second;
|
||||
}
|
||||
}
|
||||
|
||||
// No lens found, we update the "unknown" string with the lens info values
|
||||
if (lensInfoArray[0] == lensInfoArray[1]) {
|
||||
bestMatch += Glib::ustring::compose (" (%1mm", int (lensInfoArray[0]));
|
||||
} else {
|
||||
bestMatch += Glib::ustring::compose (" (%1-%2mm", int (lensInfoArray[0]), int (lensInfoArray[1]));
|
||||
}
|
||||
|
||||
if (lensInfoArray[2] == lensInfoArray[3]) {
|
||||
bestMatch += Glib::ustring::compose (" f/%1)", Glib::ustring::format (std::fixed, std::setprecision (1), lensInfoArray[2]));
|
||||
} else
|
||||
bestMatch += Glib::ustring::compose (" f/%1-%2)",
|
||||
Glib::ustring::format (std::fixed, std::setprecision (1), lensInfoArray[2]),
|
||||
Glib::ustring::format (std::fixed, std::setprecision (1), lensInfoArray[3]));
|
||||
}
|
||||
|
||||
/* SECOND TRY
|
||||
*
|
||||
* Choose the best match: thanks to exiftool by Phil Harvey
|
||||
* first throws for "out of focal range" and lower or upper aperture of the lens compared to MaxApertureAtFocal
|
||||
* if the lens is not constant aperture, calculate aprox. aperture of the lens at focalLength
|
||||
* and compare with actual aperture.
|
||||
*/
|
||||
std::ostringstream candidates;
|
||||
double deltaMin = 1000.;
|
||||
|
||||
for ( r = choices.lower_bound ( lensID ); r != choices.upper_bound (lensID); ++r ) {
|
||||
double dif;
|
||||
|
||||
if ( !extractLensInfo ( r->second, f1, f2, a1, a2) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( f1 == 0. || a1 == 0.) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( focalLength < f1 - .5 || focalLength > f2 + 0.5 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( maxApertureAtFocal > 0.1) {
|
||||
double lensAperture;
|
||||
|
||||
if ( maxApertureAtFocal < a1 - 0.15 || maxApertureAtFocal > a2 + 0.15) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( a1 == a2 || f1 == f2) {
|
||||
lensAperture = a1;
|
||||
} else {
|
||||
lensAperture = exp ( log (a1) + (log (a2) - log (a1)) / (log (f2) - log (f1)) * (log (focalLength) - log (f1)) );
|
||||
}
|
||||
|
||||
dif = std::abs (lensAperture - maxApertureAtFocal);
|
||||
} else {
|
||||
dif = 0;
|
||||
}
|
||||
|
||||
if ( dif < deltaMin ) {
|
||||
deltaMin = dif;
|
||||
bestMatch = r->second;
|
||||
}
|
||||
|
||||
if ( dif < 0.15) {
|
||||
if ( candidates.tellp() ) {
|
||||
candidates << "\n or " << r->second;
|
||||
} else {
|
||||
candidates << r->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !candidates.tellp() ) {
|
||||
return bestMatch;
|
||||
} else {
|
||||
return candidates.str();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline static int getTypeSize ( TagType type )
|
||||
{
|
||||
return ("11124811248484"[type < 14 ? type : 0] - '0');
|
||||
}
|
||||
|
||||
extern const TagAttrib exifAttribs[];
|
||||
extern const TagAttrib gpsAttribs[];
|
||||
extern const TagAttrib iopAttribs[];
|
||||
extern const TagAttrib ifdAttribs[];
|
||||
extern const TagAttrib nikon2Attribs[];
|
||||
extern const TagAttrib nikon3Attribs[];
|
||||
extern const TagAttrib canonAttribs[];
|
||||
extern const TagAttrib pentaxAttribs[];
|
||||
extern const TagAttrib pentaxLensDataAttribs[];
|
||||
extern const TagAttrib pentaxLensInfoQAttribs[];
|
||||
extern const TagAttrib pentaxLensCorrAttribs[];
|
||||
extern const TagAttrib pentaxAEInfoAttribs[];
|
||||
extern const TagAttrib pentaxAEInfo2Attribs[];
|
||||
extern const TagAttrib pentaxAEInfo3Attribs[];
|
||||
extern const TagAttrib pentaxCameraSettingsAttribs[];
|
||||
extern const TagAttrib pentaxFlashInfoAttribs[];
|
||||
extern const TagAttrib pentaxSRInfoAttribs[];
|
||||
extern const TagAttrib pentaxSRInfo2Attribs[];
|
||||
extern const TagAttrib pentaxBatteryInfoAttribs[];
|
||||
extern const TagAttrib pentaxCameraInfoAttribs[];
|
||||
extern const TagAttrib fujiAttribs[];
|
||||
extern const TagAttrib minoltaAttribs[];
|
||||
extern const TagAttrib sonyAttribs[];
|
||||
extern const TagAttrib sonyTag9405Attribs[];
|
||||
extern const TagAttrib sonyCameraInfoAttribs[];
|
||||
extern const TagAttrib sonyCameraInfo2Attribs[];
|
||||
extern const TagAttrib sonyCameraSettingsAttribs[];
|
||||
extern const TagAttrib sonyCameraSettingsAttribs2[];
|
||||
extern const TagAttrib sonyCameraSettingsAttribs3[];
|
||||
//extern const TagAttrib sonyDNGMakerNote[];
|
||||
extern const TagAttrib olympusAttribs[];
|
||||
extern const TagAttrib kodakIfdAttribs[];
|
||||
void parseKodakIfdTextualInfo (Tag *textualInfo, Tag* exif);
|
||||
extern const TagAttrib panasonicAttribs[];
|
||||
extern const TagAttrib panasonicRawAttribs[];
|
||||
|
||||
}
|
@ -1,927 +0,0 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
* Copyright (c) 2010 Oliver Duis <www.oliverduis.de>
|
||||
*
|
||||
* RawTherapee 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.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include "rtexif.h"
|
||||
|
||||
namespace rtexif
|
||||
{
|
||||
|
||||
class ColorSpaceInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
ColorSpaceInterpreter ()
|
||||
{
|
||||
choices[1] = "sRGB";
|
||||
choices[2] = "Adobe RGB";
|
||||
choices[0xffff] = "Uncalibrated";
|
||||
}
|
||||
};
|
||||
ColorSpaceInterpreter colorSpaceInterpreter;
|
||||
|
||||
class PreviewColorSpaceInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
PreviewColorSpaceInterpreter ()
|
||||
{
|
||||
choices[0] = "Unknown";
|
||||
choices[1] = "Gray Gamma 2.2";
|
||||
choices[2] = "sRGB";
|
||||
choices[3] = "Adobe RGB";
|
||||
choices[4] = "ProPhoto RGB";
|
||||
}
|
||||
};
|
||||
PreviewColorSpaceInterpreter previewColorSpaceInterpreter;
|
||||
|
||||
class LinearSRGBInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
LinearSRGBInterpreter ()
|
||||
{
|
||||
choices[0] = "Linear";
|
||||
choices[1] = "sRGB";
|
||||
}
|
||||
};
|
||||
LinearSRGBInterpreter linearSRGBInterpreter;
|
||||
|
||||
class DefaultBlackRenderInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
DefaultBlackRenderInterpreter ()
|
||||
{
|
||||
choices[0] = "Auto";
|
||||
choices[1] = "None";
|
||||
}
|
||||
};
|
||||
DefaultBlackRenderInterpreter defaultBlackRenderInterpreter;
|
||||
|
||||
class ExposureProgramInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
ExposureProgramInterpreter ()
|
||||
{
|
||||
choices[0] = "Not defined";
|
||||
choices[1] = "Manual";
|
||||
choices[2] = "Normal program";
|
||||
choices[3] = "Aperture priority";
|
||||
choices[4] = "Shutter priority";
|
||||
choices[5] = "Creative program";
|
||||
choices[6] = "Action program";
|
||||
choices[7] = "Portrait mode";
|
||||
choices[8] = "Landscape mode";
|
||||
}
|
||||
};
|
||||
ExposureProgramInterpreter exposureProgramInterpreter;
|
||||
|
||||
class MeteringModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
MeteringModeInterpreter ()
|
||||
{
|
||||
choices[0] = "Unknown";
|
||||
choices[1] = "Average";
|
||||
choices[2] = "Center weighted";
|
||||
choices[3] = "Spot";
|
||||
choices[4] = "Multispot";
|
||||
choices[5] = "Pattern";
|
||||
choices[6] = "Partial";
|
||||
choices[255] = "Other";
|
||||
}
|
||||
};
|
||||
MeteringModeInterpreter meteringModeInterpreter;
|
||||
|
||||
class ExposureModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
ExposureModeInterpreter ()
|
||||
{
|
||||
choices[0] = "Auto exposure";
|
||||
choices[1] = "Manual exposure";
|
||||
choices[2] = "Auto bracket";
|
||||
}
|
||||
};
|
||||
ExposureModeInterpreter exposureModeInterpreter;
|
||||
|
||||
class WhiteBalanceInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
WhiteBalanceInterpreter ()
|
||||
{
|
||||
choices[0] = "Auto white balance";
|
||||
choices[1] = "Manual white balance";
|
||||
}
|
||||
};
|
||||
WhiteBalanceInterpreter whiteBalanceInterpreter;
|
||||
|
||||
class SceneCaptureInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
SceneCaptureInterpreter ()
|
||||
{
|
||||
choices[0] = "Standard";
|
||||
choices[1] = "Landscape";
|
||||
choices[2] = "Portrait";
|
||||
choices[3] = "Night scene";
|
||||
}
|
||||
};
|
||||
SceneCaptureInterpreter sceneCaptureInterpreter;
|
||||
|
||||
class GainControlInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
GainControlInterpreter ()
|
||||
{
|
||||
choices[0] = "None";
|
||||
choices[1] = "Low gain up";
|
||||
choices[2] = "High gain up";
|
||||
choices[3] = "Low gain down";
|
||||
choices[4] = "High gain down";
|
||||
}
|
||||
};
|
||||
GainControlInterpreter gainControlInterpreter;
|
||||
|
||||
class ContrastInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
ContrastInterpreter ()
|
||||
{
|
||||
choices[0] = "Normal";
|
||||
choices[1] = "Soft";
|
||||
choices[2] = "Hard";
|
||||
}
|
||||
};
|
||||
ContrastInterpreter contrastInterpreter;
|
||||
|
||||
class SharpnessInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
SharpnessInterpreter ()
|
||||
{
|
||||
choices[0] = "Normal";
|
||||
choices[1] = "Soft";
|
||||
choices[2] = "Hard";
|
||||
}
|
||||
};
|
||||
SharpnessInterpreter sharpnessInterpreter;
|
||||
|
||||
class SaturationInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
SaturationInterpreter ()
|
||||
{
|
||||
choices[0] = "Normal";
|
||||
choices[1] = "Low saturation";
|
||||
choices[2] = "High saturation";
|
||||
}
|
||||
};
|
||||
SaturationInterpreter saturationInterpreter;
|
||||
|
||||
class FlashInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
FlashInterpreter ()
|
||||
{
|
||||
choices[0x0000] = "Flash did not fire";
|
||||
choices[0x0001] = "Flash fired";
|
||||
choices[0x0005] = "Strobe return light not detected";
|
||||
choices[0x0007] = "Strobe return light detected";
|
||||
choices[0x0009] = "Flash fired, compulsory flash mode";
|
||||
choices[0x000D] = "Flash fired, compulsory flash mode, return light not detected";
|
||||
choices[0x000F] = "Flash fired, compulsory flash mode, return light detected";
|
||||
choices[0x0010] = "Flash did not fire, compulsory flash mode";
|
||||
choices[0x0018] = "Flash did not fire, auto mode";
|
||||
choices[0x0019] = "Flash fired, auto mode";
|
||||
choices[0x001D] = "Flash fired, auto mode, return light not detected";
|
||||
choices[0x001F] = "Flash fired, auto mode, return light detected";
|
||||
choices[0x0020] = "No flash function";
|
||||
choices[0x0041] = "Flash fired, red-eye reduction mode";
|
||||
choices[0x0045] = "Flash fired, red-eye reduction mode, return light not detected";
|
||||
choices[0x0047] = "Flash fired, red-eye reduction mode, return light detected";
|
||||
choices[0x0049] = "Flash fired, compulsory flash mode, red-eye reduction mode";
|
||||
choices[0x004D] = "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected";
|
||||
choices[0x004F] = "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected";
|
||||
choices[0x0059] = "Flash fired, auto mode, red-eye reduction mode";
|
||||
choices[0x005D] = "Flash fired, auto mode, return light not detected, red-eye reduction mode";
|
||||
choices[0x005F] = "Flash fired, auto mode, return light detected, red-eye reduction mode";
|
||||
}
|
||||
};
|
||||
FlashInterpreter flashInterpreter;
|
||||
|
||||
class LightSourceInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
LightSourceInterpreter ()
|
||||
{
|
||||
choices[0] = "Unknown";
|
||||
choices[1] = "Daylight";
|
||||
choices[2] = "Fluorescent";
|
||||
choices[3] = "Tungsten";
|
||||
choices[4] = "Flash";
|
||||
choices[9] = "Fine weather";
|
||||
choices[10] = "Cloudy weather";
|
||||
choices[11] = "Shade";
|
||||
choices[12] = "Daylight fluorescent";
|
||||
choices[13] = "Day white fluorescent";
|
||||
choices[14] = "Cool white fluorescent";
|
||||
choices[15] = "White fluorescent";
|
||||
choices[17] = "Standard light A";
|
||||
choices[18] = "Standard light B";
|
||||
choices[19] = "Standard light C";
|
||||
choices[20] = "D55";
|
||||
choices[21] = "D65";
|
||||
choices[22] = "D75";
|
||||
choices[23] = "D50";
|
||||
choices[24] = "ISO studio tungsten";
|
||||
choices[255] = "Other light source";
|
||||
}
|
||||
};
|
||||
LightSourceInterpreter lightSourceInterpreter;
|
||||
|
||||
class CompressionInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
CompressionInterpreter ()
|
||||
{
|
||||
choices[1] = "Uncompressed";
|
||||
choices[6] = "JPEG Compression";
|
||||
}
|
||||
};
|
||||
CompressionInterpreter compressionInterpreter;
|
||||
|
||||
class PhotometricInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
PhotometricInterpreter ()
|
||||
{
|
||||
choices[2] = "RGB";
|
||||
choices[6] = "YCbCr";
|
||||
}
|
||||
};
|
||||
PhotometricInterpreter photometricInterpreter;
|
||||
|
||||
class ProfileEmbedPolicyInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
ProfileEmbedPolicyInterpreter ()
|
||||
{
|
||||
choices[0] = "Allow Copying";
|
||||
choices[1] = "Embed if Used";
|
||||
choices[2] = "Never Embed";
|
||||
choices[3] = "No Restrictions";
|
||||
}
|
||||
};
|
||||
ProfileEmbedPolicyInterpreter profileEmbedPolicyInterpreter;
|
||||
|
||||
class PlanarConfigInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
PlanarConfigInterpreter ()
|
||||
{
|
||||
choices[1] = "Chunky format";
|
||||
choices[2] = "Planar format";
|
||||
}
|
||||
};
|
||||
PlanarConfigInterpreter planarConfigInterpreter;
|
||||
|
||||
class FNumberInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
FNumberInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
char buffer[32];
|
||||
double v = t->toDouble();
|
||||
|
||||
if ( v < 0. || v > 1000. ) {
|
||||
return "undef";
|
||||
}
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%0.1f", v);
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
FNumberInterpreter fNumberInterpreter;
|
||||
|
||||
class ApertureInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
ApertureInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
char buffer[32];
|
||||
double v = pow (2.0, t->toDouble() / 2.0);
|
||||
|
||||
if ( v < 0. || v > 1000. ) {
|
||||
return "undef";
|
||||
}
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%.1f", v );
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
ApertureInterpreter apertureInterpreter;
|
||||
|
||||
class ExposureBiasInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
ExposureBiasInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
char buffer[32];
|
||||
double v = t->toDouble();
|
||||
|
||||
if ( v < -1000. || v > 1000. ) {
|
||||
return "undef";
|
||||
}
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%+0.2f", v );
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
ExposureBiasInterpreter exposureBiasInterpreter;
|
||||
|
||||
class ShutterSpeedInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
ShutterSpeedInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
char buffer[32];
|
||||
double d = pow (2.0, -t->toDouble());
|
||||
|
||||
if (d > 0.0 && d <= 0.5) {
|
||||
snprintf(buffer, sizeof(buffer), "1/%.0f", 1.0 / d);
|
||||
} else {
|
||||
snprintf(buffer, sizeof(buffer), "%.1f", d);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
ShutterSpeedInterpreter shutterSpeedInterpreter;
|
||||
|
||||
class ExposureTimeInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
ExposureTimeInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
char buffer[32];
|
||||
double d = t->toDouble();
|
||||
|
||||
if (d > 0.0 && d <= 0.5) {
|
||||
snprintf(buffer, sizeof(buffer), "1/%.0f", 1.0 / d);
|
||||
} else {
|
||||
snprintf(buffer, sizeof(buffer), "%.1f", d);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
ExposureTimeInterpreter exposureTimeInterpreter;
|
||||
|
||||
class FocalLengthInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
FocalLengthInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
char buffer[32];
|
||||
double v = t->toDouble();
|
||||
|
||||
if ( v > 1000000. || v < 0 ) {
|
||||
return "undef";
|
||||
}
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%.1f", v );
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
FocalLengthInterpreter focalLengthInterpreter;
|
||||
|
||||
class UserCommentInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
UserCommentInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
int count = t->getCount();
|
||||
|
||||
if (count <= 8) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
count = std::min (count, 65535); // limit to 65535 chars to avoid crashes in case of corrupted metadata
|
||||
unsigned char *buffer = new unsigned char[count - 6]; // include 2 ending null chars for UCS-2 string (possibly)
|
||||
unsigned char *value = t->getValue();
|
||||
|
||||
if (!memcmp(value, "ASCII\0\0\0", 8)) {
|
||||
memcpy(buffer, value + 8, count - 8);
|
||||
buffer[count - 8] = '\0';
|
||||
} else if (!memcmp(value, "UNICODE\0", 8)) {
|
||||
memcpy(buffer, value + 8, count - 8);
|
||||
buffer[count - 7] = buffer[count - 8] = '\0';
|
||||
Glib::ustring tmp1((char*)buffer);
|
||||
|
||||
|
||||
bool hasBOM = false;
|
||||
enum ByteOrder bo = UNKNOWN;
|
||||
if (count % 2 || (count >= 11 && (buffer[0] == 0xEF && buffer[1] == 0xBB && buffer[2] == 0xBF))) {
|
||||
// odd string length can only be UTF-8, don't change anything
|
||||
std::string retVal ((char*)buffer + 3);
|
||||
delete [] buffer;
|
||||
return retVal;
|
||||
} else if (count >= 10) {
|
||||
if (buffer[0] == 0xFF && buffer[1] == 0xFE) {
|
||||
bo = INTEL; // little endian
|
||||
hasBOM = true;
|
||||
} else if (buffer[0] == 0xFE && buffer[1] == 0xFF) {
|
||||
bo = MOTOROLA; // big endian
|
||||
hasBOM = true;
|
||||
}
|
||||
}
|
||||
if (bo == UNKNOWN) {
|
||||
// auto-detecting byte order; we still don't know if it's UCS-2 or UTF-8
|
||||
int a = 0, b = 0, c = 0, d = 0;
|
||||
for (int j = 8; j < count; j++) {
|
||||
unsigned char cc = value[j];
|
||||
if (!(j%2)) {
|
||||
// counting zeros for first byte
|
||||
if (!cc) {
|
||||
++a;
|
||||
}
|
||||
} else {
|
||||
// counting zeros for second byte
|
||||
if (!cc) {
|
||||
++b;
|
||||
}
|
||||
}
|
||||
if (!(cc & 0x80) || ((cc & 0xC0) == 0xC0) || ((cc & 0xC0) == 0x80)) {
|
||||
++c;
|
||||
}
|
||||
if ((cc & 0xC0) == 0x80) {
|
||||
++d;
|
||||
}
|
||||
}
|
||||
if (c == (count - 8) && d) {
|
||||
// this is an UTF-8 string
|
||||
std::string retVal ((char*)buffer);
|
||||
delete [] buffer;
|
||||
return retVal;
|
||||
}
|
||||
if ((a || b) && a != b) {
|
||||
bo = a > b ? MOTOROLA : INTEL;
|
||||
}
|
||||
}
|
||||
if (bo == UNKNOWN) {
|
||||
// assuming platform's byte order
|
||||
#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
|
||||
bo = INTEL;
|
||||
#else
|
||||
bo = MOTOROLA;
|
||||
#endif
|
||||
}
|
||||
|
||||
// now swapping if necessary
|
||||
if (!hasBOM && bo != HOSTORDER) {
|
||||
if (t->getOrder() != HOSTORDER) {
|
||||
Tag::swapByteOrder2(buffer, count - 8);
|
||||
}
|
||||
}
|
||||
|
||||
glong written;
|
||||
char* utf8Str = g_utf16_to_utf8((unsigned short int*)buffer, -1, nullptr, &written, nullptr);
|
||||
delete [] buffer;
|
||||
buffer = new unsigned char[written + 1];
|
||||
memcpy(buffer, utf8Str, written);
|
||||
buffer[written] = 0;
|
||||
g_free(utf8Str);
|
||||
} else if (!memcmp(value, "\0\0\0\0\0\0\0\0", 8)) {
|
||||
// local charset string, whatever it is
|
||||
memcpy(buffer, value + 8, count - 8);
|
||||
buffer[count - 7] = buffer[count - 8] = '\0';
|
||||
|
||||
gsize written = 0;
|
||||
char *utf8Str = g_locale_to_utf8((char*)buffer, count - 8, nullptr, &written, nullptr);
|
||||
if (utf8Str && written) {
|
||||
delete [] buffer;
|
||||
size_t length = strlen(utf8Str);
|
||||
buffer = new unsigned char[length + 1];
|
||||
strcpy((char*)buffer, utf8Str);
|
||||
} else {
|
||||
buffer[0] = 0;
|
||||
}
|
||||
if (utf8Str) {
|
||||
g_free(utf8Str);
|
||||
}
|
||||
} else {
|
||||
// JIS: unsupported
|
||||
buffer[0] = 0;
|
||||
}
|
||||
|
||||
std::string retVal ((char*)buffer);
|
||||
delete [] buffer;
|
||||
return retVal;
|
||||
}
|
||||
void fromString (Tag* t, const std::string& value) override
|
||||
{
|
||||
Glib::ustring tmpStr(value);
|
||||
t->userCommentFromString (tmpStr);
|
||||
}
|
||||
};
|
||||
UserCommentInterpreter userCommentInterpreter;
|
||||
|
||||
class CFAInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
CFAInterpreter() {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
char colors[] = "RGB";
|
||||
char buffer[1024];
|
||||
|
||||
for ( int i = 0; i < t->getCount(); i++) {
|
||||
unsigned char c = t->toInt (i, BYTE);
|
||||
buffer[i] = c < 3 ? colors[c] : ' ';
|
||||
}
|
||||
|
||||
buffer[t->getCount()] = 0;
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
CFAInterpreter cfaInterpreter;
|
||||
|
||||
class OrientationInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OrientationInterpreter ()
|
||||
{
|
||||
choices[1] = "Horizontal (normal)";
|
||||
choices[2] = "Mirror horizontal ";
|
||||
choices[3] = "Rotate 180";
|
||||
choices[4] = "Mirror vertical";
|
||||
choices[5] = "Mirror horizontal and rotate 270 CW";
|
||||
choices[6] = "Rotate 90 CW";
|
||||
choices[7] = "Mirror horizontal and rotate 90 CW";
|
||||
choices[8] = "Rotate 270 CW";
|
||||
// '9' is an "unofficial" value for Orientation but used by some older cameras that lacks orientation sensor, such as Kodak DCS
|
||||
choices[9] = "Unknown";
|
||||
}
|
||||
};
|
||||
OrientationInterpreter orientationInterpreter;
|
||||
|
||||
class UnitsInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
UnitsInterpreter()
|
||||
{
|
||||
choices[0] = "Unknown";
|
||||
choices[1] = "inches";
|
||||
choices[2] = "cm";
|
||||
}
|
||||
};
|
||||
UnitsInterpreter unitsInterpreter;
|
||||
|
||||
class UTF8BinInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
UTF8BinInterpreter () {}
|
||||
};
|
||||
UTF8BinInterpreter utf8BinInterpreter;
|
||||
|
||||
class RawImageSegmentationInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
int segmentNumber = t->toInt(0, SHORT);
|
||||
int segmentWidth = t->toInt(2, SHORT);
|
||||
int lastSegmentWidth = t->toInt(4, SHORT);
|
||||
|
||||
char buffer[32];
|
||||
snprintf(buffer, sizeof(buffer), "%d %d %d", segmentNumber, segmentWidth, lastSegmentWidth);
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
RawImageSegmentationInterpreter rawImageSegmentationInterpreter;
|
||||
|
||||
const TagAttrib exifAttribs[] = {
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0100, AUTO, "ImageWidth", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0101, AUTO, "ImageHeight", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0102, AUTO, "BitsPerSample", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0103, AUTO, "Compression", &compressionInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0153, AUTO, "SampleFormat", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x828d, AUTO, "CFAPatternDim", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x828e, AUTO, "CFAPattern", &cfaInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x829A, AUTO, "ExposureTime", &exposureTimeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x829D, AUTO, "FNumber", &fNumberInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8822, AUTO, "ExposureProgram", &exposureProgramInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8824, AUTO, "SpectralSensitivity", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8827, AUTO, "ISOSpeedRatings", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8828, AUTO, "OECF", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8832, AUTO, "RecommendedExposureIndex", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9000, AUTO, "ExifVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9003, AUTO, "DateTimeOriginal", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9004, AUTO, "DateTimeDigitized", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x9101, AUTO, "ComponentsConfiguration", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x9102, AUTO, "CompressedBitsPerPixel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9201, AUTO, "ShutterSpeedValue", &shutterSpeedInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9202, AUTO, "ApertureValue", &apertureInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9203, AUTO, "BrightnessValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9204, AUTO, "ExposureBiasValue", &exposureBiasInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9205, AUTO, "MaxApertureValue", &apertureInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9206, AUTO, "SubjectDistance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9207, AUTO, "MeteringMode", &meteringModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9208, AUTO, "LightSource", &lightSourceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9209, AUTO, "Flash", &flashInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x920A, AUTO, "FocalLength", &focalLengthInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9214, AUTO, "SubjectArea", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9215, AUTO, "ExposureIndex", &stdInterpreter}, // Note: exists as 0xA215 too, it should be that way
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0x9216, AUTO, "TIFFEPSStandardID", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9217, AUTO, "SensingMethod", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x927C, AUTO, "MakerNote", &stdInterpreter},
|
||||
{0, AC_WRITE, 1, nullptr, 0x9286, AUTO, "UserComment", &userCommentInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9290, AUTO, "SubSecTime", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9291, AUTO, "SubSecTimeOriginal", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9292, AUTO, "SubSecTimeDigitized", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0xA000, AUTO, "FlashpixVersion", &stdInterpreter},
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0xA001, AUTO, "ColorSpace", &colorSpaceInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0xA002, AUTO, "PixelXDimension", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0xA003, AUTO, "PixelYDimension", &stdInterpreter},
|
||||
{1, AC_DONTWRITE, 0, nullptr, 0xA004, AUTO, "RelatedSoundFile", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, iopAttribs, 0xA005, AUTO, "Interoperability", &stdInterpreter}, // do not enable, as it causes trouble with FUJI files
|
||||
{0, AC_WRITE, 0, nullptr, 0xA20B, AUTO, "FlashEnergy", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA20C, AUTO, "SpatialFrequencyResponse", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA20E, AUTO, "FocalPlaneXResolution", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA20F, AUTO, "FocalPlaneYResolution", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA210, AUTO, "FocalPlaneResolutionUnit", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA214, AUTO, "SubjectLocation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA215, AUTO, "ExposureIndex", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA217, AUTO, "SensingMethod", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA300, AUTO, "FileSource", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA301, AUTO, "SceneType", &stdInterpreter},
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0xA302, AUTO, "CFAPattern", &cfaInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA401, AUTO, "CustomRendered", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA402, AUTO, "ExposureMode", &exposureModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA403, AUTO, "WhiteBalance", &whiteBalanceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA404, AUTO, "DigitalZoomRatio", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA405, AUTO, "FocalLengthIn35mmFilm", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA406, AUTO, "SceneCaptureType", &sceneCaptureInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA407, AUTO, "GainControl", &gainControlInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA408, AUTO, "Contrast", &contrastInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA409, AUTO, "Saturation", &saturationInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA40A, AUTO, "Sharpness", &sharpnessInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA40B, AUTO, "DeviceSettingDescription", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA40C, AUTO, "SubjectDistanceRange", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA420, AUTO, "ImageUniqueID", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA431, AUTO, "SerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA432, AUTO, "LensInfo", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA433, AUTO, "LensMake", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA434, AUTO, "LensModel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA435, AUTO, "LensSerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA500, AUTO, "Gamma", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC618, AUTO, "LinearizationTable", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC619, AUTO, "BlackLevelRepeatDim", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC61A, AUTO, "BlackLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC61B, AUTO, "BlackLevelDeltaH", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC61C, AUTO, "BlackLevelDeltaV", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC61D, AUTO, "WhiteLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC61E, AUTO, "DefaultScale", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC61F, AUTO, "DefaultCropOrigin", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC620, AUTO, "DefaultCropSize", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC621, AUTO, "ColorMatrix1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC622, AUTO, "ColorMatrix2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC623, AUTO, "CameraCalibration1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC624, AUTO, "CameraCalibration2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC625, AUTO, "ReductionMatrix1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC626, AUTO, "ReductionMatrix2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC627, AUTO, "AnalogBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC628, AUTO, "AsShotNeutral", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC629, AUTO, "AsShotWhiteXY", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC62A, AUTO, "BaselineExposure", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC62B, AUTO, "BaselineNoise", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC62C, AUTO, "BaselineSharpness", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC62D, AUTO, "BayerGreenSplit", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC62E, AUTO, "LinearResponseLimit", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC62F, AUTO, "CameraSerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC630, AUTO, "DNGLensInfo", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC631, AUTO, "ChromaBlurRadius", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC632, AUTO, "AntiAliasStrength", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC633, AUTO, "ShadowScale", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC65A, AUTO, "CalibrationIlluminant1", &lightSourceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC65B, AUTO, "CalibrationIlluminant2", &lightSourceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC65C, AUTO, "BestQualityScale", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC65D, AUTO, "RawDataUniqueID", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC68B, AUTO, "OriginalRawFileName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC68D, AUTO, "ActiveArea", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC68E, AUTO, "MaskedAreas", &stdInterpreter},
|
||||
// {0, AC_WRITE, 0, nullptr, 0xC68F, AUTO, "AsShotICCProfile", & ???},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC690, AUTO, "AsShotPreProfileMatrix", &stdInterpreter},
|
||||
// {0, AC_WRITE, 0, nullptr, 0xC691, AUTO, "CurrentICCProfile", & ???},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC692, AUTO, "CurrentPreProfileMatrix", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6BF, AUTO, "ColorimetricReference", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6F3, AUTO, "CameraCalibrationSig", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6F4, AUTO, "ProfileCalibrationSig", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6F5, AUTO, "ProfileIFD", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6F6, AUTO, "AsShotProfileName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6F7, AUTO, "NoiseReductionApplied", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6F8, AUTO, "ProfileName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6F9, AUTO, "ProfileHueSatMapDims", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6FA, AUTO, "ProfileHueSatMapData1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6FB, AUTO, "ProfileHueSatMapData2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6FC, AUTO, "ProfileToneCurve", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6FD, AUTO, "ProfileEmbedPolicy", &profileEmbedPolicyInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6FE, AUTO, "ProfileCopyright", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC714, AUTO, "ForwardMatrix1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC715, AUTO, "ForwardMatrix2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC716, AUTO, "PreviewApplicationName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC717, AUTO, "PreviewApplicationVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC718, AUTO, "PreviewSettingsName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC719, AUTO, "PreviewSettingsDigest", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC71A, AUTO, "PreviewColorSpace", &previewColorSpaceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC71B, AUTO, "PreviewDateTime", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC71C, AUTO, "RawImageDigest", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC71D, AUTO, "OriginalRawFileDigest", &stdInterpreter},
|
||||
// {0, AC_WRITE, 0, nullptr, 0xC71E, AUTO, "SubTileBlockSize", & ???},
|
||||
// {0, AC_WRITE, 0, nullptr, 0xC71F, AUTO, "RowInterleaveFactor", & ???},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC725, AUTO, "ProfileLookTableDims", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC726, AUTO, "ProfileLookTableData", &stdInterpreter},
|
||||
// {0, AC_WRITE, 0, nullptr, 0xC740, AUTO, "OpcodeList1", & ???},
|
||||
// {0, AC_WRITE, 0, nullptr, 0xC741, AUTO, "OpcodeList2", & ???},
|
||||
// {0, AC_WRITE, 0, nullptr, 0xC74E, AUTO, "OpcodeList3", & ???},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC761, AUTO, "NoiseProfile", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC763, AUTO, "TimeCodes", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC764, AUTO, "FrameRate", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC772, AUTO, "TStop", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC789, AUTO, "ReelName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC791, AUTO, "OriginalDefaultFinalSize", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC792, AUTO, "OriginalBestQualitySize", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC793, AUTO, "OriginalDefaultCropSize", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC7A1, AUTO, "CameraLabel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC7A3, AUTO, "ProfileHueSatMapEncoding", &linearSRGBInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC7A4, AUTO, "ProfileLookTableEncoding", &linearSRGBInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC7A5, AUTO, "BaselineExposureOffset", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC7A6, AUTO, "DefaultBlackRender", &defaultBlackRenderInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC7A7, AUTO, "NewRawImageDigest", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC7A8, AUTO, "RawToPreviewGain", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC7B5, AUTO, "DefaultUserCrop", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFDE9, AUTO, "SerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFDEA, AUTO, "Lens", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE4C, AUTO, "RawFile", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE4D, AUTO, "Converter", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE4E, AUTO, "WhiteBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE51, AUTO, "Exposure", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE52, AUTO, "Shadows", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE53, AUTO, "Brightness", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE54, AUTO, "Contrast", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE55, AUTO, "Saturation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE56, AUTO, "Sharpness", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE57, AUTO, "Smoothness", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE58, AUTO, "MoireFilter", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr }
|
||||
};
|
||||
|
||||
|
||||
const TagAttrib gpsAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0000, AUTO, "GPSVersionID", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0001, AUTO, "GPSLatitudeRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0002, AUTO, "GPSLatitude", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0003, AUTO, "GPSLongitudeRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0004, AUTO, "GPSLongitude", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0005, AUTO, "GPSAltitudeRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0006, AUTO, "GPSAltitude", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0007, AUTO, "GPSTimeStamp", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0008, AUTO, "GPSSatelites", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0009, AUTO, "GPSStatus", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x000a, AUTO, "GPSMeasureMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x000b, AUTO, "GPSDOP", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x000c, AUTO, "GPSSpeedRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x000d, AUTO, "GPSSpeed", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x000e, AUTO, "GPSTrackRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x000f, AUTO, "GPSTrack", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0010, AUTO, "GPSImgDirectionRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0011, AUTO, "GPSImgDirection", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0012, AUTO, "GPSMapDatum", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0013, AUTO, "GPSDestLatitudeRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0014, AUTO, "GPSDestLatitude", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0015, AUTO, "GPSDestLongitudeRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0016, AUTO, "GPSDestLongitude", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0017, AUTO, "GPSDestBearingRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0018, AUTO, "GPSDestBearing", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0019, AUTO, "GPSDestDistanceRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x001a, AUTO, "GPSDestDistance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x001b, AUTO, "GPSProcessingMethod", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x001c, AUTO, "GPSAreaInformation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x001d, AUTO, "GPSDateStamp", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x001e, AUTO, "GPSDifferential", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr }
|
||||
};
|
||||
|
||||
const TagAttrib iopAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0001, AUTO, "InteroperabilityIndex", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0002, AUTO, "InteroperabilityVersion", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr }
|
||||
};
|
||||
|
||||
const TagAttrib ifdAttribs[] = {
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0017, AUTO, "PanaISO", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x00fe, AUTO, "NewSubFileType", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0100, AUTO, "ImageWidth", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0101, AUTO, "ImageHeight", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0102, AUTO, "BitsPerSample", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0103, AUTO, "Compression", &compressionInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0106, AUTO, "PhotometricInterpretation", &photometricInterpreter},
|
||||
{0, AC_WRITE, 1, nullptr, 0x010E, AUTO, "ImageDescription", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010F, AUTO, "Make", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0110, AUTO, "Model", &stdInterpreter},
|
||||
{1, AC_DONTWRITE, 0, nullptr, 0x0111, AUTO, "StripOffsets", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0112, AUTO, "Orientation", &orientationInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0115, AUTO, "SamplesPerPixel", &stdInterpreter},
|
||||
{1, AC_DONTWRITE, 0, nullptr, 0x0116, AUTO, "RowsPerStrip", &stdInterpreter},
|
||||
{1, AC_DONTWRITE, 0, nullptr, 0x0117, AUTO, "StripByteCounts", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x011A, AUTO, "XResolution", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x011B, AUTO, "YResolution", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x011C, AUTO, "PlanarConfiguration", &planarConfigInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0128, AUTO, "ResolutionUnit", &unitsInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x012D, AUTO, "TransferFunction", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0131, AUTO, "Software", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0132, AUTO, "DateTime", &stdInterpreter},
|
||||
{0, AC_WRITE, 1, nullptr, 0x013B, AUTO, "Artist", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x013E, AUTO, "WhitePoint", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x013F, AUTO, "PriomaryChromaticities", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, ifdAttribs, 0x014A, AUTO, "SubIFD", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0153, AUTO, "SampleFormat", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0201, AUTO, "JPEGInterchangeFormat", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0202, AUTO, "JPEGInterchangeFormatLength", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0211, AUTO, "YCbCrCoefficients", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0212, AUTO, "YCbCrSubSampling", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0213, AUTO, "YCbCrPositioning", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0214, AUTO, "ReferenceBlackWhite", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x02bc, AUTO, "ApplicationNotes", &utf8BinInterpreter}, // XMP
|
||||
{0, AC_WRITE, 0, nullptr, 0x4746, AUTO, "Rating", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x4749, AUTO, "RatingPercent", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x828d, AUTO, "CFAPatternDim", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x828e, AUTO, "CFAPattern", &cfaInterpreter},
|
||||
{0, AC_WRITE, 0, kodakIfdAttribs, 0x8290, AUTO, "KodakIFD", &stdInterpreter},
|
||||
{0, AC_WRITE, 1, nullptr, 0x8298, AUTO, "Copyright", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x83BB, AUTO, "IPTCData", &stdInterpreter},
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0x8606, AUTO, "LeafData", &stdInterpreter}, // is actually a subdir, but a proprietary format
|
||||
{0, AC_WRITE, 0, exifAttribs, 0x8769, AUTO, "Exif", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x8773, AUTO, "ICCProfile", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, gpsAttribs, 0x8825, AUTO, "GPSInfo", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9003, AUTO, "DateTimeOriginal", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9004, AUTO, "DateTimeDigitized", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9211, AUTO, "ImageNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, iopAttribs, 0xA005, AUTO, "Interoperability", &stdInterpreter},
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0xC4A5, AUTO, "PrintIMInformation", &stdInterpreter},
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0xC612, AUTO, "DNGVersion", &stdInterpreter},
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0xC613, AUTO, "DNGBackwardVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC614, AUTO, "UniqueCameraModel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC615, AUTO, "LocalizedCameraModel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xc62f, AUTO, "CameraSerialNumber", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0xc630, AUTO, "DNGLensInfo", &stdInterpreter},
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0xC634, AUTO, "MakerNote", &stdInterpreter}, //DNGPrivateData
|
||||
{0, AC_SYSTEM, 0, nullptr, 0xC640, AUTO, "RawImageSegmentation", &rawImageSegmentationInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xc65d, AUTO, "RawDataUniqueID", &stdInterpreter},
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0xc761, AUTO, "NoiseProfile", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
}
|
@ -199,7 +199,7 @@ if(WIN32)
|
||||
${RSVG_INCLUDE_DIRS}
|
||||
${TIFF_INCLUDE_DIRS}
|
||||
)
|
||||
link_directories(. "${PROJECT_SOURCE_DIR}/rtexif"
|
||||
link_directories(.
|
||||
${EXTRA_LIBDIR}
|
||||
${GIOMM_LIBRARY_DIRS}
|
||||
${GIO_LIBRARY_DIRS}
|
||||
|
@ -26,6 +26,15 @@
|
||||
#include "../rtengine/procparams.h"
|
||||
#include "../rtengine/settings.h"
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const Glib::ustring INI_GROUP_XMP_SIDECAR = "XmpSidecar";
|
||||
const Glib::ustring INI_XMP_SIDECAR_MD5 = "MD5";
|
||||
|
||||
}
|
||||
|
||||
CacheImageData::CacheImageData() :
|
||||
supported(false),
|
||||
format(FT_Invalid),
|
||||
@ -56,7 +65,9 @@ CacheImageData::CacheImageData() :
|
||||
greenAWBMul(-1.0),
|
||||
blueAWBMul(-1.0),
|
||||
rotate(0),
|
||||
thumbImgType(0)
|
||||
thumbImgType(0),
|
||||
width(-1),
|
||||
height(-1)
|
||||
{
|
||||
}
|
||||
|
||||
@ -106,6 +117,12 @@ int CacheImageData::load (const Glib::ustring& fname)
|
||||
}
|
||||
}
|
||||
|
||||
if (keyFile.has_group(INI_GROUP_XMP_SIDECAR)) {
|
||||
if (keyFile.has_key(INI_GROUP_XMP_SIDECAR, INI_XMP_SIDECAR_MD5)) {
|
||||
xmpSidecarMd5 = keyFile.get_string(INI_GROUP_XMP_SIDECAR, INI_XMP_SIDECAR_MD5);
|
||||
}
|
||||
}
|
||||
|
||||
timeValid = keyFile.has_group ("DateTime");
|
||||
|
||||
if (timeValid) {
|
||||
@ -208,6 +225,12 @@ int CacheImageData::load (const Glib::ustring& fname)
|
||||
if (keyFile.has_key ("FileInfo", "SampleFormat")) {
|
||||
sampleFormat = (rtengine::IIO_Sample_Format)keyFile.get_integer ("FileInfo", "SampleFormat");
|
||||
}
|
||||
if (keyFile.has_key("FileInfo", "Width")) {
|
||||
width = keyFile.get_integer("FileInfo", "Width");
|
||||
}
|
||||
if (keyFile.has_key("FileInfo", "Height")) {
|
||||
height = keyFile.get_integer("FileInfo", "Height");
|
||||
}
|
||||
}
|
||||
|
||||
if (format == FT_Raw && keyFile.has_group ("ExtraRawInfo")) {
|
||||
@ -260,6 +283,8 @@ int CacheImageData::save (const Glib::ustring& fname)
|
||||
keyFile.set_boolean ("General", "RecentlySaved", recentlySaved);
|
||||
keyFile.set_integer ("General", "Rating", rating);
|
||||
|
||||
keyFile.set_string(INI_GROUP_XMP_SIDECAR, INI_XMP_SIDECAR_MD5, xmpSidecarMd5);
|
||||
|
||||
// remove the old implementation of Rank and InTrash from cache
|
||||
if (keyFile.has_key ("General", "Rank")) {
|
||||
keyFile.remove_key("General", "Rank");
|
||||
@ -298,6 +323,8 @@ int CacheImageData::save (const Glib::ustring& fname)
|
||||
keyFile.set_string ("FileInfo", "Filetype", filetype);
|
||||
keyFile.set_integer ("FileInfo", "FrameCount", frameCount);
|
||||
keyFile.set_integer ("FileInfo", "SampleFormat", sampleFormat);
|
||||
keyFile.set_integer("FileInfo", "Width", width);
|
||||
keyFile.set_integer("FileInfo", "Height", height);
|
||||
|
||||
if (format == FT_Raw) {
|
||||
keyFile.set_integer ("ExtraRawInfo", "ThumbImageType", thumbImgType);
|
||||
@ -335,7 +362,3 @@ int CacheImageData::save (const Glib::ustring& fname)
|
||||
}
|
||||
}
|
||||
|
||||
rtengine::procparams::IPTCPairs CacheImageData::getIPTCData(unsigned int frame) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
@ -39,6 +39,9 @@ public:
|
||||
bool inTrashOld; // old implementation of inTrash
|
||||
bool recentlySaved;
|
||||
|
||||
// XMP sidecar info.
|
||||
Glib::ustring xmpSidecarMd5;
|
||||
|
||||
// time/date info
|
||||
bool timeValid;
|
||||
short year;
|
||||
@ -80,6 +83,9 @@ public:
|
||||
QUICK_THUMBNAIL = 1 // was the thumbnail generated from embedded jpeg
|
||||
};
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
CacheImageData ();
|
||||
|
||||
int load (const Glib::ustring& fname);
|
||||
@ -89,30 +95,30 @@ public:
|
||||
// FramesMetaData interface
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
unsigned int getRootCount () const override { return -1; }
|
||||
unsigned int getFrameCount () const override { return frameCount; }
|
||||
bool hasExif (unsigned int frame = 0) const override { return false; }
|
||||
rtexif::TagDirectory* getRootExifData (unsigned int root = 0) const override { return nullptr; }
|
||||
rtexif::TagDirectory* getFrameExifData (unsigned int frame = 0) const override { return nullptr; }
|
||||
rtexif::TagDirectory* getBestExifData (rtengine::ImageSource *imgSource, rtengine::procparams::RAWParams *rawParams) const override { return nullptr; }
|
||||
bool hasIPTC (unsigned int frame = 0) const override { return false; }
|
||||
rtengine::procparams::IPTCPairs getIPTCData (unsigned int frame = 0) const override;
|
||||
tm getDateTime (unsigned int frame = 0) const override { return tm{}; }
|
||||
time_t getDateTimeAsTS(unsigned int frame = 0) const override { return time_t(-1); }
|
||||
int getISOSpeed (unsigned int frame = 0) const override { return iso; }
|
||||
double getFNumber (unsigned int frame = 0) const override { return fnumber; }
|
||||
double getFocalLen (unsigned int frame = 0) const override { return focalLen; }
|
||||
double getFocalLen35mm (unsigned int frame = 0) const override { return focalLen35mm; }
|
||||
float getFocusDist (unsigned int frame = 0) const override { return focusDist; }
|
||||
double getShutterSpeed (unsigned int frame = 0) const override { return shutter; }
|
||||
double getExpComp (unsigned int frame = 0) const override { return atof(expcomp.c_str()); }
|
||||
std::string getMake (unsigned int frame = 0) const override { return camMake; }
|
||||
std::string getModel (unsigned int frame = 0) const override { return camModel; }
|
||||
std::string getLens (unsigned int frame = 0) const override { return lens; }
|
||||
std::string getOrientation (unsigned int frame = 0) const override { return ""; } // TODO
|
||||
int getRating (unsigned int frame = 0) const override { return rating; } // FIXME-piotr : missing rating
|
||||
bool hasExif() const override { return false; }
|
||||
tm getDateTime() const override { return tm{}; }
|
||||
time_t getDateTimeAsTS() const override { return time_t(-1); }
|
||||
int getISOSpeed() const override { return iso; }
|
||||
double getFNumber() const override { return fnumber; }
|
||||
double getFocalLen() const override { return focalLen; }
|
||||
double getFocalLen35mm() const override { return focalLen35mm; }
|
||||
float getFocusDist() const override { return focusDist; }
|
||||
double getShutterSpeed() const override { return shutter; }
|
||||
double getExpComp() const override { return atof(expcomp.c_str()); }
|
||||
std::string getMake() const override { return camMake; }
|
||||
std::string getModel() const override { return camModel; }
|
||||
std::string getLens() const override { return lens; }
|
||||
std::string getOrientation() const override { return ""; } // TODO
|
||||
Glib::ustring getFileName() const override { return ""; }
|
||||
int getRating () const override { return rating; } // FIXME-piotr : missing rating
|
||||
bool getPixelShift () const override { return isPixelShift; }
|
||||
bool getHDR (unsigned int frame = 0) const override { return isHDR; }
|
||||
std::string getImageType (unsigned int frame) const override { return isPixelShift ? "PS" : isHDR ? "HDR" : "STD"; }
|
||||
rtengine::IIOSampleFormat getSampleFormat (unsigned int frame = 0) const override { return sampleFormat; }
|
||||
bool getHDR() const override { return isHDR; }
|
||||
std::string getImageType() const override { return isPixelShift ? "PS" : isHDR ? "HDR" : "STD"; }
|
||||
rtengine::IIOSampleFormat getSampleFormat() const override { return sampleFormat; }
|
||||
void getDimensions(int &w, int &h) const override
|
||||
{
|
||||
w = width;
|
||||
h = height;
|
||||
}
|
||||
};
|
||||
|
@ -97,6 +97,10 @@ Thumbnail* CacheManager::getEntry (const Glib::ustring& fname)
|
||||
}
|
||||
|
||||
const auto cacheName = getCacheFileName ("data", fname, ".txt", md5);
|
||||
const auto xmpSidecarMd5 =
|
||||
rtengine::settings->metadata_xmp_sync != rtengine::Settings::MetadataXmpSync::NONE
|
||||
? getMD5(Thumbnail::xmpSidecarPath(fname))
|
||||
: "";
|
||||
|
||||
// let's see if we have it in the cache
|
||||
{
|
||||
@ -106,6 +110,11 @@ Thumbnail* CacheManager::getEntry (const Glib::ustring& fname)
|
||||
|
||||
if (error == 0 && imageData.supported) {
|
||||
|
||||
if (xmpSidecarMd5 != imageData.xmpSidecarMd5) {
|
||||
updateImageInfo(fname, imageData, xmpSidecarMd5);
|
||||
imageData.save(cacheName);
|
||||
}
|
||||
|
||||
thumbnail.reset (new Thumbnail (this, fname, &imageData));
|
||||
|
||||
if (!thumbnail->isSupported ()) {
|
||||
@ -117,7 +126,7 @@ Thumbnail* CacheManager::getEntry (const Glib::ustring& fname)
|
||||
// if not, create a new one
|
||||
if (!thumbnail) {
|
||||
|
||||
thumbnail.reset (new Thumbnail (this, fname, md5));
|
||||
thumbnail.reset (new Thumbnail (this, fname, md5, xmpSidecarMd5));
|
||||
|
||||
if (!thumbnail->isSupported ()) {
|
||||
thumbnail.reset ();
|
||||
@ -413,3 +422,9 @@ void CacheManager::applyCacheSizeLimitation () const
|
||||
}
|
||||
}
|
||||
|
||||
void CacheManager::updateImageInfo(const Glib::ustring &fname, CacheImageData &imageData, const Glib::ustring &xmpSidecarMd5) const
|
||||
{
|
||||
Thumbnail::infoFromImage(fname, imageData);
|
||||
imageData.xmpSidecarMd5 = xmpSidecarMd5;
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include "../rtengine/noncopyable.h"
|
||||
|
||||
class CacheImageData;
|
||||
class Thumbnail;
|
||||
|
||||
class CacheManager :
|
||||
@ -42,6 +43,7 @@ private:
|
||||
void deleteFiles (const Glib::ustring& fname, const std::string& md5, bool purgeData, bool purgeProfile) const;
|
||||
|
||||
void applyCacheSizeLimitation () const;
|
||||
void updateImageInfo(const Glib::ustring &fname, CacheImageData &imageData, const Glib::ustring &xmpSidecarMd5) const;
|
||||
|
||||
public:
|
||||
static CacheManager* getInstance ();
|
||||
|
@ -79,7 +79,7 @@ constexpr int mouseOverIdToLineId(int mouse_over_id)
|
||||
|
||||
ControlLineManager::ControlLineManager():
|
||||
EditSubscriber(ET_OBJECTS),
|
||||
canvas_area(new Rectangle()),
|
||||
canvas_area(new EditRectangle()),
|
||||
cursor(CSHandOpen),
|
||||
draw_mode(false),
|
||||
drawing_line(false),
|
||||
|
@ -26,9 +26,10 @@
|
||||
class Circle;
|
||||
class Line;
|
||||
class OPIcon;
|
||||
class Rectangle;
|
||||
class EditRectangle;
|
||||
class RTSurface;
|
||||
|
||||
|
||||
struct ControlLine {
|
||||
enum ObjectIndex {
|
||||
LINE,
|
||||
@ -52,7 +53,7 @@ class ControlLineManager: EditSubscriber
|
||||
|
||||
protected:
|
||||
/** Hidden object for capturing mouse events. */
|
||||
std::unique_ptr<Rectangle> canvas_area;
|
||||
std::unique_ptr<EditRectangle> canvas_area;
|
||||
rtengine::Coord drag_delta;
|
||||
std::vector<std::unique_ptr<ControlLine>> control_lines;
|
||||
CursorShape cursor;
|
||||
|
@ -1977,8 +1977,8 @@ void ControlSpotPanel::addControlSpotCurve(Gtk::TreeModel::Row& row)
|
||||
shape_ellipse = new Ellipse();
|
||||
shape_ellipse->datum = Geometry::IMAGE;
|
||||
shape_ellipse->radiusInImageSpace = true;
|
||||
Rectangle* shape_rectangle;
|
||||
shape_rectangle = new Rectangle();
|
||||
EditRectangle* shape_rectangle;
|
||||
shape_rectangle = new EditRectangle();
|
||||
shape_rectangle->datum = Geometry::IMAGE;
|
||||
EditSubscriber::visibleGeometry.push_back(centerCircle); // (curveid - 1) * 7
|
||||
EditSubscriber::visibleGeometry.push_back(shape_ellipse); // (curveid - 1) * 7 + 1
|
||||
@ -2012,7 +2012,7 @@ void ControlSpotPanel::addControlSpotCurve(Gtk::TreeModel::Row& row)
|
||||
shape_ellipse = new Ellipse();
|
||||
shape_ellipse->datum = Geometry::IMAGE;
|
||||
shape_ellipse->radiusInImageSpace = true;
|
||||
shape_rectangle = new Rectangle();
|
||||
shape_rectangle = new EditRectangle();
|
||||
shape_rectangle->datum = Geometry::IMAGE;
|
||||
EditSubscriber::mouseOverGeometry.push_back(centerCircle); // (curveid - 1) * 7
|
||||
EditSubscriber::mouseOverGeometry.push_back(shape_ellipse); // (curveid - 1) * 7 + 1
|
||||
@ -2082,7 +2082,7 @@ void ControlSpotPanel::updateControlSpotCurve(const Gtk::TreeModel::Row& row)
|
||||
};
|
||||
|
||||
const auto updateRectangle = [&](Geometry * geometry) {
|
||||
const auto rectangle = static_cast<Rectangle*>(geometry);
|
||||
const auto rectangle = static_cast<EditRectangle*>(geometry);
|
||||
rectangle->bottomRight.x = origin.x + decayX;
|
||||
rectangle->bottomRight.y = origin.y + decayY;
|
||||
rectangle->topLeft.x = origin.x - decayXL;
|
||||
|
@ -721,7 +721,8 @@ EditorPanel::EditorPanel (FilePanel* filePanel)
|
||||
firstProcessingDone = false;
|
||||
|
||||
// construct toolpanelcoordinator
|
||||
tpc = new ToolPanelCoordinator ();
|
||||
tpc = new ToolPanelCoordinator();
|
||||
tpc->setProgressListener(this);
|
||||
|
||||
// build GUI
|
||||
|
||||
@ -1465,6 +1466,7 @@ void EditorPanel::setProgressState(bool inProcessing)
|
||||
|
||||
void EditorPanel::error(const Glib::ustring& descr)
|
||||
{
|
||||
parent->error(descr);
|
||||
}
|
||||
|
||||
void EditorPanel::error(const Glib::ustring& title, const Glib::ustring& descr)
|
||||
@ -1571,16 +1573,16 @@ void EditorPanel::info_toggled ()
|
||||
|
||||
const rtengine::FramesMetaData* idata = ipc->getInitialImage()->getMetaData();
|
||||
|
||||
if (idata && idata->hasExif(selectedFrame)) {
|
||||
if (idata && idata->hasExif()) {
|
||||
infoString = Glib::ustring::compose ("%1 + %2\n<span size=\"small\">f/</span><span size=\"large\">%3</span> <span size=\"large\">%4</span><span size=\"small\">s</span> <span size=\"small\">%5</span><span size=\"large\">%6</span> <span size=\"large\">%7</span><span size=\"small\">mm</span>",
|
||||
escapeHtmlChars (idata->getMake() + " " + idata->getModel()),
|
||||
escapeHtmlChars (idata->getLens()),
|
||||
Glib::ustring (idata->apertureToString (idata->getFNumber(selectedFrame))),
|
||||
Glib::ustring (idata->shutterToString (idata->getShutterSpeed(selectedFrame))),
|
||||
M ("QINFO_ISO"), idata->getISOSpeed(selectedFrame),
|
||||
Glib::ustring::format (std::setw (3), std::fixed, std::setprecision (2), idata->getFocalLen(selectedFrame)));
|
||||
Glib::ustring (idata->apertureToString (idata->getFNumber())),
|
||||
Glib::ustring (idata->shutterToString (idata->getShutterSpeed())),
|
||||
M ("QINFO_ISO"), idata->getISOSpeed(),
|
||||
Glib::ustring::format (std::setw (3), std::fixed, std::setprecision (2), idata->getFocalLen()));
|
||||
|
||||
expcomp = Glib::ustring (idata->expcompToString (idata->getExpComp(selectedFrame), true)); // maskZeroexpcomp
|
||||
expcomp = Glib::ustring (idata->expcompToString (idata->getExpComp(), true)); // maskZeroexpcomp
|
||||
|
||||
if (!expcomp.empty ()) {
|
||||
infoString = Glib::ustring::compose ("%1 <span size=\"large\">%2</span><span size=\"small\">EV</span>",
|
||||
@ -1593,8 +1595,13 @@ void EditorPanel::info_toggled ()
|
||||
escapeHtmlChars (Glib::path_get_dirname (openThm->getFileName())) + G_DIR_SEPARATOR_S,
|
||||
escapeHtmlChars (Glib::path_get_basename (openThm->getFileName())) );
|
||||
|
||||
int ww = ipc->getFullWidth();
|
||||
int hh = ipc->getFullHeight();
|
||||
int ww = -1, hh = -1;
|
||||
idata->getDimensions(ww, hh);
|
||||
if (ww <= 0) {
|
||||
ww = ipc->getFullWidth();
|
||||
hh = ipc->getFullHeight();
|
||||
}
|
||||
|
||||
//megapixels
|
||||
infoString = Glib::ustring::compose ("%1\n<span size=\"small\">%2 MP (%3x%4)</span>",
|
||||
infoString,
|
||||
@ -1608,7 +1615,7 @@ void EditorPanel::info_toggled ()
|
||||
if (isHDR) {
|
||||
infoString = Glib::ustring::compose ("%1\n" + M("QINFO_HDR"), infoString, numFrames);
|
||||
if (numFrames == 1) {
|
||||
int sampleFormat = idata->getSampleFormat(selectedFrame);
|
||||
int sampleFormat = idata->getSampleFormat();
|
||||
infoString = Glib::ustring::compose ("%1 / %2", infoString, M(Glib::ustring::compose("SAMPLEFORMAT_%1", sampleFormat)));
|
||||
}
|
||||
} else if (isPixelShift) {
|
||||
|
@ -475,31 +475,31 @@ void Polyline::drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, unsigned shor
|
||||
}
|
||||
}
|
||||
|
||||
void Rectangle::setXYWH(int left, int top, int width, int height)
|
||||
void EditRectangle::setXYWH(int left, int top, int width, int height)
|
||||
{
|
||||
topLeft.set(left, top);
|
||||
bottomRight.set(left + width, top + height);
|
||||
}
|
||||
|
||||
void Rectangle::setXYXY(int left, int top, int right, int bottom)
|
||||
void EditRectangle::setXYXY(int left, int top, int right, int bottom)
|
||||
{
|
||||
topLeft.set(left, top);
|
||||
bottomRight.set(right, bottom);
|
||||
}
|
||||
|
||||
void Rectangle::setXYWH(rtengine::Coord topLeft, rtengine::Coord widthHeight)
|
||||
void EditRectangle::setXYWH(rtengine::Coord topLeft, rtengine::Coord widthHeight)
|
||||
{
|
||||
this->topLeft = topLeft;
|
||||
this->bottomRight = topLeft + widthHeight;
|
||||
}
|
||||
|
||||
void Rectangle::setXYXY(rtengine::Coord topLeft, rtengine::Coord bottomRight)
|
||||
void EditRectangle::setXYXY(rtengine::Coord topLeft, rtengine::Coord bottomRight)
|
||||
{
|
||||
this->topLeft = topLeft;
|
||||
this->bottomRight = bottomRight;
|
||||
}
|
||||
|
||||
void Rectangle::drawOuterGeometry(Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem)
|
||||
void EditRectangle::drawOuterGeometry(Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem)
|
||||
{
|
||||
double lineWidth = getOuterLineWidth();
|
||||
if ((flags & F_VISIBLE) && state != INSENSITIVE && lineWidth > 0. && innerLineWidth > 0.) {
|
||||
@ -544,7 +544,7 @@ void Rectangle::drawOuterGeometry(Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuf
|
||||
}
|
||||
}
|
||||
|
||||
void Rectangle::drawInnerGeometry(Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem)
|
||||
void EditRectangle::drawInnerGeometry(Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem)
|
||||
{
|
||||
if (flags & F_VISIBLE) {
|
||||
if (state != INSENSITIVE) {
|
||||
@ -604,7 +604,7 @@ void Rectangle::drawInnerGeometry(Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuf
|
||||
}
|
||||
}
|
||||
|
||||
void Rectangle::drawToMOChannel(Cairo::RefPtr<Cairo::Context> &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem)
|
||||
void EditRectangle::drawToMOChannel(Cairo::RefPtr<Cairo::Context> &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem)
|
||||
{
|
||||
if (flags & F_HOVERABLE) {
|
||||
cr->set_line_width( getMouseOverLineWidth() );
|
||||
|
@ -313,14 +313,14 @@ public:
|
||||
void drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) override;
|
||||
};
|
||||
|
||||
class Rectangle : public Geometry
|
||||
class EditRectangle : public Geometry // New class name to avoid conflict elsewhere (exiv2), would be nicer to put in namespace?
|
||||
{
|
||||
public:
|
||||
rtengine::Coord topLeft;
|
||||
rtengine::Coord bottomRight;
|
||||
bool filled;
|
||||
|
||||
Rectangle ();
|
||||
EditRectangle ();
|
||||
|
||||
void setXYWH(int left, int top, int width, int height);
|
||||
void setXYXY(int left, int top, int right, int bottom);
|
||||
@ -546,7 +546,7 @@ inline Circle::Circle () :
|
||||
false) {
|
||||
}
|
||||
|
||||
inline Rectangle::Rectangle () :
|
||||
inline EditRectangle::EditRectangle () :
|
||||
topLeft (0, 0), bottomRight (10, 10), filled (false) {
|
||||
}
|
||||
|
||||
|
@ -488,6 +488,13 @@ void EditWindow::set_title_decorated(Glib::ustring fname)
|
||||
set_title("RawTherapee " + M("EDITWINDOW_TITLE") + subtitle);
|
||||
}
|
||||
|
||||
void EditWindow::updateExternalEditorWidget(int selectedIndex, const std::vector<ExternalEditor> &editors)
|
||||
{
|
||||
for (const auto& panel : epanels) {
|
||||
panel.second->updateExternalEditorWidget(selectedIndex, editors);
|
||||
}
|
||||
}
|
||||
|
||||
void EditWindow::updateToolPanelToolLocations(
|
||||
const std::vector<Glib::ustring> &favorites, bool cloneFavoriteTools)
|
||||
{
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "guiutils.h"
|
||||
|
||||
class EditorPanel;
|
||||
class ExternalEditor;
|
||||
class RTWindow;
|
||||
|
||||
class EditWindow :
|
||||
@ -66,6 +67,7 @@ public:
|
||||
bool selectEditorPanel(const std::string &name);
|
||||
bool closeOpenEditors();
|
||||
bool isProcessing();
|
||||
void updateExternalEditorWidget(int selectedIndex, const std::vector<ExternalEditor> &editors);
|
||||
void updateToolPanelToolLocations(
|
||||
const std::vector<Glib::ustring> &favorites, bool cloneFavoriteTools);
|
||||
|
||||
|
1084
rtgui/exifpanel.cc
@ -21,9 +21,21 @@
|
||||
#include <memory>
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "toolpanel.h"
|
||||
#include "../rtexif/rtexif.h"
|
||||
|
||||
namespace rtengine
|
||||
{
|
||||
|
||||
namespace procparams
|
||||
{
|
||||
|
||||
class ExifPairs;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ExifPanel final :
|
||||
public Gtk::Box,
|
||||
@ -34,71 +46,82 @@ private:
|
||||
const rtengine::FramesMetaData* idata;
|
||||
const std::unique_ptr<rtengine::procparams::ExifPairs> changeList;
|
||||
const std::unique_ptr<rtengine::procparams::ExifPairs> defChangeList;
|
||||
bool recursiveOp;
|
||||
|
||||
class ExifColumns : public Gtk::TreeModelColumnRecord
|
||||
{
|
||||
public:
|
||||
Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf> > icon;
|
||||
Gtk::TreeModelColumn<Glib::ustring> field;
|
||||
Gtk::TreeModelColumn<Glib::ustring> field_nopango;
|
||||
// Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf>> expander_icon;
|
||||
Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf>> icon;
|
||||
Gtk::TreeModelColumn<std::string> key;
|
||||
Gtk::TreeModelColumn<Glib::ustring> label;
|
||||
Gtk::TreeModelColumn<Glib::ustring> value;
|
||||
Gtk::TreeModelColumn<Glib::ustring> value_nopango;
|
||||
Gtk::TreeModelColumn<Glib::ustring> orig_value;
|
||||
Gtk::TreeModelColumn<rtexif::ActionCode> action;
|
||||
Gtk::TreeModelColumn<bool> editable;
|
||||
Gtk::TreeModelColumn<bool> edited;
|
||||
Gtk::TreeModelColumn<bool> isSeparator;
|
||||
Gtk::TreeModelColumn<bool> active;
|
||||
Gtk::TreeModelColumn<bool> is_group;
|
||||
|
||||
ExifColumns()
|
||||
{
|
||||
add (field);
|
||||
add (value);
|
||||
add (icon);
|
||||
add (action);
|
||||
add (edited);
|
||||
add (field_nopango);
|
||||
add (value_nopango);
|
||||
add (editable);
|
||||
add (orig_value);
|
||||
add (isSeparator);
|
||||
add(key);
|
||||
add(label);
|
||||
add(value);
|
||||
add(icon);
|
||||
add(edited);
|
||||
add(value_nopango);
|
||||
add(editable);
|
||||
add(active);
|
||||
add(is_group);
|
||||
// add(expander_icon);
|
||||
}
|
||||
};
|
||||
Glib::RefPtr<Gdk::Pixbuf> delicon;
|
||||
Glib::RefPtr<Gdk::Pixbuf> keepicon;
|
||||
//Glib::RefPtr<Gdk::Pixbuf> keepicon;
|
||||
Glib::RefPtr<Gdk::Pixbuf> editicon;
|
||||
Glib::RefPtr<Gdk::Pixbuf> open_icon_;
|
||||
Glib::RefPtr<Gdk::Pixbuf> closed_icon_;
|
||||
|
||||
ExifColumns exifColumns;
|
||||
Gtk::TreeView* exifTree;
|
||||
Gtk::ScrolledWindow* scrolledWindow;
|
||||
Glib::RefPtr<Gtk::TreeStore> exifTreeModel;
|
||||
|
||||
Gtk::Button* remove;
|
||||
Gtk::Button* keep;
|
||||
Gtk::Button* add;
|
||||
Gtk::Button* reset;
|
||||
Gtk::Button* resetAll;
|
||||
Gtk::ToggleButton* showAll;
|
||||
Gtk::Button *activate_all_;
|
||||
Gtk::Button *activate_none_;
|
||||
|
||||
Gtk::TreeModel::Children addTag (const Gtk::TreeModel::Children& root, Glib::ustring field, Glib::ustring value, rtexif::ActionCode action, bool editable);
|
||||
void editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib::ustring value);
|
||||
void updateChangeList (Gtk::TreeModel::Children root, std::string prefix);
|
||||
void addDirectory (const rtexif::TagDirectory* dir, Gtk::TreeModel::Children root, bool checkForSeparator = false);
|
||||
Gtk::TreeModel::Children addSeparator();
|
||||
Glib::ustring getSelection (bool onlyifeditable = false);
|
||||
Glib::ustring getSelectedValue();
|
||||
void updateChangeList();
|
||||
void applyChangeList();
|
||||
void keepIt (Gtk::TreeModel::iterator iter);
|
||||
void delIt (Gtk::TreeModel::iterator iter);
|
||||
Gtk::TreeModel::iterator resetIt (Gtk::TreeModel::iterator iter);
|
||||
void removePressed();
|
||||
void keepPressed();
|
||||
Gtk::CellRendererToggle exif_active_renderer_;
|
||||
Gtk::TreeView::Column exif_active_column_;
|
||||
|
||||
std::vector<std::pair<std::string, Glib::ustring>> editableTags;
|
||||
|
||||
std::unordered_set<std::string> initial_active_keys_;
|
||||
std::unordered_set<std::string> cur_active_keys_;
|
||||
|
||||
rtengine::ProgressListener *pl_;
|
||||
|
||||
void addTag(const std::string &key, const std::pair<Glib::ustring, Glib::ustring> &label, const Glib::ustring &value, bool editable, bool edited);
|
||||
void refreshTags();
|
||||
void resetIt(const Gtk::TreeModel::const_iterator& iter);
|
||||
void resetPressed();
|
||||
void resetAllPressed();
|
||||
void addPressed();
|
||||
void showAlltoggled();
|
||||
bool rowSeperatorFunc(const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::iterator& iter);
|
||||
void activateAllPressed();
|
||||
void activateNonePressed();
|
||||
|
||||
void setKeyActive(Gtk::CellRenderer *renderer, const Gtk::TreeModel::iterator &it);
|
||||
void onKeyActiveToggled(const Glib::ustring &path);
|
||||
|
||||
bool all_keys_active() const;
|
||||
std::unordered_set<std::string> get_active_keys() const;
|
||||
|
||||
void onExifTreeClick(GdkEventButton *event);
|
||||
void onExifRowExpanded(const Gtk::TreeModel::iterator &it, const Gtk::TreeModel::Path &path);
|
||||
void onExifRowCollapsed(const Gtk::TreeModel::iterator &it, const Gtk::TreeModel::Path &path);
|
||||
|
||||
void setExifTagValue(Gtk::CellRenderer *renderer, const Gtk::TreeModel::iterator &it);
|
||||
void onEditExifTagValue(const Glib::ustring &path, const Glib::ustring &value);
|
||||
|
||||
public:
|
||||
ExifPanel ();
|
||||
@ -111,8 +134,9 @@ public:
|
||||
void setImageData (const rtengine::FramesMetaData* id);
|
||||
|
||||
void exifSelectionChanged();
|
||||
void row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column);
|
||||
// void row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column);
|
||||
|
||||
void notifyListener();
|
||||
|
||||
void setProgressListener(rtengine::ProgressListener *pl);
|
||||
};
|
||||
|
@ -291,14 +291,14 @@ FilmNegative::FilmNegative() :
|
||||
refSpotButton->signal_toggled().connect(sigc::mem_fun(*this, &FilmNegative::refSpotToggled));
|
||||
|
||||
// Editing geometry; create the spot rectangle
|
||||
Rectangle* const spotRect = new Rectangle();
|
||||
EditRectangle* const spotRect = new EditRectangle();
|
||||
spotRect->filled = false;
|
||||
|
||||
visibleGeometry.push_back(spotRect);
|
||||
|
||||
// Stick a dummy rectangle over the whole image in mouseOverGeometry.
|
||||
// This is to make sure the getCursor() call is fired everywhere.
|
||||
Rectangle* const imgRect = new Rectangle();
|
||||
EditRectangle* const imgRect = new EditRectangle();
|
||||
imgRect->filled = true;
|
||||
|
||||
mouseOverGeometry.push_back(imgRect);
|
||||
@ -564,7 +564,7 @@ CursorShape FilmNegative::getCursor(int objectID, int xPos, int yPos) const
|
||||
bool FilmNegative::mouseOver(int modifierKey)
|
||||
{
|
||||
EditDataProvider* const provider = getEditProvider();
|
||||
Rectangle* const spotRect = static_cast<Rectangle*>(visibleGeometry.at(0));
|
||||
EditRectangle* const spotRect = static_cast<EditRectangle*>(visibleGeometry.at(0));
|
||||
spotRect->setXYWH(provider->posImage.x - 16, provider->posImage.y - 16, 32, 32);
|
||||
|
||||
return true;
|
||||
@ -716,7 +716,7 @@ void FilmNegative::editToggled()
|
||||
|
||||
// Stick a dummy rectangle over the whole image in mouseOverGeometry.
|
||||
// This is to make sure the getCursor() call is fired everywhere.
|
||||
Rectangle* const imgRect = static_cast<Rectangle*>(mouseOverGeometry.at(0));
|
||||
EditRectangle* const imgRect = static_cast<EditRectangle*>(mouseOverGeometry.at(0));
|
||||
imgRect->setXYWH(0, 0, w, h);
|
||||
} else {
|
||||
refSpotCoords.clear();
|
||||
@ -739,7 +739,7 @@ void FilmNegative::refSpotToggled()
|
||||
|
||||
// Stick a dummy rectangle over the whole image in mouseOverGeometry.
|
||||
// This is to make sure the getCursor() call is fired everywhere.
|
||||
Rectangle* const imgRect = static_cast<Rectangle*>(mouseOverGeometry.at(0));
|
||||
EditRectangle* const imgRect = static_cast<EditRectangle*>(mouseOverGeometry.at(0));
|
||||
imgRect->setXYWH(0, 0, w, h);
|
||||
|
||||
} else {
|
||||
|
@ -1246,23 +1246,201 @@ bool MyHScale::on_key_press_event (GdkEventKey* event)
|
||||
}
|
||||
}
|
||||
|
||||
MyFileChooserButton::MyFileChooserButton(const Glib::ustring &title, Gtk::FileChooserAction action):
|
||||
title_(title),
|
||||
action_(action),
|
||||
lbl_("", Gtk::ALIGN_START),
|
||||
show_hidden_(false)
|
||||
class MyFileChooserWidget::Impl
|
||||
{
|
||||
lbl_.set_ellipsize(Pango::ELLIPSIZE_MIDDLE);
|
||||
lbl_.set_justify(Gtk::JUSTIFY_LEFT);
|
||||
set_none();
|
||||
box_.pack_start(lbl_, true, true);
|
||||
Gtk::Image *img = Gtk::manage(new Gtk::Image());
|
||||
img->set_from_icon_name("folder-open", Gtk::ICON_SIZE_BUTTON);
|
||||
box_.pack_start(*Gtk::manage(new Gtk::Separator(Gtk::ORIENTATION_VERTICAL)), false, false, 5);
|
||||
box_.pack_start(*img, false, false);
|
||||
box_.show_all_children();
|
||||
add(box_);
|
||||
signal_clicked().connect(sigc::mem_fun(*this, &MyFileChooserButton::show_chooser));
|
||||
public:
|
||||
Impl(const Glib::ustring &title, Gtk::FileChooserAction action) :
|
||||
title_(title),
|
||||
action_(action)
|
||||
{
|
||||
}
|
||||
|
||||
Glib::ustring title_;
|
||||
Gtk::FileChooserAction action_;
|
||||
std::string filename_;
|
||||
std::string current_folder_;
|
||||
std::vector<Glib::RefPtr<Gtk::FileFilter>> file_filters_;
|
||||
Glib::RefPtr<Gtk::FileFilter> cur_filter_;
|
||||
std::vector<std::string> shortcut_folders_;
|
||||
bool show_hidden_{false};
|
||||
sigc::signal<void> selection_changed_;
|
||||
};
|
||||
|
||||
|
||||
MyFileChooserWidget::MyFileChooserWidget(const Glib::ustring &title, Gtk::FileChooserAction action) :
|
||||
pimpl(new Impl(title, action))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<Gtk::Image> MyFileChooserWidget::make_folder_image()
|
||||
{
|
||||
return std::unique_ptr<Gtk::Image>(new RTImage("folder-open-small.png"));
|
||||
}
|
||||
|
||||
void MyFileChooserWidget::show_chooser(Gtk::Widget *parent)
|
||||
{
|
||||
Gtk::FileChooserDialog dlg(getToplevelWindow(parent), pimpl->title_, pimpl->action_);
|
||||
dlg.add_button(M("GENERAL_CANCEL"), Gtk::RESPONSE_CANCEL);
|
||||
dlg.add_button(M(pimpl->action_ == Gtk::FILE_CHOOSER_ACTION_SAVE ? "GENERAL_SAVE" : "GENERAL_OPEN"), Gtk::RESPONSE_OK);
|
||||
dlg.set_filename(pimpl->filename_);
|
||||
for (auto &f : pimpl->file_filters_) {
|
||||
dlg.add_filter(f);
|
||||
}
|
||||
if (pimpl->cur_filter_) {
|
||||
dlg.set_filter(pimpl->cur_filter_);
|
||||
}
|
||||
for (auto &f : pimpl->shortcut_folders_) {
|
||||
dlg.add_shortcut_folder(f);
|
||||
}
|
||||
if (!pimpl->current_folder_.empty()) {
|
||||
dlg.set_current_folder(pimpl->current_folder_);
|
||||
}
|
||||
dlg.set_show_hidden(pimpl->show_hidden_);
|
||||
int res = dlg.run();
|
||||
if (res == Gtk::RESPONSE_OK) {
|
||||
pimpl->filename_ = dlg.get_filename();
|
||||
pimpl->current_folder_ = dlg.get_current_folder();
|
||||
on_filename_set();
|
||||
pimpl->selection_changed_.emit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MyFileChooserWidget::on_filename_set()
|
||||
{
|
||||
// Sub-classes decide if anything needs to be done.
|
||||
}
|
||||
|
||||
|
||||
sigc::signal<void> &MyFileChooserWidget::signal_selection_changed()
|
||||
{
|
||||
return pimpl->selection_changed_;
|
||||
}
|
||||
|
||||
|
||||
sigc::signal<void> &MyFileChooserWidget::signal_file_set()
|
||||
{
|
||||
return pimpl->selection_changed_;
|
||||
}
|
||||
|
||||
|
||||
std::string MyFileChooserWidget::get_filename() const
|
||||
{
|
||||
return pimpl->filename_;
|
||||
}
|
||||
|
||||
|
||||
bool MyFileChooserWidget::set_filename(const std::string &filename)
|
||||
{
|
||||
pimpl->filename_ = filename;
|
||||
on_filename_set();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void MyFileChooserWidget::add_filter(const Glib::RefPtr<Gtk::FileFilter> &filter)
|
||||
{
|
||||
pimpl->file_filters_.push_back(filter);
|
||||
}
|
||||
|
||||
|
||||
void MyFileChooserWidget::remove_filter(const Glib::RefPtr<Gtk::FileFilter> &filter)
|
||||
{
|
||||
auto it = std::find(pimpl->file_filters_.begin(), pimpl->file_filters_.end(), filter);
|
||||
if (it != pimpl->file_filters_.end()) {
|
||||
pimpl->file_filters_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MyFileChooserWidget::set_filter(const Glib::RefPtr<Gtk::FileFilter> &filter)
|
||||
{
|
||||
pimpl->cur_filter_ = filter;
|
||||
}
|
||||
|
||||
|
||||
std::vector<Glib::RefPtr<Gtk::FileFilter>> MyFileChooserWidget::list_filters() const
|
||||
{
|
||||
return pimpl->file_filters_;
|
||||
}
|
||||
|
||||
|
||||
bool MyFileChooserWidget::set_current_folder(const std::string &filename)
|
||||
{
|
||||
pimpl->current_folder_ = filename;
|
||||
if (pimpl->action_ == Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER) {
|
||||
set_filename(filename);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MyFileChooserWidget::get_current_folder() const
|
||||
{
|
||||
return pimpl->current_folder_;
|
||||
}
|
||||
|
||||
|
||||
bool MyFileChooserWidget::add_shortcut_folder(const std::string &folder)
|
||||
{
|
||||
pimpl->shortcut_folders_.push_back(folder);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool MyFileChooserWidget::remove_shortcut_folder(const std::string &folder)
|
||||
{
|
||||
auto it = std::find(pimpl->shortcut_folders_.begin(), pimpl->shortcut_folders_.end(), folder);
|
||||
if (it != pimpl->shortcut_folders_.end()) {
|
||||
pimpl->shortcut_folders_.erase(it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void MyFileChooserWidget::unselect_all()
|
||||
{
|
||||
pimpl->filename_ = "";
|
||||
on_filename_set();
|
||||
}
|
||||
|
||||
|
||||
void MyFileChooserWidget::unselect_filename(const std::string &filename)
|
||||
{
|
||||
if (pimpl->filename_ == filename) {
|
||||
unselect_all();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MyFileChooserWidget::set_show_hidden(bool yes)
|
||||
{
|
||||
pimpl->show_hidden_ = yes;
|
||||
}
|
||||
|
||||
|
||||
class MyFileChooserButton::Impl
|
||||
{
|
||||
public:
|
||||
Gtk::Box box_;
|
||||
Gtk::Label lbl_{"", Gtk::ALIGN_START};
|
||||
};
|
||||
|
||||
MyFileChooserButton::MyFileChooserButton(const Glib::ustring &title, Gtk::FileChooserAction action):
|
||||
MyFileChooserWidget(title, action),
|
||||
pimpl(new Impl())
|
||||
{
|
||||
pimpl->lbl_.set_ellipsize(Pango::ELLIPSIZE_MIDDLE);
|
||||
pimpl->lbl_.set_justify(Gtk::JUSTIFY_LEFT);
|
||||
on_filename_set();
|
||||
pimpl->box_.pack_start(pimpl->lbl_, true, true);
|
||||
pimpl->box_.pack_start(*Gtk::manage(new Gtk::Separator(Gtk::ORIENTATION_VERTICAL)), false, false, 5);
|
||||
pimpl->box_.pack_start(*Gtk::manage(make_folder_image().release()), false, false);
|
||||
pimpl->box_.show_all_children();
|
||||
add(pimpl->box_);
|
||||
signal_clicked().connect([this]() {
|
||||
show_chooser(this);
|
||||
});
|
||||
|
||||
if (GTK_MINOR_VERSION < 20) {
|
||||
set_border_width(2); // margin doesn't work on GTK < 3.20
|
||||
@ -1271,151 +1449,16 @@ MyFileChooserButton::MyFileChooserButton(const Glib::ustring &title, Gtk::FileCh
|
||||
set_name("MyFileChooserButton");
|
||||
}
|
||||
|
||||
|
||||
void MyFileChooserButton::show_chooser()
|
||||
void MyFileChooserButton::on_filename_set()
|
||||
{
|
||||
Gtk::FileChooserDialog dlg(getToplevelWindow(this), title_, action_);
|
||||
dlg.add_button(M("GENERAL_CANCEL"), Gtk::RESPONSE_CANCEL);
|
||||
dlg.add_button(M(action_ == Gtk::FILE_CHOOSER_ACTION_SAVE ? "GENERAL_SAVE" : "GENERAL_OPEN"), Gtk::RESPONSE_OK);
|
||||
dlg.set_filename(filename_);
|
||||
for (auto &f : file_filters_) {
|
||||
dlg.add_filter(f);
|
||||
}
|
||||
if (cur_filter_) {
|
||||
dlg.set_filter(cur_filter_);
|
||||
}
|
||||
for (auto &f : shortcut_folders_) {
|
||||
dlg.add_shortcut_folder(f);
|
||||
}
|
||||
if (!current_folder_.empty()) {
|
||||
dlg.set_current_folder(current_folder_);
|
||||
}
|
||||
dlg.set_show_hidden(show_hidden_);
|
||||
int res = dlg.run();
|
||||
if (res == Gtk::RESPONSE_OK) {
|
||||
filename_ = dlg.get_filename();
|
||||
current_folder_ = dlg.get_current_folder();
|
||||
lbl_.set_label(Glib::path_get_basename(filename_));
|
||||
selection_changed_.emit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sigc::signal<void> &MyFileChooserButton::signal_selection_changed()
|
||||
{
|
||||
return selection_changed_;
|
||||
}
|
||||
|
||||
|
||||
sigc::signal<void> &MyFileChooserButton::signal_file_set()
|
||||
{
|
||||
return selection_changed_;
|
||||
}
|
||||
|
||||
|
||||
std::string MyFileChooserButton::get_filename() const
|
||||
{
|
||||
return filename_;
|
||||
}
|
||||
|
||||
|
||||
bool MyFileChooserButton::set_filename(const std::string &filename)
|
||||
{
|
||||
filename_ = filename;
|
||||
if (Glib::file_test(filename_, Glib::FILE_TEST_EXISTS)) {
|
||||
lbl_.set_label(Glib::path_get_basename(filename_));
|
||||
if (Glib::file_test(get_filename(), Glib::FILE_TEST_EXISTS)) {
|
||||
pimpl->lbl_.set_label(Glib::path_get_basename(get_filename()));
|
||||
} else {
|
||||
set_none();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void MyFileChooserButton::add_filter(const Glib::RefPtr<Gtk::FileFilter> &filter)
|
||||
{
|
||||
file_filters_.push_back(filter);
|
||||
}
|
||||
|
||||
|
||||
void MyFileChooserButton::remove_filter(const Glib::RefPtr<Gtk::FileFilter> &filter)
|
||||
{
|
||||
auto it = std::find(file_filters_.begin(), file_filters_.end(), filter);
|
||||
if (it != file_filters_.end()) {
|
||||
file_filters_.erase(it);
|
||||
pimpl->lbl_.set_label(Glib::ustring("(") + M("GENERAL_NONE") + ")");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MyFileChooserButton::set_filter(const Glib::RefPtr<Gtk::FileFilter> &filter)
|
||||
{
|
||||
cur_filter_ = filter;
|
||||
}
|
||||
|
||||
|
||||
std::vector<Glib::RefPtr<Gtk::FileFilter>> MyFileChooserButton::list_filters()
|
||||
{
|
||||
return file_filters_;
|
||||
}
|
||||
|
||||
|
||||
bool MyFileChooserButton::set_current_folder(const std::string &filename)
|
||||
{
|
||||
current_folder_ = filename;
|
||||
if (action_ == Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER) {
|
||||
set_filename(filename);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MyFileChooserButton::get_current_folder() const
|
||||
{
|
||||
return current_folder_;
|
||||
}
|
||||
|
||||
|
||||
bool MyFileChooserButton::add_shortcut_folder(const std::string &folder)
|
||||
{
|
||||
shortcut_folders_.push_back(folder);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool MyFileChooserButton::remove_shortcut_folder(const std::string &folder)
|
||||
{
|
||||
auto it = std::find(shortcut_folders_.begin(), shortcut_folders_.end(), folder);
|
||||
if (it != shortcut_folders_.end()) {
|
||||
shortcut_folders_.erase(it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void MyFileChooserButton::unselect_all()
|
||||
{
|
||||
filename_ = "";
|
||||
set_none();
|
||||
}
|
||||
|
||||
|
||||
void MyFileChooserButton::unselect_filename(const std::string &filename)
|
||||
{
|
||||
if (filename_ == filename) {
|
||||
unselect_all();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MyFileChooserButton::set_show_hidden(bool yes)
|
||||
{
|
||||
show_hidden_ = yes;
|
||||
}
|
||||
|
||||
|
||||
void MyFileChooserButton::set_none()
|
||||
{
|
||||
lbl_.set_label(Glib::ustring("(") + M("GENERAL_NONE") + ")");
|
||||
}
|
||||
|
||||
// For an unknown reason (a bug ?), it doesn't work when action = FILE_CHOOSER_ACTION_SELECT_FOLDER !
|
||||
bool MyFileChooserButton::on_scroll_event (GdkEventScroll* event)
|
||||
{
|
||||
@ -1440,6 +1483,57 @@ void MyFileChooserButton::get_preferred_width_for_height_vfunc (int height, int
|
||||
}
|
||||
|
||||
|
||||
class MyFileChooserEntry::Impl
|
||||
{
|
||||
public:
|
||||
Gtk::Entry entry;
|
||||
Gtk::Button file_chooser_button;
|
||||
};
|
||||
|
||||
|
||||
MyFileChooserEntry::MyFileChooserEntry(const Glib::ustring &title, Gtk::FileChooserAction action) :
|
||||
MyFileChooserWidget(title, action),
|
||||
pimpl(new Impl())
|
||||
{
|
||||
const auto on_text_changed = [this]() {
|
||||
set_filename(pimpl->entry.get_text());
|
||||
};
|
||||
pimpl->entry.get_buffer()->signal_deleted_text().connect([on_text_changed](guint, guint) { on_text_changed(); });
|
||||
pimpl->entry.get_buffer()->signal_inserted_text().connect([on_text_changed](guint, const gchar *, guint) { on_text_changed(); });
|
||||
|
||||
pimpl->file_chooser_button.set_image(*Gtk::manage(make_folder_image().release()));
|
||||
pimpl->file_chooser_button.signal_clicked().connect([this]() {
|
||||
const auto &filename = get_filename();
|
||||
if (Glib::file_test(filename, Glib::FILE_TEST_IS_DIR)) {
|
||||
set_current_folder(filename);
|
||||
}
|
||||
show_chooser(this);
|
||||
});
|
||||
|
||||
pack_start(pimpl->entry, true, true);
|
||||
pack_start(pimpl->file_chooser_button, false, false);
|
||||
}
|
||||
|
||||
|
||||
Glib::ustring MyFileChooserEntry::get_placeholder_text() const
|
||||
{
|
||||
return pimpl->entry.get_placeholder_text();
|
||||
}
|
||||
|
||||
|
||||
void MyFileChooserEntry::set_placeholder_text(const Glib::ustring &text)
|
||||
{
|
||||
pimpl->entry.set_placeholder_text(text);
|
||||
}
|
||||
|
||||
|
||||
void MyFileChooserEntry::on_filename_set()
|
||||
{
|
||||
if (pimpl->entry.get_text() != get_filename()) {
|
||||
pimpl->entry.set_text(get_filename());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TextOrIcon::TextOrIcon (const Glib::ustring &fname, const Glib::ustring &labelTx, const Glib::ustring &tooltipTx)
|
||||
{
|
||||
|
@ -396,34 +396,10 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief subclass of Gtk::FileChooserButton in order to handle the scrollwheel
|
||||
*/
|
||||
class MyFileChooserButton final : public Gtk::Button {
|
||||
private:
|
||||
void show_chooser();
|
||||
|
||||
Glib::ustring title_;
|
||||
Gtk::FileChooserAction action_;
|
||||
Gtk::Box box_;
|
||||
Gtk::Label lbl_;
|
||||
std::string filename_;
|
||||
std::string current_folder_;
|
||||
std::vector<Glib::RefPtr<Gtk::FileFilter>> file_filters_;
|
||||
Glib::RefPtr<Gtk::FileFilter> cur_filter_;
|
||||
std::vector<std::string> shortcut_folders_;
|
||||
bool show_hidden_;
|
||||
sigc::signal<void> selection_changed_;
|
||||
|
||||
protected:
|
||||
bool on_scroll_event (GdkEventScroll* event) override;
|
||||
void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const override;
|
||||
void get_preferred_width_for_height_vfunc (int height, int &minimum_width, int &natural_width) const override;
|
||||
|
||||
void set_none();
|
||||
|
||||
class MyFileChooserWidget
|
||||
{
|
||||
public:
|
||||
explicit MyFileChooserButton(const Glib::ustring &title, Gtk::FileChooserAction action=Gtk::FILE_CHOOSER_ACTION_OPEN);
|
||||
virtual ~MyFileChooserWidget() = default;
|
||||
|
||||
sigc::signal<void> &signal_selection_changed();
|
||||
sigc::signal<void> &signal_file_set();
|
||||
@ -434,7 +410,7 @@ public:
|
||||
void add_filter(const Glib::RefPtr<Gtk::FileFilter> &filter);
|
||||
void remove_filter(const Glib::RefPtr<Gtk::FileFilter> &filter);
|
||||
void set_filter(const Glib::RefPtr<Gtk::FileFilter> &filter);
|
||||
std::vector<Glib::RefPtr<Gtk::FileFilter>> list_filters();
|
||||
std::vector<Glib::RefPtr<Gtk::FileFilter>> list_filters() const;
|
||||
|
||||
bool set_current_folder(const std::string &filename);
|
||||
std::string get_current_folder() const;
|
||||
@ -446,6 +422,57 @@ public:
|
||||
void unselect_filename(const std::string &filename);
|
||||
|
||||
void set_show_hidden(bool yes);
|
||||
|
||||
protected:
|
||||
explicit MyFileChooserWidget(const Glib::ustring &title, Gtk::FileChooserAction action=Gtk::FILE_CHOOSER_ACTION_OPEN);
|
||||
|
||||
static std::unique_ptr<Gtk::Image> make_folder_image();
|
||||
|
||||
void show_chooser(Gtk::Widget *parent);
|
||||
virtual void on_filename_set();
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
|
||||
std::unique_ptr<Impl> pimpl;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief subclass of Gtk::FileChooserButton in order to handle the scrollwheel
|
||||
*/
|
||||
class MyFileChooserButton final : public Gtk::Button, public MyFileChooserWidget
|
||||
{
|
||||
private:
|
||||
class Impl;
|
||||
|
||||
std::unique_ptr<Impl> pimpl;
|
||||
|
||||
protected:
|
||||
bool on_scroll_event (GdkEventScroll* event) override;
|
||||
void get_preferred_width_vfunc (int &minimum_width, int &natural_width) const override;
|
||||
void get_preferred_width_for_height_vfunc (int height, int &minimum_width, int &natural_width) const override;
|
||||
|
||||
void on_filename_set() override;
|
||||
|
||||
public:
|
||||
explicit MyFileChooserButton(const Glib::ustring &title, Gtk::FileChooserAction action=Gtk::FILE_CHOOSER_ACTION_OPEN);
|
||||
};
|
||||
|
||||
class MyFileChooserEntry : public Gtk::Box, public MyFileChooserWidget
|
||||
{
|
||||
public:
|
||||
explicit MyFileChooserEntry(const Glib::ustring &title, Gtk::FileChooserAction action = Gtk::FILE_CHOOSER_ACTION_OPEN);
|
||||
|
||||
Glib::ustring get_placeholder_text() const;
|
||||
void set_placeholder_text(const Glib::ustring &text);
|
||||
|
||||
protected:
|
||||
void on_filename_set() override;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
|
||||
std::unique_ptr<Impl> pimpl;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -34,6 +34,7 @@ private:
|
||||
const std::unique_ptr<rtengine::procparams::IPTCPairs> changeList;
|
||||
const std::unique_ptr<rtengine::procparams::IPTCPairs> defChangeList;
|
||||
const std::unique_ptr<rtengine::procparams::IPTCPairs> embeddedData;
|
||||
bool changelist_valid_;
|
||||
|
||||
Gtk::TextView* captionView;
|
||||
Glib::RefPtr<Gtk::TextBuffer> captionText;
|
||||
|
@ -67,25 +67,6 @@ Glib::ustring argv1;
|
||||
namespace
|
||||
{
|
||||
|
||||
// For an unknown reason, Glib::filename_to_utf8 doesn't work on reliably Windows,
|
||||
// so we're using Glib::filename_to_utf8 for Linux/Apple and Glib::locale_to_utf8 for Windows.
|
||||
Glib::ustring fname_to_utf8 (const char* fname)
|
||||
{
|
||||
#ifdef WIN32
|
||||
|
||||
try {
|
||||
return Glib::locale_to_utf8 (fname);
|
||||
} catch (Glib::Error&) {
|
||||
return Glib::convert_with_fallback (fname, "UTF-8", "ISO-8859-1", "?");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
return Glib::filename_to_utf8 (fname);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
bool fast_export = false;
|
||||
|
||||
}
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "extprog.h"
|
||||
#include "../rtengine/dynamicprofile.h"
|
||||
#include "../rtengine/procparams.h"
|
||||
#include "pathutils.h"
|
||||
|
||||
#ifndef WIN32
|
||||
#include <glibmm/fileutils.h>
|
||||
@ -71,27 +72,7 @@ bool remote = false;
|
||||
unsigned char initialGdkScale = 1;
|
||||
//Glib::Threads::Thread* mainThread;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// For an unknown reason, Glib::filename_to_utf8 doesn't work on reliably Windows,
|
||||
// so we're using Glib::filename_to_utf8 for Linux/Apple and Glib::locale_to_utf8 for Windows.
|
||||
Glib::ustring fname_to_utf8 (const char* fname)
|
||||
{
|
||||
#ifdef WIN32
|
||||
|
||||
try {
|
||||
return Glib::locale_to_utf8 (fname);
|
||||
} catch (Glib::Error&) {
|
||||
return Glib::convert_with_fallback (fname, "UTF-8", "ISO-8859-1", "?");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
return Glib::filename_to_utf8 (fname);
|
||||
|
||||
#endif
|
||||
}
|
||||
namespace {
|
||||
|
||||
// This recursive mutex will be used by gdk_threads_enter/leave instead of a simple mutex
|
||||
static Glib::Threads::RecMutex myGdkRecMutex;
|
||||
|
@ -127,3 +127,9 @@ void MetaDataPanel::metaDataModeChanged()
|
||||
listener->panelChanged(EvMetaDataMode, M("HISTORY_CHANGED"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MetaDataPanel::setProgressListener(rtengine::ProgressListener *pl)
|
||||
{
|
||||
exifpanel->setProgressListener(pl);
|
||||
}
|
||||
|
@ -45,5 +45,7 @@ public:
|
||||
|
||||
void setImageData(const rtengine::FramesMetaData* id);
|
||||
void setListener(ToolPanelListener *tpl) override;
|
||||
|
||||
void setProgressListener(rtengine::ProgressListener *pl);
|
||||
};
|
||||
|
||||
|
@ -697,6 +697,9 @@ void Options::setDefaults()
|
||||
cropAutoFit = false;
|
||||
|
||||
rtSettings.thumbnail_inspector_mode = rtengine::Settings::ThumbnailInspectorMode::JPEG;
|
||||
|
||||
rtSettings.xmp_sidecar_style = rtengine::Settings::XmpSidecarStyle::STD;
|
||||
rtSettings.metadata_xmp_sync = rtengine::Settings::MetadataXmpSync::NONE;
|
||||
}
|
||||
|
||||
Options* Options::copyFrom(Options* other)
|
||||
@ -2257,6 +2260,27 @@ void Options::readFromFile(Glib::ustring fname)
|
||||
}
|
||||
}
|
||||
|
||||
if (keyFile.has_group("Metadata")) {
|
||||
if (keyFile.has_key("Metadata", "XMPSidecarStyle")) {
|
||||
std::string val = keyFile.get_string("Metadata", "XMPSidecarStyle");
|
||||
if (val == "ext") {
|
||||
rtSettings.xmp_sidecar_style = rtengine::Settings::XmpSidecarStyle::EXT;
|
||||
} else {
|
||||
rtSettings.xmp_sidecar_style = rtengine::Settings::XmpSidecarStyle::STD;
|
||||
}
|
||||
}
|
||||
if (keyFile.has_key("Metadata", "XMPSynchronization")) {
|
||||
std::string val = keyFile.get_string("Metadata", "XMPSynchronization");
|
||||
if (val == "read") {
|
||||
rtSettings.metadata_xmp_sync = rtengine::Settings::MetadataXmpSync::READ;
|
||||
} else if (val == "readwrite") {
|
||||
rtSettings.metadata_xmp_sync = rtengine::Settings::MetadataXmpSync::READ_WRITE;
|
||||
} else {
|
||||
rtSettings.metadata_xmp_sync = rtengine::Settings::MetadataXmpSync::NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------
|
||||
|
||||
filterOutParsedExtensions();
|
||||
@ -2708,6 +2732,25 @@ void Options::saveToFile(Glib::ustring fname)
|
||||
|
||||
keyFile.set_string("Lensfun", "DBDirectory", rtSettings.lensfunDbDirectory);
|
||||
|
||||
switch (rtSettings.xmp_sidecar_style) {
|
||||
case rtengine::Settings::XmpSidecarStyle::EXT:
|
||||
keyFile.set_string("Metadata", "XMPSidecarStyle", "ext");
|
||||
break;
|
||||
default:
|
||||
keyFile.set_string("Metadata", "XMPSidecarStyle", "std");
|
||||
}
|
||||
|
||||
switch (rtSettings.metadata_xmp_sync) {
|
||||
case rtengine::Settings::MetadataXmpSync::READ:
|
||||
keyFile.set_string("Metadata", "XMPSynchronization", "read");
|
||||
break;
|
||||
case rtengine::Settings::MetadataXmpSync::READ_WRITE:
|
||||
keyFile.set_string("Metadata", "XMPSynchronization", "readwrite");
|
||||
break;
|
||||
default:
|
||||
keyFile.set_string("Metadata", "XMPSynchronization", "none");
|
||||
}
|
||||
|
||||
keyData = keyFile.to_data();
|
||||
|
||||
} catch (Glib::KeyFileError &e) {
|
||||
|
@ -718,6 +718,7 @@ void ParamsEdited::set(bool v)
|
||||
dehaze.depth = v;
|
||||
dehaze.saturation = v;
|
||||
metadata.mode = v;
|
||||
metadata.exifKeys = v;
|
||||
filmNegative.enabled = v;
|
||||
filmNegative.redRatio = v;
|
||||
filmNegative.greenExp = v;
|
||||
@ -2139,6 +2140,7 @@ void ParamsEdited::initFrom(const std::vector<rtengine::procparams::ProcParams>&
|
||||
dehaze.depth = dehaze.depth && p.dehaze.depth == other.dehaze.depth;
|
||||
dehaze.saturation = dehaze.saturation && p.dehaze.saturation == other.dehaze.saturation;
|
||||
metadata.mode = metadata.mode && p.metadata.mode == other.metadata.mode;
|
||||
metadata.exifKeys = metadata.exifKeys && p.metadata.exifKeys == other.metadata.exifKeys;
|
||||
filmNegative.enabled = filmNegative.enabled && p.filmNegative.enabled == other.filmNegative.enabled;
|
||||
filmNegative.redRatio = filmNegative.redRatio && p.filmNegative.redRatio == other.filmNegative.redRatio;
|
||||
filmNegative.greenExp = filmNegative.greenExp && p.filmNegative.greenExp == other.filmNegative.greenExp;
|
||||
@ -7427,6 +7429,10 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
|
||||
toEdit.metadata.mode = mods.metadata.mode;
|
||||
}
|
||||
|
||||
if (metadata.exifKeys) {
|
||||
toEdit.metadata.exifKeys = mods.metadata.exifKeys;
|
||||
}
|
||||
|
||||
if (filmNegative.enabled) {
|
||||
toEdit.filmNegative.enabled = mods.filmNegative.enabled;
|
||||
}
|
||||
@ -7464,15 +7470,15 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
|
||||
|
||||
// Exif changes are added to the existing ones
|
||||
if (exif) {
|
||||
for (procparams::ExifPairs::const_iterator i = mods.exif.begin(); i != mods.exif.end(); ++i) {
|
||||
toEdit.exif[i->first] = i->second;
|
||||
for (procparams::ExifPairs::const_iterator i = mods.metadata.exif.begin(); i != mods.metadata.exif.end(); ++i) {
|
||||
toEdit.metadata.exif[i->first] = i->second;
|
||||
}
|
||||
}
|
||||
|
||||
// IPTC changes are added to the existing ones
|
||||
if (iptc) {
|
||||
for (procparams::IPTCPairs::const_iterator i = mods.iptc.begin(); i != mods.iptc.end(); ++i) {
|
||||
toEdit.iptc[i->first] = i->second;
|
||||
for (procparams::IPTCPairs::const_iterator i = mods.metadata.iptc.begin(); i != mods.metadata.iptc.end(); ++i) {
|
||||
toEdit.metadata.iptc[i->first] = i->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1531,6 +1531,7 @@ struct RAWParamsEdited {
|
||||
|
||||
struct MetaDataParamsEdited {
|
||||
bool mode;
|
||||
bool exifKeys;
|
||||
};
|
||||
|
||||
struct FilmNegativeParamsEdited {
|
||||
|
@ -16,6 +16,7 @@
|
||||
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <glibmm/convert.h>
|
||||
#include <glibmm/miscutils.h>
|
||||
|
||||
#include "pathutils.h"
|
||||
@ -48,3 +49,23 @@ Glib::ustring getExtension (const Glib::ustring& filename)
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// For an unknown reason, Glib::filename_to_utf8 doesn't work on reliably Windows,
|
||||
// so we're using Glib::filename_to_utf8 for Linux/Apple and Glib::locale_to_utf8 for Windows.
|
||||
Glib::ustring fname_to_utf8(const std::string &fname)
|
||||
{
|
||||
#ifdef WIN32
|
||||
|
||||
try {
|
||||
return Glib::locale_to_utf8(fname);
|
||||
} catch (Glib::Error&) {
|
||||
return Glib::convert_with_fallback(fname, "UTF-8", "ISO-8859-1", "?");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
return Glib::filename_to_utf8(fname);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*
|
||||
/* -*- C++ -*-
|
||||
*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
@ -18,7 +19,9 @@
|
||||
*/
|
||||
#pragma once
|
||||
#include <glibmm/ustring.h>
|
||||
#include <string>
|
||||
|
||||
// Removed from guiutils because used by rawtherapee-cli
|
||||
Glib::ustring removeExtension (const Glib::ustring& filename);
|
||||
Glib::ustring getExtension (const Glib::ustring& filename);
|
||||
Glib::ustring fname_to_utf8(const std::string& fname);
|
||||
|
@ -106,9 +106,32 @@ void PlacesBrowser::refreshPlacesList ()
|
||||
{
|
||||
placesModel->clear ();
|
||||
|
||||
// append favorites
|
||||
for (size_t i = 0; i < options.favoriteDirs.size(); i++) {
|
||||
Glib::RefPtr<Gio::File> fav = Gio::File::create_for_path (options.favoriteDirs[i]);
|
||||
|
||||
if (fav && fav->query_exists()) {
|
||||
try {
|
||||
if (auto info = fav->query_info ()) {
|
||||
Gtk::TreeModel::Row newrow = *(placesModel->append());
|
||||
newrow[placesColumns.label] = info->get_display_name ();
|
||||
newrow[placesColumns.icon] = info->get_icon ();
|
||||
newrow[placesColumns.root] = fav->get_parse_name ();
|
||||
newrow[placesColumns.type] = 5;
|
||||
newrow[placesColumns.rowSeparator] = false;
|
||||
}
|
||||
} catch(Gio::Error&) {}
|
||||
}
|
||||
}
|
||||
|
||||
// append home directory
|
||||
Glib::RefPtr<Gio::File> hfile = Gio::File::create_for_path (userHomeDir()); // Will send back "My documents" on Windows now, which has no restricted access
|
||||
|
||||
if (!placesModel->children().empty()) {
|
||||
Gtk::TreeModel::Row newrow = *(placesModel->append());
|
||||
newrow[placesColumns.rowSeparator] = true;
|
||||
}
|
||||
|
||||
if (hfile && hfile->query_exists()) {
|
||||
try {
|
||||
if (auto info = hfile->query_info ()) {
|
||||
@ -223,29 +246,6 @@ void PlacesBrowser::refreshPlacesList ()
|
||||
newrow[placesColumns.rowSeparator] = false;
|
||||
}
|
||||
}
|
||||
|
||||
// append favorites
|
||||
if (!placesModel->children().empty()) {
|
||||
Gtk::TreeModel::Row newrow = *(placesModel->append());
|
||||
newrow[placesColumns.rowSeparator] = true;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < options.favoriteDirs.size(); i++) {
|
||||
Glib::RefPtr<Gio::File> fav = Gio::File::create_for_path (options.favoriteDirs[i]);
|
||||
|
||||
if (fav && fav->query_exists()) {
|
||||
try {
|
||||
if (auto info = fav->query_info ()) {
|
||||
Gtk::TreeModel::Row newrow = *(placesModel->append());
|
||||
newrow[placesColumns.label] = info->get_display_name ();
|
||||
newrow[placesColumns.icon] = info->get_icon ();
|
||||
newrow[placesColumns.root] = fav->get_parse_name ();
|
||||
newrow[placesColumns.type] = 5;
|
||||
newrow[placesColumns.rowSeparator] = false;
|
||||
}
|
||||
} catch(Gio::Error&) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PlacesBrowser::rowSeparatorFunc (const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::iterator& iter)
|
||||
|
@ -20,10 +20,12 @@
|
||||
*/
|
||||
|
||||
#include <gtkmm.h>
|
||||
|
||||
#include "guiutils.h"
|
||||
#include "multilangmgr.h"
|
||||
#include "popupcommon.h"
|
||||
#include "rtimage.h"
|
||||
#include "guiutils.h"
|
||||
#include "threadutils.h"
|
||||
|
||||
PopUpCommon::PopUpCommon (Gtk::Button* thisButton, const Glib::ustring& label)
|
||||
: buttonImage (nullptr)
|
||||
@ -203,6 +205,15 @@ void PopUpCommon::changeImage(const Glib::ustring& fileName, const Glib::RefPtr<
|
||||
|
||||
void PopUpCommon::entrySelected(Gtk::Widget* widget)
|
||||
{
|
||||
if (widget != menu->get_active()) { // Not actually selected.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!entrySelectionMutex.trylock()) { // Already being updated.
|
||||
return;
|
||||
}
|
||||
entrySelectionMutex.unlock();
|
||||
|
||||
int i = 0;
|
||||
for (const auto & child : menu->get_children()) {
|
||||
if (widget == child) {
|
||||
@ -249,7 +260,8 @@ bool PopUpCommon::setSelected (int entryNum)
|
||||
setButtonHint();
|
||||
|
||||
auto radioMenuItem = dynamic_cast<Gtk::RadioMenuItem*>(menu->get_children()[entryNum]);
|
||||
if (radioMenuItem && menu->get_active() != radioMenuItem) {
|
||||
if (radioMenuItem && !radioMenuItem->get_active()) {
|
||||
MyMutex::MyLock updateLock(entrySelectionMutex);
|
||||
radioMenuItem->set_active();
|
||||
}
|
||||
|
||||
|
@ -20,12 +20,13 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "glibmm/refptr.h"
|
||||
#include "threadutils.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <glibmm/refptr.h>
|
||||
#include <glibmm/ustring.h>
|
||||
|
||||
#include <sigc++/signal.h>
|
||||
|
||||
namespace Gio
|
||||
@ -91,6 +92,7 @@ private:
|
||||
Gtk::Button* arrowButton;
|
||||
int selected;
|
||||
bool hasMenu;
|
||||
MyMutex entrySelectionMutex;
|
||||
|
||||
void changeImage(int position);
|
||||
void changeImage(const Glib::ustring& fileName, const Glib::RefPtr<const Gio::Icon>& gIcon);
|
||||
|
@ -614,9 +614,36 @@ Gtk::Widget* Preferences::getImageProcessingPanel ()
|
||||
fdp->add(*vbdp);
|
||||
vbImageProcessing->pack_start (*fdp, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
// Gtk::Frame* fdf = Gtk::manage (new Gtk::Frame (M ("PREFERENCES_DARKFRAME")) );
|
||||
// Gtk::Box* hb42 = Gtk::manage (new Gtk::Box ());
|
||||
// darkFrameDir = Gtk::manage (new Gtk::FileChooserButton (M ("PREFERENCES_DIRDARKFRAMES"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER));
|
||||
// Metadata
|
||||
Gtk::Frame *mf = Gtk::manage(new Gtk::Frame(M("PREFERENCES_METADATA")));
|
||||
Gtk::Grid *mtbl = Gtk::manage(new Gtk::Grid());
|
||||
setExpandAlignProperties(mtbl, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
|
||||
|
||||
metadataSyncCombo = Gtk::manage(new Gtk::ComboBoxText());
|
||||
metadataSyncCombo->set_active(0);
|
||||
metadataSyncCombo->append(M("PREFERENCES_METADATA_SYNC_NONE"));
|
||||
metadataSyncCombo->append(M("PREFERENCES_METADATA_SYNC_READ"));
|
||||
metadataSyncCombo->append(M("PREFERENCES_METADATA_SYNC_READWRITE"));
|
||||
Gtk::Label *mlbl = Gtk::manage(new Gtk::Label(M("PREFERENCES_METADATA_SYNC") + ": "));
|
||||
mtbl->attach(*mlbl, 0, 0, 1, 1);
|
||||
mtbl->attach_next_to(*metadataSyncCombo, *mlbl, Gtk::POS_RIGHT, 1, 1);
|
||||
setExpandAlignProperties(mlbl, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
|
||||
setExpandAlignProperties(metadataSyncCombo, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
|
||||
|
||||
xmpSidecarCombo = Gtk::manage(new Gtk::ComboBoxText());
|
||||
xmpSidecarCombo->set_active(0);
|
||||
xmpSidecarCombo->append(M("PREFERENCES_XMP_SIDECAR_MODE_STD"));
|
||||
xmpSidecarCombo->append(M("PREFERENCES_XMP_SIDECAR_MODE_EXT"));
|
||||
|
||||
mlbl = Gtk::manage(new Gtk::Label(M("PREFERENCES_XMP_SIDECAR_MODE") + ": "));
|
||||
mtbl->attach(*mlbl, 0, 2, 1, 1);
|
||||
mtbl->attach_next_to(*xmpSidecarCombo, *mlbl, Gtk::POS_RIGHT, 1, 1);
|
||||
setExpandAlignProperties(mlbl, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
|
||||
setExpandAlignProperties(xmpSidecarCombo, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
|
||||
|
||||
mf->add(*mtbl);
|
||||
vbImageProcessing->pack_start(*mf, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
// Directories
|
||||
Gtk::Frame* cdf = Gtk::manage(new Gtk::Frame(M("PREFERENCES_DIRECTORIES")));
|
||||
Gtk::Grid* dirgrid = Gtk::manage(new Gtk::Grid());
|
||||
@ -673,6 +700,7 @@ Gtk::Widget* Preferences::getImageProcessingPanel ()
|
||||
|
||||
//Lens Profiles Dir
|
||||
Gtk::Label *lensProfilesDirLabel = Gtk::manage(new Gtk::Label(M("PREFERENCES_LENSPROFILESDIR") + ":"));
|
||||
lensProfilesDirLabel->set_tooltip_text(M("PREFERENCES_LENSPROFILESDIR_TOOLTIP"));
|
||||
setExpandAlignProperties(lensProfilesDirLabel, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
|
||||
lensProfilesDir = Gtk::manage(new MyFileChooserButton(M("PREFERENCES_LENSPROFILESDIR"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER));
|
||||
setExpandAlignProperties(lensProfilesDir, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
|
||||
@ -680,6 +708,20 @@ Gtk::Widget* Preferences::getImageProcessingPanel ()
|
||||
dirgrid->attach_next_to(*lensProfilesDirLabel, *cameraProfilesDirLabel, Gtk::POS_BOTTOM, 1, 1);
|
||||
dirgrid->attach_next_to(*lensProfilesDir, *lensProfilesDirLabel, Gtk::POS_RIGHT, 1, 1);
|
||||
|
||||
// Lensfun DB dir
|
||||
Gtk::Label *lensfunDbDirLabel = Gtk::manage(new Gtk::Label(M("PREFERENCES_LENSFUNDBDIR") + ":"));
|
||||
lensfunDbDirLabel->set_tooltip_text(M("PREFERENCES_LENSFUNDBDIR_TOOLTIP"));
|
||||
setExpandAlignProperties(lensfunDbDirLabel, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
|
||||
lensfunDbDir = Gtk::manage(new MyFileChooserEntry(M("PREFERENCES_LENSFUNDBDIR"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER));
|
||||
lensfunDbDir->set_placeholder_text(Glib::ustring::compose("(%1)", M("GENERAL_AUTO")));
|
||||
setExpandAlignProperties(lensfunDbDir, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
|
||||
Gtk::Label* lensfunDbDirRestartNeededLabel = Gtk::manage(new Gtk::Label(Glib::ustring(" (") + M("PREFERENCES_APPLNEXTSTARTUP") + ")"));
|
||||
setExpandAlignProperties(lensfunDbDirRestartNeededLabel, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
|
||||
|
||||
dirgrid->attach_next_to(*lensfunDbDirLabel, *lensProfilesDirLabel, Gtk::POS_BOTTOM, 1, 1);
|
||||
dirgrid->attach_next_to(*lensfunDbDir, *lensfunDbDirLabel, Gtk::POS_RIGHT, 1, 1);
|
||||
dirgrid->attach_next_to(*lensfunDbDirRestartNeededLabel, *lensfunDbDir, Gtk::POS_RIGHT, 1, 1);
|
||||
|
||||
//Pack directories to Image Processing panel
|
||||
cdf->add(*dirgrid);
|
||||
vbImageProcessing->pack_start (*cdf, Gtk::PACK_SHRINK, 4 );
|
||||
@ -1350,10 +1392,7 @@ Gtk::Widget* Preferences::getFileBrowserPanel()
|
||||
sdlast = Gtk::manage(new Gtk::RadioButton(M("PREFERENCES_DIRLAST")));
|
||||
sdhome = Gtk::manage(new Gtk::RadioButton(M("PREFERENCES_DIRHOME")));
|
||||
sdother = Gtk::manage(new Gtk::RadioButton(M("PREFERENCES_DIROTHER") + ": "));
|
||||
startupdir = Gtk::manage(new Gtk::Entry());
|
||||
|
||||
Gtk::Button* sdselect = Gtk::manage(new Gtk::Button());
|
||||
sdselect->set_image (*Gtk::manage (new RTImage ("folder-open-small.png")));
|
||||
startupdir = Gtk::manage(new MyFileChooserEntry(M("PREFERENCES_DIRSELECTDLG"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER));
|
||||
|
||||
Gtk::RadioButton::Group opts = sdcurrent->get_group();
|
||||
sdlast->set_group(opts);
|
||||
@ -1367,14 +1406,11 @@ Gtk::Widget* Preferences::getFileBrowserPanel()
|
||||
Gtk::Box* otherbox = Gtk::manage(new Gtk::Box());
|
||||
otherbox->pack_start(*sdother, Gtk::PACK_SHRINK);
|
||||
otherbox->pack_start(*startupdir);
|
||||
otherbox->pack_end(*sdselect, Gtk::PACK_SHRINK, 4);
|
||||
vbsd->pack_start(*otherbox, Gtk::PACK_SHRINK, 0);
|
||||
|
||||
fsd->add(*vbsd);
|
||||
vbFileBrowser->pack_start (*fsd, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
sdselect->signal_clicked().connect(sigc::mem_fun(*this, &Preferences::selectStartupDir));
|
||||
|
||||
//---
|
||||
|
||||
|
||||
@ -1880,7 +1916,7 @@ void Preferences::storePreferences()
|
||||
moptions.startupDir = STARTUPDIR_LAST;
|
||||
} else if (sdother->get_active()) {
|
||||
moptions.startupDir = STARTUPDIR_CUSTOM;
|
||||
moptions.startupPath = startupdir->get_text();
|
||||
moptions.startupPath = startupdir->get_filename();
|
||||
}
|
||||
|
||||
moptions.parseExtensions.clear();
|
||||
@ -1911,6 +1947,7 @@ void Preferences::storePreferences()
|
||||
moptions.clutsDir = clutsDir->get_filename();
|
||||
moptions.rtSettings.cameraProfilesPath = cameraProfilesDir->get_filename();
|
||||
moptions.rtSettings.lensProfilesPath = lensProfilesDir->get_filename();
|
||||
moptions.rtSettings.lensfunDbDirectory = lensfunDbDir->get_filename();
|
||||
|
||||
moptions.baBehav.resize(ADDSET_PARAM_NUM);
|
||||
|
||||
@ -1960,6 +1997,9 @@ void Preferences::storePreferences()
|
||||
moptions.cropAutoFit = cropAutoFitCB->get_active();
|
||||
|
||||
toolLocationPreference->updateOptions();
|
||||
|
||||
moptions.rtSettings.metadata_xmp_sync = rtengine::Settings::MetadataXmpSync(metadataSyncCombo->get_active_row_number());
|
||||
moptions.rtSettings.xmp_sidecar_style = rtengine::Settings::XmpSidecarStyle(xmpSidecarCombo->get_active_row_number());
|
||||
}
|
||||
|
||||
void Preferences::fillPreferences()
|
||||
@ -2107,7 +2147,7 @@ void Preferences::fillPreferences()
|
||||
sdhome->set_active();
|
||||
} else if (moptions.startupDir == STARTUPDIR_CUSTOM) {
|
||||
sdother->set_active();
|
||||
startupdir->set_text(moptions.startupPath);
|
||||
startupdir->set_current_folder(moptions.startupPath);
|
||||
}
|
||||
|
||||
extensionModel->clear();
|
||||
@ -2172,6 +2212,8 @@ void Preferences::fillPreferences()
|
||||
|
||||
lensProfilesDir->set_current_folder(moptions.rtSettings.lensProfilesPath);
|
||||
|
||||
lensfunDbDir->set_current_folder(moptions.rtSettings.lensfunDbDirectory);
|
||||
|
||||
addc.block(true);
|
||||
setc.block(true);
|
||||
|
||||
@ -2209,6 +2251,9 @@ void Preferences::fillPreferences()
|
||||
txtSndLngEditProcDone->set_text(moptions.sndLngEditProcDone);
|
||||
spbSndLngEditProcDoneSecs->set_value(moptions.sndLngEditProcDoneSecs);
|
||||
#endif
|
||||
|
||||
metadataSyncCombo->set_active(int(moptions.rtSettings.metadata_xmp_sync));
|
||||
xmpSidecarCombo->set_active(int(moptions.rtSettings.xmp_sidecar_style));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2299,23 +2344,6 @@ void Preferences::cancelPressed()
|
||||
hide();
|
||||
}
|
||||
|
||||
void Preferences::selectStartupDir()
|
||||
{
|
||||
|
||||
Gtk::FileChooserDialog dialog(getToplevelWindow(this), M("PREFERENCES_DIRSELECTDLG"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER);
|
||||
//dialog.set_transient_for(*this);
|
||||
|
||||
//Add response buttons to the dialog:
|
||||
dialog.add_button(M("GENERAL_CANCEL"), Gtk::RESPONSE_CANCEL);
|
||||
dialog.add_button(M("GENERAL_OPEN"), Gtk::RESPONSE_OK);
|
||||
|
||||
int result = dialog.run();
|
||||
|
||||
if (result == Gtk::RESPONSE_OK) {
|
||||
startupdir->set_text(dialog.get_filename());
|
||||
}
|
||||
}
|
||||
|
||||
void Preferences::aboutPressed()
|
||||
{
|
||||
|
||||
|