You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
6.7 KiB
197 lines
6.7 KiB
/*
|
|
* Copyright 2017 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <algorithm>
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
#include <iostream>
|
|
#include <string>
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <ui/ColorSpace.h>
|
|
|
|
using namespace android;
|
|
using namespace std;
|
|
|
|
uint32_t gSize = 32;
|
|
ColorSpace gColorSpaceSrc = ColorSpace::DisplayP3();
|
|
ColorSpace gColorSpaceDst = ColorSpace::extendedSRGB();
|
|
string gNameSrc = "DisplayP3";
|
|
string gNameDst = "extendedSRGB";
|
|
|
|
static void printHelp() {
|
|
cout << "lutgen -d SIZE -s SOURCE -t TARGET <lut file>" << endl;
|
|
cout << endl;
|
|
cout << "Generate a 3D LUT to convert between two color spaces." << endl;
|
|
cout << endl;
|
|
cout << "If <lut file> ends in .inc, data is generated without the array declaration." << endl;
|
|
cout << endl;
|
|
cout << "Options:" << endl;
|
|
cout << " --help, -h" << endl;
|
|
cout << " print this message" << endl;
|
|
cout << " --dimension=, -d" << endl;
|
|
cout << " the dimension of the 3D LUT. Example: 17 for a 17x17x17 LUT. 32 by default" << endl;
|
|
cout << " --source=COLORSPACE, -s" << endl;
|
|
cout << " the source color space, see below for available names. DisplayP3 by default" << endl;
|
|
cout << " --target=COLORSPACE, -t" << endl;
|
|
cout << " the target color space, see below for available names. extendedSRGB by default" << endl;
|
|
cout << endl;
|
|
cout << "Colorspace names:" << endl;
|
|
cout << " sRGB" << endl;
|
|
cout << " linearSRGB" << endl;
|
|
cout << " extendedSRGB" << endl;
|
|
cout << " linearExtendedSRGB" << endl;
|
|
cout << " NTSC" << endl;
|
|
cout << " BT709" << endl;
|
|
cout << " BT2020" << endl;
|
|
cout << " AdobeRGB" << endl;
|
|
cout << " ProPhotoRGB" << endl;
|
|
cout << " DisplayP3" << endl;
|
|
cout << " DCIP3" << endl;
|
|
cout << " ACES" << endl;
|
|
cout << " ACEScg" << endl;
|
|
}
|
|
|
|
static const ColorSpace findColorSpace(const string& name) {
|
|
if (name == "linearSRGB") return ColorSpace::linearSRGB();
|
|
if (name == "extendedSRGB") return ColorSpace::extendedSRGB();
|
|
if (name == "linearExtendedSRGB") return ColorSpace::linearExtendedSRGB();
|
|
if (name == "NTSC") return ColorSpace::NTSC();
|
|
if (name == "BT709") return ColorSpace::BT709();
|
|
if (name == "BT2020") return ColorSpace::BT2020();
|
|
if (name == "AdobeRGB") return ColorSpace::AdobeRGB();
|
|
if (name == "ProPhotoRGB") return ColorSpace::ProPhotoRGB();
|
|
if (name == "DisplayP3") return ColorSpace::DisplayP3();
|
|
if (name == "DCIP3") return ColorSpace::DCIP3();
|
|
if (name == "ACES") return ColorSpace::ACES();
|
|
if (name == "ACEScg") return ColorSpace::ACEScg();
|
|
return ColorSpace::sRGB();
|
|
}
|
|
|
|
static int handleCommandLineArgments(int argc, char* argv[]) {
|
|
static constexpr const char* OPTSTR = "h:d:s:t:";
|
|
static const struct option OPTIONS[] = {
|
|
{ "help", no_argument, nullptr, 'h' },
|
|
{ "dimension", required_argument, nullptr, 'd' },
|
|
{ "source", required_argument, nullptr, 's' },
|
|
{ "target", required_argument, nullptr, 't' },
|
|
{ nullptr, 0, nullptr, 0 } // termination of the option list
|
|
};
|
|
|
|
int opt;
|
|
int index = 0;
|
|
|
|
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &index)) >= 0) {
|
|
string arg(optarg ? optarg : "");
|
|
switch (opt) {
|
|
default:
|
|
case 'h':
|
|
printHelp();
|
|
exit(0);
|
|
break;
|
|
case 'd':
|
|
gSize = max(2, min(stoi(arg), 256));
|
|
break;
|
|
case 's':
|
|
gNameSrc = arg;
|
|
gColorSpaceSrc = findColorSpace(arg);
|
|
break;
|
|
case 't':
|
|
gNameDst = arg;
|
|
gColorSpaceDst = findColorSpace(arg);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return optind;
|
|
}
|
|
|
|
int main(int argc, char* argv[]) {
|
|
int optionIndex = handleCommandLineArgments(argc, argv);
|
|
int numArgs = argc - optionIndex;
|
|
|
|
if (numArgs < 1) {
|
|
printHelp();
|
|
return 1;
|
|
}
|
|
|
|
bool isInclude = false;
|
|
|
|
string filename(argv[optionIndex]);
|
|
size_t index = filename.find_last_of('.');
|
|
|
|
if (index != string::npos) {
|
|
string extension(filename.substr(index + 1));
|
|
isInclude = extension == "inc";
|
|
}
|
|
|
|
ofstream outputStream(filename, ios::trunc);
|
|
if (outputStream.good()) {
|
|
auto lut = ColorSpace::createLUT(gSize, gColorSpaceSrc, gColorSpaceDst);
|
|
auto data = lut.get();
|
|
|
|
outputStream << "// generated with lutgen " << filename.c_str() << endl;
|
|
outputStream << "// 3D LUT stored as an RGB16F texture, in GL order" << endl;
|
|
outputStream << "// Size is " << gSize << "x" << gSize << "x" << gSize << endl;
|
|
|
|
string src(gNameSrc);
|
|
string dst(gNameDst);
|
|
|
|
if (!isInclude) {
|
|
transform(src.begin(), src.end(), src.begin(), ::toupper);
|
|
transform(dst.begin(), dst.end(), dst.begin(), ::toupper);
|
|
|
|
outputStream << "const size_t LUT_" << src << "_TO_" << dst << "_SIZE = " << gSize << endl;
|
|
outputStream << "const uint16_t LUT_" << src << "_TO_" << dst << "[] = {";
|
|
} else {
|
|
outputStream << "// From " << src << " to " << dst << endl;
|
|
}
|
|
|
|
for (size_t z = 0; z < gSize; z++) {
|
|
for (size_t y = 0; y < gSize; y++) {
|
|
for (size_t x = 0; x < gSize; x++) {
|
|
if (x % 4 == 0) outputStream << endl << " ";
|
|
|
|
half3 rgb = half3(*data++);
|
|
|
|
const uint16_t r = rgb.r.getBits();
|
|
const uint16_t g = rgb.g.getBits();
|
|
const uint16_t b = rgb.b.getBits();
|
|
|
|
outputStream << "0x" << setfill('0') << setw(4) << hex << r << ", ";
|
|
outputStream << "0x" << setfill('0') << setw(4) << hex << g << ", ";
|
|
outputStream << "0x" << setfill('0') << setw(4) << hex << b << ", ";
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!isInclude) {
|
|
outputStream << endl << "}; // end LUT" << endl;
|
|
}
|
|
|
|
outputStream << endl;
|
|
outputStream.flush();
|
|
outputStream.close();
|
|
} else {
|
|
cerr << "Could not write to file: " << filename << endl;
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|