Merge "Add tool to generate color space conversion 3D LUTs"
diff --git a/include/ui/ColorSpace.h b/include/ui/ColorSpace.h
index b1863df..e9260b5 100644
--- a/include/ui/ColorSpace.h
+++ b/include/ui/ColorSpace.h
@@ -212,14 +212,14 @@
return v;
}
- const std::string mName;
+ std::string mName;
- const mat3 mRGBtoXYZ;
- const mat3 mXYZtoRGB;
+ mat3 mRGBtoXYZ;
+ mat3 mXYZtoRGB;
- const transfer_function mOETF;
- const transfer_function mEOTF;
- const clamping_function mClamper;
+ transfer_function mOETF;
+ transfer_function mEOTF;
+ clamping_function mClamper;
std::array<float2, 3> mPrimaries;
float2 mWhitePoint;
diff --git a/libs/ui/tools/Android.bp b/libs/ui/tools/Android.bp
new file mode 100644
index 0000000..fb46c2b
--- /dev/null
+++ b/libs/ui/tools/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 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.
+//
+
+cc_defaults {
+ name: "libui_tools_default",
+ clang_cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+}
+
+cc_binary {
+ name: "lutgen",
+ cppflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+ shared_libs: ["libui"],
+ srcs: ["lutgen.cpp"],
+}
diff --git a/libs/ui/tools/lutgen.cpp b/libs/ui/tools/lutgen.cpp
new file mode 100644
index 0000000..97b0822
--- /dev/null
+++ b/libs/ui/tools/lutgen.cpp
@@ -0,0 +1,196 @@
+/*
+ * 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, 0, 'h' },
+ { "dimension", required_argument, 0, 'd' },
+ { "source", required_argument, 0, 's' },
+ { "target", required_argument, 0, 't' },
+ { 0, 0, 0, 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;
+}