diff options
-rw-r--r-- | include/ui/ColorSpace.h | 12 | ||||
-rw-r--r-- | libs/ui/tools/Android.bp | 35 | ||||
-rw-r--r-- | libs/ui/tools/lutgen.cpp | 196 |
3 files changed, 237 insertions, 6 deletions
diff --git a/include/ui/ColorSpace.h b/include/ui/ColorSpace.h index b1863df0d7..e9260b5e23 100644 --- a/include/ui/ColorSpace.h +++ b/include/ui/ColorSpace.h @@ -212,14 +212,14 @@ private: 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 0000000000..fb46c2b20c --- /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 0000000000..97b0822238 --- /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; +} |