work on internal color management
This commit is contained in:
@@ -18,8 +18,10 @@ add_subdirectory(gl)
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
render/colorservice.h
|
||||
render/colorservice.cpp
|
||||
render/colormanager.h
|
||||
render/colormanager.cpp
|
||||
render/colorprocessor.h
|
||||
render/colorprocessor.cpp
|
||||
render/pixelformat.h
|
||||
render/pixelformat.cpp
|
||||
render/pixelservice.h
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
#include "colormanager.h"
|
||||
|
||||
#include <QFloat16>
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
ColorManager* ColorManager::instance_ = nullptr;
|
||||
|
||||
void ColorManager::SetConfig(const QString &filename)
|
||||
{
|
||||
SetConfig(OCIO::Config::CreateFromFile(filename.toUtf8()));
|
||||
}
|
||||
|
||||
void ColorManager::SetConfig(OpenColorIO::v1::ConstConfigRcPtr config)
|
||||
{
|
||||
OCIO::SetCurrentConfig(config);
|
||||
|
||||
emit ConfigChanged();
|
||||
}
|
||||
|
||||
void ColorManager::CreateInstance()
|
||||
{
|
||||
if (instance_ == nullptr) {
|
||||
instance_ = new ColorManager();
|
||||
}
|
||||
}
|
||||
|
||||
ColorManager *ColorManager::instance()
|
||||
{
|
||||
return instance_;
|
||||
}
|
||||
|
||||
void ColorManager::DestroyInstance()
|
||||
{
|
||||
delete instance_;
|
||||
instance_ = nullptr;
|
||||
}
|
||||
|
||||
void ColorManager::DisassociateAlpha(FramePtr f)
|
||||
{
|
||||
AssociateAlphaPixFmtFilter(kDisassociate, f);
|
||||
}
|
||||
|
||||
void ColorManager::AssociateAlpha(FramePtr f)
|
||||
{
|
||||
AssociateAlphaPixFmtFilter(kAssociate, f);
|
||||
}
|
||||
|
||||
void ColorManager::ReassociateAlpha(FramePtr f)
|
||||
{
|
||||
AssociateAlphaPixFmtFilter(kReassociate, f);
|
||||
}
|
||||
|
||||
QStringList ColorManager::ListAvailableDisplays()
|
||||
{
|
||||
QStringList displays;
|
||||
|
||||
OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
|
||||
|
||||
int number_of_displays = config->getNumDisplays();
|
||||
|
||||
for (int i=0;i<number_of_displays;i++) {
|
||||
displays.append(config->getDisplay(i));
|
||||
}
|
||||
|
||||
return displays;
|
||||
}
|
||||
|
||||
QString ColorManager::GetDefaultDisplay()
|
||||
{
|
||||
return OCIO::GetCurrentConfig()->getDefaultDisplay();
|
||||
}
|
||||
|
||||
QStringList ColorManager::ListAvailableViews(QString display)
|
||||
{
|
||||
QStringList views;
|
||||
|
||||
OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
|
||||
|
||||
int number_of_views = config->getNumViews(display.toUtf8());
|
||||
|
||||
for (int i=0;i<number_of_views;i++) {
|
||||
views.append(config->getView(display.toUtf8(), i));
|
||||
}
|
||||
|
||||
return views;
|
||||
}
|
||||
|
||||
QString ColorManager::GetDefaultView(const QString &display)
|
||||
{
|
||||
return OCIO::GetCurrentConfig()->getDefaultView(display.toUtf8());
|
||||
}
|
||||
|
||||
QStringList ColorManager::ListAvailableLooks()
|
||||
{
|
||||
QStringList looks;
|
||||
|
||||
OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
|
||||
|
||||
int number_of_looks = config->getNumLooks();
|
||||
|
||||
for (int i=0;i<number_of_looks;i++) {
|
||||
looks.append(config->getLookNameByIndex(i));
|
||||
}
|
||||
|
||||
return looks;
|
||||
}
|
||||
|
||||
ColorManager::ColorManager()
|
||||
{
|
||||
}
|
||||
|
||||
void ColorManager::AssociateAlphaPixFmtFilter(ColorManager::AlphaAction action, FramePtr f)
|
||||
{
|
||||
int pixel_count = f->width() * f->height() * kRGBAChannels;
|
||||
|
||||
switch (static_cast<olive::PixelFormat>(f->format())) {
|
||||
case olive::PIX_FMT_INVALID:
|
||||
case olive::PIX_FMT_COUNT:
|
||||
qWarning() << "Alpha association functions received an invalid pixel format";
|
||||
break;
|
||||
case olive::PIX_FMT_RGBA8:
|
||||
case olive::PIX_FMT_RGBA16U:
|
||||
qWarning() << "Alpha association functions only works on float-based pixel formats at this time";
|
||||
break;
|
||||
case olive::PIX_FMT_RGBA16F:
|
||||
{
|
||||
AssociateAlphaInternal<qfloat16>(action, reinterpret_cast<qfloat16*>(f->data()), pixel_count);
|
||||
break;
|
||||
}
|
||||
case olive::PIX_FMT_RGBA32F:
|
||||
{
|
||||
AssociateAlphaInternal<float>(action, reinterpret_cast<float*>(f->data()), pixel_count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ColorManager::AssociateAlphaInternal(ColorManager::AlphaAction action, T *data, int pix_count)
|
||||
{
|
||||
for (int i=0;i<pix_count;i+=kRGBAChannels) {
|
||||
T alpha = data[i+kRGBChannels];
|
||||
|
||||
if (action == kAssociate || alpha > 0) {
|
||||
for (int j=0;j<kRGBChannels;j++) {
|
||||
if (action == kDisassociate) {
|
||||
data[i+j] /= alpha;
|
||||
} else {
|
||||
data[i+j] *= alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
#ifndef COLORSERVICE_H
|
||||
#define COLORSERVICE_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "colorprocessor.h"
|
||||
#include "decoder/frame.h"
|
||||
#include "render/gl/shadergenerators.h"
|
||||
|
||||
class ColorManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
void SetConfig(const QString& filename);
|
||||
|
||||
void SetConfig(OCIO::ConstConfigRcPtr config);
|
||||
|
||||
static void CreateInstance();
|
||||
|
||||
static ColorManager* instance();
|
||||
|
||||
static void DestroyInstance();
|
||||
|
||||
static void DisassociateAlpha(FramePtr f);
|
||||
|
||||
static void AssociateAlpha(FramePtr f);
|
||||
|
||||
static void ReassociateAlpha(FramePtr f);
|
||||
|
||||
static QStringList ListAvailableDisplays();
|
||||
|
||||
static QString GetDefaultDisplay();
|
||||
|
||||
static QStringList ListAvailableViews(QString display);
|
||||
|
||||
static QString GetDefaultView(const QString& display);
|
||||
|
||||
static QStringList ListAvailableLooks();
|
||||
|
||||
signals:
|
||||
void ConfigChanged();
|
||||
|
||||
private:
|
||||
ColorManager();
|
||||
|
||||
static ColorManager* instance_;
|
||||
|
||||
enum AlphaAction {
|
||||
kAssociate,
|
||||
kDisassociate,
|
||||
kReassociate
|
||||
};
|
||||
|
||||
static void AssociateAlphaPixFmtFilter(AlphaAction action, FramePtr f);
|
||||
|
||||
template<typename T>
|
||||
static void AssociateAlphaInternal(AlphaAction action, T* data, int pix_count);
|
||||
};
|
||||
|
||||
#endif // COLORSERVICE_H
|
||||
@@ -0,0 +1,62 @@
|
||||
#include "colorprocessor.h"
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
ColorProcessor::ColorProcessor(const QString& source_space, const QString& dest_space)
|
||||
{
|
||||
OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
|
||||
|
||||
processor = config->getProcessor(source_space.toUtf8(),
|
||||
dest_space.toUtf8());
|
||||
}
|
||||
|
||||
ColorProcessor::ColorProcessor(const QString& source_space,
|
||||
QString display,
|
||||
QString view,
|
||||
const QString& look)
|
||||
{
|
||||
OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
|
||||
|
||||
if (display.isEmpty()) {
|
||||
display = config->getDefaultDisplay();
|
||||
}
|
||||
|
||||
if (view.isEmpty()) {
|
||||
view = config->getDefaultView(display.toUtf8());
|
||||
}
|
||||
|
||||
// Get current display stats
|
||||
OCIO::DisplayTransformRcPtr transform = OCIO::DisplayTransform::Create();
|
||||
transform->setInputColorSpaceName(source_space.toUtf8());
|
||||
transform->setDisplay(display.toUtf8());
|
||||
transform->setView(view.toUtf8());
|
||||
|
||||
if (!look.isEmpty()) {
|
||||
transform->setLooksOverride(look.toUtf8());
|
||||
transform->setLooksOverrideEnabled(true);
|
||||
}
|
||||
|
||||
processor = config->getProcessor(transform);
|
||||
}
|
||||
|
||||
void ColorProcessor::ConvertFrame(FramePtr f)
|
||||
{
|
||||
OCIO::PackedImageDesc img(reinterpret_cast<float*>(f->data()), f->width(), f->height(), kRGBAChannels);
|
||||
|
||||
processor->apply(img);
|
||||
}
|
||||
|
||||
ColorProcessorPtr ColorProcessor::Create(const QString& source_space, const QString& dest_space)
|
||||
{
|
||||
return std::make_shared<ColorProcessor>(source_space, dest_space);
|
||||
}
|
||||
|
||||
ColorProcessorPtr ColorProcessor::Create(const QString &source_space, const QString &display, const QString &view, const QString &look)
|
||||
{
|
||||
return std::make_shared<ColorProcessor>(source_space, display, view, look);
|
||||
}
|
||||
|
||||
OpenColorIO::v1::ConstProcessorRcPtr ColorProcessor::GetProcessor()
|
||||
{
|
||||
return processor;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef COLORPROCESSOR_H
|
||||
#define COLORPROCESSOR_H
|
||||
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
namespace OCIO = OCIO_NAMESPACE::v1;
|
||||
|
||||
#include "decoder/frame.h"
|
||||
|
||||
class ColorProcessor;
|
||||
using ColorProcessorPtr = std::shared_ptr<ColorProcessor>;
|
||||
|
||||
class ColorProcessor
|
||||
{
|
||||
public:
|
||||
ColorProcessor(const QString &source_space, const QString &dest_space);
|
||||
|
||||
ColorProcessor(const QString& source_space,
|
||||
QString display,
|
||||
QString view,
|
||||
const QString& look);
|
||||
|
||||
static ColorProcessorPtr Create(const QString& source_space, const QString& dest_space);
|
||||
|
||||
static ColorProcessorPtr Create(const QString& source_space,
|
||||
const QString& display,
|
||||
const QString& view,
|
||||
const QString& look);
|
||||
|
||||
OCIO::ConstProcessorRcPtr GetProcessor();
|
||||
|
||||
void ConvertFrame(FramePtr f);
|
||||
|
||||
private:
|
||||
OCIO::ConstProcessorRcPtr processor;
|
||||
|
||||
};
|
||||
|
||||
#endif // COLORPROCESSOR_H
|
||||
@@ -1,102 +0,0 @@
|
||||
#include "colorservice.h"
|
||||
|
||||
#include <QFloat16>
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
ColorService::ColorService(const char* source_space, const char* dest_space)
|
||||
{
|
||||
OCIO::ConstConfigRcPtr config = OCIO::GetCurrentConfig();
|
||||
|
||||
processor = config->getProcessor(source_space,
|
||||
dest_space);
|
||||
}
|
||||
|
||||
void ColorService::Init()
|
||||
{
|
||||
// FIXME: Load configured config file for this session
|
||||
/*try {
|
||||
// FIXME: Hardcoded values for testing purposes
|
||||
OCIO::ConstConfigRcPtr config = OCIO::Config::CreateFromFile("/run/media/matt/Home/OpenColorIO/ocio.configs.0.7v4/nuke-default/config.ocio");
|
||||
|
||||
OCIO::SetCurrentConfig(config);
|
||||
} catch (OCIO::Exception& exception) {
|
||||
qWarning() << "OpenColorIO Error:" << exception.what();
|
||||
}*/
|
||||
}
|
||||
|
||||
ColorServicePtr ColorService::Create(const char *source_space, const char *dest_space)
|
||||
{
|
||||
return std::make_shared<ColorService>(source_space, dest_space);
|
||||
}
|
||||
|
||||
void ColorService::ConvertFrame(FramePtr f)
|
||||
{
|
||||
OCIO::PackedImageDesc img(reinterpret_cast<float*>(f->data()), f->width(), f->height(), kRGBAChannels);
|
||||
|
||||
processor->apply(img);
|
||||
}
|
||||
|
||||
void ColorService::DisassociateAlpha(FramePtr f)
|
||||
{
|
||||
AssociateAlphaPixFmtFilter(kDisassociate, f);
|
||||
}
|
||||
|
||||
void ColorService::AssociateAlpha(FramePtr f)
|
||||
{
|
||||
AssociateAlphaPixFmtFilter(kAssociate, f);
|
||||
}
|
||||
|
||||
void ColorService::ReassociateAlpha(FramePtr f)
|
||||
{
|
||||
AssociateAlphaPixFmtFilter(kReassociate, f);
|
||||
}
|
||||
|
||||
OpenColorIO::v1::ConstProcessorRcPtr ColorService::GetProcessor()
|
||||
{
|
||||
return processor;
|
||||
}
|
||||
|
||||
void ColorService::AssociateAlphaPixFmtFilter(ColorService::AlphaAction action, FramePtr f)
|
||||
{
|
||||
int pixel_count = f->width() * f->height() * kRGBAChannels;
|
||||
|
||||
switch (static_cast<olive::PixelFormat>(f->format())) {
|
||||
case olive::PIX_FMT_INVALID:
|
||||
case olive::PIX_FMT_COUNT:
|
||||
qWarning() << "Alpha association functions received an invalid pixel format";
|
||||
break;
|
||||
case olive::PIX_FMT_RGBA8:
|
||||
case olive::PIX_FMT_RGBA16U:
|
||||
qWarning() << "Alpha association functions only works on float-based pixel formats at this time";
|
||||
break;
|
||||
case olive::PIX_FMT_RGBA16F:
|
||||
{
|
||||
AssociateAlphaInternal<qfloat16>(action, reinterpret_cast<qfloat16*>(f->data()), pixel_count);
|
||||
break;
|
||||
}
|
||||
case olive::PIX_FMT_RGBA32F:
|
||||
{
|
||||
AssociateAlphaInternal<float>(action, reinterpret_cast<float*>(f->data()), pixel_count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ColorService::AssociateAlphaInternal(ColorService::AlphaAction action, T *data, int pix_count)
|
||||
{
|
||||
for (int i=0;i<pix_count;i+=kRGBAChannels) {
|
||||
T alpha = data[i+kRGBChannels];
|
||||
|
||||
if (action == kAssociate || alpha > 0) {
|
||||
for (int j=0;j<kRGBChannels;j++) {
|
||||
if (action == kDisassociate) {
|
||||
data[i+j] /= alpha;
|
||||
} else {
|
||||
data[i+j] *= alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
#ifndef COLORSERVICE_H
|
||||
#define COLORSERVICE_H
|
||||
|
||||
#include <memory>
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
namespace OCIO = OCIO_NAMESPACE::v1;
|
||||
|
||||
#include "decoder/frame.h"
|
||||
#include "render/gl/shadergenerators.h"
|
||||
|
||||
class ColorService;
|
||||
using ColorServicePtr = std::shared_ptr<ColorService>;
|
||||
|
||||
class ColorService
|
||||
{
|
||||
public:
|
||||
ColorService(const char *source_space, const char *dest_space);
|
||||
|
||||
static void Init();
|
||||
|
||||
static ColorServicePtr Create(const char *source_space, const char *dest_space);
|
||||
|
||||
void ConvertFrame(FramePtr f);
|
||||
|
||||
static void DisassociateAlpha(FramePtr f);
|
||||
|
||||
static void AssociateAlpha(FramePtr f);
|
||||
|
||||
static void ReassociateAlpha(FramePtr f);
|
||||
|
||||
OCIO::ConstProcessorRcPtr GetProcessor();
|
||||
|
||||
private:
|
||||
OCIO::ConstProcessorRcPtr processor;
|
||||
|
||||
enum AlphaAction {
|
||||
kAssociate,
|
||||
kDisassociate,
|
||||
kReassociate
|
||||
};
|
||||
|
||||
static void AssociateAlphaPixFmtFilter(AlphaAction action, FramePtr f);
|
||||
|
||||
template<typename T>
|
||||
static void AssociateAlphaInternal(AlphaAction action, T* data, int pix_count);
|
||||
};
|
||||
|
||||
#endif // COLORSERVICE_H
|
||||
Reference in New Issue
Block a user