|
shun-iwasawa |
ad7711 |
#include "toonzqt/lutcalibrator.h"
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
// Tnzlib includes
|
|
shun-iwasawa |
ad7711 |
#include "toonz/preferences.h"
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
// TnzCore includes
|
|
shun-iwasawa |
ad7711 |
#include "tmsgcore.h"
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
#include <qopenglshader></qopenglshader>
|
|
shun-iwasawa |
ad7711 |
#include <qopenglshaderprogram></qopenglshaderprogram>
|
|
shun-iwasawa |
ad7711 |
#include <qopenglframebufferobject></qopenglframebufferobject>
|
|
shun-iwasawa |
ad7711 |
#include <qopengltexture></qopengltexture>
|
|
shun-iwasawa |
ad7711 |
#include <qopenglcontext></qopenglcontext>
|
|
shun-iwasawa |
ad7711 |
#include <qoffscreensurface></qoffscreensurface>
|
|
shun-iwasawa |
ad7711 |
#include <qfile></qfile>
|
|
shun-iwasawa |
ad7711 |
#include <qcolor></qcolor>
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
namespace {
|
|
shun-iwasawa |
ad7711 |
inline bool execWarning(const QString& s) {
|
|
shun-iwasawa |
ad7711 |
DVGui::MsgBox(DVGui::WARNING, s);
|
|
shun-iwasawa |
ad7711 |
return false;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
};
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
#ifdef WIN32
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
#include <qstringlist></qstringlist>
|
|
shun-iwasawa |
ad7711 |
#include <qsettings></qsettings>
|
|
shun-iwasawa |
ad7711 |
#include <qbytearray></qbytearray>
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
namespace {
|
|
shun-iwasawa |
ad7711 |
// obtain monitor information from registry
|
|
shun-iwasawa |
ad7711 |
QStringList getMonitorNames() {
|
|
shun-iwasawa |
ad7711 |
QStringList subPathSet;
|
|
shun-iwasawa |
ad7711 |
// QSettings regSys("SYSTEM\\CurrentControlSet\\Enum\\DISPLAY",
|
|
shun-iwasawa |
ad7711 |
// QSettings::NativeFormat);
|
|
shun-iwasawa |
ad7711 |
QSettings regSys(
|
|
shun-iwasawa |
ad7711 |
"HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Enum\\DISPLAY",
|
|
shun-iwasawa |
ad7711 |
QSettings::NativeFormat);
|
|
shun-iwasawa |
ad7711 |
QStringList children = regSys.childGroups();
|
|
shun-iwasawa |
ad7711 |
// return value
|
|
shun-iwasawa |
ad7711 |
QStringList nameList;
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
if (children.isEmpty()) {
|
|
shun-iwasawa |
ad7711 |
std::cout << "getMonitorNames : Failed to Open Registry" << std::endl;
|
|
shun-iwasawa |
ad7711 |
return nameList;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
for (int c = 0; c < children.size(); c++) {
|
|
shun-iwasawa |
ad7711 |
// Parent Key : DISPLAY
|
|
shun-iwasawa |
ad7711 |
// Child Keys : AVO0000, ENC2174, etc.
|
|
shun-iwasawa |
ad7711 |
// Grandchild Key : 5&388..
|
|
shun-iwasawa |
ad7711 |
// Find grandchild key which contains a great-grandchild key named "Control"
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
regSys.beginGroup(children.at(c)); // Child keys : AVO0000, ENC2174, etc.
|
|
shun-iwasawa |
ad7711 |
QStringList grandChildren = regSys.childGroups();
|
|
shun-iwasawa |
ad7711 |
for (int gc = 0; gc < grandChildren.size(); gc++) {
|
|
shun-iwasawa |
ad7711 |
regSys.beginGroup(grandChildren.at(gc)); // Grandchild key : 5&388..
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
QStringList greatGrandChildren = regSys.childGroups();
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
if (greatGrandChildren.contains(
|
|
shun-iwasawa |
ad7711 |
"Control")) // If the key "Control" is found
|
|
shun-iwasawa |
ad7711 |
{
|
|
shun-iwasawa |
ad7711 |
// Obtain variable "EDID" from the key "Device Parameters"
|
|
shun-iwasawa |
ad7711 |
regSys.beginGroup("Device Parameters");
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
// the key may be not "EDID", but "BAD_EDID"
|
|
shun-iwasawa |
ad7711 |
if (regSys.contains("EDID")) {
|
|
shun-iwasawa |
ad7711 |
QString subPath = regSys.group().replace("/", "\\").prepend(
|
|
shun-iwasawa |
ad7711 |
"SYSTEM\\CurrentControlSet\\Enum\\DISPLAY\\");
|
|
shun-iwasawa |
ad7711 |
subPathSet.push_back(subPath);
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
regSys.endGroup();
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
regSys.endGroup();
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
// subPath may not be one...?
|
|
shun-iwasawa |
ad7711 |
// if(!subPath.isEmpty())
|
|
shun-iwasawa |
ad7711 |
// break;
|
|
shun-iwasawa |
ad7711 |
regSys.endGroup();
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
if (subPathSet.isEmpty()) {
|
|
shun-iwasawa |
ad7711 |
std::cout << "getMonitorNames : Failed to Find Current EDID" << std::endl;
|
|
shun-iwasawa |
ad7711 |
return nameList;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
// for each subPath ( it may become more than one when using submonitor )
|
|
shun-iwasawa |
ad7711 |
for (int sp = 0; sp < subPathSet.size(); sp++) {
|
|
shun-iwasawa |
ad7711 |
QString subPath = subPathSet.at(sp);
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
HKEY handle = 0;
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
LONG res = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
|
shun-iwasawa |
ad7711 |
reinterpret_cast<const wchar_t*="">(subPath.utf16()),</const>
|
|
shun-iwasawa |
ad7711 |
0, KEY_READ, &handle);
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
if (res == ERROR_SUCCESS && handle) {
|
|
shun-iwasawa |
ad7711 |
QString keyStr("EDID");
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
// get the size and type of the value
|
|
shun-iwasawa |
ad7711 |
DWORD dataType;
|
|
shun-iwasawa |
ad7711 |
DWORD dataSize;
|
|
shun-iwasawa |
ad7711 |
LONG res = RegQueryValueExW(
|
|
shun-iwasawa |
ad7711 |
handle, reinterpret_cast<const wchar_t*="">(keyStr.utf16()), 0,</const>
|
|
shun-iwasawa |
ad7711 |
&dataType, 0, &dataSize);
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
if (res != ERROR_SUCCESS) {
|
|
shun-iwasawa |
ad7711 |
RegCloseKey(handle);
|
|
shun-iwasawa |
ad7711 |
continue;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
// get the value
|
|
shun-iwasawa |
ad7711 |
QByteArray ba(dataSize, 0);
|
|
shun-iwasawa |
ad7711 |
res = RegQueryValueExW(
|
|
shun-iwasawa |
ad7711 |
handle, reinterpret_cast<const wchar_t*="">(keyStr.utf16()), 0, 0,</const>
|
|
shun-iwasawa |
ad7711 |
reinterpret_cast<unsigned char*="">(ba.data()), &dataSize);</unsigned>
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
if (res != ERROR_SUCCESS) {
|
|
shun-iwasawa |
ad7711 |
RegCloseKey(handle);
|
|
shun-iwasawa |
ad7711 |
continue;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
QString s;
|
|
shun-iwasawa |
ad7711 |
if (dataSize) {
|
|
shun-iwasawa |
ad7711 |
s = QString::fromUtf16((const ushort*)ba.constData(), ba.size() / 2);
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
QString valStr;
|
|
shun-iwasawa |
ad7711 |
QList<int> valArray;</int>
|
|
shun-iwasawa |
ad7711 |
for (int b = 0; b < s.length(); b++) {
|
|
shun-iwasawa |
ad7711 |
QChar c1((int)s[b].unicode() % 256);
|
|
shun-iwasawa |
ad7711 |
QChar c2((int)s[b].unicode() / 256);
|
|
shun-iwasawa |
ad7711 |
valStr.append(c1.toLatin1());
|
|
shun-iwasawa |
ad7711 |
valStr.append(c2.toLatin1());
|
|
shun-iwasawa |
ad7711 |
valArray.append((int)s[b].unicode() % 256);
|
|
shun-iwasawa |
ad7711 |
valArray.append((int)s[b].unicode() / 256);
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
// machine name starts from "FC 00", end with "0A"
|
|
shun-iwasawa |
ad7711 |
int index1 = valArray.indexOf(252); // FC
|
|
shun-iwasawa |
ad7711 |
int index2 = valArray.indexOf(10, index1); // 0A
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
if (index1 > 0 && index2 > 0) {
|
|
shun-iwasawa |
ad7711 |
QString machineName = valStr.mid(index1 + 2, index2 - index1 - 2);
|
|
shun-iwasawa |
ad7711 |
nameList.push_back(machineName);
|
|
shun-iwasawa |
ad7711 |
// std::wcout << "machine name = " << machineName.toStdWString() <<
|
|
shun-iwasawa |
ad7711 |
// std::endl;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
RegCloseKey(handle);
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
} else {
|
|
shun-iwasawa |
ad7711 |
std::cout << "getMonitorNames : failed to get handle" << std::endl;
|
|
shun-iwasawa |
ad7711 |
continue;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
if (nameList.isEmpty())
|
|
shun-iwasawa |
ad7711 |
std::cout << "getMonitorNames : No Monitor Name Found" << std::endl;
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
return nameList;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
};
|
|
shun-iwasawa |
ad7711 |
#endif
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
//-----------------------------------------------------------------------------
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
void LutCalibrator::initialize() {
|
|
shun-iwasawa |
ad7711 |
initializeOpenGLFunctions();
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
388550 |
if (!LutManager::instance()->isValid()) return;
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
// create shader
|
|
shun-iwasawa |
ad7711 |
if (!initializeLutTextureShader()) {
|
|
shun-iwasawa |
ad7711 |
if (m_shader.program) delete m_shader.program;
|
|
shun-iwasawa |
ad7711 |
if (m_shader.vert) delete m_shader.vert;
|
|
shun-iwasawa |
ad7711 |
if (m_shader.frag) delete m_shader.frag;
|
|
shun-iwasawa |
ad7711 |
return;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
createViewerVBO();
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
// input 3dlut data to the shader
|
|
shun-iwasawa |
ad7711 |
assignLutTexture();
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
m_isValid = true;
|
|
shun-iwasawa |
388550 |
|
|
shun-iwasawa |
ad7711 |
return;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
//-----------------------------------------------------------------------------
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
388550 |
void LutCalibrator::cleanup() {
|
|
shun-iwasawa |
388550 |
if (!isValid()) return;
|
|
shun-iwasawa |
ad7711 |
// release shader
|
|
shun-iwasawa |
388550 |
if (m_shader.program) {
|
|
shun-iwasawa |
388550 |
delete m_shader.program;
|
|
shun-iwasawa |
388550 |
m_shader.program = NULL;
|
|
shun-iwasawa |
388550 |
}
|
|
shun-iwasawa |
388550 |
if (m_shader.vert) {
|
|
shun-iwasawa |
388550 |
delete m_shader.vert;
|
|
shun-iwasawa |
388550 |
m_shader.vert = NULL;
|
|
shun-iwasawa |
388550 |
}
|
|
shun-iwasawa |
388550 |
if (m_shader.frag) {
|
|
shun-iwasawa |
388550 |
delete m_shader.frag;
|
|
shun-iwasawa |
388550 |
m_shader.frag = NULL;
|
|
shun-iwasawa |
388550 |
}
|
|
shun-iwasawa |
ad7711 |
// release VBO
|
|
shun-iwasawa |
ad7711 |
if (m_viewerVBO.isCreated()) m_viewerVBO.destroy();
|
|
shun-iwasawa |
ad7711 |
// release LUT texture
|
|
shun-iwasawa |
388550 |
if (m_lutTex && m_lutTex->isCreated()) {
|
|
shun-iwasawa |
388550 |
m_lutTex->destroy();
|
|
shun-iwasawa |
388550 |
delete m_lutTex;
|
|
shun-iwasawa |
388550 |
m_lutTex = NULL;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
//-----------------------------------------------------------------------------
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
bool LutCalibrator::initializeLutTextureShader() {
|
|
shun-iwasawa |
ad7711 |
m_shader.vert = new QOpenGLShader(QOpenGLShader::Vertex);
|
|
shun-iwasawa |
ad7711 |
const char* simple_vsrc =
|
|
shun-iwasawa |
ad7711 |
"#version 330 core\n"
|
|
shun-iwasawa |
ad7711 |
"// Input vertex data, different for all executions of this shader.\n"
|
|
shun-iwasawa |
ad7711 |
"layout(location = 0) in vec3 vertexPosition;\n"
|
|
shun-iwasawa |
ad7711 |
"layout(location = 1) in vec2 texCoord;\n"
|
|
shun-iwasawa |
ad7711 |
"// Output data ; will be interpolated for each fragment.\n"
|
|
shun-iwasawa |
ad7711 |
"out vec2 UV;\n"
|
|
shun-iwasawa |
ad7711 |
"// Values that stay constant for the whole mesh.\n"
|
|
shun-iwasawa |
ad7711 |
"void main() {\n"
|
|
shun-iwasawa |
ad7711 |
" // Output position of the vertex, in clip space : MVP * position\n"
|
|
shun-iwasawa |
ad7711 |
" gl_Position = vec4(vertexPosition, 1);\n"
|
|
shun-iwasawa |
ad7711 |
" // UV of the vertex. No special space for this one.\n"
|
|
shun-iwasawa |
ad7711 |
" UV = texCoord;\n"
|
|
shun-iwasawa |
ad7711 |
"}\n";
|
|
shun-iwasawa |
ad7711 |
bool ret = m_shader.vert->compileSourceCode(simple_vsrc);
|
|
shun-iwasawa |
ad7711 |
if (!ret)
|
|
shun-iwasawa |
ad7711 |
return execWarning(
|
|
shun-iwasawa |
ad7711 |
QObject::tr("Failed to compile m_textureShader.vert.", "gl"));
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
m_shader.frag = new QOpenGLShader(QOpenGLShader::Fragment);
|
|
shun-iwasawa |
ad7711 |
const char* simple_fsrc =
|
|
shun-iwasawa |
ad7711 |
"#version 330 core \n"
|
|
shun-iwasawa |
ad7711 |
"// Interpolated values from the vertex shaders \n"
|
|
shun-iwasawa |
ad7711 |
"in vec2 UV; \n"
|
|
shun-iwasawa |
ad7711 |
"// Ouput data \n"
|
|
shun-iwasawa |
ad7711 |
"out vec4 color; \n"
|
|
shun-iwasawa |
ad7711 |
"// Values that stay constant for the whole mesh. \n"
|
|
shun-iwasawa |
ad7711 |
"uniform sampler2D tex; \n"
|
|
shun-iwasawa |
ad7711 |
"uniform sampler3D lut; \n"
|
|
shun-iwasawa |
ad7711 |
"uniform vec3 lutSize; \n"
|
|
shun-iwasawa |
ad7711 |
"void main() { \n"
|
|
shun-iwasawa |
ad7711 |
" vec3 rawColor = texture(tex,UV).rgb; \n"
|
|
shun-iwasawa |
ad7711 |
" vec3 scale = (lutSize - 1.0) / lutSize; \n"
|
|
shun-iwasawa |
ad7711 |
" vec3 offset = 1.0 / (2.0 * lutSize); \n"
|
|
shun-iwasawa |
ad7711 |
" color = vec4(texture(lut, scale * rawColor + offset).rgb, 1.0); \n"
|
|
shun-iwasawa |
ad7711 |
"} \n";
|
|
shun-iwasawa |
ad7711 |
ret = m_shader.frag->compileSourceCode(simple_fsrc);
|
|
shun-iwasawa |
ad7711 |
if (!ret)
|
|
shun-iwasawa |
ad7711 |
return execWarning(QObject::tr("Failed to compile m_shader.frag.", "gl"));
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
m_shader.program = new QOpenGLShaderProgram();
|
|
shun-iwasawa |
ad7711 |
// add shaders
|
|
shun-iwasawa |
ad7711 |
ret = m_shader.program->addShader(m_shader.vert);
|
|
shun-iwasawa |
ad7711 |
if (!ret)
|
|
shun-iwasawa |
ad7711 |
return execWarning(QObject::tr("Failed to add m_shader.vert.", "gl"));
|
|
shun-iwasawa |
ad7711 |
ret = m_shader.program->addShader(m_shader.frag);
|
|
shun-iwasawa |
ad7711 |
if (!ret)
|
|
shun-iwasawa |
ad7711 |
return execWarning(QObject::tr("Failed to add m_shader.frag.", "gl"));
|
|
shun-iwasawa |
ad7711 |
// link shaders
|
|
shun-iwasawa |
ad7711 |
ret = m_shader.program->link();
|
|
shun-iwasawa |
ad7711 |
if (!ret)
|
|
shun-iwasawa |
ad7711 |
return execWarning(QObject::tr("Failed to link simple shader: %1", "gl")
|
|
shun-iwasawa |
ad7711 |
.arg(m_shader.program->log()));
|
|
shun-iwasawa |
ad7711 |
// obtain parameter locations
|
|
shun-iwasawa |
ad7711 |
m_shader.vertexAttrib = m_shader.program->attributeLocation("vertexPosition");
|
|
shun-iwasawa |
ad7711 |
if (m_shader.vertexAttrib == -1)
|
|
shun-iwasawa |
ad7711 |
return execWarning(
|
|
shun-iwasawa |
ad7711 |
QObject::tr("Failed to get attribute location of %1", "gl")
|
|
shun-iwasawa |
ad7711 |
.arg("vertexPosition"));
|
|
shun-iwasawa |
ad7711 |
m_shader.texCoordAttrib = m_shader.program->attributeLocation("texCoord");
|
|
shun-iwasawa |
ad7711 |
if (m_shader.texCoordAttrib == -1)
|
|
shun-iwasawa |
ad7711 |
return execWarning(
|
|
shun-iwasawa |
ad7711 |
QObject::tr("Failed to get attribute location of %1", "gl")
|
|
shun-iwasawa |
ad7711 |
.arg("texCoord"));
|
|
shun-iwasawa |
ad7711 |
m_shader.texUniform = m_shader.program->uniformLocation("tex");
|
|
shun-iwasawa |
ad7711 |
if (m_shader.texUniform == -1)
|
|
shun-iwasawa |
ad7711 |
return execWarning(
|
|
shun-iwasawa |
ad7711 |
QObject::tr("Failed to get uniform location of %1", "gl").arg("tex"));
|
|
shun-iwasawa |
ad7711 |
m_shader.lutUniform = m_shader.program->uniformLocation("lut");
|
|
shun-iwasawa |
ad7711 |
if (m_shader.lutUniform == -1)
|
|
shun-iwasawa |
ad7711 |
return execWarning(
|
|
shun-iwasawa |
ad7711 |
QObject::tr("Failed to get uniform location of %1", "gl").arg("lut"));
|
|
shun-iwasawa |
ad7711 |
m_shader.lutSizeUniform = m_shader.program->uniformLocation("lutSize");
|
|
shun-iwasawa |
ad7711 |
if (m_shader.lutSizeUniform == -1)
|
|
shun-iwasawa |
ad7711 |
return execWarning(QObject::tr("Failed to get uniform location of %1", "gl")
|
|
shun-iwasawa |
ad7711 |
.arg("lutSize"));
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
return true;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
//-----------------------------------------------------------------------------
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
void LutCalibrator::createViewerVBO() {
|
|
shun-iwasawa |
ad7711 |
GLfloat vertex[] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f};
|
|
shun-iwasawa |
ad7711 |
GLfloat texCoord[] = {0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f};
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
m_viewerVBO.create();
|
|
shun-iwasawa |
ad7711 |
m_viewerVBO.bind();
|
|
shun-iwasawa |
ad7711 |
m_viewerVBO.allocate(4 * 4 * sizeof(GLfloat));
|
|
shun-iwasawa |
ad7711 |
m_viewerVBO.write(0, vertex, sizeof(vertex));
|
|
shun-iwasawa |
ad7711 |
m_viewerVBO.write(sizeof(vertex), texCoord, sizeof(texCoord));
|
|
shun-iwasawa |
ad7711 |
m_viewerVBO.release();
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
//-----------------------------------------------------------------------------
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
void LutCalibrator::onEndDraw(QOpenGLFramebufferObject* fbo) {
|
|
shun-iwasawa |
ad7711 |
assert((glGetError()) == GL_NO_ERROR);
|
|
shun-iwasawa |
ad7711 |
fbo->release();
|
|
shun-iwasawa |
ad7711 |
GLuint textureId = fbo->texture();
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
glEnable(GL_TEXTURE_2D);
|
|
shun-iwasawa |
ad7711 |
glActiveTexture(GL_TEXTURE4);
|
|
shun-iwasawa |
ad7711 |
glBindTexture(GL_TEXTURE_2D, textureId);
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
glActiveTexture(GL_TEXTURE5);
|
|
shun-iwasawa |
388550 |
m_lutTex->bind();
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
glPushMatrix();
|
|
shun-iwasawa |
ad7711 |
glLoadIdentity();
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
m_shader.program->bind();
|
|
shun-iwasawa |
ad7711 |
m_shader.program->setUniformValue(m_shader.texUniform,
|
|
shun-iwasawa |
ad7711 |
4); // use texture unit 4
|
|
shun-iwasawa |
ad7711 |
m_shader.program->setUniformValue(m_shader.lutUniform,
|
|
shun-iwasawa |
ad7711 |
5); // use texture unit 5
|
|
shun-iwasawa |
388550 |
GLfloat size = (GLfloat)LutManager::instance()->meshSize();
|
|
shun-iwasawa |
ad7711 |
m_shader.program->setUniformValue(m_shader.lutSizeUniform, size, size, size);
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
m_shader.program->enableAttributeArray(m_shader.vertexAttrib);
|
|
shun-iwasawa |
ad7711 |
m_shader.program->enableAttributeArray(m_shader.texCoordAttrib);
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
m_viewerVBO.bind();
|
|
shun-iwasawa |
ad7711 |
m_shader.program->setAttributeBuffer(m_shader.vertexAttrib, GL_FLOAT, 0, 2);
|
|
shun-iwasawa |
ad7711 |
m_shader.program->setAttributeBuffer(m_shader.texCoordAttrib, GL_FLOAT,
|
|
shun-iwasawa |
ad7711 |
4 * 2 * sizeof(GLfloat), 2);
|
|
shun-iwasawa |
ad7711 |
m_viewerVBO.release();
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
m_shader.program->disableAttributeArray(m_shader.vertexAttrib);
|
|
shun-iwasawa |
ad7711 |
m_shader.program->disableAttributeArray(m_shader.texCoordAttrib);
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
m_shader.program->release();
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
glPopMatrix();
|
|
shun-iwasawa |
ad7711 |
glDisable(GL_TEXTURE_2D);
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
assert((glGetError()) == GL_NO_ERROR);
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
//-----------------------------------------------------------------------------
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
388550 |
void LutCalibrator::assignLutTexture() {
|
|
shun-iwasawa |
388550 |
assert(glGetError() == GL_NO_ERROR);
|
|
shun-iwasawa |
388550 |
int meshSize = LutManager::instance()->meshSize();
|
|
shun-iwasawa |
388550 |
m_lutTex = new QOpenGLTexture(QOpenGLTexture::Target3D);
|
|
shun-iwasawa |
388550 |
m_lutTex->setSize(meshSize, meshSize, meshSize);
|
|
shun-iwasawa |
388550 |
m_lutTex->setFormat(QOpenGLTexture::RGB32F);
|
|
shun-iwasawa |
388550 |
// m_lutTex->setLayers(1);
|
|
shun-iwasawa |
388550 |
m_lutTex->setMipLevels(1);
|
|
shun-iwasawa |
388550 |
m_lutTex->allocateStorage();
|
|
shun-iwasawa |
388550 |
m_lutTex->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear);
|
|
shun-iwasawa |
388550 |
m_lutTex->setWrapMode(QOpenGLTexture::ClampToEdge);
|
|
shun-iwasawa |
388550 |
|
|
shun-iwasawa |
388550 |
m_lutTex->setData(QOpenGLTexture::RGB, QOpenGLTexture::Float32,
|
|
shun-iwasawa |
388550 |
LutManager::instance()->data());
|
|
shun-iwasawa |
388550 |
|
|
shun-iwasawa |
388550 |
assert(glGetError() == GL_NO_ERROR);
|
|
shun-iwasawa |
388550 |
}
|
|
shun-iwasawa |
388550 |
|
|
shun-iwasawa |
388550 |
//=============================================================================
|
|
shun-iwasawa |
388550 |
|
|
shun-iwasawa |
388550 |
LutManager* LutManager::instance() {
|
|
shun-iwasawa |
388550 |
static LutManager _instance;
|
|
shun-iwasawa |
388550 |
return &_instance;
|
|
shun-iwasawa |
388550 |
}
|
|
shun-iwasawa |
388550 |
|
|
shun-iwasawa |
388550 |
//-----------------------------------------------------------------------------
|
|
shun-iwasawa |
388550 |
|
|
shun-iwasawa |
388550 |
LutManager::LutManager() {
|
|
shun-iwasawa |
388550 |
// check whether preference enables color calibration
|
|
shun-iwasawa |
388550 |
if (!Preferences::instance()->isColorCalibrationEnabled()) return;
|
|
shun-iwasawa |
388550 |
|
|
shun-iwasawa |
388550 |
// obtain current monitor name
|
|
shun-iwasawa |
388550 |
QString monitorName = getMonitorName();
|
|
shun-iwasawa |
388550 |
|
|
shun-iwasawa |
388550 |
// obtain 3dlut path associated to the monitor name
|
|
shun-iwasawa |
388550 |
QString lutPath =
|
|
shun-iwasawa |
388550 |
Preferences::instance()->getColorCalibrationLutPath(monitorName);
|
|
shun-iwasawa |
388550 |
|
|
shun-iwasawa |
388550 |
if (lutPath.isEmpty()) return;
|
|
shun-iwasawa |
388550 |
|
|
shun-iwasawa |
388550 |
// check existence of the 3dlut file
|
|
shun-iwasawa |
388550 |
// load 3dlut data
|
|
shun-iwasawa |
388550 |
if (!loadLutFile(lutPath)) return;
|
|
shun-iwasawa |
388550 |
|
|
shun-iwasawa |
388550 |
m_isValid = true;
|
|
shun-iwasawa |
388550 |
}
|
|
shun-iwasawa |
388550 |
|
|
shun-iwasawa |
388550 |
//-----------------------------------------------------------------------------
|
|
shun-iwasawa |
388550 |
|
|
shun-iwasawa |
388550 |
LutManager::~LutManager() {
|
|
shun-iwasawa |
388550 |
if (m_lut.data) delete[] m_lut.data;
|
|
shun-iwasawa |
388550 |
}
|
|
shun-iwasawa |
388550 |
|
|
shun-iwasawa |
388550 |
//-----------------------------------------------------------------------------
|
|
shun-iwasawa |
388550 |
|
|
shun-iwasawa |
388550 |
QString& LutManager::getMonitorName() const {
|
|
shun-iwasawa |
ad7711 |
static QString monitorName;
|
|
shun-iwasawa |
ad7711 |
if (!monitorName.isEmpty()) return monitorName;
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
#ifdef WIN32
|
|
shun-iwasawa |
ad7711 |
QStringList list = getMonitorNames();
|
|
shun-iwasawa |
ad7711 |
if (list.isEmpty())
|
|
shun-iwasawa |
ad7711 |
monitorName = "Any Monitor"; // this should not be translated
|
|
shun-iwasawa |
ad7711 |
else
|
|
shun-iwasawa |
ad7711 |
monitorName = list.at(0); // for now only the first monitor is handled
|
|
shun-iwasawa |
ad7711 |
#else
|
|
shun-iwasawa |
ad7711 |
monitorName = "Any Monitor"; // this should not be translated
|
|
shun-iwasawa |
ad7711 |
#endif
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
return monitorName;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
//-----------------------------------------------------------------------------
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
388550 |
bool LutManager::loadLutFile(const QString& fp) {
|
|
shun-iwasawa |
ad7711 |
struct locals {
|
|
shun-iwasawa |
ad7711 |
// skip empty or comment lines
|
|
shun-iwasawa |
ad7711 |
static inline QString readDataLine(QTextStream& stream) {
|
|
shun-iwasawa |
ad7711 |
while (1) {
|
|
shun-iwasawa |
ad7711 |
if (stream.atEnd()) return QString();
|
|
shun-iwasawa |
ad7711 |
QString ret = stream.readLine();
|
|
shun-iwasawa |
ad7711 |
if (!ret.isEmpty() && ret[0] != QChar('#')) return ret;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
static inline int lutCoords(int r, int g, int b, int meshSize) {
|
|
shun-iwasawa |
ad7711 |
return b * meshSize * meshSize * 3 + g * meshSize * 3 + r * 3;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
};
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
QFile file(fp);
|
|
shun-iwasawa |
ad7711 |
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
|
shun-iwasawa |
ad7711 |
return execWarning(QObject::tr("Failed to Open 3DLUT File."));
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
QTextStream stream(&file);
|
|
shun-iwasawa |
ad7711 |
QString line;
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
//---- read the 3DLUT files
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
// The first line shoud start from "3DMESH" keyword (case sensitive)
|
|
shun-iwasawa |
ad7711 |
line = locals::readDataLine(stream);
|
|
shun-iwasawa |
ad7711 |
if (line != "3DMESH") {
|
|
shun-iwasawa |
ad7711 |
file.close();
|
|
shun-iwasawa |
ad7711 |
return execWarning(
|
|
shun-iwasawa |
ad7711 |
QObject::tr("Failed to Load 3DLUT File.\nIt should start with "
|
|
shun-iwasawa |
ad7711 |
"\"3DMESH\" keyword."));
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
// The second line is "Mesh [Input bit depth] [Output bit depth]"
|
|
shun-iwasawa |
ad7711 |
// "Mesh" is a keyword (case sensitive)
|
|
shun-iwasawa |
ad7711 |
line = locals::readDataLine(stream);
|
|
shun-iwasawa |
ad7711 |
QStringList list = line.split(" ");
|
|
shun-iwasawa |
ad7711 |
if (list.size() != 3 || list.at(0) != "Mesh") {
|
|
shun-iwasawa |
ad7711 |
file.close();
|
|
shun-iwasawa |
ad7711 |
return execWarning(
|
|
shun-iwasawa |
ad7711 |
QObject::tr("Failed to Load 3DLUT File.\nThe second line should be "
|
|
shun-iwasawa |
ad7711 |
"\"Mesh [Input bit depth] [Output bit depth]\""));
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
int inputBitDepth = list.at(1).toInt();
|
|
shun-iwasawa |
ad7711 |
int outputBitDepth = list.at(2).toInt();
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
m_lut.meshSize = (int)pow(2.0, inputBitDepth) + 1;
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
float maxValue = pow(2.0, outputBitDepth) - 1.0f;
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
// The third line is corrections of values at each LUT grid
|
|
shun-iwasawa |
ad7711 |
line = locals::readDataLine(stream);
|
|
shun-iwasawa |
ad7711 |
list = line.split(" ", QString::SkipEmptyParts);
|
|
shun-iwasawa |
ad7711 |
if (list.size() != m_lut.meshSize) {
|
|
shun-iwasawa |
ad7711 |
file.close();
|
|
shun-iwasawa |
ad7711 |
return execWarning(QObject::tr("Failed to Load 3DLUT File."));
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
m_lut.data = new float[m_lut.meshSize * m_lut.meshSize * m_lut.meshSize * 3];
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
for (int k = 0; k < m_lut.meshSize; ++k) // r
|
|
shun-iwasawa |
ad7711 |
{
|
|
shun-iwasawa |
ad7711 |
for (int j = 0; j < m_lut.meshSize; ++j) // g
|
|
shun-iwasawa |
ad7711 |
{
|
|
shun-iwasawa |
ad7711 |
for (int i = 0; i < m_lut.meshSize; ++i) // b
|
|
shun-iwasawa |
ad7711 |
{
|
|
shun-iwasawa |
ad7711 |
line = locals::readDataLine(stream);
|
|
shun-iwasawa |
ad7711 |
list = line.split(" ", QString::SkipEmptyParts);
|
|
shun-iwasawa |
ad7711 |
if (list.size() != 3) {
|
|
shun-iwasawa |
ad7711 |
file.close();
|
|
shun-iwasawa |
ad7711 |
delete[] m_lut.data;
|
|
shun-iwasawa |
ad7711 |
return execWarning(QObject::tr("Failed to Load 3DLUT File."));
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
float* lut = m_lut.data + locals::lutCoords(k, j, i, m_lut.meshSize);
|
|
shun-iwasawa |
ad7711 |
*lut = (float)(list.at(0).toInt()) / maxValue;
|
|
shun-iwasawa |
ad7711 |
lut++;
|
|
shun-iwasawa |
ad7711 |
*lut = (float)(list.at(1).toInt()) / maxValue;
|
|
shun-iwasawa |
ad7711 |
lut++;
|
|
shun-iwasawa |
ad7711 |
*lut = (float)(list.at(2).toInt()) / maxValue;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
file.close();
|
|
shun-iwasawa |
ad7711 |
return true;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
//-----------------------------------------------------------------------------
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
// input : 0-1
|
|
shun-iwasawa |
388550 |
void LutManager::convert(float& r, float& g, float& b) {
|
|
shun-iwasawa |
ad7711 |
struct locals {
|
|
shun-iwasawa |
ad7711 |
static inline float lerp(float val1, float val2, float ratio) {
|
|
shun-iwasawa |
ad7711 |
return val1 * (1.0f - ratio) + val2 * ratio;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
static inline int getCoord(int r, int g, int b, int meshSize) {
|
|
shun-iwasawa |
ad7711 |
return b * meshSize * meshSize * 3 + g * meshSize * 3 + r * 3;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
};
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
if (!m_isValid) return;
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
float ratio[3]; // RGB軸
|
|
shun-iwasawa |
ad7711 |
int index[3][2]; // rgb インデックス
|
|
shun-iwasawa |
ad7711 |
float rawVal[3] = {r, g, b};
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
float vertex_color[2][2][2][3]; //補間用の1ボクセルの頂点色
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
for (int c = 0; c < 3; c++) {
|
|
shun-iwasawa |
ad7711 |
float val = rawVal[c] * (float)(m_lut.meshSize - 1);
|
|
shun-iwasawa |
ad7711 |
index[c][0] = (int)val;
|
|
shun-iwasawa |
ad7711 |
// boundary condition: if rawVal == 1 the value will not be interporated
|
|
shun-iwasawa |
ad7711 |
index[c][1] = (rawVal[c] >= 1.0f) ? index[c][0] : index[c][0] + 1;
|
|
shun-iwasawa |
ad7711 |
ratio[c] = val - (float)index[c][0];
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
for (int rr = 0; rr < 2; rr++)
|
|
shun-iwasawa |
ad7711 |
for (int gg = 0; gg < 2; gg++)
|
|
shun-iwasawa |
ad7711 |
for (int bb = 0; bb < 2; bb++) {
|
|
shun-iwasawa |
ad7711 |
float* val = &m_lut.data[locals::getCoord(
|
|
shun-iwasawa |
ad7711 |
index[0][rr], index[1][gg], index[2][bb], m_lut.meshSize)];
|
|
shun-iwasawa |
ad7711 |
for (int chan = 0; chan < 3; chan++, val++)
|
|
shun-iwasawa |
ad7711 |
vertex_color[rr][gg][bb][chan] = *val;
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
float result[3];
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
for (int chan = 0; chan < 3; chan++) {
|
|
shun-iwasawa |
ad7711 |
result[chan] = locals::lerp(
|
|
shun-iwasawa |
ad7711 |
locals::lerp(locals::lerp(vertex_color[0][0][0][chan],
|
|
shun-iwasawa |
ad7711 |
vertex_color[0][0][1][chan], ratio[2]),
|
|
shun-iwasawa |
ad7711 |
locals::lerp(vertex_color[0][1][0][chan],
|
|
shun-iwasawa |
ad7711 |
vertex_color[0][1][1][chan], ratio[2]),
|
|
shun-iwasawa |
ad7711 |
ratio[1]),
|
|
shun-iwasawa |
ad7711 |
locals::lerp(locals::lerp(vertex_color[1][0][0][chan],
|
|
shun-iwasawa |
ad7711 |
vertex_color[1][0][1][chan], ratio[2]),
|
|
shun-iwasawa |
ad7711 |
locals::lerp(vertex_color[1][1][0][chan],
|
|
shun-iwasawa |
ad7711 |
vertex_color[1][1][1][chan], ratio[2]),
|
|
shun-iwasawa |
ad7711 |
ratio[1]),
|
|
shun-iwasawa |
ad7711 |
ratio[0]);
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
r = result[0];
|
|
shun-iwasawa |
ad7711 |
g = result[1];
|
|
shun-iwasawa |
ad7711 |
b = result[2];
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
//-----------------------------------------------------------------------------
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
388550 |
void LutManager::convert(QColor& col) {
|
|
shun-iwasawa |
ad7711 |
if (!m_isValid) return;
|
|
shun-iwasawa |
ad7711 |
float r = col.redF();
|
|
shun-iwasawa |
ad7711 |
float g = col.greenF();
|
|
shun-iwasawa |
ad7711 |
float b = col.blueF();
|
|
shun-iwasawa |
ad7711 |
convert(r, g, b);
|
|
shun-iwasawa |
ad7711 |
// 0.5 offset is necessary for converting to 255 grading
|
|
shun-iwasawa |
ad7711 |
col = QColor((int)(r * 255.0 + 0.5), (int)(g * 255.0 + 0.5),
|
|
shun-iwasawa |
ad7711 |
(int)(b * 255.0 + 0.5), col.alpha());
|
|
shun-iwasawa |
ad7711 |
}
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
ad7711 |
//-----------------------------------------------------------------------------
|
|
shun-iwasawa |
ad7711 |
|
|
shun-iwasawa |
388550 |
void LutManager::convert(TPixel32& col) {
|
|
shun-iwasawa |
ad7711 |
if (!m_isValid) return;
|
|
shun-iwasawa |
ad7711 |
float r = (float)col.r / 255.0;
|
|
shun-iwasawa |
ad7711 |
float g = (float)col.g / 255.0;
|
|
shun-iwasawa |
ad7711 |
float b = (float)col.b / 255.0;
|
|
shun-iwasawa |
ad7711 |
convert(r, g, b);
|
|
shun-iwasawa |
ad7711 |
col = TPixel32((int)(r * 255.0 + 0.5), (int)(g * 255.0 + 0.5),
|
|
shun-iwasawa |
ad7711 |
(int)(b * 255.0 + 0.5), col.m);
|
|
shun-iwasawa |
ad7711 |
}
|