parent
76064f0d2a
commit
36b86ddaf3
@ -4,6 +4,7 @@ file (GLOB LANGUAGEFILES "languages/*")
|
||||
file (GLOB SOUNDFILES "sounds/*")
|
||||
file (GLOB INPUTICCFILES "iccprofiles/input/*")
|
||||
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.
|
||||
set (THEMEDIR "themes")
|
||||
set (IMAGESDIR "images")
|
||||
@ -33,6 +34,7 @@ install (FILES ${PROFILEFILES} DESTINATION ${DATADIR}/profiles)
|
||||
install (FILES ${SOUNDFILES} DESTINATION ${DATADIR}/sounds)
|
||||
install (FILES ${INPUTICCFILES} DESTINATION ${DATADIR}/iccprofiles/input)
|
||||
install (FILES ${OUTPUTICCFILES} DESTINATION ${DATADIR}/iccprofiles/output)
|
||||
install (FILES ${DCPFILES} DESTINATION ${DATADIR}/dcpprofiles)
|
||||
install (DIRECTORY ${THEMEDIR} DESTINATION ${DATADIR})
|
||||
install (DIRECTORY ${IMAGESDIR} DESTINATION ${DATADIR} FILES_MATCHING PATTERN "index.theme")
|
||||
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_TOOLTIP;Stellt bei Verwendung von LUT-basierten\nICC-Profilen die Lichter wieder her
|
||||
TP_ICM_FILEDLGFILTERANY;Alle Dateien
|
||||
TP_ICM_FILEDLGFILTERICM;ICC-Profildateien
|
||||
TP_ICM_INPUTCAMERAICC;Kamera-Standard oder 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_FILEDLGFILTERICM;Profildateien
|
||||
TP_ICM_INPUTCAMERAICC;Kamera-Standard oder DCP/ICC
|
||||
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_TOOLTIP;Einfache Standard Farbkorrektur-Matrix von DCRAW oder die im DNG eingebettete verwenden
|
||||
TP_ICM_INPUTCUSTOM;Benutzerdefiniert
|
||||
TP_ICM_INPUTCUSTOM_TOOLTIP;Eigene ICC-Farbprofildatei für die Kamera verwenden
|
||||
TP_ICM_INPUTDLGLABEL;Wähle Eingabe-ICC-Profil...
|
||||
TP_ICM_INPUTCUSTOM_TOOLTIP;Eigene DCP/ICC-Farbprofildatei für die Kamera verwenden
|
||||
TP_ICM_INPUTDLGLABEL;Wähle Eingabe-DCP/ICC-Profil...
|
||||
TP_ICM_INPUTEMBEDDED;Eingebettetes verwenden, falls möglich
|
||||
TP_ICM_INPUTEMBEDDED_TOOLTIP;Farbprofil verwenden, das ggf. in nicht-RAW Dateien eingebettet ist
|
||||
TP_ICM_INPUTNONE;Kein Profil
|
||||
|
@ -917,14 +917,14 @@ TP_HSVEQUALIZER_VAL;V
|
||||
TP_ICM_BLENDCMSMATRIX;Blend highlights with matrix
|
||||
TP_ICM_BLENDCMSMATRIX_TOOLTIP;Enable to recover blown highlights when using LUT based ICC profiles
|
||||
TP_ICM_FILEDLGFILTERANY;Any files
|
||||
TP_ICM_FILEDLGFILTERICM;ICC Profile Files
|
||||
TP_ICM_INPUTCAMERAICC;Auto-matched camera-specific ICC
|
||||
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_FILEDLGFILTERICM;Profile files
|
||||
TP_ICM_INPUTCAMERAICC;Auto-matched camera-specific profile
|
||||
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_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_TOOLTIP;Select your own ICC color profile file for the camera
|
||||
TP_ICM_INPUTDLGLABEL;Select Input ICC Profile...
|
||||
TP_ICM_INPUTCUSTOM_TOOLTIP;Select your own DCP/ICC color profile file for the camera
|
||||
TP_ICM_INPUTDLGLABEL;Select Input DCP/ICC Profile...
|
||||
TP_ICM_INPUTEMBEDDED;Use Embedded, if possible
|
||||
TP_ICM_INPUTEMBEDDED_TOOLTIP;Use color profile embedded in non-raw files
|
||||
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
|
||||
PF_correct_RT.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/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) {
|
||||
|
||||
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 p = v * ( 1 - s );
|
||||
|
@ -162,8 +162,8 @@ class ImProcFunctions {
|
||||
static double getAutoDistor (const Glib::ustring& fname, int thumb_size);
|
||||
double getTransformAutoFill (int oW, int oH);
|
||||
|
||||
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 rgb2hsv (float r, float g, float b, float &h, float &s, float &v);
|
||||
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 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);
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
#include "rtengine.h"
|
||||
#include "iccstore.h"
|
||||
#include "dcp.h"
|
||||
#include "improcfun.h"
|
||||
#include "improccoordinator.h"
|
||||
#include "curves.h"
|
||||
@ -37,6 +38,8 @@ int init (const Settings* s, Glib::ustring baseDir) {
|
||||
iccStore->init (s->iccDirectory, baseDir + "/iccprofiles");
|
||||
iccStore->findDefaultMonitorProfile();
|
||||
|
||||
dcpStore->init (baseDir + "/dcpprofiles");
|
||||
|
||||
ProcParams::init ();
|
||||
CurveFactory::init ();
|
||||
ImProcFunctions::initMunsell();
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "slicer.h"
|
||||
#include <iostream>
|
||||
#include "../rtgui/options.h"
|
||||
#include "dcp.h"
|
||||
|
||||
|
||||
|
||||
@ -1680,10 +1681,16 @@ void RawImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams
|
||||
//MyTime t1, t2, t3;
|
||||
//t1.set ();
|
||||
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
|
||||
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 j=0; j<3; j++)
|
||||
for (int k=0; k<3; k++)
|
||||
@ -1887,7 +1894,7 @@ void RawImageSource::colorSpaceConversion (Imagefloat* im, ColorManagementParams
|
||||
|
||||
if (imgPreLCMS!=NULL) delete imgPreLCMS;
|
||||
}
|
||||
|
||||
}
|
||||
//t3.set ();
|
||||
// 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
|
||||
void RawImageSource::colorSpaceConversion16 (Image16* im, ColorManagementParams cmp, cmsHPROFILE embedded, cmsHPROFILE camprofile, double camMatrix[3][3], std::string camName, double& defgain) {
|
||||
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) {
|
||||
// Take camprofile from DCRAW
|
||||
// in this case we avoid using the slllllooooooowwww lcms
|
||||
@ -1970,23 +1982,30 @@ TMatrix work = iccStore->workingSpaceInverseMatrix (cmp.working);
|
||||
|
||||
cmsDeleteTransform(hTransform);
|
||||
}
|
||||
|
||||
}
|
||||
//t3.set ();
|
||||
// printf ("ICM TIME: %d\n", t3.etime(t1));
|
||||
}
|
||||
|
||||
// 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
|
||||
*dcpProf=NULL;
|
||||
|
||||
if (inProfile == "(none)") return false;
|
||||
|
||||
if (inProfile == "(embedded)" && embedded) {
|
||||
in = embedded;
|
||||
} 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!="") {
|
||||
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
|
||||
@ -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] -
|
||||
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] );
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "imagesource.h"
|
||||
#include <lcms2.h>
|
||||
#include "dcp.h"
|
||||
#include "array2D.h"
|
||||
#include "curves.h"
|
||||
#include "../rtgui/cacheimagedata.h"
|
||||
@ -60,7 +61,7 @@ class RawImageSource : public ImageSource {
|
||||
private:
|
||||
static LUTf invGrad; // for fast_demosaic
|
||||
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:
|
||||
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 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 boxblur_resamp(float **src, float **dst, float & max, int H, int W, int box, int samp );
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <ctime>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "rtexif.h"
|
||||
|
||||
@ -45,7 +46,7 @@ TagDirectory::TagDirectory ()
|
||||
TagDirectory::TagDirectory (TagDirectory* p, const TagAttrib* ta, ByteOrder border)
|
||||
: 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;
|
||||
order = border;
|
||||
@ -66,6 +67,7 @@ TagDirectory::TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib*
|
||||
continue;
|
||||
}
|
||||
|
||||
if (skipIgnored) {
|
||||
int id = newTag->getID();
|
||||
|
||||
// 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;
|
||||
else
|
||||
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 SRATIONAL:
|
||||
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;
|
||||
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) {
|
||||
union IntFloat { uint32_t i; float f; } conv;
|
||||
|
||||
double ud, dd;
|
||||
switch (type) {
|
||||
@ -778,7 +782,10 @@ double Tag::toDouble (int ofs) {
|
||||
case LONG: return (double)((int)sget4 (value+ofs, getOrder()));
|
||||
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 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.;
|
||||
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
|
||||
// read tiff header
|
||||
fseek (f, base, SEEK_SET);
|
||||
@ -1316,7 +1323,7 @@ TagDirectory* ExifManager::parse (FILE* f, int base) {
|
||||
fseek (f, base+firstifd, SEEK_SET);
|
||||
|
||||
// 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
|
||||
Tag* exif = root->getTag ("Exif");
|
||||
@ -1373,9 +1380,9 @@ TagDirectory* ExifManager::parseJPEG (FILE* f) {
|
||||
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;
|
||||
|
@ -69,7 +69,7 @@ class TagDirectory {
|
||||
|
||||
public:
|
||||
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);
|
||||
virtual ~TagDirectory ();
|
||||
|
||||
@ -197,9 +197,9 @@ class ExifManager {
|
||||
|
||||
static Tag* saveCIFFMNTag (FILE* f, TagDirectory* root, int len, const char* name);
|
||||
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* parseTIFF (FILE*f);
|
||||
static TagDirectory* parseTIFF (FILE*f, bool skipIgnored=true);
|
||||
static TagDirectory* parseCIFF (FILE* f, int base, int length);
|
||||
static void parseCIFF (FILE* f, int base, int length, TagDirectory* root);
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "guiutils.h"
|
||||
#include "../rtengine/safegtk.h"
|
||||
#include "../rtengine/iccstore.h"
|
||||
#include "../rtengine/dcp.h"
|
||||
#include "rtimage.h"
|
||||
|
||||
using namespace rtengine;
|
||||
@ -160,6 +161,8 @@ ICMPanel::ICMPanel () : Gtk::VBox(), FoldableToolPanel(this), iunchanged(NULL),
|
||||
|
||||
Gtk::FileFilter filter_icc;
|
||||
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("*.icm");
|
||||
filter_icc.add_pattern("*.ICC");
|
||||
@ -437,7 +440,7 @@ void ICMPanel::setRawMeta (bool raw, const rtengine::ImageData* pMeta) {
|
||||
icamera->set_active (raw);
|
||||
iembedded->set_active (!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);
|
||||
|
||||
enableListener ();
|
||||
|
Loading…
x
Reference in New Issue
Block a user