Add decoding through LibRaw
Decode raw files with LibRaw and fall back to dcraw if LibRaw is unable to read the file.
This commit is contained in:
parent
3f5c3988e5
commit
20d3311931
4
.github/workflows/macos.yml
vendored
4
.github/workflows/macos.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
|||||||
mkdir build
|
mkdir build
|
||||||
date +%s > build/stamp
|
date +%s > build/stamp
|
||||||
brew uninstall --ignore-dependencies libtiff
|
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 exiv2 | 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 automake | tee -a depslog
|
||||||
date -u
|
date -u
|
||||||
echo "----====Pourage====----"
|
echo "----====Pourage====----"
|
||||||
cat depslog | grep Pouring
|
cat depslog | grep Pouring
|
||||||
@ -42,6 +42,7 @@ jobs:
|
|||||||
export REF=${GITHUB_REF##*/}
|
export REF=${GITHUB_REF##*/}
|
||||||
export C_FLAGS=$(echo -e $C_FLAGS | tr -d '\n')
|
export C_FLAGS=$(echo -e $C_FLAGS | tr -d '\n')
|
||||||
cd build && date -u && date +%s > configstamp
|
cd build && date -u && date +%s > configstamp
|
||||||
|
curl -L https://github.com/Homebrew/homebrew-core/raw/679923b4eb48a8dc7ecc1f05d06063cd79b3fc00/Formula/libomp.rb -o libomp.rb && brew install --formula libomp.rb
|
||||||
cmake \
|
cmake \
|
||||||
-DCMAKE_BUILD_TYPE="Release" \
|
-DCMAKE_BUILD_TYPE="Release" \
|
||||||
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \
|
-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \
|
||||||
@ -66,7 +67,6 @@ jobs:
|
|||||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \
|
-DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 \
|
||||||
-DOSX_CONTINUOUS=ON \
|
-DOSX_CONTINUOUS=ON \
|
||||||
..
|
..
|
||||||
curl -L https://github.com/Homebrew/homebrew-core/raw/679923b4eb48a8dc7ecc1f05d06063cd79b3fc00/Formula/libomp.rb -o libomp.rb && brew install --formula libomp.rb
|
|
||||||
zsh -c 'echo "Configured in $(printf "%0.2f" $(($[$(date +%s)-$(cat configstamp)]/$((60.))))) minutes"'
|
zsh -c 'echo "Configured in $(printf "%0.2f" $(($[$(date +%s)-$(cat configstamp)]/$((60.))))) minutes"'
|
||||||
- name: Compile RawTherapee
|
- name: Compile RawTherapee
|
||||||
run: |
|
run: |
|
||||||
|
1
.github/workflows/windows.yml
vendored
1
.github/workflows/windows.yml
vendored
@ -43,6 +43,7 @@ jobs:
|
|||||||
cc:p
|
cc:p
|
||||||
pkgconf:p
|
pkgconf:p
|
||||||
cmake:p
|
cmake:p
|
||||||
|
autotools:p
|
||||||
ninja:p
|
ninja:p
|
||||||
gtkmm3:p
|
gtkmm3:p
|
||||||
lcms2:p
|
lcms2:p
|
||||||
|
@ -226,6 +226,7 @@ option(WITH_LTO "Build with link-time optimizations" OFF)
|
|||||||
option(WITH_SAN "Build with run-time sanitizer" OFF)
|
option(WITH_SAN "Build with run-time sanitizer" OFF)
|
||||||
option(WITH_PROF "Build with profiling instrumentation" OFF)
|
option(WITH_PROF "Build with profiling instrumentation" OFF)
|
||||||
option(WITH_SYSTEM_KLT "Build using system KLT library." OFF)
|
option(WITH_SYSTEM_KLT "Build using system KLT library." OFF)
|
||||||
|
option(WITH_SYSTEM_LIBRAW "Build using system LibRaw library." OFF)
|
||||||
option(OPTION_OMP "Build with OpenMP support" ON)
|
option(OPTION_OMP "Build with OpenMP support" ON)
|
||||||
option(
|
option(
|
||||||
STRICT_MUTEX
|
STRICT_MUTEX
|
||||||
@ -522,6 +523,13 @@ foreach(l ${_exiv2_libs})
|
|||||||
set(EXIV2_LIBRARIES ${EXIV2_LIBRARIES} ${_el})
|
set(EXIV2_LIBRARIES ${EXIV2_LIBRARIES} ${_el})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
if(NOT WITH_SYSTEM_LIBRAW)
|
||||||
|
set(LIBRAW_LIBRARIES "${CMAKE_CURRENT_BINARY_DIR}/rtengine/libraw/lib/.libs/libraw_r.a")
|
||||||
|
if(WIN32)
|
||||||
|
set(LIBRAW_LIBRARIES ${LIBRAW_LIBRARIES} -lws2_32)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_definitions(-DWIN32)
|
add_definitions(-DWIN32)
|
||||||
add_definitions(-D_WIN32)
|
add_definitions(-D_WIN32)
|
||||||
@ -551,6 +559,9 @@ find_package(ZLIB REQUIRED)
|
|||||||
if(WITH_SYSTEM_KLT)
|
if(WITH_SYSTEM_KLT)
|
||||||
find_package(KLT REQUIRED)
|
find_package(KLT REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
if(WITH_SYSTEM_LIBRAW)
|
||||||
|
pkg_check_modules(LIBRAW REQUIRED libraw_r>=0.21)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Check for libcanberra-gtk3 (sound events on Linux):
|
# Check for libcanberra-gtk3 (sound events on Linux):
|
||||||
if(UNIX AND (NOT APPLE))
|
if(UNIX AND (NOT APPLE))
|
||||||
|
@ -45,6 +45,11 @@ endif()
|
|||||||
if(EXIV2_INCLUDE_DIRS)
|
if(EXIV2_INCLUDE_DIRS)
|
||||||
include_directories("${EXIV2_INCLUDE_DIRS}")
|
include_directories("${EXIV2_INCLUDE_DIRS}")
|
||||||
endif()
|
endif()
|
||||||
|
if(NOT WITH_SYSTEM_LIBRAW)
|
||||||
|
include_directories("${CMAKE_SOURCE_DIR}/rtengine/libraw")
|
||||||
|
else()
|
||||||
|
include_directories("${LIBRAW_INCLUDE_DIRS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
link_directories(
|
link_directories(
|
||||||
"${EXPAT_LIBRARY_DIRS}"
|
"${EXPAT_LIBRARY_DIRS}"
|
||||||
@ -245,10 +250,16 @@ target_link_libraries(rtengine
|
|||||||
${RSVG_LIBRARIES}
|
${RSVG_LIBRARIES}
|
||||||
${KLT_LIBRARIES}
|
${KLT_LIBRARIES}
|
||||||
${EXIV2_LIBRARIES}
|
${EXIV2_LIBRARIES}
|
||||||
|
${LIBRAW_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(OpenMP_FOUND)
|
if(OpenMP_FOUND)
|
||||||
target_link_libraries(rtengine ${OpenMP_CXX_LIBRARIES})
|
target_link_libraries(rtengine ${OpenMP_CXX_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Configure LibRaw
|
||||||
|
if(NOT WITH_SYSTEM_LIBRAW)
|
||||||
|
include(LibRaw.cmake)
|
||||||
|
endif()
|
||||||
|
|
||||||
install(FILES ${CAMCONSTSFILE} DESTINATION "${DATADIR}" PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)
|
install(FILES ${CAMCONSTSFILE} DESTINATION "${DATADIR}" PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)
|
||||||
|
124
rtengine/LibRaw.cmake
Normal file
124
rtengine/LibRaw.cmake
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
# LibRaw has its own configuration script and uses make to build. Here we add
|
||||||
|
# the LibRaw configuration commands so they run during the CMake configuration.
|
||||||
|
# Also, add a target which always runs make.
|
||||||
|
|
||||||
|
set(LIBRAW_DIR "${CMAKE_CURRENT_BINARY_DIR}/libraw")
|
||||||
|
set(LIBRAW_LIB_DIR "${LIBRAW_DIR}/lib")
|
||||||
|
set(LIBRAW_PHANTOM_FILE "${LIBRAW_LIB_DIR}/phantom_file")
|
||||||
|
if(DEFINED ENV{SHELL})
|
||||||
|
set(SHELL "$ENV{SHELL}")
|
||||||
|
else()
|
||||||
|
set(SHELL "sh")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_target(
|
||||||
|
LibRaw ALL
|
||||||
|
DEPENDS ${LIBRAW_PHANTOM_FILE} # Ensures target always executes.
|
||||||
|
)
|
||||||
|
|
||||||
|
# Configuration flags.
|
||||||
|
set(CONFIGURE_FLAGS "--disable-examples")
|
||||||
|
set(LIBRAW_CXX_FLAGS "${CXX_FLAGS} -std=gnu++11 -Wno-error=unknown-pragmas")
|
||||||
|
# Let the configure script handle OpenMP flags.
|
||||||
|
string(REPLACE "${OpenMP_CXX_FLAGS}" "" LIBRAW_CXX_FLAGS "${LIBRAW_CXX_FLAGS}")
|
||||||
|
if(OPTION_OMP)
|
||||||
|
set(CONFIGURE_FLAGS "${CONFIGURE_FLAGS} --enable-openmp")
|
||||||
|
else()
|
||||||
|
set(CONFIGURE_FLAGS "${CONFIGURE_FLAGS} --disable-openmp")
|
||||||
|
endif()
|
||||||
|
set(CONFIGURE_FLAGS "${CONFIGURE_FLAGS} CC=\"${CMAKE_C_COMPILER}\"")
|
||||||
|
set(CONFIGURE_FLAGS "${CONFIGURE_FLAGS} CXX=\"${CMAKE_CXX_COMPILER}\"")
|
||||||
|
set(CONFIGURE_FLAGS "${CONFIGURE_FLAGS} CXXFLAGS=\"${LIBRAW_CXX_FLAGS}\"")
|
||||||
|
|
||||||
|
# Configuration commands.
|
||||||
|
message(STATUS "Configuring LibRaw")
|
||||||
|
execute_process(
|
||||||
|
COMMAND cp -p -R "${CMAKE_CURRENT_SOURCE_DIR}/libraw" .
|
||||||
|
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||||
|
RESULT_VARIABLE PROCESS_RESULT
|
||||||
|
COMMAND_ECHO STDOUT
|
||||||
|
)
|
||||||
|
if(PROCESS_RESULT AND NOT PROCESS_RESULT EQUAL 0)
|
||||||
|
message(FATAL_ERROR "Could not copy LibRaw files into build directory")
|
||||||
|
endif()
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${SHELL}" -l -c "autoreconf -v --install"
|
||||||
|
WORKING_DIRECTORY "${LIBRAW_DIR}"
|
||||||
|
RESULT_VARIABLE PROCESS_RESULT
|
||||||
|
COMMAND_ECHO STDOUT
|
||||||
|
)
|
||||||
|
if(PROCESS_RESULT AND NOT PROCESS_RESULT EQUAL 0)
|
||||||
|
message(FATAL_ERROR "Could not generate LibRaw configuration script")
|
||||||
|
endif()
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${SHELL}" -l -c "./configure ${CONFIGURE_FLAGS}"
|
||||||
|
WORKING_DIRECTORY "${LIBRAW_DIR}"
|
||||||
|
RESULT_VARIABLE PROCESS_RESULT
|
||||||
|
COMMAND_ECHO STDOUT
|
||||||
|
)
|
||||||
|
if(PROCESS_RESULT AND NOT PROCESS_RESULT EQUAL 0)
|
||||||
|
execute_process(
|
||||||
|
COMMAND cat config.log
|
||||||
|
WORKING_DIRECTORY "${LIBRAW_DIR}"
|
||||||
|
COMMAND_ECHO STDOUT
|
||||||
|
)
|
||||||
|
message(FATAL_ERROR "LibRaw configure failed")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Build flags.
|
||||||
|
set(LIBRAW_MAKE_FLAGS "")
|
||||||
|
if(CMAKE_GENERATOR MATCHES ".*Makefiles.*")
|
||||||
|
set(LIBRAW_MAKE_COMMAND "$(MAKE)")
|
||||||
|
else()
|
||||||
|
# If not using Makefiles, set number of jobs equal to logical processors
|
||||||
|
# count. Not necessary for make because of the jobserver.
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${SHELL}" -l -c "nproc"
|
||||||
|
OUTPUT_VARIABLE LOGICAL_PROCESSORS
|
||||||
|
RESULT_VARIABLE PROCESS_RESULT
|
||||||
|
ERROR_QUIET
|
||||||
|
)
|
||||||
|
if(PROCESS_RESULT AND NOT PROCESS_RESULT EQUAL 0)
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${SHELL}" -l -c "sysctl -n hw.ncpu"
|
||||||
|
OUTPUT_VARIABLE LOGICAL_PROCESSORS
|
||||||
|
RESULT_VARIABLE PROCESS_RESULT
|
||||||
|
ERROR_QUIET
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if(PROCESS_RESULT AND NOT PROCESS_RESULT EQUAL 0)
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${SHELL}" -l -c "getconf _NPROCESSORS_ONLN"
|
||||||
|
OUTPUT_VARIABLE LOGICAL_PROCESSORS
|
||||||
|
RESULT_VARIABLE PROCESS_RESULT
|
||||||
|
ERROR_QUIET
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if(PROCESS_RESULT AND NOT PROCESS_RESULT EQUAL 0)
|
||||||
|
set(LOGICAL_PROCESSORS "1")
|
||||||
|
endif()
|
||||||
|
string(STRIP "${LOGICAL_PROCESSORS}" LOGICAL_PROCESSORS)
|
||||||
|
set(LIBRAW_MAKE_FLAGS "${LIBRAW_MAKE_FLAGS} -j${LOGICAL_PROCESSORS}")
|
||||||
|
|
||||||
|
set(LIBRAW_MAKE_COMMAND "make")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Build commands.
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT "${LIBRAW_PHANTOM_FILE}" "${LIBRAW_LIB_DIR}/.libs/libraw_r.a"
|
||||||
|
COMMAND cp -p -R "${CMAKE_CURRENT_SOURCE_DIR}/libraw" ..
|
||||||
|
COMMAND "${SHELL}" -l -c "${LIBRAW_MAKE_COMMAND} ${LIBRAW_MAKE_FLAGS}"
|
||||||
|
COMMENT "Building LibRaw"
|
||||||
|
WORKING_DIRECTORY libraw
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add a `make clean-libraw` command because there's no good way to automatically
|
||||||
|
# clean the LibRaw build with `make`clean`.
|
||||||
|
add_custom_target(
|
||||||
|
clean-libraw
|
||||||
|
COMMAND make clean
|
||||||
|
COMMAND rm -rf lib
|
||||||
|
WORKING_DIRECTORY libraw
|
||||||
|
)
|
||||||
|
|
@ -67,6 +67,7 @@ public:
|
|||||||
,getbithuff(this,ifp,zero_after_ff)
|
,getbithuff(this,ifp,zero_after_ff)
|
||||||
,nikbithuff(ifp)
|
,nikbithuff(ifp)
|
||||||
{
|
{
|
||||||
|
shrink=0;
|
||||||
memset(&hbd, 0, sizeof(hbd));
|
memset(&hbd, 0, sizeof(hbd));
|
||||||
aber[0]=aber[1]=aber[2]=aber[3]=1;
|
aber[0]=aber[1]=aber[2]=aber[3]=1;
|
||||||
gamm[0]=0.45;gamm[1]=4.5;gamm[2]=gamm[3]=gamm[4]=gamm[5]=0;
|
gamm[0]=0.45;gamm[1]=4.5;gamm[2]=gamm[3]=gamm[4]=gamm[5]=0;
|
||||||
|
@ -44,6 +44,7 @@ const Settings* settings;
|
|||||||
|
|
||||||
MyMutex* lcmsMutex = nullptr;
|
MyMutex* lcmsMutex = nullptr;
|
||||||
MyMutex *fftwMutex = nullptr;
|
MyMutex *fftwMutex = nullptr;
|
||||||
|
MyMutex *librawMutex = nullptr;
|
||||||
|
|
||||||
int init (const Settings* s, const Glib::ustring& baseDir, const Glib::ustring& userSettingsDir, bool loadAll)
|
int init (const Settings* s, const Glib::ustring& baseDir, const Glib::ustring& userSettingsDir, bool loadAll)
|
||||||
{
|
{
|
||||||
@ -120,6 +121,8 @@ int init (const Settings* s, const Glib::ustring& baseDir, const Glib::ustring&
|
|||||||
delete lcmsMutex;
|
delete lcmsMutex;
|
||||||
lcmsMutex = new MyMutex;
|
lcmsMutex = new MyMutex;
|
||||||
fftwMutex = new MyMutex;
|
fftwMutex = new MyMutex;
|
||||||
|
delete librawMutex;
|
||||||
|
librawMutex = new MyMutex;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +58,9 @@ unsigned DCraw::pana_bits_t::operator() (int nbits, unsigned *bytes)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
class pana_cs6_page_decoder
|
class pana_cs6_page_decoder
|
||||||
{
|
{
|
||||||
unsigned int pixelbuffer[14], lastoffset, maxoffset;
|
unsigned int pixelbuffer[14], lastoffset, maxoffset;
|
||||||
@ -99,6 +102,8 @@ void pana_cs6_page_decoder::read_page()
|
|||||||
}
|
}
|
||||||
#undef wbuffer
|
#undef wbuffer
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void DCraw::panasonic_load_raw()
|
void DCraw::panasonic_load_raw()
|
||||||
{
|
{
|
||||||
int enc_blck_size = RT_pana_info.bpp == 12 ? 10 : 9;
|
int enc_blck_size = RT_pana_info.bpp == 12 ? 10 : 9;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of RawTherapee.
|
* This file is part of RawTherapee.
|
||||||
*
|
*
|
||||||
|
* LibRaw integration adapted from ART.
|
||||||
|
*
|
||||||
* Created on: 20/nov/2010
|
* Created on: 20/nov/2010
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -11,17 +13,24 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "image8.h"
|
||||||
#include "rawimage.h"
|
#include "rawimage.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "camconst.h"
|
#include "camconst.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "rtengine.h"
|
#include "rtengine.h"
|
||||||
|
#include "libraw/libraw/libraw.h"
|
||||||
|
|
||||||
namespace rtengine
|
namespace rtengine
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
extern MyMutex *librawMutex;
|
||||||
|
|
||||||
|
|
||||||
RawImage::RawImage(const Glib::ustring &name)
|
RawImage::RawImage(const Glib::ustring &name)
|
||||||
: data(nullptr)
|
: DCraw()
|
||||||
|
, data(nullptr)
|
||||||
, prefilters(0)
|
, prefilters(0)
|
||||||
, filename(name)
|
, filename(name)
|
||||||
, rotate_deg(0)
|
, rotate_deg(0)
|
||||||
@ -29,9 +38,12 @@ RawImage::RawImage(const Glib::ustring &name)
|
|||||||
, allocation(nullptr)
|
, allocation(nullptr)
|
||||||
{
|
{
|
||||||
memset(maximum_c4, 0, sizeof(maximum_c4));
|
memset(maximum_c4, 0, sizeof(maximum_c4));
|
||||||
|
memset(white, 0, sizeof(white));
|
||||||
RT_matrix_from_constant = ThreeValBool::X;
|
RT_matrix_from_constant = ThreeValBool::X;
|
||||||
RT_blacklevel_from_constant = ThreeValBool::X;
|
RT_blacklevel_from_constant = ThreeValBool::X;
|
||||||
RT_whitelevel_from_constant = ThreeValBool::X;
|
RT_whitelevel_from_constant = ThreeValBool::X;
|
||||||
|
memset(make, 0, sizeof(make));
|
||||||
|
memset(model, 0, sizeof(model));
|
||||||
}
|
}
|
||||||
|
|
||||||
RawImage::~RawImage()
|
RawImage::~RawImage()
|
||||||
@ -41,7 +53,7 @@ RawImage::~RawImage()
|
|||||||
ifp = nullptr;
|
ifp = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image) {
|
if (image && decoder == Decoder::DCRAW) {
|
||||||
free(image);
|
free(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +78,18 @@ RawImage::~RawImage()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RawImage::pre_interpolate()
|
||||||
|
{
|
||||||
|
int w = width, h = height;
|
||||||
|
if (decoder == Decoder::LIBRAW) {
|
||||||
|
width = iwidth;
|
||||||
|
height = iheight;
|
||||||
|
}
|
||||||
|
DCraw::pre_interpolate();
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
}
|
||||||
|
|
||||||
eSensorType RawImage::getSensorType() const
|
eSensorType RawImage::getSensorType() const
|
||||||
{
|
{
|
||||||
if (isBayer()) {
|
if (isBayer()) {
|
||||||
@ -467,7 +491,176 @@ int RawImage::loadRaw(bool loadData, unsigned int imageNum, bool closeFile, Prog
|
|||||||
// set the number of the frame to extract. If the number is larger then number of existing frames - 1, dcraw will handle that correctly
|
// set the number of the frame to extract. If the number is larger then number of existing frames - 1, dcraw will handle that correctly
|
||||||
|
|
||||||
shot_select = imageNum;
|
shot_select = imageNum;
|
||||||
identify();
|
|
||||||
|
libraw.reset(new LibRaw());
|
||||||
|
int libraw_error = [&]() -> int {
|
||||||
|
libraw->imgdata.params.use_camera_wb = 1;
|
||||||
|
|
||||||
|
int err = libraw->open_buffer(ifp->data, ifp->size);
|
||||||
|
if (err == LIBRAW_FILE_UNSUPPORTED || err == LIBRAW_TOO_BIG) {
|
||||||
|
// fallback to the internal one
|
||||||
|
return err;
|
||||||
|
} else if (err != LIBRAW_SUCCESS && strncmp(libraw->imgdata.idata.software, "make_arq", 8) == 0) {
|
||||||
|
return err;
|
||||||
|
} else if (err == LIBRAW_FILE_UNSUPPORTED && (strncmp(libraw->unpack_function_name(), "sony_arq_load_raw", 17) == 0 || strncmp(libraw->imgdata.idata.software, "HDRMerge", 8) == 0)) {
|
||||||
|
return err;
|
||||||
|
} else if (err != LIBRAW_SUCCESS) {
|
||||||
|
decoder = Decoder::LIBRAW;
|
||||||
|
return err;
|
||||||
|
} else if (libraw->is_floating_point() && libraw->imgdata.idata.dng_version) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &d = libraw->imgdata.idata;
|
||||||
|
is_raw = d.raw_count;
|
||||||
|
strncpy(make, d.normalized_make, sizeof(make)-1);
|
||||||
|
make[sizeof(make)-1] = 0;
|
||||||
|
strncpy(model, d.normalized_model, sizeof(model)-1);
|
||||||
|
model[sizeof(model)-1] = 0;
|
||||||
|
RT_software = d.software;
|
||||||
|
dng_version = d.dng_version;
|
||||||
|
filters = d.filters;
|
||||||
|
is_foveon = d.is_foveon;
|
||||||
|
colors = d.colors;
|
||||||
|
tiff_bps = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; ++i) {
|
||||||
|
for (int j = 0; j < 6; ++j) {
|
||||||
|
xtrans[i][j] = d.xtrans[i][j];
|
||||||
|
xtrans_abs[i][j] = d.xtrans_abs[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto &s = libraw->imgdata.sizes;
|
||||||
|
raw_width = s.raw_width;
|
||||||
|
raw_height = s.raw_height;
|
||||||
|
width = s.width;
|
||||||
|
height = s.height;
|
||||||
|
top_margin = s.top_margin;
|
||||||
|
left_margin = s.left_margin;
|
||||||
|
iheight = s.iheight;
|
||||||
|
iwidth = s.iwidth;
|
||||||
|
flip = s.flip;
|
||||||
|
|
||||||
|
auto &o = libraw->imgdata.other;
|
||||||
|
iso_speed = o.iso_speed;
|
||||||
|
shutter = o.shutter;
|
||||||
|
aperture = o.aperture;
|
||||||
|
focal_len = o.focal_len;
|
||||||
|
timestamp = o.timestamp;
|
||||||
|
shot_order = o.shot_order;
|
||||||
|
|
||||||
|
auto &io = libraw->imgdata.rawdata.ioparams;
|
||||||
|
shrink = io.shrink;
|
||||||
|
zero_is_bad = io.zero_is_bad;
|
||||||
|
fuji_width = io.fuji_width;
|
||||||
|
raw_color = io.raw_color;
|
||||||
|
mix_green = io.mix_green;
|
||||||
|
|
||||||
|
auto &cd = libraw->imgdata.color;
|
||||||
|
black = cd.black;
|
||||||
|
maximum = cd.maximum;
|
||||||
|
tiff_bps = cd.raw_bps;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(cblack)/sizeof(unsigned); ++i) {
|
||||||
|
cblack[i] = cd.cblack[i];
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
cam_mul[i] = cd.cam_mul[i];
|
||||||
|
pre_mul[i] = cd.pre_mul[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
for (int j = 0; j < 4; ++j) {
|
||||||
|
cmatrix[i][j] = cd.cmatrix[i][j];
|
||||||
|
rgb_cam[i][j] = cd.rgb_cam[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
for (int j = 0; j < 8; ++j) {
|
||||||
|
white[i][j] = cd.white[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
for (int j = 0; j < 4; ++j) {
|
||||||
|
mask[i][j] = s.mask[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &mkn = libraw->imgdata.makernotes;
|
||||||
|
|
||||||
|
// if (!strcmp(make, "Panasonic") && mkn.panasonic.BlackLevelDim > 0) {
|
||||||
|
// memset(cblack, 0, sizeof(cblack));
|
||||||
|
// if (mkn.panasonic.BlackLevelDim >= 4) {
|
||||||
|
// for (size_t i = 0; i < 4; ++i) {
|
||||||
|
// cblack[i] = mkn.panasonic.BlackLevel[i];
|
||||||
|
// }
|
||||||
|
// black = 0;
|
||||||
|
// } else {
|
||||||
|
// black = mkn.panasonic.BlackLevel[0];
|
||||||
|
// }
|
||||||
|
// } else
|
||||||
|
if (!strcmp(make, "Canon") && isBayer() && !dng_version) {
|
||||||
|
if (mkn.canon.AverageBlackLevel) {
|
||||||
|
memset(cblack, 0, sizeof(cblack));
|
||||||
|
for (size_t i = 0; i < 4; ++i) {
|
||||||
|
cblack[i] = mkn.canon.ChannelBlackLevel[i];
|
||||||
|
}
|
||||||
|
black = 0;
|
||||||
|
}
|
||||||
|
if (mkn.canon.SpecularWhiteLevel) {
|
||||||
|
maximum = mkn.canon.SpecularWhiteLevel;
|
||||||
|
} else if (mkn.canon.NormalWhiteLevel) {
|
||||||
|
maximum = mkn.canon.NormalWhiteLevel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (tiff_bps < 16 && (size_t(1) << size_t(tiff_bps)) < maximum) {
|
||||||
|
++tiff_bps;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dng_version) {
|
||||||
|
RT_whitelevel_from_constant = ThreeValBool::F;
|
||||||
|
RT_blacklevel_from_constant = ThreeValBool::F;
|
||||||
|
if (!isBayer() && !isXtrans()) {
|
||||||
|
RT_matrix_from_constant = ThreeValBool::F;
|
||||||
|
}
|
||||||
|
} else if (strcmp(make, "Panasonic") != 0) {
|
||||||
|
RT_whitelevel_from_constant = ThreeValBool::T;
|
||||||
|
RT_blacklevel_from_constant = ThreeValBool::T;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_foveon) {
|
||||||
|
raw_width = width;
|
||||||
|
raw_height = height;
|
||||||
|
top_margin = 0;
|
||||||
|
left_margin = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder = Decoder::LIBRAW;
|
||||||
|
return err;
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (libraw_error && verbose) {
|
||||||
|
printf("LibRaw could not load image.");
|
||||||
|
if (decoder == Decoder::DCRAW) {
|
||||||
|
printf(" Falling back to dcraw.");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decoder == Decoder::LIBRAW) {
|
||||||
|
if (libraw_error) {
|
||||||
|
return libraw_error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
libraw->recycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decoder == Decoder::DCRAW) {
|
||||||
|
identify();
|
||||||
|
}
|
||||||
|
|
||||||
// in case dcraw didn't handle the above mentioned case...
|
// in case dcraw didn't handle the above mentioned case...
|
||||||
shot_select = std::min(shot_select, std::max(is_raw, 1u) - 1);
|
shot_select = std::min(shot_select, std::max(is_raw, 1u) - 1);
|
||||||
|
|
||||||
@ -482,7 +675,7 @@ int RawImage::loadRaw(bool loadData, unsigned int imageNum, bool closeFile, Prog
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(make, "Fujifilm") && raw_height * raw_width * 2u != raw_size) {
|
if (decoder == Decoder::DCRAW && !strcmp(make, "Fujifilm") && raw_height * raw_width * 2u != raw_size) {
|
||||||
if (raw_width * raw_height * 7u / 4u == raw_size) {
|
if (raw_width * raw_height * 7u / 4u == raw_size) {
|
||||||
load_raw = &RawImage::fuji_14bit_load_raw;
|
load_raw = &RawImage::fuji_14bit_load_raw;
|
||||||
} else {
|
} else {
|
||||||
@ -514,29 +707,87 @@ int RawImage::loadRaw(bool loadData, unsigned int imageNum, bool closeFile, Prog
|
|||||||
iheight = height;
|
iheight = height;
|
||||||
iwidth = width;
|
iwidth = width;
|
||||||
|
|
||||||
if (filters || colors == 1) {
|
if (decoder == Decoder::DCRAW) {
|
||||||
raw_image = (ushort *) calloc ((static_cast<unsigned int>(raw_height) + 7u) * static_cast<unsigned int>(raw_width), 2);
|
if (filters || colors == 1) {
|
||||||
merror(raw_image, "main()");
|
raw_image = (ushort *) calloc ((static_cast<unsigned int>(raw_height) + 7u) * static_cast<unsigned int>(raw_width), 2);
|
||||||
}
|
merror(raw_image, "main()");
|
||||||
|
}
|
||||||
|
|
||||||
// dcraw needs this global variable to hold pixel data
|
// dcraw needs this global variable to hold pixel data
|
||||||
image = (dcrawImage_t)calloc (static_cast<unsigned int>(height) * static_cast<unsigned int>(width) * sizeof * image + meta_length, 1);
|
image = (dcrawImage_t)calloc (static_cast<unsigned int>(height) * static_cast<unsigned int>(width) * sizeof * image + meta_length, 1);
|
||||||
if(!image) {
|
if(!image) {
|
||||||
return 200;
|
return 200;
|
||||||
}
|
}
|
||||||
meta_data = (char *) (image + static_cast<unsigned int>(height) * static_cast<unsigned int>(width));
|
meta_data = (char *) (image + static_cast<unsigned int>(height) * static_cast<unsigned int>(width));
|
||||||
|
|
||||||
/* Issue 2467
|
/* Issue 2467
|
||||||
if (setjmp (failure)) {
|
if (setjmp (failure)) {
|
||||||
if (image) { free (image); image=NULL; }
|
if (image) { free (image); image=NULL; }
|
||||||
if (raw_image) { free(raw_image); raw_image=NULL; }
|
if (raw_image) { free(raw_image); raw_image=NULL; }
|
||||||
fclose(ifp); ifp=NULL;
|
fclose(ifp); ifp=NULL;
|
||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
// Load raw pixels data
|
// Load raw pixels data
|
||||||
fseek(ifp, data_offset, SEEK_SET);
|
fseek(ifp, data_offset, SEEK_SET);
|
||||||
(this->*load_raw)();
|
(this->*load_raw)();
|
||||||
|
} else if (decoder == Decoder::LIBRAW) {
|
||||||
|
libraw->imgdata.rawparams.shot_select = shot_select;
|
||||||
|
|
||||||
|
int err = libraw->open_buffer(ifp->data, ifp->size);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
#ifdef LIBRAW_USE_OPENMP
|
||||||
|
MyMutex::MyLock lock(*librawMutex);
|
||||||
|
#endif
|
||||||
|
err = libraw->unpack();
|
||||||
|
}
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &rd = libraw->imgdata.rawdata;
|
||||||
|
raw_image = rd.raw_image;
|
||||||
|
if (rd.float_image) {
|
||||||
|
float_raw_image = new float[raw_width * raw_height];
|
||||||
|
for (int y = 0; y < raw_height; ++y) {
|
||||||
|
for (int x = 0; x < raw_width; ++x) {
|
||||||
|
size_t idx = y * raw_width + x;
|
||||||
|
float_raw_image[idx] = rd.float_image[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#ifdef LIBRAW_USE_OPENMP
|
||||||
|
MyMutex::MyLock lock(*librawMutex);
|
||||||
|
#endif
|
||||||
|
float_raw_image = nullptr;
|
||||||
|
err = libraw->raw2image();
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
image = libraw->imgdata.image;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get our custom camera matrices, but don't mess with black/white levels yet
|
||||||
|
// (if we have custom levels in json files, we will get them later)
|
||||||
|
auto bl = RT_blacklevel_from_constant;
|
||||||
|
auto wl = RT_whitelevel_from_constant;
|
||||||
|
RT_blacklevel_from_constant = ThreeValBool::F;
|
||||||
|
RT_whitelevel_from_constant = ThreeValBool::F;
|
||||||
|
|
||||||
|
adobe_coeff(make, model);
|
||||||
|
|
||||||
|
RT_blacklevel_from_constant = bl;
|
||||||
|
RT_whitelevel_from_constant = wl;
|
||||||
|
|
||||||
|
if (libraw->imgdata.color.profile_length) {
|
||||||
|
profile_length = libraw->imgdata.color.profile_length;
|
||||||
|
profile_data = new char[profile_length];
|
||||||
|
memcpy(profile_data, libraw->imgdata.color.profile, profile_length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!float_raw_image) { // apply baseline exposure only for float DNGs
|
if (!float_raw_image) { // apply baseline exposure only for float DNGs
|
||||||
RT_baseline_exposure = 0;
|
RT_baseline_exposure = 0;
|
||||||
@ -551,6 +802,10 @@ int RawImage::loadRaw(bool loadData, unsigned int imageNum, bool closeFile, Prog
|
|||||||
bool raw_crop_cc = false;
|
bool raw_crop_cc = false;
|
||||||
int orig_raw_width = width;
|
int orig_raw_width = width;
|
||||||
int orig_raw_height = height;
|
int orig_raw_height = height;
|
||||||
|
// For raw crop when using LibRaw.
|
||||||
|
int raw_top_margin = 0;
|
||||||
|
int raw_left_margin = 0;
|
||||||
|
bool adjust_margins = false;
|
||||||
|
|
||||||
if (raw_image) {
|
if (raw_image) {
|
||||||
orig_raw_width = raw_width;
|
orig_raw_width = raw_width;
|
||||||
@ -561,33 +816,82 @@ int RawImage::loadRaw(bool loadData, unsigned int imageNum, bool closeFile, Prog
|
|||||||
int lm, tm, w, h;
|
int lm, tm, w, h;
|
||||||
cc->get_rawCrop(raw_width, raw_height, lm, tm, w, h);
|
cc->get_rawCrop(raw_width, raw_height, lm, tm, w, h);
|
||||||
|
|
||||||
if (isXtrans()) {
|
if ((w < 0 || h < 0) && decoder != Decoder::DCRAW) {
|
||||||
shiftXtransMatrix(6 - ((top_margin - tm) % 6), 6 - ((left_margin - lm) % 6));
|
raw_crop_cc = false;
|
||||||
} else {
|
} else {
|
||||||
if (((int)top_margin - tm) & 1) { // we have an odd border difference
|
// protect against DNG files that are already cropped
|
||||||
filters = (filters << 4) | (filters >> 28); // left rotate filters by 4 bits
|
if (int(raw_width) <= w+lm) {
|
||||||
|
lm = max(int(raw_width) - w, 0);
|
||||||
|
}
|
||||||
|
if (int(raw_height) <= h+tm) {
|
||||||
|
tm = max(int(raw_height) - h, 0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
left_margin = lm;
|
if (decoder == Decoder::DCRAW) {
|
||||||
top_margin = tm;
|
if (isXtrans()) {
|
||||||
|
shiftXtransMatrix(6 - ((top_margin - tm) % 6), 6 - ((left_margin - lm) % 6));
|
||||||
|
} else {
|
||||||
|
if (((int)top_margin - tm) & 1) { // we have an odd border difference
|
||||||
|
filters = (filters << 4) | (filters >> 28); // left rotate filters by 4 bits
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (w < 0) {
|
left_margin = lm;
|
||||||
iwidth += w;
|
top_margin = tm;
|
||||||
iwidth -= left_margin;
|
} else {
|
||||||
width += w;
|
if (lm < left_margin) {
|
||||||
width -= left_margin;
|
lm = left_margin;
|
||||||
} else if (w > 0) {
|
}
|
||||||
iwidth = width = min((int)width, w);
|
if (tm < top_margin) {
|
||||||
}
|
tm = top_margin;
|
||||||
|
}
|
||||||
|
// make sure we do not rotate filters
|
||||||
|
if (isXtrans()) {
|
||||||
|
if ((tm - top_margin) % 6) {
|
||||||
|
tm = top_margin;
|
||||||
|
}
|
||||||
|
if ((lm - left_margin) % 6) {
|
||||||
|
lm = left_margin;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((tm - top_margin) & 1) {
|
||||||
|
tm = top_margin;
|
||||||
|
}
|
||||||
|
if ((lm - left_margin) & 1) {
|
||||||
|
lm = left_margin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
raw_left_margin = lm - left_margin;
|
||||||
|
raw_top_margin = tm - top_margin;
|
||||||
|
}
|
||||||
|
|
||||||
if (h < 0) {
|
if (w < 0) {
|
||||||
iheight += h;
|
iwidth += w;
|
||||||
iheight -= top_margin;
|
iwidth -= left_margin;
|
||||||
height += h;
|
width += w;
|
||||||
height -= top_margin;
|
width -= left_margin;
|
||||||
} else if (h > 0) {
|
} else if (w > 0) {
|
||||||
iheight = height = min((int)height, h);
|
width = min((int)width, w);
|
||||||
|
if (decoder == Decoder::DCRAW) {
|
||||||
|
iwidth = width;
|
||||||
|
} else if (width > iwidth) {
|
||||||
|
width = iwidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h < 0) {
|
||||||
|
iheight += h;
|
||||||
|
iheight -= top_margin;
|
||||||
|
height += h;
|
||||||
|
height -= top_margin;
|
||||||
|
} else if (h > 0) {
|
||||||
|
height = min((int)height, h);
|
||||||
|
if (decoder == Decoder::DCRAW) {
|
||||||
|
iheight = height;
|
||||||
|
} else if (height > iheight) {
|
||||||
|
height = iheight;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -597,11 +901,14 @@ int RawImage::loadRaw(bool loadData, unsigned int imageNum, bool closeFile, Prog
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crop_masked_pixels();
|
if (decoder == Decoder::DCRAW) {
|
||||||
free(raw_image);
|
crop_masked_pixels();
|
||||||
|
free(raw_image);
|
||||||
|
}
|
||||||
raw_image = nullptr;
|
raw_image = nullptr;
|
||||||
|
adjust_margins = !float_raw_image; //true;
|
||||||
} else {
|
} else {
|
||||||
if (get_maker() == "Sigma" && cc && cc->has_rawCrop(width, height)) { // foveon images
|
if (decoder == Decoder::DCRAW && get_maker() == "Sigma" && cc && cc->has_rawCrop(width, height)) { // foveon images
|
||||||
raw_crop_cc = true;
|
raw_crop_cc = true;
|
||||||
int lm, tm, w, h;
|
int lm, tm, w, h;
|
||||||
cc->get_rawCrop(width, height, lm, tm, w, h);
|
cc->get_rawCrop(width, height, lm, tm, w, h);
|
||||||
@ -611,21 +918,27 @@ int RawImage::loadRaw(bool loadData, unsigned int imageNum, bool closeFile, Prog
|
|||||||
if (w < 0) {
|
if (w < 0) {
|
||||||
width += w;
|
width += w;
|
||||||
width -= left_margin;
|
width -= left_margin;
|
||||||
|
iwidth += w;
|
||||||
|
iwidth -= left_margin;
|
||||||
} else if (w > 0) {
|
} else if (w > 0) {
|
||||||
width = min((int)width, w);
|
width = min((int)width, w);
|
||||||
|
iwidth = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h < 0) {
|
if (h < 0) {
|
||||||
height += h;
|
height += h;
|
||||||
height -= top_margin;
|
height -= top_margin;
|
||||||
|
iheight += h;
|
||||||
|
iheight -= top_margin;
|
||||||
} else if (h > 0) {
|
} else if (h > 0) {
|
||||||
height = min((int)height, h);
|
height = min((int)height, h);
|
||||||
|
iheight = height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load embedded profile
|
// Load embedded profile
|
||||||
if (profile_length) {
|
if (decoder == Decoder::DCRAW && profile_length) {
|
||||||
profile_data = new char[profile_length];
|
profile_data = new char[profile_length];
|
||||||
fseek(ifp, profile_offset, SEEK_SET);
|
fseek(ifp, profile_offset, SEEK_SET);
|
||||||
fread(profile_data, 1, profile_length, ifp);
|
fread(profile_data, 1, profile_length, ifp);
|
||||||
@ -690,23 +1003,30 @@ int RawImage::loadRaw(bool loadData, unsigned int imageNum, bool closeFile, Prog
|
|||||||
for (int c = 0; c < 4; c++) {
|
for (int c = 0; c < 4; c++) {
|
||||||
if (static_cast<int>(cblack[c]) < black_c4[c]) {
|
if (static_cast<int>(cblack[c]) < black_c4[c]) {
|
||||||
cblack[c] = black_c4[c];
|
cblack[c] = black_c4[c];
|
||||||
|
cblack[4] = cblack[5] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings->verbose) {
|
if (settings->verbose) {
|
||||||
|
const char *decoder_name = decoder == Decoder::DCRAW ? "dcraw" : decoder == Decoder::LIBRAW ? "libraw" : "unknown";
|
||||||
if (cc) {
|
if (cc) {
|
||||||
printf("constants exists for \"%s %s\" in camconst.json\n", make, model);
|
printf("constants exists for \"%s %s\" in camconst.json\n", make, model);
|
||||||
} else {
|
} else {
|
||||||
printf("no constants in camconst.json exists for \"%s %s\" (relying only on dcraw defaults)\n", make, model);
|
printf("no constants in camconst.json exists for \"%s %s\" (relying only on %s defaults)\n", make, model, decoder_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("raw dimensions: %d x %d\n", orig_raw_width, orig_raw_height);
|
printf("raw dimensions: %d x %d\n", orig_raw_width, orig_raw_height);
|
||||||
printf("black levels: R:%d G1:%d B:%d G2:%d (%s)\n", get_cblack(0), get_cblack(1), get_cblack(2), get_cblack(3),
|
printf("black levels: R:%d G1:%d B:%d G2:%d (provided by %s)\n", get_cblack(0), get_cblack(1), get_cblack(2), get_cblack(3),
|
||||||
black_from_cc ? "provided by camconst.json" : "provided by dcraw");
|
black_from_cc ? "camconst.json" : decoder_name);
|
||||||
printf("white levels: R:%d G1:%d B:%d G2:%d (%s)\n", get_white(0), get_white(1), get_white(2), get_white(3),
|
printf("white levels: R:%d G1:%d B:%d G2:%d (provided by %s)\n", get_white(0), get_white(1), get_white(2), get_white(3),
|
||||||
white_from_cc ? "provided by camconst.json" : "provided by dcraw");
|
white_from_cc ? "camconst.json" : decoder_name);
|
||||||
printf("raw crop: %d %d %d %d (provided by %s)\n", left_margin, top_margin, iwidth, iheight, raw_crop_cc ? "camconst.json" : "dcraw");
|
printf("raw crop: %d %d %d %d (provided by %s)\n", left_margin, top_margin, iwidth, iheight, raw_crop_cc ? "camconst.json" : decoder_name);
|
||||||
printf("color matrix provided by %s\n", (cc && cc->has_dcrawMatrix()) ? "camconst.json" : "dcraw");
|
printf("color matrix provided by %s\n", (cc && cc->has_dcrawMatrix()) ? "camconst.json" : decoder_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adjust_margins) {
|
||||||
|
top_margin = raw_top_margin;
|
||||||
|
left_margin = raw_left_margin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -779,7 +1099,7 @@ float** RawImage::compress_image(unsigned int frameNum, bool freeImage)
|
|||||||
|
|
||||||
for (int row = 0; row < height; row++)
|
for (int row = 0; row < height; row++)
|
||||||
for (int col = 0; col < width; col++) {
|
for (int col = 0; col < width; col++) {
|
||||||
this->data[row][col] = image[row * width + col][FC(row, col)];
|
this->data[row][col] = image[(row + top_margin) * iwidth + col + left_margin][FC(row, col)];
|
||||||
}
|
}
|
||||||
} else if (isXtrans()) {
|
} else if (isXtrans()) {
|
||||||
#ifdef _OPENMP
|
#ifdef _OPENMP
|
||||||
@ -788,7 +1108,7 @@ float** RawImage::compress_image(unsigned int frameNum, bool freeImage)
|
|||||||
|
|
||||||
for (int row = 0; row < height; row++)
|
for (int row = 0; row < height; row++)
|
||||||
for (int col = 0; col < width; col++) {
|
for (int col = 0; col < width; col++) {
|
||||||
this->data[row][col] = image[row * width + col][XTRANSFC(row, col)];
|
this->data[row][col] = image[(row + top_margin) * iwidth + col + left_margin][XTRANSFC(row, col)];
|
||||||
}
|
}
|
||||||
} else if (colors == 1) {
|
} else if (colors == 1) {
|
||||||
#ifdef _OPENMP
|
#ifdef _OPENMP
|
||||||
@ -797,7 +1117,7 @@ float** RawImage::compress_image(unsigned int frameNum, bool freeImage)
|
|||||||
|
|
||||||
for (int row = 0; row < height; row++)
|
for (int row = 0; row < height; row++)
|
||||||
for (int col = 0; col < width; col++) {
|
for (int col = 0; col < width; col++) {
|
||||||
this->data[row][col] = image[row * width + col][0];
|
this->data[row][col] = image[row * iwidth + col][0];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if((get_maker() == "Sigma" || get_maker() == "Pentax" || get_maker() == "Sony") && dng_version) { // Hack to prevent sigma dng files and dng files from PixelShift2DNG from crashing
|
if((get_maker() == "Sigma" || get_maker() == "Pentax" || get_maker() == "Sony") && dng_version) { // Hack to prevent sigma dng files and dng files from PixelShift2DNG from crashing
|
||||||
@ -817,7 +1137,11 @@ float** RawImage::compress_image(unsigned int frameNum, bool freeImage)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (freeImage) {
|
if (freeImage) {
|
||||||
free(image); // we don't need this anymore
|
if (decoder == Decoder::DCRAW) {
|
||||||
|
free(image); // we don't need this anymore
|
||||||
|
} else if (decoder == Decoder::LIBRAW) {
|
||||||
|
libraw->recycle();
|
||||||
|
}
|
||||||
image = nullptr;
|
image = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -872,6 +1196,89 @@ RawImage::get_thumbSwap() const
|
|||||||
return (order == 0x4949) == (ntohs(0x1234) == 0x1234);
|
return (order == 0x4949) == (ntohs(0x1234) == 0x1234);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool RawImage::checkThumbOk() const
|
||||||
|
{
|
||||||
|
if (!is_supportedThumb()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_thumbOffset() >= get_file()->size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ssize_t length =
|
||||||
|
fdata (get_thumbOffset(), get_file())[1] != 0xD8 && is_ppmThumb()
|
||||||
|
? get_thumbWidth() * get_thumbHeight() * (get_thumbBPS() / 8) * 3
|
||||||
|
: get_thumbLength();
|
||||||
|
|
||||||
|
return get_thumbOffset() + length <= get_file()->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Image8 *RawImage::getThumbnail() const
|
||||||
|
{
|
||||||
|
if (decoder == Decoder::DCRAW) {
|
||||||
|
if (!checkThumbOk()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image8 *img = new Image8();
|
||||||
|
img->setSampleFormat(IIOSF_UNSIGNED_CHAR);
|
||||||
|
img->setSampleArrangement(IIOSA_CHUNKY);
|
||||||
|
|
||||||
|
const char *data = reinterpret_cast<const char *>(fdata(get_thumbOffset(), get_file()));
|
||||||
|
|
||||||
|
int err = 1;
|
||||||
|
if ((unsigned char)data[1] == 0xd8) {
|
||||||
|
err = img->loadJPEGFromMemory(data, get_thumbLength());
|
||||||
|
} else if (is_ppmThumb()) {
|
||||||
|
err = img->loadPPMFromMemory(data, get_thumbWidth(), get_thumbHeight(), get_thumbSwap(), get_thumbBPS());
|
||||||
|
}
|
||||||
|
|
||||||
|
// did we succeed?
|
||||||
|
if (err) {
|
||||||
|
delete img;
|
||||||
|
img = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ifp) {
|
||||||
|
return nullptr;
|
||||||
|
} else {
|
||||||
|
int err = libraw->unpack_thumb();
|
||||||
|
if (err) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto &t = libraw->imgdata.thumbnail;
|
||||||
|
if (!t.thumb) {
|
||||||
|
return nullptr;
|
||||||
|
} else if (t.tformat != LIBRAW_THUMBNAIL_JPEG && t.tformat != LIBRAW_THUMBNAIL_BITMAP) {
|
||||||
|
return nullptr;
|
||||||
|
} else {
|
||||||
|
Image8 *img = new Image8();
|
||||||
|
img->setSampleFormat(IIOSF_UNSIGNED_CHAR);
|
||||||
|
img->setSampleArrangement(IIOSA_CHUNKY);
|
||||||
|
if (t.tformat == LIBRAW_THUMBNAIL_JPEG) {
|
||||||
|
err = img->loadJPEGFromMemory(t.thumb, t.tlength);
|
||||||
|
} else {
|
||||||
|
err = img->loadPPMFromMemory(t.thumb, t.twidth, t.theight, false, 8);
|
||||||
|
}
|
||||||
|
if (err) {
|
||||||
|
delete img;
|
||||||
|
return nullptr;
|
||||||
|
} else {
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} //namespace rtengine
|
} //namespace rtengine
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -21,14 +21,23 @@
|
|||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
#include <glibmm/ustring.h>
|
#include <glibmm/ustring.h>
|
||||||
|
|
||||||
#include "dcraw.h"
|
#include "dcraw.h"
|
||||||
#include "imageformat.h"
|
#include "imageformat.h"
|
||||||
|
|
||||||
|
|
||||||
|
class LibRaw;
|
||||||
|
|
||||||
|
|
||||||
namespace rtengine
|
namespace rtengine
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
class Image8;
|
||||||
|
|
||||||
|
|
||||||
class RawImage: public DCraw
|
class RawImage: public DCraw
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -57,11 +66,18 @@ public:
|
|||||||
double getBaselineExposure() const { return RT_baseline_exposure; }
|
double getBaselineExposure() const { return RT_baseline_exposure; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
enum class Decoder {
|
||||||
|
DCRAW,
|
||||||
|
LIBRAW,
|
||||||
|
};
|
||||||
|
|
||||||
Glib::ustring filename; // complete filename
|
Glib::ustring filename; // complete filename
|
||||||
int rotate_deg; // 0,90,180,270 degree of rotation: info taken by dcraw from exif
|
int rotate_deg; // 0,90,180,270 degree of rotation: info taken by dcraw from exif
|
||||||
char* profile_data; // Embedded ICC color profile
|
char* profile_data; // Embedded ICC color profile
|
||||||
float* allocation; // pointer to allocated memory
|
float* allocation; // pointer to allocated memory
|
||||||
int maximum_c4[4];
|
int maximum_c4[4];
|
||||||
|
Decoder decoder{Decoder::DCRAW};
|
||||||
|
std::unique_ptr<LibRaw> libraw;
|
||||||
bool isFoveon() const
|
bool isFoveon() const
|
||||||
{
|
{
|
||||||
return is_foveon;
|
return is_foveon;
|
||||||
@ -261,10 +277,7 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// dcraw functions
|
// dcraw functions
|
||||||
void pre_interpolate()
|
void pre_interpolate();
|
||||||
{
|
|
||||||
DCraw::pre_interpolate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool ISRED(unsigned row, unsigned col) const
|
bool ISRED(unsigned row, unsigned col) const
|
||||||
@ -304,6 +317,11 @@ public:
|
|||||||
{
|
{
|
||||||
return dng_version;
|
return dng_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool checkThumbOk() const;
|
||||||
|
Image8 *getThumbnail() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -495,32 +495,14 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, eSensorType
|
|||||||
|
|
||||||
sensorType = ri->getSensorType();
|
sensorType = ri->getSensorType();
|
||||||
|
|
||||||
Image8* img = new Image8 ();
|
Image8 *img = ri->getThumbnail();
|
||||||
// No sample format detection occurred earlier, so we set them here,
|
|
||||||
// as they are mandatory for the setScanline method
|
|
||||||
img->setSampleFormat (IIOSF_UNSIGNED_CHAR);
|
|
||||||
img->setSampleArrangement (IIOSA_CHUNKY);
|
|
||||||
|
|
||||||
int err = 1;
|
|
||||||
|
|
||||||
// See if it is something we support
|
|
||||||
if (checkRawImageThumb (*ri)) {
|
|
||||||
const char* data ((const char*)fdata (ri->get_thumbOffset(), ri->get_file()));
|
|
||||||
|
|
||||||
if ( (unsigned char)data[1] == 0xd8 ) {
|
|
||||||
err = img->loadJPEGFromMemory (data, ri->get_thumbLength());
|
|
||||||
} else if (ri->is_ppmThumb()) {
|
|
||||||
err = img->loadPPMFromMemory (data, ri->get_thumbWidth(), ri->get_thumbHeight(), ri->get_thumbSwap(), ri->get_thumbBPS());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// did we succeed?
|
// did we succeed?
|
||||||
if ( err ) {
|
if (!img) {
|
||||||
if (settings->verbose) {
|
if (settings->verbose) {
|
||||||
std::cout << "Could not extract thumb from " << fname.c_str() << std::endl;
|
std::cout << "Could not extract thumb from " << fname.c_str() << std::endl;
|
||||||
}
|
}
|
||||||
delete tpp;
|
delete tpp;
|
||||||
delete img;
|
|
||||||
delete ri;
|
delete ri;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -627,6 +609,11 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, eSensorType &sens
|
|||||||
|
|
||||||
int width = ri->get_width();
|
int width = ri->get_width();
|
||||||
int height = ri->get_height();
|
int height = ri->get_height();
|
||||||
|
int iwidth = ri->get_iwidth();
|
||||||
|
int iheight = ri->get_iheight();
|
||||||
|
int left_margin = ri->get_leftmargin();
|
||||||
|
int top_margin = ri->get_topmargin();
|
||||||
|
|
||||||
rtengine::Thumbnail* tpp = new rtengine::Thumbnail;
|
rtengine::Thumbnail* tpp = new rtengine::Thumbnail;
|
||||||
|
|
||||||
tpp->isRaw = true;
|
tpp->isRaw = true;
|
||||||
@ -717,19 +704,19 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, eSensorType &sens
|
|||||||
if (ri->getSensorType() == ST_BAYER) {
|
if (ri->getSensorType() == ST_BAYER) {
|
||||||
// demosaicing! (sort of)
|
// demosaicing! (sort of)
|
||||||
for (int row = 1, y = 0; row < height - 1 && y < tmph; row += vskip, y++) {
|
for (int row = 1, y = 0; row < height - 1 && y < tmph; row += vskip, y++) {
|
||||||
rofs = row * width;
|
rofs = (row + top_margin) * iwidth;
|
||||||
|
|
||||||
for (int col = firstgreen, x = 0; col < width - 1 && x < tmpw; col += hskip, x++) {
|
for (int col = firstgreen, x = 0; col < width - 1 && x < tmpw; col += hskip, x++) {
|
||||||
int ofs = rofs + col;
|
int ofs = rofs + col + left_margin;
|
||||||
int g = image[ofs][1];
|
int g = image[ofs][1];
|
||||||
int r, b;
|
int r, b;
|
||||||
|
|
||||||
if (FISRED (filter, row, col + 1)) {
|
if (FISRED (filter, row, col + 1)) {
|
||||||
r = (image[ofs + 1 ][0] + image[ofs - 1 ][0]) >> 1;
|
r = (image[ofs + 1 ][0] + image[ofs - 1 ][0]) >> 1;
|
||||||
b = (image[ofs + width][2] + image[ofs - width][2]) >> 1;
|
b = (image[ofs + iwidth][2] + image[ofs - iwidth][2]) >> 1;
|
||||||
} else {
|
} else {
|
||||||
b = (image[ofs + 1 ][2] + image[ofs - 1 ][2]) >> 1;
|
b = (image[ofs + 1 ][2] + image[ofs - 1 ][2]) >> 1;
|
||||||
r = (image[ofs + width][0] + image[ofs - width][0]) >> 1;
|
r = (image[ofs + iwidth][0] + image[ofs - iwidth][0]) >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpImg->r (y, x) = r;
|
tmpImg->r (y, x) = r;
|
||||||
@ -739,28 +726,28 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, eSensorType &sens
|
|||||||
}
|
}
|
||||||
} else if (ri->get_colors() == 1) {
|
} else if (ri->get_colors() == 1) {
|
||||||
for (int row = 1, y = 0; row < height - 1 && y < tmph; row += vskip, y++) {
|
for (int row = 1, y = 0; row < height - 1 && y < tmph; row += vskip, y++) {
|
||||||
rofs = row * width;
|
rofs = (row + top_margin) * iwidth;
|
||||||
|
|
||||||
for (int col = firstgreen, x = 0; col < width - 1 && x < tmpw; col
|
for (int col = firstgreen, x = 0; col < width - 1 && x < tmpw; col
|
||||||
+= hskip, x++) {
|
+= hskip, x++) {
|
||||||
int ofs = rofs + col;
|
int ofs = rofs + col + left_margin;
|
||||||
tmpImg->r (y, x) = tmpImg->g (y, x) = tmpImg->b (y, x) = image[ofs][0];
|
tmpImg->r (y, x) = tmpImg->g (y, x) = tmpImg->b (y, x) = image[ofs][0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (ri->getSensorType() == ST_FUJI_XTRANS) {
|
if (ri->getSensorType() == ST_FUJI_XTRANS) {
|
||||||
for ( int row = 1, y = 0; row < height - 1 && y < tmph; row += vskip, y++) {
|
for ( int row = 1, y = 0; row < height - 1 && y < tmph; row += vskip, y++) {
|
||||||
rofs = row * width;
|
rofs = (row + top_margin) * iwidth;
|
||||||
|
|
||||||
for ( int col = 1, x = 0; col < width - 1 && x < tmpw; col += hskip, x++ ) {
|
for ( int col = 1, x = 0; col < width - 1 && x < tmpw; col += hskip, x++ ) {
|
||||||
int ofs = rofs + col;
|
int ofs = rofs + col + left_margin;
|
||||||
float sum[3] = {};
|
float sum[3] = {};
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
for (int v = -1; v <= 1; v++) {
|
for (int v = -1; v <= 1; v++) {
|
||||||
for (int h = -1; h <= 1; h++) {
|
for (int h = -1; h <= 1; h++) {
|
||||||
c = ri->XTRANSFC (row + v, col + h);
|
c = ri->XTRANSFC (row + v, col + h);
|
||||||
sum[c] += image[ofs + v * width + h][c];
|
sum[c] += image[ofs + v * iwidth + h][c];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -788,11 +775,11 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, eSensorType &sens
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int iwidth = ri->get_iwidth();
|
// int iwidth = ri->get_iwidth();
|
||||||
int iheight = ri->get_iheight();
|
// int iheight = ri->get_iheight();
|
||||||
int left_margin = ri->get_leftmargin();
|
// int left_margin = ri->get_leftmargin();
|
||||||
firstgreen += left_margin;
|
firstgreen += left_margin;
|
||||||
int top_margin = ri->get_topmargin();
|
// int top_margin = ri->get_topmargin();
|
||||||
int wmax = tmpw;
|
int wmax = tmpw;
|
||||||
int hmax = tmph;
|
int hmax = tmph;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user