163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil/*
263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * vivid-color.c - A table that converts colors to various colorspaces
363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil *
463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * The test pattern generator uses the tpg_colors for its test patterns.
563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * For testing colorspaces the first 8 colors of that table need to be
663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * converted to their equivalent in the target colorspace.
763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil *
863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * The tpg_csc_colors[] table is the result of that conversion and since
963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * it is precalculated the colorspace conversion is just a simple table
1063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * lookup.
1163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil *
1263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * This source also contains the code used to generate the tpg_csc_colors
1363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * table. Run the following command to compile it:
1463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil *
1563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil *	gcc vivid-colors.c -DCOMPILE_APP -o gen-colors -lm
1663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil *
1763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * and run the utility.
1863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil *
1963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * Note that the converted colors are in the range 0x000-0xff0 (so times 16)
2063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * in order to preserve precision.
2163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil *
2263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
2363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil *
2463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * This program is free software; you may redistribute it and/or modify
2563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * it under the terms of the GNU General Public License as published by
2663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * the Free Software Foundation; version 2 of the License.
2763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil *
2863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
2963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
3063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
3163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
3263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
3363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
3463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil * SOFTWARE.
3663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil */
3763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
3863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil#include <linux/videodev2.h>
3963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
4063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil#include "vivid-tpg-colors.h"
4163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
4263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil/* sRGB colors with range [0-255] */
4363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuilconst struct color tpg_colors[TPG_COLOR_MAX] = {
4463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	/*
4563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	 * Colors to test colorspace conversion: converting these colors
4663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	 * to other colorspaces will never lead to out-of-gamut colors.
4763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	 */
4863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 191, 191, 191 }, /* TPG_COLOR_CSC_WHITE */
4963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 191, 191,  50 }, /* TPG_COLOR_CSC_YELLOW */
5063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{  50, 191, 191 }, /* TPG_COLOR_CSC_CYAN */
5163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{  50, 191,  50 }, /* TPG_COLOR_CSC_GREEN */
5263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 191,  50, 191 }, /* TPG_COLOR_CSC_MAGENTA */
5363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 191,  50,  50 }, /* TPG_COLOR_CSC_RED */
5463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{  50,  50, 191 }, /* TPG_COLOR_CSC_BLUE */
5563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{  50,  50,  50 }, /* TPG_COLOR_CSC_BLACK */
5663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
5763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	/* 75% colors */
5863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 191, 191,   0 }, /* TPG_COLOR_75_YELLOW */
5963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{   0, 191, 191 }, /* TPG_COLOR_75_CYAN */
6063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{   0, 191,   0 }, /* TPG_COLOR_75_GREEN */
6163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 191,   0, 191 }, /* TPG_COLOR_75_MAGENTA */
6263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 191,   0,   0 }, /* TPG_COLOR_75_RED */
6363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{   0,   0, 191 }, /* TPG_COLOR_75_BLUE */
6463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
6563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	/* 100% colors */
6663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 255, 255, 255 }, /* TPG_COLOR_100_WHITE */
6763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 255, 255,   0 }, /* TPG_COLOR_100_YELLOW */
6863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{   0, 255, 255 }, /* TPG_COLOR_100_CYAN */
6963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{   0, 255,   0 }, /* TPG_COLOR_100_GREEN */
7063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 255,   0, 255 }, /* TPG_COLOR_100_MAGENTA */
7163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 255,   0,   0 }, /* TPG_COLOR_100_RED */
7263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{   0,   0, 255 }, /* TPG_COLOR_100_BLUE */
7363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{   0,   0,   0 }, /* TPG_COLOR_100_BLACK */
7463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
7563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{   0,   0,   0 }, /* TPG_COLOR_RANDOM placeholder */
7663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil};
7763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
7863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil#ifndef COMPILE_APP
7963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
8063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil/* Generated table */
8163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuilconst struct color16 tpg_csc_colors[V4L2_COLORSPACE_SRGB + 1][TPG_COLOR_CSC_BLACK + 1] = {
8263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SMPTE170M][0] = { 2953, 2939, 2939 },
8363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SMPTE170M][1] = { 2954, 2963, 585 },
8463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SMPTE170M][2] = { 84, 2967, 2937 },
8563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SMPTE170M][3] = { 93, 2990, 575 },
8663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SMPTE170M][4] = { 3030, 259, 2933 },
8763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SMPTE170M][5] = { 3031, 406, 557 },
8863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SMPTE170M][6] = { 544, 428, 2931 },
8963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SMPTE170M][7] = { 551, 547, 547 },
9063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SMPTE240M][0] = { 2926, 2926, 2926 },
9163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SMPTE240M][1] = { 2926, 2926, 857 },
9263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SMPTE240M][2] = { 1594, 2901, 2901 },
9363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SMPTE240M][3] = { 1594, 2901, 774 },
9463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SMPTE240M][4] = { 2484, 618, 2858 },
9563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SMPTE240M][5] = { 2484, 618, 617 },
9663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SMPTE240M][6] = { 507, 507, 2832 },
9763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SMPTE240M][7] = { 507, 507, 507 },
9863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_REC709][0] = { 2939, 2939, 2939 },
9963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_REC709][1] = { 2939, 2939, 547 },
10063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_REC709][2] = { 547, 2939, 2939 },
10163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_REC709][3] = { 547, 2939, 547 },
10263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_REC709][4] = { 2939, 547, 2939 },
10363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_REC709][5] = { 2939, 547, 547 },
10463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_REC709][6] = { 547, 547, 2939 },
10563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_REC709][7] = { 547, 547, 547 },
10663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_470_SYSTEM_M][0] = { 2894, 2988, 2808 },
10763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_470_SYSTEM_M][1] = { 2847, 3070, 843 },
10863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_470_SYSTEM_M][2] = { 1656, 2962, 2783 },
10963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_470_SYSTEM_M][3] = { 1572, 3045, 763 },
11063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_470_SYSTEM_M][4] = { 2477, 229, 2743 },
11163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_470_SYSTEM_M][5] = { 2422, 672, 614 },
11263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_470_SYSTEM_M][6] = { 725, 63, 2718 },
11363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_470_SYSTEM_M][7] = { 534, 561, 509 },
11463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_470_SYSTEM_BG][0] = { 2939, 2939, 2939 },
11563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_470_SYSTEM_BG][1] = { 2939, 2939, 621 },
11663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_470_SYSTEM_BG][2] = { 786, 2939, 2939 },
11763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_470_SYSTEM_BG][3] = { 786, 2939, 621 },
11863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_470_SYSTEM_BG][4] = { 2879, 547, 2923 },
11963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_470_SYSTEM_BG][5] = { 2879, 547, 547 },
12063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_470_SYSTEM_BG][6] = { 547, 547, 2923 },
12163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_470_SYSTEM_BG][7] = { 547, 547, 547 },
12263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SRGB][0] = { 3056, 3056, 3056 },
12363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SRGB][1] = { 3056, 3056, 800 },
12463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SRGB][2] = { 800, 3056, 3056 },
12563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SRGB][3] = { 800, 3056, 800 },
12663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SRGB][4] = { 3056, 800, 3056 },
12763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SRGB][5] = { 3056, 800, 800 },
12863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SRGB][6] = { 800, 800, 3056 },
12963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	[V4L2_COLORSPACE_SRGB][7] = { 800, 800, 800 },
13063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil};
13163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
13263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil#else
13363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
13463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil/* This code generates the table above */
13563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
13663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil#include <math.h>
13763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil#include <stdio.h>
13863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil#include <stdlib.h>
13963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
14063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuilstatic const double rec709_to_ntsc1953[3][3] = {
14163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 0.6698, 0.2678,  0.0323 },
14263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 0.0185, 1.0742, -0.0603 },
14363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 0.0162, 0.0432,  0.8551 }
14463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil};
14563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
14663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuilstatic const double rec709_to_ebu[3][3] = {
14763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 0.9578, 0.0422, 0      },
14863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 0     , 1     , 0      },
14963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 0     , 0.0118, 0.9882 }
15063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil};
15163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
15263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuilstatic const double rec709_to_170m[3][3] = {
15363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{  1.0654, -0.0554, -0.0010 },
15463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ -0.0196,  1.0364, -0.0167 },
15563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{  0.0016,  0.0044,  0.9940 }
15663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil};
15763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
15863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuilstatic const double rec709_to_240m[3][3] = {
15963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 0.7151, 0.2849, 0      },
16063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 0.0179, 0.9821, 0      },
16163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	{ 0.0177, 0.0472, 0.9350 }
16263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil};
16363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
16463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
16563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuilstatic void mult_matrix(double *r, double *g, double *b, const double m[3][3])
16663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil{
16763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	double ir, ig, ib;
16863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
16963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	ir = m[0][0] * (*r) + m[0][1] * (*g) + m[0][2] * (*b);
17063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	ig = m[1][0] * (*r) + m[1][1] * (*g) + m[1][2] * (*b);
17163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	ib = m[2][0] * (*r) + m[2][1] * (*g) + m[2][2] * (*b);
17263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	*r = ir;
17363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	*g = ig;
17463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	*b = ib;
17563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil}
17663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
17763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuilstatic double transfer_srgb_to_rgb(double v)
17863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil{
17963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	return (v <= 0.03928) ? v / 12.92 : pow((v + 0.055) / 1.055, 2.4);
18063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil}
18163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
18263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuilstatic double transfer_rgb_to_smpte240m(double v)
18363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil{
18463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	return (v <= 0.0228) ? v * 4.0 : 1.1115 * pow(v, 0.45) - 0.1115;
18563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil}
18663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
18763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuilstatic double transfer_rgb_to_rec709(double v)
18863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil{
18963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	return (v < 0.018) ? v * 4.5 : 1.099 * pow(v, 0.45) - 0.099;
19063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil}
19163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
19263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuilstatic double transfer_srgb_to_rec709(double v)
19363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil{
19463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	return transfer_rgb_to_rec709(transfer_srgb_to_rgb(v));
19563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil}
19663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
19763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuilstatic void csc(enum v4l2_colorspace colorspace, double *r, double *g, double *b)
19863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil{
19963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	/* Convert the primaries of Rec. 709 Linear RGB */
20063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	switch (colorspace) {
20163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	case V4L2_COLORSPACE_SMPTE240M:
20263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*r = transfer_srgb_to_rgb(*r);
20363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*g = transfer_srgb_to_rgb(*g);
20463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*b = transfer_srgb_to_rgb(*b);
20563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		mult_matrix(r, g, b, rec709_to_240m);
20663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		break;
20763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	case V4L2_COLORSPACE_SMPTE170M:
20863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*r = transfer_srgb_to_rgb(*r);
20963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*g = transfer_srgb_to_rgb(*g);
21063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*b = transfer_srgb_to_rgb(*b);
21163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		mult_matrix(r, g, b, rec709_to_170m);
21263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		break;
21363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	case V4L2_COLORSPACE_470_SYSTEM_BG:
21463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*r = transfer_srgb_to_rgb(*r);
21563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*g = transfer_srgb_to_rgb(*g);
21663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*b = transfer_srgb_to_rgb(*b);
21763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		mult_matrix(r, g, b, rec709_to_ebu);
21863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		break;
21963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	case V4L2_COLORSPACE_470_SYSTEM_M:
22063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*r = transfer_srgb_to_rgb(*r);
22163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*g = transfer_srgb_to_rgb(*g);
22263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*b = transfer_srgb_to_rgb(*b);
22363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		mult_matrix(r, g, b, rec709_to_ntsc1953);
22463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		break;
22563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	case V4L2_COLORSPACE_SRGB:
22663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	case V4L2_COLORSPACE_REC709:
22763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	default:
22863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		break;
22963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	}
23063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
23163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	*r = ((*r) < 0) ? 0 : (((*r) > 1) ? 1 : (*r));
23263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	*g = ((*g) < 0) ? 0 : (((*g) > 1) ? 1 : (*g));
23363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	*b = ((*b) < 0) ? 0 : (((*b) > 1) ? 1 : (*b));
23463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
23563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	/* Encode to gamma corrected colorspace */
23663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	switch (colorspace) {
23763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	case V4L2_COLORSPACE_SMPTE240M:
23863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*r = transfer_rgb_to_smpte240m(*r);
23963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*g = transfer_rgb_to_smpte240m(*g);
24063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*b = transfer_rgb_to_smpte240m(*b);
24163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		break;
24263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	case V4L2_COLORSPACE_SMPTE170M:
24363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	case V4L2_COLORSPACE_470_SYSTEM_M:
24463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	case V4L2_COLORSPACE_470_SYSTEM_BG:
24563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*r = transfer_rgb_to_rec709(*r);
24663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*g = transfer_rgb_to_rec709(*g);
24763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*b = transfer_rgb_to_rec709(*b);
24863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		break;
24963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	case V4L2_COLORSPACE_SRGB:
25063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		break;
25163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	case V4L2_COLORSPACE_REC709:
25263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	default:
25363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*r = transfer_srgb_to_rec709(*r);
25463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*g = transfer_srgb_to_rec709(*g);
25563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		*b = transfer_srgb_to_rec709(*b);
25663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		break;
25763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	}
25863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil}
25963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
26063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuilint main(int argc, char **argv)
26163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil{
26263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	static const unsigned colorspaces[] = {
26363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		0,
26463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		V4L2_COLORSPACE_SMPTE170M,
26563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		V4L2_COLORSPACE_SMPTE240M,
26663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		V4L2_COLORSPACE_REC709,
26763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		0,
26863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		V4L2_COLORSPACE_470_SYSTEM_M,
26963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		V4L2_COLORSPACE_470_SYSTEM_BG,
27063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		0,
27163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		V4L2_COLORSPACE_SRGB,
27263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	};
27363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	static const char * const colorspace_names[] = {
27463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		"",
27563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		"V4L2_COLORSPACE_SMPTE170M",
27663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		"V4L2_COLORSPACE_SMPTE240M",
27763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		"V4L2_COLORSPACE_REC709",
27863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		"",
27963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		"V4L2_COLORSPACE_470_SYSTEM_M",
28063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		"V4L2_COLORSPACE_470_SYSTEM_BG",
28163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		"",
28263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		"V4L2_COLORSPACE_SRGB",
28363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	};
28463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	int i;
28563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	int c;
28663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
28763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	printf("/* Generated table */\n");
28863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	printf("const struct color16 tpg_csc_colors[V4L2_COLORSPACE_SRGB + 1][TPG_COLOR_CSC_BLACK + 1] = {\n");
28963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	for (c = 0; c <= V4L2_COLORSPACE_SRGB; c++) {
29063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		for (i = 0; i <= TPG_COLOR_CSC_BLACK; i++) {
29163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil			double r, g, b;
29263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
29363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil			if (colorspaces[c] == 0)
29463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil				continue;
29563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
29663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil			r = tpg_colors[i].r / 255.0;
29763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil			g = tpg_colors[i].g / 255.0;
29863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil			b = tpg_colors[i].b / 255.0;
29963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
30063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil			csc(c, &r, &g, &b);
30163881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
30263881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil			printf("\t[%s][%d] = { %d, %d, %d },\n", colorspace_names[c], i,
30363881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil				(int)(r * 4080), (int)(g * 4080), (int)(b * 4080));
30463881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil		}
30563881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	}
30663881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	printf("};\n\n");
30763881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil	return 0;
30863881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil}
30963881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil
31063881df94d3ecbb0deafa0b77da62ff2f32961c4Hans Verkuil#endif
311