Move film_simulation_strength
calculation into HaldCLUT::getRGB()
- Moved `film_simulation_strength` calculation into `HaldCLUT::getRGB()` - Removed unneeded base class `CLUT` - Used `_MM_SHUFFLE`
This commit is contained in:
@@ -87,40 +87,6 @@ inline vfloat getClutValue(const AlignedBuffer<std::uint16_t>& clut_image, size_
|
||||
|
||||
}
|
||||
|
||||
void rtengine::CLUT::splitClutFilename(
|
||||
const Glib::ustring& filename,
|
||||
Glib::ustring& name,
|
||||
Glib::ustring& extension,
|
||||
Glib::ustring& profile_name
|
||||
)
|
||||
{
|
||||
Glib::ustring basename = Glib::path_get_basename(filename);
|
||||
|
||||
Glib::ustring::size_type last_slash_pos = basename.rfind('/');
|
||||
if (last_slash_pos == Glib::ustring::npos) {
|
||||
last_slash_pos = basename.rfind('\\');
|
||||
}
|
||||
|
||||
const Glib::ustring::size_type last_dot_pos = basename.rfind('.');
|
||||
|
||||
if (last_dot_pos != Glib::ustring::npos) {
|
||||
name.assign(basename, 0, last_dot_pos);
|
||||
extension.assign(basename, last_dot_pos + 1, Glib::ustring::npos);
|
||||
} else {
|
||||
name = basename;
|
||||
}
|
||||
|
||||
profile_name = "sRGB";
|
||||
|
||||
for (const auto& working_profile : rtengine::getWorkingProfiles()) {
|
||||
if ( std::search( name.rbegin(), name.rend(), working_profile.rbegin(), working_profile.rend() ) == name.rbegin() ) {
|
||||
profile_name = working_profile;
|
||||
name.erase(name.size() - working_profile.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rtengine::HaldCLUT::HaldCLUT() :
|
||||
clut_level(0),
|
||||
flevel_minus_one(0.0f),
|
||||
@@ -164,7 +130,14 @@ Glib::ustring rtengine::HaldCLUT::getProfile() const
|
||||
return clut_profile;
|
||||
}
|
||||
|
||||
void rtengine::HaldCLUT::getRGB(std::size_t line_size, const float* r, const float* g, const float* b, float* out_rgbx) const
|
||||
void rtengine::HaldCLUT::getRGB(
|
||||
float strength,
|
||||
std::size_t line_size,
|
||||
const float* r,
|
||||
const float* g,
|
||||
const float* b,
|
||||
float* out_rgbx
|
||||
) const
|
||||
{
|
||||
const unsigned int level = clut_level; // This is important
|
||||
|
||||
@@ -219,13 +192,18 @@ void rtengine::HaldCLUT::getRGB(std::size_t line_size, const float* r, const flo
|
||||
out_rgbx[0] = intp<float>(bl, tmp1[0], out_rgbx[0]);
|
||||
out_rgbx[1] = intp<float>(bl, tmp1[1], out_rgbx[1]);
|
||||
out_rgbx[2] = intp<float>(bl, tmp1[2], out_rgbx[2]);
|
||||
|
||||
out_rgbx[0] = intp<float>(strength, out_rgbx[0], *r);
|
||||
out_rgbx[1] = intp<float>(strength, out_rgbx[1], *g);
|
||||
out_rgbx[2] = intp<float>(strength, out_rgbx[2], *b);
|
||||
#else
|
||||
const vfloat v_tmp = _mm_set_ps(0.0f, *b, *g, *r) * _mm_load_ps1(&flevel_minus_one);
|
||||
const vfloat v_in = _mm_set_ps(0.0f, *b, *g, *r);
|
||||
const vfloat v_tmp = v_in * _mm_load_ps1(&flevel_minus_one);
|
||||
const vfloat v_rgb = v_tmp - _mm_cvtepi32_ps(_mm_cvttps_epi32(_mm_min_ps(_mm_load_ps1(&flevel_minus_two), v_tmp)));
|
||||
|
||||
size_t index = color * 4;
|
||||
|
||||
const vfloat v_r = PERMUTEPS(v_rgb, 0x00);
|
||||
const vfloat v_r = PERMUTEPS(v_rgb, _MM_SHUFFLE(0, 0, 0, 0));
|
||||
|
||||
vfloat v_tmp1 = vintpf(v_r, getClutValue(clut_image, index + 4), getClutValue(clut_image, index));
|
||||
|
||||
@@ -233,7 +211,7 @@ void rtengine::HaldCLUT::getRGB(std::size_t line_size, const float* r, const flo
|
||||
|
||||
vfloat v_tmp2 = vintpf(v_r, getClutValue(clut_image, index + 4), getClutValue(clut_image, index));
|
||||
|
||||
const vfloat v_g = PERMUTEPS(v_rgb, 0x55);
|
||||
const vfloat v_g = PERMUTEPS(v_rgb, _MM_SHUFFLE(1, 1, 1, 1));
|
||||
|
||||
vfloat v_out = vintpf(v_g, v_tmp2, v_tmp1);
|
||||
|
||||
@@ -247,22 +225,58 @@ void rtengine::HaldCLUT::getRGB(std::size_t line_size, const float* r, const flo
|
||||
|
||||
v_tmp1 = vintpf(v_g, v_tmp2, v_tmp1);
|
||||
|
||||
const vfloat v_b = PERMUTEPS(v_rgb, 0xAA);
|
||||
const vfloat v_b = PERMUTEPS(v_rgb, _MM_SHUFFLE(2, 2, 2, 2));
|
||||
|
||||
_mm_store_ps(out_rgbx, vintpf(v_b, v_tmp1, v_out));
|
||||
v_out = vintpf(v_b, v_tmp1, v_out);
|
||||
|
||||
_mm_store_ps(out_rgbx, vintpf(_mm_load_ps1(&strength), v_out, v_in));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void rtengine::HaldCLUT::splitClutFilename(
|
||||
const Glib::ustring& filename,
|
||||
Glib::ustring& name,
|
||||
Glib::ustring& extension,
|
||||
Glib::ustring& profile_name
|
||||
)
|
||||
{
|
||||
Glib::ustring basename = Glib::path_get_basename(filename);
|
||||
|
||||
Glib::ustring::size_type last_slash_pos = basename.rfind('/');
|
||||
if (last_slash_pos == Glib::ustring::npos) {
|
||||
last_slash_pos = basename.rfind('\\');
|
||||
}
|
||||
|
||||
const Glib::ustring::size_type last_dot_pos = basename.rfind('.');
|
||||
|
||||
if (last_dot_pos != Glib::ustring::npos) {
|
||||
name.assign(basename, 0, last_dot_pos);
|
||||
extension.assign(basename, last_dot_pos + 1, Glib::ustring::npos);
|
||||
} else {
|
||||
name = basename;
|
||||
}
|
||||
|
||||
profile_name = "sRGB";
|
||||
|
||||
for (const auto& working_profile : rtengine::getWorkingProfiles()) {
|
||||
if ( std::search( name.rbegin(), name.rend(), working_profile.rbegin(), working_profile.rend() ) == name.rbegin() ) {
|
||||
profile_name = working_profile;
|
||||
name.erase(name.size() - working_profile.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rtengine::CLUTStore& rtengine::CLUTStore::getInstance()
|
||||
{
|
||||
static CLUTStore instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::shared_ptr<rtengine::CLUT> rtengine::CLUTStore::getClut(const Glib::ustring& filename)
|
||||
std::shared_ptr<rtengine::HaldCLUT> rtengine::CLUTStore::getClut(const Glib::ustring& filename)
|
||||
{
|
||||
std::shared_ptr<rtengine::CLUT> result;
|
||||
std::shared_ptr<rtengine::HaldCLUT> result;
|
||||
|
||||
if (!cache.get(filename, result)) {
|
||||
std::unique_ptr<rtengine::HaldCLUT> clut(new rtengine::HaldCLUT);
|
||||
@@ -275,11 +289,6 @@ std::shared_ptr<rtengine::CLUT> rtengine::CLUTStore::getClut(const Glib::ustring
|
||||
return result;
|
||||
}
|
||||
|
||||
void rtengine::CLUTStore::releaseClut(const std::shared_ptr<rtengine::CLUT>& clut)
|
||||
{
|
||||
cache.remove(clut->getFilename());
|
||||
}
|
||||
|
||||
void rtengine::CLUTStore::clearCache()
|
||||
{
|
||||
cache.clear();
|
||||
|
@@ -11,20 +11,29 @@
|
||||
namespace rtengine
|
||||
{
|
||||
|
||||
class CLUT
|
||||
class HaldCLUT
|
||||
{
|
||||
public:
|
||||
CLUT() = default;
|
||||
CLUT(const CLUT& other) = delete;
|
||||
CLUT& operator =(const CLUT& other) = delete;
|
||||
virtual ~CLUT() = default;
|
||||
HaldCLUT();
|
||||
HaldCLUT(const HaldCLUT& other) = delete;
|
||||
HaldCLUT& operator =(const HaldCLUT& other) = delete;
|
||||
~HaldCLUT();
|
||||
|
||||
virtual explicit operator bool() const = 0;
|
||||
bool load(const Glib::ustring& filename);
|
||||
|
||||
virtual Glib::ustring getFilename() const = 0;
|
||||
virtual Glib::ustring getProfile() const = 0;
|
||||
explicit operator bool() const;
|
||||
|
||||
virtual void getRGB(std::size_t line_size, const float* r, const float* g, const float* b, float* out_rgbx) const = 0;
|
||||
Glib::ustring getFilename() const;
|
||||
Glib::ustring getProfile() const;
|
||||
|
||||
void getRGB(
|
||||
float strength,
|
||||
std::size_t line_size,
|
||||
const float* r,
|
||||
const float* g,
|
||||
const float* b,
|
||||
float* out_rgbx
|
||||
) const;
|
||||
|
||||
static void splitClutFilename(
|
||||
const Glib::ustring& filename,
|
||||
@@ -32,23 +41,6 @@ public:
|
||||
Glib::ustring& extension,
|
||||
Glib::ustring& profile_name
|
||||
);
|
||||
};
|
||||
|
||||
class HaldCLUT
|
||||
: public CLUT
|
||||
{
|
||||
public:
|
||||
HaldCLUT();
|
||||
~HaldCLUT();
|
||||
|
||||
bool load(const Glib::ustring& filename);
|
||||
|
||||
explicit operator bool() const override;
|
||||
|
||||
Glib::ustring getFilename() const override;
|
||||
Glib::ustring getProfile() const override;
|
||||
|
||||
void getRGB(std::size_t line_size, const float* r, const float* g, const float* b, float* out_rgbx) const override;
|
||||
|
||||
private:
|
||||
AlignedBuffer<std::uint16_t> clut_image;
|
||||
@@ -67,15 +59,14 @@ public:
|
||||
CLUTStore(const CLUTStore& other) = delete;
|
||||
CLUTStore& operator =(const CLUTStore& other) = delete;
|
||||
|
||||
std::shared_ptr<CLUT> getClut(const Glib::ustring& filename);
|
||||
void releaseClut(const std::shared_ptr<CLUT>& clut);
|
||||
std::shared_ptr<HaldCLUT> getClut(const Glib::ustring& filename);
|
||||
|
||||
void clearCache();
|
||||
|
||||
private:
|
||||
CLUTStore();
|
||||
|
||||
Cache<Glib::ustring, std::shared_ptr<CLUT>> cache;
|
||||
Cache<Glib::ustring, std::shared_ptr<HaldCLUT>> cache;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -16,7 +16,6 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <memory>
|
||||
#include <cmath>
|
||||
#include <glib.h>
|
||||
#include <glibmm.h>
|
||||
@@ -3206,27 +3205,26 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<CLUT> colorLUT;
|
||||
std::shared_ptr<HaldCLUT> hald_clut;
|
||||
bool clutAndWorkingProfilesAreSame = false;
|
||||
TMatrix work2xyz, xyz2clut, clut2xyz, xyz2work;
|
||||
|
||||
if ( params->filmSimulation.enabled && !params->filmSimulation.clutFilename.empty() ) {
|
||||
colorLUT = CLUTStore::getInstance().getClut( params->filmSimulation.clutFilename );
|
||||
hald_clut = CLUTStore::getInstance().getClut( params->filmSimulation.clutFilename );
|
||||
|
||||
if ( colorLUT ) {
|
||||
clutAndWorkingProfilesAreSame = colorLUT->getProfile() == params->icm.working;
|
||||
if ( hald_clut ) {
|
||||
clutAndWorkingProfilesAreSame = hald_clut->getProfile() == params->icm.working;
|
||||
|
||||
if ( !clutAndWorkingProfilesAreSame ) {
|
||||
work2xyz = iccStore->workingSpaceMatrix( params->icm.working );
|
||||
xyz2clut = iccStore->workingSpaceInverseMatrix( colorLUT->getProfile() );
|
||||
xyz2clut = iccStore->workingSpaceInverseMatrix( hald_clut->getProfile() );
|
||||
xyz2work = iccStore->workingSpaceInverseMatrix( params->icm.working );
|
||||
clut2xyz = iccStore->workingSpaceMatrix( colorLUT->getProfile() );
|
||||
clut2xyz = iccStore->workingSpaceMatrix( hald_clut->getProfile() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float filmSimCorrectedStrength = static_cast<float>(params->filmSimulation.strength) / 100.0f;
|
||||
float filmSimSourceStrength = 1.0f - filmSimCorrectedStrength;
|
||||
const float film_simulation_strength = static_cast<float>(params->filmSimulation.strength) / 100.0f;
|
||||
|
||||
const float exp_scale = pow (2.0, expcomp);
|
||||
const float comp = (max(0.0, expcomp) + 1.0) * hlcompr / 100.0;
|
||||
@@ -4337,11 +4335,8 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
||||
|
||||
|
||||
//Film Simulations
|
||||
if ( colorLUT ) {
|
||||
std::size_t out_rgbx_size = 4 * (TS + 16);
|
||||
std::unique_ptr<float> out_rgbx_buf(new float[out_rgbx_size]);
|
||||
void* out_rgbx_ptr = out_rgbx_buf.get();
|
||||
float* const out_rgbx = reinterpret_cast<float*>(std::align(16, 4 * TS, out_rgbx_ptr, out_rgbx_size));
|
||||
if ( hald_clut ) {
|
||||
float out_rgbx[4 * TS] ALIGNED16;
|
||||
|
||||
for (int i = istart, ti = 0; i < tH; i++, ti++) {
|
||||
for (int j = jstart, tj = 0; j < tW; j++, tj++) {
|
||||
@@ -4362,21 +4357,25 @@ void ImProcFunctions::rgbProc (Imagefloat* working, LabImage* lab, PipetteBuffer
|
||||
sourceB = CLIP<float>( Color::gamma_srgb( sourceB ) );
|
||||
}
|
||||
|
||||
colorLUT->getRGB(std::min(TS, tW - jstart), rtemp + ti * TS, gtemp + ti * TS, btemp + ti * TS, out_rgbx);
|
||||
const std::size_t line_offset = ti * TS;
|
||||
hald_clut->getRGB(
|
||||
film_simulation_strength,
|
||||
std::min(TS, tW - jstart),
|
||||
rtemp + line_offset,
|
||||
gtemp + line_offset,
|
||||
btemp + line_offset,
|
||||
out_rgbx
|
||||
);
|
||||
|
||||
for (int j = jstart, tj = 0; j < tW; j++, tj++) {
|
||||
float &sourceR = rtemp[ti * TS + tj];
|
||||
float &sourceG = gtemp[ti * TS + tj];
|
||||
float &sourceB = btemp[ti * TS + tj];
|
||||
|
||||
// apply strength
|
||||
sourceR = out_rgbx[tj * 4 + 0] * filmSimCorrectedStrength + sourceR * filmSimSourceStrength;
|
||||
sourceG = out_rgbx[tj * 4 + 1] * filmSimCorrectedStrength + sourceG * filmSimSourceStrength;
|
||||
sourceB = out_rgbx[tj * 4 + 2] * filmSimCorrectedStrength + sourceB * filmSimSourceStrength;
|
||||
// apply inverse gamma sRGB
|
||||
sourceR = Color::igamma_srgb( sourceR );
|
||||
sourceG = Color::igamma_srgb( sourceG );
|
||||
sourceB = Color::igamma_srgb( sourceB );
|
||||
sourceR = Color::igamma_srgb(out_rgbx[tj * 4 + 0]);
|
||||
sourceG = Color::igamma_srgb(out_rgbx[tj * 4 + 1]);
|
||||
sourceB = Color::igamma_srgb(out_rgbx[tj * 4 + 2]);
|
||||
|
||||
if (!clutAndWorkingProfilesAreSame) {
|
||||
//convert from clut to working profile
|
||||
|
@@ -72,7 +72,7 @@ void FilmSimulation::onClutSelected()
|
||||
|
||||
if ( getEnabled() && !currentClutFilename.empty() && listener && currentClutFilename != m_oldClutFilename ) {
|
||||
Glib::ustring clutName, dummy;
|
||||
CLUT::splitClutFilename( currentClutFilename, clutName, dummy, dummy );
|
||||
HaldCLUT::splitClutFilename( currentClutFilename, clutName, dummy, dummy );
|
||||
listener->panelChanged( EvFilmSimulationFilename, clutName );
|
||||
|
||||
m_oldClutFilename = currentClutFilename;
|
||||
@@ -279,7 +279,7 @@ int ClutComboBox::parseDir (const Glib::ustring& path)
|
||||
for (const auto& entry : entries) {
|
||||
|
||||
Glib::ustring name, extension, profileName;
|
||||
CLUT::splitClutFilename (entry, name, extension, profileName);
|
||||
HaldCLUT::splitClutFilename (entry, name, extension, profileName);
|
||||
|
||||
extension = extension.casefold ();
|
||||
if (extension.compare ("tif") != 0 && extension.compare ("png") != 0) {
|
||||
|
Reference in New Issue
Block a user