parent
76064f0d2a
commit
36b86ddaf3
@ -4,6 +4,7 @@ file (GLOB LANGUAGEFILES "languages/*")
|
|||||||
file (GLOB SOUNDFILES "sounds/*")
|
file (GLOB SOUNDFILES "sounds/*")
|
||||||
file (GLOB INPUTICCFILES "iccprofiles/input/*")
|
file (GLOB INPUTICCFILES "iccprofiles/input/*")
|
||||||
file (GLOB OUTPUTICCFILES "iccprofiles/output/*")
|
file (GLOB OUTPUTICCFILES "iccprofiles/output/*")
|
||||||
|
file (GLOB DCPFILES "dcpprofiles/*")
|
||||||
# THEMEDIR includes subfolders for image resources for some themes; doing the normal glob won't work.
|
# THEMEDIR includes subfolders for image resources for some themes; doing the normal glob won't work.
|
||||||
set (THEMEDIR "themes")
|
set (THEMEDIR "themes")
|
||||||
set (IMAGESDIR "images")
|
set (IMAGESDIR "images")
|
||||||
@ -33,6 +34,7 @@ install (FILES ${PROFILEFILES} DESTINATION ${DATADIR}/profiles)
|
|||||||
install (FILES ${SOUNDFILES} DESTINATION ${DATADIR}/sounds)
|
install (FILES ${SOUNDFILES} DESTINATION ${DATADIR}/sounds)
|
||||||
install (FILES ${INPUTICCFILES} DESTINATION ${DATADIR}/iccprofiles/input)
|
install (FILES ${INPUTICCFILES} DESTINATION ${DATADIR}/iccprofiles/input)
|
||||||
install (FILES ${OUTPUTICCFILES} DESTINATION ${DATADIR}/iccprofiles/output)
|
install (FILES ${OUTPUTICCFILES} DESTINATION ${DATADIR}/iccprofiles/output)
|
||||||
|
install (FILES ${DCPFILES} DESTINATION ${DATADIR}/dcpprofiles)
|
||||||
install (DIRECTORY ${THEMEDIR} DESTINATION ${DATADIR})
|
install (DIRECTORY ${THEMEDIR} DESTINATION ${DATADIR})
|
||||||
install (DIRECTORY ${IMAGESDIR} DESTINATION ${DATADIR} FILES_MATCHING PATTERN "index.theme")
|
install (DIRECTORY ${IMAGESDIR} DESTINATION ${DATADIR} FILES_MATCHING PATTERN "index.theme")
|
||||||
install (DIRECTORY ${IMAGESDIR} DESTINATION ${DATADIR} FILES_MATCHING PATTERN "*.png")
|
install (DIRECTORY ${IMAGESDIR} DESTINATION ${DATADIR} FILES_MATCHING PATTERN "*.png")
|
||||||
|
BIN
rtdata/dcpprofiles/Canon EOS 20D.dcp
Normal file
BIN
rtdata/dcpprofiles/Canon EOS 20D.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Canon EOS 40D.dcp
Normal file
BIN
rtdata/dcpprofiles/Canon EOS 40D.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Canon EOS 450D.dcp
Normal file
BIN
rtdata/dcpprofiles/Canon EOS 450D.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Canon EOS 5D.dcp
Normal file
BIN
rtdata/dcpprofiles/Canon EOS 5D.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Canon EOS-1D Mark III.dcp
Normal file
BIN
rtdata/dcpprofiles/Canon EOS-1D Mark III.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Canon PowerShot G10.dcp
Normal file
BIN
rtdata/dcpprofiles/Canon PowerShot G10.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Canon PowerShot G12.dcp
Normal file
BIN
rtdata/dcpprofiles/Canon PowerShot G12.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Nikon D200.dcp
Normal file
BIN
rtdata/dcpprofiles/Nikon D200.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Nikon D3000.dcp
Normal file
BIN
rtdata/dcpprofiles/Nikon D3000.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Nikon D3100.dcp
Normal file
BIN
rtdata/dcpprofiles/Nikon D3100.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Nikon D3S.dcp
Normal file
BIN
rtdata/dcpprofiles/Nikon D3S.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Nikon D700.dcp
Normal file
BIN
rtdata/dcpprofiles/Nikon D700.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Olympus E-P2.dcp
Normal file
BIN
rtdata/dcpprofiles/Olympus E-P2.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Panasonic DMC-FZ150.dcp
Normal file
BIN
rtdata/dcpprofiles/Panasonic DMC-FZ150.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Panasonic DMC-FZ38.dcp
Normal file
BIN
rtdata/dcpprofiles/Panasonic DMC-FZ38.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Panasonic DMC-G1.dcp
Normal file
BIN
rtdata/dcpprofiles/Panasonic DMC-G1.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Panasonic DMC-G3.dcp
Normal file
BIN
rtdata/dcpprofiles/Panasonic DMC-G3.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Panasonic DMC-GH1.dcp
Normal file
BIN
rtdata/dcpprofiles/Panasonic DMC-GH1.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Panasonic DMC-GH2.dcp
Normal file
BIN
rtdata/dcpprofiles/Panasonic DMC-GH2.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Pentax K200D.dcp
Normal file
BIN
rtdata/dcpprofiles/Pentax K200D.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Sony DSLR-A700.dcp
Normal file
BIN
rtdata/dcpprofiles/Sony DSLR-A700.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Sony DSLR-A900.dcp
Normal file
BIN
rtdata/dcpprofiles/Sony DSLR-A900.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Sony NEX-5N.dcp
Normal file
BIN
rtdata/dcpprofiles/Sony NEX-5N.dcp
Normal file
Binary file not shown.
BIN
rtdata/dcpprofiles/Sony SLT-A55V.dcp
Normal file
BIN
rtdata/dcpprofiles/Sony SLT-A55V.dcp
Normal file
Binary file not shown.
@ -886,14 +886,14 @@ TP_HSVEQUALIZER_VAL;V
|
|||||||
TP_ICM_BLENDCMSMATRIX;Lichter aus Matrix einmischen
|
TP_ICM_BLENDCMSMATRIX;Lichter aus Matrix einmischen
|
||||||
TP_ICM_BLENDCMSMATRIX_TOOLTIP;Stellt bei Verwendung von LUT-basierten\nICC-Profilen die Lichter wieder her
|
TP_ICM_BLENDCMSMATRIX_TOOLTIP;Stellt bei Verwendung von LUT-basierten\nICC-Profilen die Lichter wieder her
|
||||||
TP_ICM_FILEDLGFILTERANY;Alle Dateien
|
TP_ICM_FILEDLGFILTERANY;Alle Dateien
|
||||||
TP_ICM_FILEDLGFILTERICM;ICC-Profildateien
|
TP_ICM_FILEDLGFILTERICM;Profildateien
|
||||||
TP_ICM_INPUTCAMERAICC;Kamera-Standard oder ICC
|
TP_ICM_INPUTCAMERAICC;Kamera-Standard oder DCP/ICC
|
||||||
TP_ICM_INPUTCAMERAICC_TOOLTIP;RawTherapee Standard ICC-Farbprofil verwenden; präziser als einfache Matrix, aber nur für einige Kameras verfügbar
|
TP_ICM_INPUTCAMERAICC_TOOLTIP;RawTherapee Standard DCP/ICC-Farbprofil verwenden; präziser als einfache Matrix, aber nur für einige Kameras verfügbar
|
||||||
TP_ICM_INPUTCAMERA;Kamera-Standard
|
TP_ICM_INPUTCAMERA;Kamera-Standard
|
||||||
TP_ICM_INPUTCAMERA_TOOLTIP;Einfache Standard Farbkorrektur-Matrix von DCRAW oder die im DNG eingebettete verwenden
|
TP_ICM_INPUTCAMERA_TOOLTIP;Einfache Standard Farbkorrektur-Matrix von DCRAW oder die im DNG eingebettete verwenden
|
||||||
TP_ICM_INPUTCUSTOM;Benutzerdefiniert
|
TP_ICM_INPUTCUSTOM;Benutzerdefiniert
|
||||||
TP_ICM_INPUTCUSTOM_TOOLTIP;Eigene ICC-Farbprofildatei für die Kamera verwenden
|
TP_ICM_INPUTCUSTOM_TOOLTIP;Eigene DCP/ICC-Farbprofildatei für die Kamera verwenden
|
||||||
TP_ICM_INPUTDLGLABEL;Wähle Eingabe-ICC-Profil...
|
TP_ICM_INPUTDLGLABEL;Wähle Eingabe-DCP/ICC-Profil...
|
||||||
TP_ICM_INPUTEMBEDDED;Eingebettetes verwenden, falls möglich
|
TP_ICM_INPUTEMBEDDED;Eingebettetes verwenden, falls möglich
|
||||||
TP_ICM_INPUTEMBEDDED_TOOLTIP;Farbprofil verwenden, das ggf. in nicht-RAW Dateien eingebettet ist
|
TP_ICM_INPUTEMBEDDED_TOOLTIP;Farbprofil verwenden, das ggf. in nicht-RAW Dateien eingebettet ist
|
||||||
TP_ICM_INPUTNONE;Kein Profil
|
TP_ICM_INPUTNONE;Kein Profil
|
||||||
|
@ -917,14 +917,14 @@ TP_HSVEQUALIZER_VAL;V
|
|||||||
TP_ICM_BLENDCMSMATRIX;Blend highlights with matrix
|
TP_ICM_BLENDCMSMATRIX;Blend highlights with matrix
|
||||||
TP_ICM_BLENDCMSMATRIX_TOOLTIP;Enable to recover blown highlights when using LUT based ICC profiles
|
TP_ICM_BLENDCMSMATRIX_TOOLTIP;Enable to recover blown highlights when using LUT based ICC profiles
|
||||||
TP_ICM_FILEDLGFILTERANY;Any files
|
TP_ICM_FILEDLGFILTERANY;Any files
|
||||||
TP_ICM_FILEDLGFILTERICM;ICC Profile Files
|
TP_ICM_FILEDLGFILTERICM;Profile files
|
||||||
TP_ICM_INPUTCAMERAICC;Auto-matched camera-specific ICC
|
TP_ICM_INPUTCAMERAICC;Auto-matched camera-specific profile
|
||||||
TP_ICM_INPUTCAMERAICC_TOOLTIP;Use RawTherapee's camera-specific ICC input profile that is more precise than a simpler matrix. Available for some cameras, these profiles are stored in /iccprofiles/input directory and are automatically retrieved based on file name matching the exact model name of the camera.
|
TP_ICM_INPUTCAMERAICC_TOOLTIP;Use RawTherapee's camera-specific DCP or ICC input profile that is more precise than a simpler matrix. Available for some cameras, these profiles are stored in /iccprofiles/input directory and are automatically retrieved based on file name matching the exact model name of the camera.
|
||||||
TP_ICM_INPUTCAMERA;Camera standard
|
TP_ICM_INPUTCAMERA;Camera standard
|
||||||
TP_ICM_INPUTCAMERA_TOOLTIP;Use simple color matrix by DCRAW, enhanced RawTherapee version (whichever is available based on camera model) or embedded in DNG.
|
TP_ICM_INPUTCAMERA_TOOLTIP;Use simple color matrix by DCRAW, enhanced RawTherapee version (whichever is available based on camera model) or embedded in DNG.
|
||||||
TP_ICM_INPUTCUSTOM;Custom
|
TP_ICM_INPUTCUSTOM;Custom
|
||||||
TP_ICM_INPUTCUSTOM_TOOLTIP;Select your own ICC color profile file for the camera
|
TP_ICM_INPUTCUSTOM_TOOLTIP;Select your own DCP/ICC color profile file for the camera
|
||||||
TP_ICM_INPUTDLGLABEL;Select Input ICC Profile...
|
TP_ICM_INPUTDLGLABEL;Select Input DCP/ICC Profile...
|
||||||
TP_ICM_INPUTEMBEDDED;Use Embedded, if possible
|
TP_ICM_INPUTEMBEDDED;Use Embedded, if possible
|
||||||
TP_ICM_INPUTEMBEDDED_TOOLTIP;Use color profile embedded in non-raw files
|
TP_ICM_INPUTEMBEDDED_TOOLTIP;Use color profile embedded in non-raw files
|
||||||
TP_ICM_INPUTNONE;No profile
|
TP_ICM_INPUTNONE;No profile
|
||||||
|
@ -14,7 +14,7 @@ set (RTENGINESOURCEFILES safegtk.cc colortemp.cc curves.cc flatcurves.cc diagona
|
|||||||
jpeg_memsrc.cc jdatasrc.cc
|
jpeg_memsrc.cc jdatasrc.cc
|
||||||
PF_correct_RT.cc
|
PF_correct_RT.cc
|
||||||
dirpyrLab_denoise.cc dirpyrLab_equalizer.cc dirpyr_equalizer.cc
|
dirpyrLab_denoise.cc dirpyrLab_equalizer.cc dirpyr_equalizer.cc
|
||||||
calc_distort.cc
|
calc_distort.cc dcp.cc
|
||||||
klt/convolve.cc klt/error.cc klt/klt.cc klt/klt_util.cc klt/pnmio.cc klt/pyramid.cc klt/selectGoodFeatures.cc
|
klt/convolve.cc klt/error.cc klt/klt.cc klt/klt_util.cc klt/pnmio.cc klt/pyramid.cc klt/selectGoodFeatures.cc
|
||||||
klt/storeFeatures.cc klt/trackFeatures.cc klt/writeFeatures.cc
|
klt/storeFeatures.cc klt/trackFeatures.cc klt/writeFeatures.cc
|
||||||
)
|
)
|
||||||
|
458
rtengine/dcp.cc
Normal file
458
rtengine/dcp.cc
Normal file
@ -0,0 +1,458 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of RawTherapee.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dcp.h"
|
||||||
|
#include <cstring>
|
||||||
|
#include "safegtk.h"
|
||||||
|
#include "iccmatrices.h"
|
||||||
|
#include "iccstore.h"
|
||||||
|
#include "rawimagesource.h"
|
||||||
|
#include "improcfun.h"
|
||||||
|
|
||||||
|
using namespace rtengine;
|
||||||
|
using namespace rtexif;
|
||||||
|
|
||||||
|
#undef CLIP
|
||||||
|
#define MAXVAL 0xffff
|
||||||
|
#define CLIP(a) ((a)>0?((a)<MAXVAL?(a):MAXVAL):0)
|
||||||
|
|
||||||
|
DCPProfile::DCPProfile(Glib::ustring fname) {
|
||||||
|
const int TagColorMatrix1=50721, TagColorMatrix2=50722, TagProfileHueSatMapDims=50937;
|
||||||
|
const int TagProfileHueSatMapData1=50938, TagProfileHueSatMapData2=50939;
|
||||||
|
const int TagCalibrationIlluminant1=50778, TagCalibrationIlluminant2=50779;
|
||||||
|
const int TagProfileLookTableData=50982, TagProfileLookTableDims=50981; // ProfileLookup is the low quality variant
|
||||||
|
|
||||||
|
aDeltas=NULL; iHueDivisions=iSatDivisions=iValDivisions=iArrayCount=0;
|
||||||
|
|
||||||
|
FILE *pFile = safe_g_fopen(fname, "rb");
|
||||||
|
|
||||||
|
TagDirectory *tagDir=ExifManager::parseTIFF(pFile, false);
|
||||||
|
|
||||||
|
// If there are two profiles, check what is the best target to take
|
||||||
|
// We don't mix the profiles as adobe does, since with more and more non-tungsten light
|
||||||
|
// it makes no sense. Take the daylight reference light
|
||||||
|
Tag* tag = tagDir->getTag(TagCalibrationIlluminant2);
|
||||||
|
bool use2nd = (tag!=NULL && tag->toInt(0,SHORT)>=20 && tag->toInt(0,SHORT)<=23);
|
||||||
|
|
||||||
|
// Color Matrix
|
||||||
|
tag = tagDir->getTag( use2nd ? TagColorMatrix2 : TagColorMatrix1);
|
||||||
|
|
||||||
|
for (int row=0;row<3;row++) {
|
||||||
|
for (int col=0;col<3;col++) {
|
||||||
|
mColorMatrix[col][row]=(float)tag->toDouble((col+row*3)*8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LUT profile? Divisions counts
|
||||||
|
bool useSimpleLookup=false;
|
||||||
|
tag = tagDir->getTag(TagProfileHueSatMapDims);
|
||||||
|
if (tag==NULL) {
|
||||||
|
tag=tagDir->getTag(TagProfileLookTableDims);
|
||||||
|
useSimpleLookup=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag!=NULL) {
|
||||||
|
iHueDivisions=tag->toInt(0); iSatDivisions=tag->toInt(4); iValDivisions=tag->toInt(8);
|
||||||
|
|
||||||
|
// Saturation maps. Need to be unwinded.
|
||||||
|
tag = tagDir->getTag(useSimpleLookup ? TagProfileLookTableData : ( use2nd ? TagProfileHueSatMapData2 : TagProfileHueSatMapData1));
|
||||||
|
iArrayCount = tag->getCount()/3;
|
||||||
|
|
||||||
|
aDeltas=new HSBModify[iArrayCount];
|
||||||
|
|
||||||
|
const int TIFFFloatSize=4;
|
||||||
|
for (int i=0;i<iArrayCount;i++) {
|
||||||
|
aDeltas[i].fHueShift=tag->toDouble((i*3)*TIFFFloatSize);
|
||||||
|
aDeltas[i].fSatScale=tag->toDouble((i*3+1)*TIFFFloatSize);
|
||||||
|
aDeltas[i].fValScale=tag->toDouble((i*3+2)*TIFFFloatSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pFile!=NULL) fclose(pFile);
|
||||||
|
delete tagDir;
|
||||||
|
|
||||||
|
if (iArrayCount>0) {
|
||||||
|
// Convert DNG color matrix to xyz_cam compatible matrix
|
||||||
|
int i,j,k;
|
||||||
|
|
||||||
|
double cam_xyz[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||||
|
for (i=0; i<3; i++)
|
||||||
|
for (j=0; j<3; j++)
|
||||||
|
for (k=0; k<3; k++)
|
||||||
|
cam_xyz[i][j] += mColorMatrix[j][k] * (i==k);
|
||||||
|
|
||||||
|
|
||||||
|
// Multiply out XYZ colorspace
|
||||||
|
double cam_rgb[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||||
|
for (i=0; i < 3; i++)
|
||||||
|
for (j=0; j < 3; j++)
|
||||||
|
for (k=0; k < 3; k++)
|
||||||
|
cam_rgb[i][j] += cam_xyz[i][k] * xyz_sRGB[k][j];
|
||||||
|
|
||||||
|
// Normalize cam_rgb so that: cam_rgb * (1,1,1) is (1,1,1,1)
|
||||||
|
double num;
|
||||||
|
for (i=0; i<3; i++) {
|
||||||
|
for (num=j=0; j<3; j++) num += cam_rgb[i][j];
|
||||||
|
for (j=0; j<3; j++) cam_rgb[i][j] /= num;
|
||||||
|
}
|
||||||
|
|
||||||
|
double rgb_cam[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||||
|
RawImageSource::inverse33 (cam_rgb, rgb_cam);
|
||||||
|
|
||||||
|
memset(mXYZCAM,0,sizeof(mXYZCAM));
|
||||||
|
for (i=0; i<3; i++)
|
||||||
|
for (j=0; j<3; j++)
|
||||||
|
for (k=0; k<3; k++)
|
||||||
|
mXYZCAM[i][j] += xyz_sRGB[i][k] * rgb_cam[k][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DCPProfile::~DCPProfile() {
|
||||||
|
delete[] aDeltas;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DCPProfile::Apply(Imagefloat *pImg, Glib::ustring workingSpace) const {
|
||||||
|
TMatrix mWork = iccStore->workingSpaceInverseMatrix (workingSpace);
|
||||||
|
|
||||||
|
if (iArrayCount==0) {
|
||||||
|
//===== No LUT- Calculate matrix for direct conversion raw>working space
|
||||||
|
double mat[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||||
|
for (int i=0; i<3; i++)
|
||||||
|
for (int j=0; j<3; j++)
|
||||||
|
for (int k=0; k<3; k++)
|
||||||
|
mat[i][j] += mWork[i][k] * mXYZCAM[k][j];
|
||||||
|
|
||||||
|
// Apply the matrix part
|
||||||
|
#pragma omp parallel for
|
||||||
|
for (int y=0; y<pImg->height; y++) {
|
||||||
|
float newr, newg, newb;
|
||||||
|
for (int x=0; x<pImg->width; x++) {
|
||||||
|
newr = mat[0][0]*pImg->r[y][x] + mat[0][1]*pImg->g[y][x] + mat[0][2]*pImg->b[y][x];
|
||||||
|
newg = mat[1][0]*pImg->r[y][x] + mat[1][1]*pImg->g[y][x] + mat[1][2]*pImg->b[y][x];
|
||||||
|
newb = mat[2][0]*pImg->r[y][x] + mat[2][1]*pImg->g[y][x] + mat[2][2]*pImg->b[y][x];
|
||||||
|
|
||||||
|
pImg->r[y][x] = newr; pImg->g[y][x] = newg; pImg->b[y][x] = newb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//===== LUT available- Calculate matrix for conversion raw>ProPhoto
|
||||||
|
double m2ProPhoto[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||||
|
for (int i=0; i<3; i++)
|
||||||
|
for (int j=0; j<3; j++)
|
||||||
|
for (int k=0; k<3; k++)
|
||||||
|
m2ProPhoto[i][j] += prophoto_xyz[i][k] * mXYZCAM[k][j];
|
||||||
|
|
||||||
|
double m2Work[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||||
|
for (int i=0; i<3; i++)
|
||||||
|
for (int j=0; j<3; j++)
|
||||||
|
for (int k=0; k<3; k++)
|
||||||
|
m2Work[i][j] += mWork[i][k] * xyz_prophoto[k][j];
|
||||||
|
|
||||||
|
// Preperations for LUT
|
||||||
|
float hScale = (iHueDivisions < 2) ? 0.0f : (iHueDivisions * (1.0f / 6.0f));
|
||||||
|
float sScale = (float) (iSatDivisions - 1);
|
||||||
|
float vScale = (float) (iValDivisions - 1);
|
||||||
|
|
||||||
|
int maxHueIndex0 = iHueDivisions - 1;
|
||||||
|
int maxSatIndex0 = iSatDivisions - 2;
|
||||||
|
int maxValIndex0 = iValDivisions - 2;
|
||||||
|
|
||||||
|
const HSBModify *tableBase = aDeltas;
|
||||||
|
|
||||||
|
int hueStep = iSatDivisions;
|
||||||
|
int valStep = iHueDivisions * hueStep;
|
||||||
|
|
||||||
|
// Convert to prophoto and apply LUT
|
||||||
|
#pragma omp parallel for
|
||||||
|
for (int y=0; y<pImg->height; y++) {
|
||||||
|
float newr, newg, newb, h,s,v;
|
||||||
|
for (int x=0; x<pImg->width; x++) {
|
||||||
|
newr = m2ProPhoto[0][0]*pImg->r[y][x] + m2ProPhoto[0][1]*pImg->g[y][x] + m2ProPhoto[0][2]*pImg->b[y][x];
|
||||||
|
newg = m2ProPhoto[1][0]*pImg->r[y][x] + m2ProPhoto[1][1]*pImg->g[y][x] + m2ProPhoto[1][2]*pImg->b[y][x];
|
||||||
|
newb = m2ProPhoto[2][0]*pImg->r[y][x] + m2ProPhoto[2][1]*pImg->g[y][x] + m2ProPhoto[2][2]*pImg->b[y][x];
|
||||||
|
|
||||||
|
ImProcFunctions::rgb2hsv(newr, newg, newb, h , s, v);
|
||||||
|
h*=6.f; // RT calculates in [0,1]
|
||||||
|
|
||||||
|
// Apply the HueSatMap. Ported from Adobes reference implementation
|
||||||
|
float hueShift, satScale, valScale;
|
||||||
|
|
||||||
|
if (iValDivisions < 2) // Optimize most common case of "2.5D" table.
|
||||||
|
{
|
||||||
|
float hScaled = h * hScale;
|
||||||
|
float sScaled = s * sScale;
|
||||||
|
|
||||||
|
int hIndex0 = (int) hScaled;
|
||||||
|
int sIndex0 = (int) sScaled;
|
||||||
|
|
||||||
|
sIndex0 = MIN (sIndex0, maxSatIndex0);
|
||||||
|
|
||||||
|
int hIndex1 = hIndex0 + 1;
|
||||||
|
|
||||||
|
if (hIndex0 >= maxHueIndex0)
|
||||||
|
{
|
||||||
|
hIndex0 = maxHueIndex0;
|
||||||
|
hIndex1 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float hFract1 = hScaled - (float) hIndex0;
|
||||||
|
float sFract1 = sScaled - (float) sIndex0;
|
||||||
|
|
||||||
|
float hFract0 = 1.0f - hFract1;
|
||||||
|
float sFract0 = 1.0f - sFract1;
|
||||||
|
|
||||||
|
const HSBModify *entry00 = tableBase + hIndex0 * hueStep +
|
||||||
|
sIndex0;
|
||||||
|
|
||||||
|
const HSBModify *entry01 = entry00 + (hIndex1 - hIndex0) * hueStep;
|
||||||
|
|
||||||
|
float hueShift0 = hFract0 * entry00->fHueShift +
|
||||||
|
hFract1 * entry01->fHueShift;
|
||||||
|
|
||||||
|
float satScale0 = hFract0 * entry00->fSatScale +
|
||||||
|
hFract1 * entry01->fSatScale;
|
||||||
|
|
||||||
|
float valScale0 = hFract0 * entry00->fValScale +
|
||||||
|
hFract1 * entry01->fValScale;
|
||||||
|
|
||||||
|
entry00++;
|
||||||
|
entry01++;
|
||||||
|
|
||||||
|
float hueShift1 = hFract0 * entry00->fHueShift +
|
||||||
|
hFract1 * entry01->fHueShift;
|
||||||
|
|
||||||
|
float satScale1 = hFract0 * entry00->fSatScale +
|
||||||
|
hFract1 * entry01->fSatScale;
|
||||||
|
|
||||||
|
float valScale1 = hFract0 * entry00->fValScale +
|
||||||
|
hFract1 * entry01->fValScale;
|
||||||
|
|
||||||
|
hueShift = sFract0 * hueShift0 + sFract1 * hueShift1;
|
||||||
|
satScale = sFract0 * satScale0 + sFract1 * satScale1;
|
||||||
|
valScale = sFract0 * valScale0 + sFract1 * valScale1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
float hScaled = h * hScale;
|
||||||
|
float sScaled = s * sScale;
|
||||||
|
float vScaled = v * vScale;
|
||||||
|
|
||||||
|
int hIndex0 = (int) hScaled;
|
||||||
|
int sIndex0 = (int) sScaled;
|
||||||
|
int vIndex0 = (int) vScaled;
|
||||||
|
|
||||||
|
sIndex0 = MIN (sIndex0, maxSatIndex0);
|
||||||
|
vIndex0 = MIN (vIndex0, maxValIndex0);
|
||||||
|
|
||||||
|
int hIndex1 = hIndex0 + 1;
|
||||||
|
|
||||||
|
if (hIndex0 >= maxHueIndex0)
|
||||||
|
{
|
||||||
|
hIndex0 = maxHueIndex0;
|
||||||
|
hIndex1 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float hFract1 = hScaled - (float) hIndex0;
|
||||||
|
float sFract1 = sScaled - (float) sIndex0;
|
||||||
|
float vFract1 = vScaled - (float) vIndex0;
|
||||||
|
|
||||||
|
float hFract0 = 1.0f - hFract1;
|
||||||
|
float sFract0 = 1.0f - sFract1;
|
||||||
|
float vFract0 = 1.0f - vFract1;
|
||||||
|
|
||||||
|
const HSBModify *entry00 = tableBase + vIndex0 * valStep +
|
||||||
|
hIndex0 * hueStep +
|
||||||
|
sIndex0;
|
||||||
|
|
||||||
|
const HSBModify *entry01 = entry00 + (hIndex1 - hIndex0) * hueStep;
|
||||||
|
|
||||||
|
const HSBModify *entry10 = entry00 + valStep;
|
||||||
|
const HSBModify *entry11 = entry01 + valStep;
|
||||||
|
|
||||||
|
float hueShift0 = vFract0 * (hFract0 * entry00->fHueShift +
|
||||||
|
hFract1 * entry01->fHueShift) +
|
||||||
|
vFract1 * (hFract0 * entry10->fHueShift +
|
||||||
|
hFract1 * entry11->fHueShift);
|
||||||
|
|
||||||
|
float satScale0 = vFract0 * (hFract0 * entry00->fSatScale +
|
||||||
|
hFract1 * entry01->fSatScale) +
|
||||||
|
vFract1 * (hFract0 * entry10->fSatScale +
|
||||||
|
hFract1 * entry11->fSatScale);
|
||||||
|
|
||||||
|
float valScale0 = vFract0 * (hFract0 * entry00->fValScale +
|
||||||
|
hFract1 * entry01->fValScale) +
|
||||||
|
vFract1 * (hFract0 * entry10->fValScale +
|
||||||
|
hFract1 * entry11->fValScale);
|
||||||
|
|
||||||
|
entry00++;
|
||||||
|
entry01++;
|
||||||
|
entry10++;
|
||||||
|
entry11++;
|
||||||
|
|
||||||
|
float hueShift1 = vFract0 * (hFract0 * entry00->fHueShift +
|
||||||
|
hFract1 * entry01->fHueShift) +
|
||||||
|
vFract1 * (hFract0 * entry10->fHueShift +
|
||||||
|
hFract1 * entry11->fHueShift);
|
||||||
|
|
||||||
|
float satScale1 = vFract0 * (hFract0 * entry00->fSatScale +
|
||||||
|
hFract1 * entry01->fSatScale) +
|
||||||
|
vFract1 * (hFract0 * entry10->fSatScale +
|
||||||
|
hFract1 * entry11->fSatScale);
|
||||||
|
|
||||||
|
float valScale1 = vFract0 * (hFract0 * entry00->fValScale +
|
||||||
|
hFract1 * entry01->fValScale) +
|
||||||
|
vFract1 * (hFract0 * entry10->fValScale +
|
||||||
|
hFract1 * entry11->fValScale);
|
||||||
|
|
||||||
|
hueShift = sFract0 * hueShift0 + sFract1 * hueShift1;
|
||||||
|
satScale = sFract0 * satScale0 + sFract1 * satScale1;
|
||||||
|
valScale = sFract0 * valScale0 + sFract1 * valScale1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hueShift *= (6.0f / 360.0f); // Convert to internal hue range.
|
||||||
|
|
||||||
|
h += hueShift;
|
||||||
|
s *= satScale; // no clipping here, we are RT float :-)
|
||||||
|
v *= valScale;
|
||||||
|
|
||||||
|
// RT range correction
|
||||||
|
if (h < 0.0f) h += 6.0f;
|
||||||
|
if (h >= 6.0f) h -= 6.0f;
|
||||||
|
h/=6.f;
|
||||||
|
ImProcFunctions::hsv2rgb( h, s, v, newr, newg, newb);
|
||||||
|
|
||||||
|
pImg->r[y][x] = m2Work[0][0]*newr + m2Work[0][1]*newg + m2Work[0][2]*newb;
|
||||||
|
pImg->g[y][x] = m2Work[1][0]*newr + m2Work[1][1]*newg + m2Work[1][2]*newb;
|
||||||
|
pImg->b[y][x] = m2Work[2][0]*newr + m2Work[2][1]*newg + m2Work[2][2]*newb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Integer variant is legacy, only used for thumbs. Simply take the matrix here
|
||||||
|
void DCPProfile::Apply(Image16 *pImg, Glib::ustring workingSpace) const {
|
||||||
|
TMatrix mWork = iccStore->workingSpaceInverseMatrix (workingSpace);
|
||||||
|
|
||||||
|
// Calculate matrix for direct conversion raw>working space
|
||||||
|
double mat[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||||
|
for (int i=0; i<3; i++)
|
||||||
|
for (int j=0; j<3; j++)
|
||||||
|
for (int k=0; k<3; k++)
|
||||||
|
mat[i][j] += mWork[i][k] * mXYZCAM[k][j];
|
||||||
|
|
||||||
|
// Apply the matrix part
|
||||||
|
#pragma omp parallel for
|
||||||
|
for (int y=0; y<pImg->height; y++) {
|
||||||
|
float newr, newg, newb;
|
||||||
|
for (int x=0; x<pImg->width; x++) {
|
||||||
|
newr = mat[0][0]*pImg->r[y][x] + mat[0][1]*pImg->g[y][x] + mat[0][2]*pImg->b[y][x];
|
||||||
|
newg = mat[1][0]*pImg->r[y][x] + mat[1][1]*pImg->g[y][x] + mat[1][2]*pImg->b[y][x];
|
||||||
|
newb = mat[2][0]*pImg->r[y][x] + mat[2][1]*pImg->g[y][x] + mat[2][2]*pImg->b[y][x];
|
||||||
|
|
||||||
|
pImg->r[y][x] = CLIP((int)newr); pImg->g[y][x] = CLIP((int)newg); pImg->b[y][x] = CLIP((int)newb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Generates as singleton
|
||||||
|
DCPStore* DCPStore::getInstance()
|
||||||
|
{
|
||||||
|
static DCPStore* instance_ = 0;
|
||||||
|
if ( instance_ == 0 )
|
||||||
|
{
|
||||||
|
static Glib::Mutex smutex_;
|
||||||
|
Glib::Mutex::Lock lock(smutex_);
|
||||||
|
if ( instance_ == 0 )
|
||||||
|
{
|
||||||
|
instance_ = new DCPStore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reads all profiles from the given profiles dir
|
||||||
|
void DCPStore::init (Glib::ustring rtProfileDir) {
|
||||||
|
Glib::Mutex::Lock lock(mtx);
|
||||||
|
|
||||||
|
fileStdProfiles.clear();
|
||||||
|
|
||||||
|
Glib::ustring rootDirName=rtProfileDir;
|
||||||
|
|
||||||
|
if (rootDirName!="") {
|
||||||
|
std::deque<Glib::ustring> qDirs;
|
||||||
|
|
||||||
|
qDirs.push_front(rootDirName);
|
||||||
|
|
||||||
|
while (qDirs.size()) {
|
||||||
|
// process directory
|
||||||
|
Glib::ustring dirname = qDirs.back();
|
||||||
|
qDirs.pop_back();
|
||||||
|
|
||||||
|
Glib::Dir* dir = NULL;
|
||||||
|
try {
|
||||||
|
if (!safe_file_test (dirname, Glib::FILE_TEST_IS_DIR)) return;
|
||||||
|
dir = new Glib::Dir (dirname);
|
||||||
|
}
|
||||||
|
catch (Glib::Exception& fe) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dirname = dirname + "/";
|
||||||
|
for (Glib::DirIterator i = dir->begin(); i!=dir->end(); ++i) {
|
||||||
|
Glib::ustring fname = dirname + *i;
|
||||||
|
Glib::ustring sname = *i;
|
||||||
|
// ignore directories
|
||||||
|
if (!safe_file_test (fname, Glib::FILE_TEST_IS_DIR)) {
|
||||||
|
int lastdot = sname.find_last_of ('.');
|
||||||
|
if (lastdot!=Glib::ustring::npos && lastdot<=(int)sname.size()-4 && (!sname.casefold().compare (lastdot, 4, ".dcp"))) {
|
||||||
|
Glib::ustring camShortName = sname.substr(0,lastdot).uppercase();
|
||||||
|
fileStdProfiles[camShortName]=fname; // they will be loaded and cached on demand
|
||||||
|
}
|
||||||
|
} else qDirs.push_front(fname); // for later scanning
|
||||||
|
}
|
||||||
|
delete dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DCPProfile* DCPStore::getProfile (Glib::ustring filename) {
|
||||||
|
Glib::Mutex::Lock lock(mtx);
|
||||||
|
|
||||||
|
std::map<Glib::ustring, DCPProfile*>::iterator r = profileCache.find (filename);
|
||||||
|
if (r!=profileCache.end()) return r->second;
|
||||||
|
|
||||||
|
// Add profile
|
||||||
|
profileCache[filename]=new DCPProfile(filename);
|
||||||
|
|
||||||
|
return profileCache[filename];
|
||||||
|
}
|
||||||
|
|
||||||
|
DCPProfile* DCPStore::getStdProfile(Glib::ustring camShortName) {
|
||||||
|
std::map<Glib::ustring, Glib::ustring>::iterator r = fileStdProfiles.find (camShortName);
|
||||||
|
if (r==fileStdProfiles.end()) return NULL;
|
||||||
|
|
||||||
|
return getProfile(r->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DCPStore::isValidDCPFileName(Glib::ustring filename) const {
|
||||||
|
return safe_file_test (filename, Glib::FILE_TEST_EXISTS)
|
||||||
|
&& !filename.casefold().compare (filename.find_last_of ('.'), 4, ".dcp");
|
||||||
|
}
|
76
rtengine/dcp.h
Normal file
76
rtengine/dcp.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of RawTherapee.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DCP_
|
||||||
|
#define _DCP_
|
||||||
|
|
||||||
|
#include "imagefloat.h"
|
||||||
|
#include <glibmm.h>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace rtengine {
|
||||||
|
|
||||||
|
class DCPProfile {
|
||||||
|
struct HSBModify
|
||||||
|
{
|
||||||
|
float fHueShift;
|
||||||
|
float fSatScale;
|
||||||
|
float fValScale;
|
||||||
|
};
|
||||||
|
|
||||||
|
double mColorMatrix[3][3];
|
||||||
|
double mXYZCAM[3][3]; // compatible to RTs xyz_cam
|
||||||
|
HSBModify *aDeltas;
|
||||||
|
|
||||||
|
int iHueDivisions, iSatDivisions, iValDivisions;
|
||||||
|
|
||||||
|
int iHueStep, iValStep, iArrayCount;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DCPProfile(Glib::ustring fname);
|
||||||
|
~DCPProfile();
|
||||||
|
|
||||||
|
void Apply(Imagefloat *pImg, Glib::ustring workingSpace) const;
|
||||||
|
void Apply(Image16 *pImg, Glib::ustring workingSpace) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DCPStore {
|
||||||
|
Glib::Mutex mtx;
|
||||||
|
|
||||||
|
// these contain standard profiles from RT. keys are all in uppercase, file path is value
|
||||||
|
std::map<Glib::ustring, Glib::ustring> fileStdProfiles;
|
||||||
|
|
||||||
|
// Maps file name to profile as cache
|
||||||
|
std::map<Glib::ustring, DCPProfile*> profileCache;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void init(Glib::ustring rtProfileDir);
|
||||||
|
|
||||||
|
bool isValidDCPFileName(Glib::ustring filename) const;
|
||||||
|
|
||||||
|
DCPProfile* getProfile(Glib::ustring filename);
|
||||||
|
DCPProfile* getStdProfile(Glib::ustring camShortName);
|
||||||
|
|
||||||
|
static DCPStore* getInstance();
|
||||||
|
};
|
||||||
|
|
||||||
|
#define dcpStore DCPStore::getInstance()
|
||||||
|
};
|
||||||
|
#endif
|
@ -944,7 +944,7 @@ fclose(f);*/
|
|||||||
void ImProcFunctions::hsv2rgb (float h, float s, float v, float &r, float &g, float &b) {
|
void ImProcFunctions::hsv2rgb (float h, float s, float v, float &r, float &g, float &b) {
|
||||||
|
|
||||||
float h1 = h*6; // sector 0 to 5
|
float h1 = h*6; // sector 0 to 5
|
||||||
int i = floor( h1 );
|
int i = (int)h1; // floor() is very slow, and h1 is always >0
|
||||||
float f = h1 - i; // fractional part of h
|
float f = h1 - i; // fractional part of h
|
||||||
|
|
||||||
float p = v * ( 1 - s );
|
float p = v * ( 1 - s );
|
||||||
|
@ -162,8 +162,8 @@ class ImProcFunctions {
|
|||||||
static double getAutoDistor (const Glib::ustring& fname, int thumb_size);
|
static double getAutoDistor (const Glib::ustring& fname, int thumb_size);
|
||||||
double getTransformAutoFill (int oW, int oH);
|
double getTransformAutoFill (int oW, int oH);
|
||||||
|
|
||||||
void rgb2hsv (float r, float g, float b, float &h, float &s, float &v);
|
static void rgb2hsv (float r, float g, float b, float &h, float &s, float &v);
|
||||||
void hsv2rgb (float h, float s, float v, float &r, float &g, float &b);
|
static void hsv2rgb (float h, float s, float v, float &r, float &g, float &b);
|
||||||
void xyz2srgb (float x, float y, float z, float &r, float &g, float &b);
|
void xyz2srgb (float x, float y, float z, float &r, float &g, float &b);
|
||||||
void xyz2rgb (float x, float y, float z, float &r, float &g, float &b, float rgb_xyz[3][3]);
|
void xyz2rgb (float x, float y, float z, float &r, float &g, float &b, float rgb_xyz[3][3]);
|
||||||
void Lab2XYZ(float L, float a, float b, float &x, float &y, float &z);
|
void Lab2XYZ(float L, float a, float b, float &x, float &y, float &z);
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "rtengine.h"
|
#include "rtengine.h"
|
||||||
#include "iccstore.h"
|
#include "iccstore.h"
|
||||||
|
#include "dcp.h"
|
||||||
#include "improcfun.h"
|
#include "improcfun.h"
|
||||||
#include "improccoordinator.h"
|
#include "improccoordinator.h"
|
||||||
#include "curves.h"
|
#include "curves.h"
|
||||||
@ -37,6 +38,8 @@ int init (const Settings* s, Glib::ustring baseDir) {
|
|||||||
iccStore->init (s->iccDirectory, baseDir + "/iccprofiles");
|
iccStore->init (s->iccDirectory, baseDir + "/iccprofiles");
|
||||||
iccStore->findDefaultMonitorProfile();
|
iccStore->findDefaultMonitorProfile();
|
||||||
|
|
||||||
|
dcpStore->init (baseDir + "/dcpprofiles");
|
||||||
|
|
||||||
ProcParams::init ();
|
ProcParams::init ();
|
||||||
CurveFactory::init ();
|
CurveFactory::init ();
|
||||||
ImProcFunctions::initMunsell();
|
ImProcFunctions::initMunsell();
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "slicer.h"
|
#include "slicer.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "../rtgui/options.h"
|
#include "../rtgui/options.h"
|
||||||
|
#include "dcp.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1680,10 +1681,16 @@ void RawImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams
|
|||||||
//MyTime t1, t2, t3;
|
//MyTime t1, t2, t3;
|
||||||
//t1.set ();
|
//t1.set ();
|
||||||
cmsHPROFILE in;
|
cmsHPROFILE in;
|
||||||
if (!findInputProfile(cmp.input, embedded, camName, in)) return;
|
DCPProfile *dcpProf;
|
||||||
|
|
||||||
|
if (!findInputProfile(cmp.input, embedded, camName, &dcpProf, in)) return;
|
||||||
|
|
||||||
|
if (dcpProf!=NULL) {
|
||||||
|
dcpProf->Apply(im, cmp.working);
|
||||||
|
} else {
|
||||||
// Calculate matrix for direct conversion raw>working space
|
// Calculate matrix for direct conversion raw>working space
|
||||||
TMatrix work = iccStore->workingSpaceInverseMatrix (cmp.working);
|
TMatrix work = iccStore->workingSpaceInverseMatrix (cmp.working);
|
||||||
float mat[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
double mat[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||||
for (int i=0; i<3; i++)
|
for (int i=0; i<3; i++)
|
||||||
for (int j=0; j<3; j++)
|
for (int j=0; j<3; j++)
|
||||||
for (int k=0; k<3; k++)
|
for (int k=0; k<3; k++)
|
||||||
@ -1887,7 +1894,7 @@ void RawImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams
|
|||||||
|
|
||||||
if (imgPreLCMS!=NULL) delete imgPreLCMS;
|
if (imgPreLCMS!=NULL) delete imgPreLCMS;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//t3.set ();
|
//t3.set ();
|
||||||
// printf ("ICM TIME: %d\n", t3.etime(t1));
|
// printf ("ICM TIME: %d\n", t3.etime(t1));
|
||||||
}
|
}
|
||||||
@ -1897,8 +1904,13 @@ void RawImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams
|
|||||||
// Converts raw image including ICC input profile to working space - 16bit int version
|
// Converts raw image including ICC input profile to working space - 16bit int version
|
||||||
void RawImageSource::colorSpaceConversion16 (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double camMatrix[3][3], std::string camName, double& defgain) {
|
void RawImageSource::colorSpaceConversion16 (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double camMatrix[3][3], std::string camName, double& defgain) {
|
||||||
cmsHPROFILE in;
|
cmsHPROFILE in;
|
||||||
if (!findInputProfile(cmp.input, embedded, camName, in)) return;
|
DCPProfile *dcpProf;
|
||||||
|
|
||||||
|
if (!findInputProfile(cmp.input, embedded, camName, &dcpProf, in)) return;
|
||||||
|
|
||||||
|
if (dcpProf!=NULL) {
|
||||||
|
dcpProf->Apply(im, cmp.working);
|
||||||
|
} else {
|
||||||
if (in==NULL) {
|
if (in==NULL) {
|
||||||
// Take camprofile from DCRAW
|
// Take camprofile from DCRAW
|
||||||
// in this case we avoid using the slllllooooooowwww lcms
|
// in this case we avoid using the slllllooooooowwww lcms
|
||||||
@ -1970,23 +1982,30 @@ TMatrix work = iccStore->workingSpaceInverseMatrix (cmp.working);
|
|||||||
|
|
||||||
cmsDeleteTransform(hTransform);
|
cmsDeleteTransform(hTransform);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//t3.set ();
|
//t3.set ();
|
||||||
// printf ("ICM TIME: %d\n", t3.etime(t1));
|
// printf ("ICM TIME: %d\n", t3.etime(t1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine RAW input and output profiles. Returns TRUE on success
|
// Determine RAW input and output profiles. Returns TRUE on success
|
||||||
bool RawImageSource::findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, cmsHPROFILE& in) {
|
bool RawImageSource::findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, DCPProfile **dcpProf, cmsHPROFILE& in) {
|
||||||
in=NULL; // cam will be taken on NULL
|
in=NULL; // cam will be taken on NULL
|
||||||
|
*dcpProf=NULL;
|
||||||
|
|
||||||
if (inProfile == "(none)") return false;
|
if (inProfile == "(none)") return false;
|
||||||
|
|
||||||
if (inProfile == "(embedded)" && embedded) {
|
if (inProfile == "(embedded)" && embedded) {
|
||||||
in = embedded;
|
in = embedded;
|
||||||
} else if (inProfile=="(cameraICC)") {
|
} else if (inProfile=="(cameraICC)") {
|
||||||
in = iccStore->getStdProfile(camName);
|
// DCPs have higher quality, so use them first
|
||||||
|
*dcpProf=dcpStore->getStdProfile(camName);
|
||||||
|
if (*dcpProf==NULL) in = iccStore->getStdProfile(camName);
|
||||||
} else if (inProfile!="(camera)" && inProfile!="") {
|
} else if (inProfile!="(camera)" && inProfile!="") {
|
||||||
in = iccStore->getProfile (inProfile);
|
Glib::ustring normalName=inProfile;
|
||||||
|
if (!inProfile.compare (0, 5, "file:")) normalName=inProfile.substr(5);
|
||||||
|
|
||||||
|
if (dcpStore->isValidDCPFileName(normalName)) *dcpProf=dcpStore->getProfile(normalName);
|
||||||
|
if (*dcpProf==NULL) in = iccStore->getProfile (inProfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
// "in" might be NULL because of "not found". That's ok, we take the cam profile then
|
// "in" might be NULL because of "not found". That's ok, we take the cam profile then
|
||||||
@ -2561,7 +2580,7 @@ void RawImageSource::transformPosition (int x, int y, int tran, int& ttx, int& t
|
|||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
void RawImageSource::inverse33 (double (*rgb_cam)[3], double (*cam_rgb)[3]) {
|
void RawImageSource::inverse33 (const double (*rgb_cam)[3], double (*cam_rgb)[3]) {
|
||||||
double nom = (rgb_cam[0][2]*rgb_cam[1][1]*rgb_cam[2][0] - rgb_cam[0][1]*rgb_cam[1][2]*rgb_cam[2][0] -
|
double nom = (rgb_cam[0][2]*rgb_cam[1][1]*rgb_cam[2][0] - rgb_cam[0][1]*rgb_cam[1][2]*rgb_cam[2][0] -
|
||||||
rgb_cam[0][2]*rgb_cam[1][0]*rgb_cam[2][1] + rgb_cam[0][0]*rgb_cam[1][2]*rgb_cam[2][1] +
|
rgb_cam[0][2]*rgb_cam[1][0]*rgb_cam[2][1] + rgb_cam[0][0]*rgb_cam[1][2]*rgb_cam[2][1] +
|
||||||
rgb_cam[0][1]*rgb_cam[1][0]*rgb_cam[2][2] - rgb_cam[0][0]*rgb_cam[1][1]*rgb_cam[2][2] );
|
rgb_cam[0][1]*rgb_cam[1][0]*rgb_cam[2][2] - rgb_cam[0][0]*rgb_cam[1][1]*rgb_cam[2][2] );
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "imagesource.h"
|
#include "imagesource.h"
|
||||||
#include <lcms2.h>
|
#include <lcms2.h>
|
||||||
|
#include "dcp.h"
|
||||||
#include "array2D.h"
|
#include "array2D.h"
|
||||||
#include "curves.h"
|
#include "curves.h"
|
||||||
#include "../rtgui/cacheimagedata.h"
|
#include "../rtgui/cacheimagedata.h"
|
||||||
@ -60,7 +61,7 @@ class RawImageSource : public ImageSource {
|
|||||||
private:
|
private:
|
||||||
static LUTf invGrad; // for fast_demosaic
|
static LUTf invGrad; // for fast_demosaic
|
||||||
static LUTf initInvGrad ();
|
static LUTf initInvGrad ();
|
||||||
static bool findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, cmsHPROFILE& in);
|
static bool findInputProfile(Glib::ustring inProfile, cmsHPROFILE embedded, std::string camName, DCPProfile **dcpProf, cmsHPROFILE& in);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Glib::Mutex getImageMutex; // locks getImage
|
Glib::Mutex getImageMutex; // locks getImage
|
||||||
@ -167,7 +168,7 @@ class RawImageSource : public ImageSource {
|
|||||||
|
|
||||||
static void colorSpaceConversion16 (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], std::string camName, double& defgain);
|
static void colorSpaceConversion16 (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], std::string camName, double& defgain);
|
||||||
static void colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], std::string camName, double& defgain);
|
static void colorSpaceConversion (Imagefloat* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double cam[3][3], std::string camName, double& defgain);
|
||||||
static void inverse33 (double (*coeff)[3], double (*icoeff)[3]);
|
static void inverse33 (const double (*coeff)[3], double (*icoeff)[3]);
|
||||||
|
|
||||||
void boxblur2(float** src, float** dst, int H, int W, int box );
|
void boxblur2(float** src, float** dst, int H, int W, int box );
|
||||||
void boxblur_resamp(float **src, float **dst, float & max, int H, int W, int box, int samp );
|
void boxblur_resamp(float **src, float **dst, float & max, int H, int W, int box, int samp );
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "rtexif.h"
|
#include "rtexif.h"
|
||||||
|
|
||||||
@ -45,7 +46,7 @@ TagDirectory::TagDirectory ()
|
|||||||
TagDirectory::TagDirectory (TagDirectory* p, const TagAttrib* ta, ByteOrder border)
|
TagDirectory::TagDirectory (TagDirectory* p, const TagAttrib* ta, ByteOrder border)
|
||||||
: attribs(ta), order(border), parent(p) {}
|
: attribs(ta), order(border), parent(p) {}
|
||||||
|
|
||||||
TagDirectory::TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib* ta, ByteOrder border) {
|
TagDirectory::TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib* ta, ByteOrder border, bool skipIgnored) {
|
||||||
|
|
||||||
attribs = ta;
|
attribs = ta;
|
||||||
order = border;
|
order = border;
|
||||||
@ -66,6 +67,7 @@ TagDirectory::TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib*
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (skipIgnored) {
|
||||||
int id = newTag->getID();
|
int id = newTag->getID();
|
||||||
|
|
||||||
// detect and possibly ignore tags of directories belonging to the embedded thumbnail image
|
// detect and possibly ignore tags of directories belonging to the embedded thumbnail image
|
||||||
@ -78,6 +80,7 @@ TagDirectory::TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib*
|
|||||||
delete newTag;
|
delete newTag;
|
||||||
else
|
else
|
||||||
addTag (newTag);
|
addTag (newTag);
|
||||||
|
} else addTag (newTag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -759,7 +762,7 @@ int Tag::toInt (int ofs, TagType astype) {
|
|||||||
case LONG: return (int)sget4 (value+ofs, getOrder());
|
case LONG: return (int)sget4 (value+ofs, getOrder());
|
||||||
case SRATIONAL:
|
case SRATIONAL:
|
||||||
case RATIONAL: a = (int)sget4 (value+ofs+4, getOrder()); return a==0 ? 0 : (int)sget4 (value+ofs, getOrder()) / a;
|
case RATIONAL: a = (int)sget4 (value+ofs+4, getOrder()); return a==0 ? 0 : (int)sget4 (value+ofs, getOrder()) / a;
|
||||||
case FLOAT: return (int)((float) sget4 (value+ofs, getOrder()));
|
case FLOAT: return (int)toDouble(ofs);
|
||||||
case UNDEFINED: return 0;
|
case UNDEFINED: return 0;
|
||||||
default: return 0; // Quick fix for missing cases (INVALID, DOUBLE, OLYUNDEF, SUBDIR)
|
default: return 0; // Quick fix for missing cases (INVALID, DOUBLE, OLYUNDEF, SUBDIR)
|
||||||
}
|
}
|
||||||
@ -767,6 +770,7 @@ int Tag::toInt (int ofs, TagType astype) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double Tag::toDouble (int ofs) {
|
double Tag::toDouble (int ofs) {
|
||||||
|
union IntFloat { uint32_t i; float f; } conv;
|
||||||
|
|
||||||
double ud, dd;
|
double ud, dd;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -778,7 +782,10 @@ double Tag::toDouble (int ofs) {
|
|||||||
case LONG: return (double)((int)sget4 (value+ofs, getOrder()));
|
case LONG: return (double)((int)sget4 (value+ofs, getOrder()));
|
||||||
case SRATIONAL:
|
case SRATIONAL:
|
||||||
case RATIONAL: ud = (int)sget4 (value+ofs, getOrder()); dd = (int)sget4 (value+ofs+4, getOrder()); return dd==0. ? 0. : (double)ud / (double)dd;
|
case RATIONAL: ud = (int)sget4 (value+ofs, getOrder()); dd = (int)sget4 (value+ofs+4, getOrder()); return dd==0. ? 0. : (double)ud / (double)dd;
|
||||||
case FLOAT: return (float) sget4 (value+ofs, getOrder());
|
case FLOAT:
|
||||||
|
conv.i=sget4 (value+ofs, getOrder());
|
||||||
|
return conv.f; // IEEE FLOATs are already C format, they just need a recast
|
||||||
|
|
||||||
case UNDEFINED: return 0.;
|
case UNDEFINED: return 0.;
|
||||||
default: return 0.; // Quick fix for missing cases (INVALID, DOUBLE, OLYUNDEF, SUBDIR)
|
default: return 0.; // Quick fix for missing cases (INVALID, DOUBLE, OLYUNDEF, SUBDIR)
|
||||||
}
|
}
|
||||||
@ -1302,7 +1309,7 @@ void ExifManager::parseCIFF (FILE* f, int base, int length, TagDirectory* root)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TagDirectory* ExifManager::parse (FILE* f, int base) {
|
TagDirectory* ExifManager::parse (FILE* f, int base, bool skipIgnored) {
|
||||||
setlocale(LC_NUMERIC, "C"); // to set decimal point in sscanf
|
setlocale(LC_NUMERIC, "C"); // to set decimal point in sscanf
|
||||||
// read tiff header
|
// read tiff header
|
||||||
fseek (f, base, SEEK_SET);
|
fseek (f, base, SEEK_SET);
|
||||||
@ -1316,7 +1323,7 @@ TagDirectory* ExifManager::parse (FILE* f, int base) {
|
|||||||
fseek (f, base+firstifd, SEEK_SET);
|
fseek (f, base+firstifd, SEEK_SET);
|
||||||
|
|
||||||
// first read the IFD directory
|
// first read the IFD directory
|
||||||
TagDirectory* root = new TagDirectory (NULL, f, base, ifdAttribs, order);
|
TagDirectory* root = new TagDirectory (NULL, f, base, ifdAttribs, order, skipIgnored);
|
||||||
|
|
||||||
// fix ISO issue with nikon and panasonic cameras
|
// fix ISO issue with nikon and panasonic cameras
|
||||||
Tag* exif = root->getTag ("Exif");
|
Tag* exif = root->getTag ("Exif");
|
||||||
@ -1373,9 +1380,9 @@ TagDirectory* ExifManager::parseJPEG (FILE* f) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
TagDirectory* ExifManager::parseTIFF (FILE* f) {
|
TagDirectory* ExifManager::parseTIFF (FILE* f, bool skipIgnored) {
|
||||||
|
|
||||||
return parse (f, 0);
|
return parse (f, 0, skipIgnored);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Tag*> ExifManager::defTags;
|
std::vector<Tag*> ExifManager::defTags;
|
||||||
|
@ -69,7 +69,7 @@ class TagDirectory {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
TagDirectory ();
|
TagDirectory ();
|
||||||
TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib* ta, ByteOrder border);
|
TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib* ta, ByteOrder border, bool skipIgnored=true);
|
||||||
TagDirectory (TagDirectory* p, const TagAttrib* ta, ByteOrder border);
|
TagDirectory (TagDirectory* p, const TagAttrib* ta, ByteOrder border);
|
||||||
virtual ~TagDirectory ();
|
virtual ~TagDirectory ();
|
||||||
|
|
||||||
@ -197,9 +197,9 @@ class ExifManager {
|
|||||||
|
|
||||||
static Tag* saveCIFFMNTag (FILE* f, TagDirectory* root, int len, const char* name);
|
static Tag* saveCIFFMNTag (FILE* f, TagDirectory* root, int len, const char* name);
|
||||||
public:
|
public:
|
||||||
static TagDirectory* parse (FILE*f, int base);
|
static TagDirectory* parse (FILE*f, int base, bool skipIgnored=true);
|
||||||
static TagDirectory* parseJPEG (FILE*f);
|
static TagDirectory* parseJPEG (FILE*f);
|
||||||
static TagDirectory* parseTIFF (FILE*f);
|
static TagDirectory* parseTIFF (FILE*f, bool skipIgnored=true);
|
||||||
static TagDirectory* parseCIFF (FILE* f, int base, int length);
|
static TagDirectory* parseCIFF (FILE* f, int base, int length);
|
||||||
static void parseCIFF (FILE* f, int base, int length, TagDirectory* root);
|
static void parseCIFF (FILE* f, int base, int length, TagDirectory* root);
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "guiutils.h"
|
#include "guiutils.h"
|
||||||
#include "../rtengine/safegtk.h"
|
#include "../rtengine/safegtk.h"
|
||||||
#include "../rtengine/iccstore.h"
|
#include "../rtengine/iccstore.h"
|
||||||
|
#include "../rtengine/dcp.h"
|
||||||
#include "rtimage.h"
|
#include "rtimage.h"
|
||||||
|
|
||||||
using namespace rtengine;
|
using namespace rtengine;
|
||||||
@ -160,6 +161,8 @@ ICMPanel::ICMPanel () : Gtk::VBox(), FoldableToolPanel(this), iunchanged(NULL),
|
|||||||
|
|
||||||
Gtk::FileFilter filter_icc;
|
Gtk::FileFilter filter_icc;
|
||||||
filter_icc.set_name(M("TP_ICM_FILEDLGFILTERICM"));
|
filter_icc.set_name(M("TP_ICM_FILEDLGFILTERICM"));
|
||||||
|
filter_icc.add_pattern("*.dcp");
|
||||||
|
filter_icc.add_pattern("*.DCP");
|
||||||
filter_icc.add_pattern("*.icc");
|
filter_icc.add_pattern("*.icc");
|
||||||
filter_icc.add_pattern("*.icm");
|
filter_icc.add_pattern("*.icm");
|
||||||
filter_icc.add_pattern("*.ICC");
|
filter_icc.add_pattern("*.ICC");
|
||||||
@ -437,7 +440,7 @@ void ICMPanel::setRawMeta (bool raw, const rtengine::ImageData* pMeta) {
|
|||||||
icamera->set_active (raw);
|
icamera->set_active (raw);
|
||||||
iembedded->set_active (!raw);
|
iembedded->set_active (!raw);
|
||||||
icamera->set_sensitive (raw);
|
icamera->set_sensitive (raw);
|
||||||
icameraICC->set_sensitive (raw && iccStore->getStdProfile(pMeta->getCamera()) != NULL);
|
icameraICC->set_sensitive (raw && (iccStore->getStdProfile(pMeta->getCamera()) != NULL || dcpStore->getStdProfile(pMeta->getCamera()) != NULL));
|
||||||
iembedded->set_sensitive (!raw);
|
iembedded->set_sensitive (!raw);
|
||||||
|
|
||||||
enableListener ();
|
enableListener ();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user