-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 16fe987
Showing
7 changed files
with
1,004 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
*.dll | ||
*.so | ||
*.dylib | ||
*.o | ||
*.dSYM | ||
testCIEDE2000 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
/* | ||
* CIEDE2000.cpp | ||
* Part of http://github.com/gfiumara/CIEDE2000 by Gregory Fiumara. | ||
* See LICENSE for details. | ||
*/ | ||
|
||
#include <cmath> | ||
|
||
#include <CIEDE2000.h> | ||
|
||
/******************************************************************************* | ||
* Conversions. | ||
******************************************************************************/ | ||
|
||
constexpr double | ||
CIEDE2000::deg2Rad( | ||
const double deg) | ||
{ | ||
return (deg * (M_PI / 180.0)); | ||
} | ||
|
||
constexpr double | ||
CIEDE2000::rad2Deg( | ||
const double rad) | ||
{ | ||
return ((180.0 / M_PI) * rad); | ||
} | ||
|
||
double | ||
CIEDE2000::CIEDE2000( | ||
const LAB &lab1, | ||
const LAB &lab2) | ||
{ | ||
/* | ||
* "For these and all other numerical/graphical delta E00 values | ||
* reported in this article, we set the parametric weighting factors | ||
* to unity(i.e., k_L = k_C = k_H = 1.0)." (Page 27). | ||
*/ | ||
const double k_L = 1.0, k_C = 1.0, k_H = 1.0; | ||
const double deg360InRad = CIEDE2000::deg2Rad(360.0); | ||
const double deg180InRad = CIEDE2000::deg2Rad(180.0); | ||
const double pow25To7 = 6103515625.0; /* pow(25, 7) */ | ||
|
||
/* | ||
* Step 1 | ||
*/ | ||
/* Equation 2 */ | ||
double C1 = sqrt((lab1.a * lab1.a) + (lab1.b * lab1.b)); | ||
double C2 = sqrt((lab2.a * lab2.a) + (lab2.b * lab2.b)); | ||
/* Equation 3 */ | ||
double barC = (C1 + C2) / 2.0; | ||
/* Equation 4 */ | ||
double G = 0.5 * (1 - sqrt(pow(barC, 7) / (pow(barC, 7) + pow25To7))); | ||
/* Equation 5 */ | ||
double a1Prime = (1.0 + G) * lab1.a; | ||
double a2Prime = (1.0 + G) * lab2.a; | ||
/* Equation 6 */ | ||
double CPrime1 = sqrt((a1Prime * a1Prime) + (lab1.b * lab1.b)); | ||
double CPrime2 = sqrt((a2Prime * a2Prime) + (lab2.b * lab2.b)); | ||
/* Equation 7 */ | ||
double hPrime1; | ||
if (lab1.b == 0 && a1Prime == 0) | ||
hPrime1 = 0.0; | ||
else | ||
hPrime1 = atan2(lab1.b, a1Prime); | ||
/* | ||
* This must be converted to a hue angle in degrees between 0 | ||
* and 360 by addition of 2 to negative hue angles. | ||
*/ | ||
if (hPrime1 < 0) | ||
hPrime1 += deg360InRad; | ||
double hPrime2; | ||
if (lab2.b == 0 && a2Prime == 0) | ||
hPrime2 = 0.0; | ||
else | ||
hPrime2 = atan2(lab2.b, a2Prime); | ||
/* | ||
* This must be converted to a hue angle in degrees between 0 | ||
* and 360 by addition of 2 to negative hue angles. | ||
*/ | ||
if (hPrime2 < 0) | ||
hPrime2 += deg360InRad; | ||
|
||
/* | ||
* Step 2 | ||
*/ | ||
/* Equation 8 */ | ||
double deltaLPrime = lab2.l - lab1.l; | ||
/* Equation 9 */ | ||
double deltaCPrime = CPrime2 - CPrime1; | ||
/* Equation 10 */ | ||
double deltahPrime; | ||
double CPrimeProduct = CPrime1 * CPrime2; | ||
if (CPrimeProduct == 0) | ||
deltahPrime = 0; | ||
else { | ||
/* Avoid the fabs() call */ | ||
deltahPrime = hPrime2 - hPrime1; | ||
if (deltahPrime < -deg180InRad) | ||
deltahPrime += deg360InRad; | ||
else if (deltahPrime > deg180InRad) | ||
deltahPrime -= deg360InRad; | ||
} | ||
/* Equation 11 */ | ||
double deltaHPrime = 2.0 * sqrt(CPrimeProduct) * | ||
sin(deltahPrime / 2.0); | ||
|
||
/* | ||
* Step 3 | ||
*/ | ||
/* Equation 12 */ | ||
double barLPrime = (lab1.l + lab2.l) / 2.0; | ||
/* Equation 13 */ | ||
double barCPrime = (CPrime1 + CPrime2) / 2.0; | ||
/* Equation 14 */ | ||
double barhPrime, hPrimeSum = hPrime1 + hPrime2; | ||
if (CPrime1 * CPrime2 == 0) { | ||
barhPrime = hPrimeSum; | ||
} else { | ||
if (fabs(hPrime1 - hPrime2) <= deg180InRad) | ||
barhPrime = hPrimeSum / 2.0; | ||
else { | ||
if (hPrimeSum < deg360InRad) | ||
barhPrime = (hPrimeSum + deg360InRad) / 2.0; | ||
else | ||
barhPrime = (hPrimeSum - deg360InRad) / 2.0; | ||
} | ||
} | ||
/* Equation 15 */ | ||
double T = 1.0 - (0.17 * cos(barhPrime - CIEDE2000::deg2Rad(30.0))) + | ||
(0.24 * cos(2.0 * barhPrime)) + | ||
(0.32 * cos((3.0 * barhPrime) + CIEDE2000::deg2Rad(6.0))) - | ||
(0.20 * cos((4.0 * barhPrime) - CIEDE2000::deg2Rad(63.0))); | ||
/* Equation 16 */ | ||
double deltaTheta = CIEDE2000::deg2Rad(30.0) * | ||
exp(-pow((barhPrime - deg2Rad(275.0)) / deg2Rad(25.0), 2.0)); | ||
/* Equation 17 */ | ||
double R_C = 2.0 * sqrt(pow(barCPrime, 7.0) / | ||
(pow(barCPrime, 7.0) + pow25To7)); | ||
/* Equation 18 */ | ||
double S_L = 1 + ((0.015 * pow(barLPrime - 50.0, 2.0)) / | ||
sqrt(20 + pow(barLPrime - 50.0, 2.0))); | ||
/* Equation 19 */ | ||
double S_C = 1 + (0.045 * barCPrime); | ||
/* Equation 20 */ | ||
double S_H = 1 + (0.015 * barCPrime * T); | ||
/* Equation 21 */ | ||
double R_T = (-sin(2.0 * deltaTheta)) * R_C; | ||
|
||
/* Equation 22 */ | ||
double deltaE = sqrt( | ||
pow(deltaLPrime / (k_L * S_L), 2.0) + | ||
pow(deltaCPrime / (k_C * S_C), 2.0) + | ||
pow(deltaHPrime / (k_H * S_H), 2.0) + | ||
(R_T * (deltaCPrime / (k_C * S_C)) * (deltaHPrime / (k_H * S_H)))); | ||
|
||
return (deltaE); | ||
} | ||
|
||
/******************************************************************************* | ||
* Operators. | ||
******************************************************************************/ | ||
|
||
std::ostream& | ||
operator<<( | ||
std::ostream &s, | ||
const CIEDE2000::LAB &labColor) | ||
{ | ||
return (s << "CIELAB(" << labColor.l << "," << labColor.a << "," << | ||
labColor.b << ")"); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
/* | ||
* CIEDE2000.h | ||
* Part of http://github.com/gfiumara/CIEDE2000 by Gregory Fiumara. | ||
* See LICENSE for details. | ||
*/ | ||
|
||
#ifndef GPF_CIEDE2000_H_ | ||
#define GPF_CIEDE2000_H_ | ||
|
||
#include <ostream> | ||
|
||
#ifndef M_PI | ||
#define M_PI 3.14159265358979323846264338327950288 /* pi */ | ||
#endif | ||
|
||
/** Namespace containing all necessary objects and methods for CIEDE2000 */ | ||
namespace CIEDE2000 | ||
{ | ||
/*********************************************************************** | ||
* Types. | ||
**********************************************************************/ | ||
|
||
/** A color in CIELAB colorspace */ | ||
struct LAB | ||
{ | ||
/** Lightness */ | ||
double l; | ||
/** Color-opponent a dimension */ | ||
double a; | ||
/** Color-opponent b dimension */ | ||
double b; | ||
}; | ||
/** Convenience definition for struct LAB */ | ||
using LAB = struct LAB; | ||
|
||
/*********************************************************************** | ||
* Operations. | ||
**********************************************************************/ | ||
|
||
/** | ||
* @brief | ||
* Obtain Delta-E 2000 value. | ||
* @details | ||
* Based on the paper "The CIEDE2000 Color-Difference Formula: | ||
* Implementation Notes, Supplementary Test Data, and Mathematical | ||
* Observations" by Gaurav Sharma, Wencheng Wu, and Edul N. Dalal, | ||
* from http://www.ece.rochester.edu/~gsharma/ciede2000/. | ||
* | ||
* @param lab1 | ||
* First color in LAB colorspace. | ||
* @param lab2 | ||
* Second color in LAB colorspace. | ||
* | ||
* @return | ||
* Delta-E difference between lab1 and lab2. | ||
*/ | ||
double | ||
CIEDE2000( | ||
const LAB &lab1, | ||
const LAB &lab2); | ||
|
||
/*********************************************************************** | ||
* Conversions. | ||
**********************************************************************/ | ||
|
||
/** | ||
* @brief | ||
* Convert degrees to radians. | ||
* | ||
* @param deg | ||
* Angle in degrees. | ||
* | ||
* @return | ||
* deg in radians. | ||
*/ | ||
constexpr double | ||
deg2Rad( | ||
const double deg); | ||
|
||
/** | ||
* @brief | ||
* Convert radians to degrees. | ||
* | ||
* @param rad | ||
* Angle in radians. | ||
* | ||
* @return | ||
* rad in degrees. | ||
*/ | ||
constexpr double | ||
rad2Deg( | ||
const double rad); | ||
} | ||
|
||
/******************************************************************************* | ||
* Conversions. | ||
******************************************************************************/ | ||
|
||
/** | ||
* @brief | ||
* LAB output stream operator. | ||
* | ||
* @param s | ||
* Output stream. | ||
* @param labColor | ||
* Color to output. | ||
* | ||
* @return | ||
* s with labColor appended. | ||
*/ | ||
std::ostream& | ||
operator<<( | ||
std::ostream &s, | ||
const CIEDE2000::LAB &labColor); | ||
|
||
#endif /* GPF_CIEDE2000_H_ */ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) 2015 Greg Fiumara | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# | ||
# Makefile | ||
# Part of http://github.com/gfiumara/CIEDE2000 by Gregory Fiumara. | ||
# See LICENSE for details. | ||
# | ||
|
||
.PHONY: all clean debug library test | ||
|
||
LIBRARY = CIEDE2000 | ||
SOURCE = $(LIBRARY).cpp | ||
OBJECT = $(SOURCE:%.cpp=%.o) | ||
DISPOSABLE_FILES = lib$(LIBRARY).so lib$(LIBRARY).dylib $(LIBRARY).dll \ | ||
$(OBJECT) test$(OBJECT) test$(LIBRARY) | ||
DISPOSABLE_DIRS = *dSYM | ||
OS = $(shell uname) | ||
|
||
ifneq ($(findstring MINGW,$(OS)),MINGW) | ||
WARNING_FLAGS = -Wall -Wextra -pedantic | ||
PRODUCTION_FLAGS = -O3 | ||
endif | ||
DEBUG_FLAGS = -g | ||
TEST_FLAGS = -Wno-unused-parameter | ||
|
||
CXXFLAGS += -I. -std=c++11 $(WARNING_FLAGS) $(PRODUCTION_FLAGS) | ||
|
||
all: library | ||
|
||
debug: CXXFLAGS += $(DEBUG_FLAGS) | ||
debug: CXXFLAGS := $(filter-out $(PRODUCTION_FLAGS),$(CXXFLAGS)) | ||
debug: all | ||
|
||
test$(LIBRARY): LDFLAGS += -L. -lCIEDE2000 | ||
test$(LIBRARY): CXXFLAGS += $(TEST_FLAGS) | ||
test$(LIBRARY): test$(OBJECT) | ||
$(CXX) $^ -o $@ $(LDFLAGS) | ||
|
||
test: library test$(LIBRARY) | ||
|
||
library: $(LIBRARY).cpp | ||
ifeq ($(findstring Darwin,$(OS)),Darwin) | ||
$(CXX) -dynamiclib $(CXXFLAGS) $^ -o lib$(LIBRARY).dylib | ||
else | ||
ifeq ($(findstring MINGW,$(OS)),MINGW) | ||
$(CXX) -shared $(CXXFLAGS) $^ -o lib$(LIBRARY).dll | ||
else | ||
$(CXX) -shared $(CXXFLAGS) $^ -o lib$(LIBRARY).so | ||
endif | ||
endif | ||
|
||
clean: | ||
$(RM) $(DISPOSABLE_FILES) | ||
$(RM) -r $(DISPOSABLE_DIRS) | ||
|
Oops, something went wrong.