2016-11-10 18:42:37 +01:00
|
|
|
/****************************************************************************
|
|
|
|
* apps/graphics/traveler/tools/libwld/wld_rgblookup.c
|
|
|
|
*
|
|
|
|
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
|
|
|
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
*
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
* distribution.
|
|
|
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
|
|
|
* used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
|
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
|
|
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
|
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
|
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Included Files
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#include "wld_mem.h"
|
|
|
|
#include "wld_utils.h"
|
|
|
|
#include "wld_color.h"
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Pre-processor Definitions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#undef MIN
|
|
|
|
#undef MAX
|
|
|
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
|
|
|
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Private Data
|
|
|
|
****************************************************************************/
|
|
|
|
|
2016-11-10 20:08:04 +01:00
|
|
|
#if RGB_CUBE_SIZE >= MIN_LUM_LEVELS
|
2016-11-11 23:54:51 +01:00
|
|
|
static color_rgb_t *g_rgb_lut;
|
2016-11-10 20:08:04 +01:00
|
|
|
static float g_wld_cube2pixel;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Public Data
|
|
|
|
****************************************************************************/
|
|
|
|
|
2016-11-10 18:42:37 +01:00
|
|
|
#if RGB_CUBE_SIZE < MIN_LUM_LEVELS
|
2016-11-11 23:54:51 +01:00
|
|
|
/* Lookup tables */
|
|
|
|
|
|
|
|
color_rgb_t *g_rgb_lut;
|
2016-11-11 14:04:01 +01:00
|
|
|
color_lum_t *g_lum_lut;
|
2016-11-10 20:08:04 +01:00
|
|
|
|
|
|
|
/* The following defines the "form" of each color in the g_unit_vector array */
|
|
|
|
|
|
|
|
const color_form_t g_wld_colorform[NCOLOR_FORMS] =
|
|
|
|
{
|
|
|
|
{1.0, 0.0, 0.0},
|
|
|
|
{0.875, 0.4841229, 0.0},
|
|
|
|
{0.7071068, 0.7071068, 0.0},
|
|
|
|
{0.6666667, 0.5270463, 0.5270463},
|
|
|
|
{0.5773503, 0.5773503, 0.5773503}
|
|
|
|
};
|
2016-11-10 19:21:47 +01:00
|
|
|
|
2016-11-10 18:42:37 +01:00
|
|
|
/* These arrays map color forms into g_unit_vector array indices */
|
|
|
|
|
2016-11-10 20:08:04 +01:00
|
|
|
const enum unit_vector_index_e g_wld_bgrform_map[NCOLOR_FORMS] =
|
2016-11-10 18:42:37 +01:00
|
|
|
{
|
|
|
|
BLUE_NDX, GREENERBLUE_NDX, BLUEGREEN_NDX, LIGHTBLUE_NDX, GREY_NDX
|
|
|
|
};
|
|
|
|
|
2016-11-10 20:08:04 +01:00
|
|
|
const enum unit_vector_index_e g_wld_brgform_map[NCOLOR_FORMS] =
|
2016-11-10 18:42:37 +01:00
|
|
|
{
|
|
|
|
BLUE_NDX, BLUEVIOLET_NDX, VIOLET_NDX, LIGHTBLUE_NDX, GREY_NDX
|
|
|
|
};
|
|
|
|
|
2016-11-10 20:08:04 +01:00
|
|
|
const enum unit_vector_index_e g_wld_gbrform_map[NCOLOR_FORMS] =
|
2016-11-10 18:42:37 +01:00
|
|
|
{
|
|
|
|
GREEN_NDX, BLUERGREN_NDX, BLUEGREEN_NDX, LIGHTGREEN_NDX, GREY_NDX
|
|
|
|
};
|
|
|
|
|
2016-11-10 20:08:04 +01:00
|
|
|
const enum unit_vector_index_e g_wld_grbform_map[NCOLOR_FORMS] =
|
2016-11-10 18:42:37 +01:00
|
|
|
{
|
|
|
|
GREEN_NDX, YELLOWGREEN_NDX, YELLOW_NDX, LIGHTGREEN_NDX, GREY_NDX
|
|
|
|
};
|
|
|
|
|
2016-11-10 20:08:04 +01:00
|
|
|
const enum unit_vector_index_e g_wld_rbgform_map[NCOLOR_FORMS] =
|
2016-11-10 18:42:37 +01:00
|
|
|
{
|
|
|
|
RED_NDX, REDVIOLET_NDX, VIOLET_NDX, PINK_NDX, GREY_NDX
|
|
|
|
};
|
|
|
|
|
2016-11-10 20:08:04 +01:00
|
|
|
const enum unit_vector_index_e g_wld_rgbform_map[NCOLOR_FORMS] =
|
2016-11-10 18:42:37 +01:00
|
|
|
{
|
|
|
|
RED_NDX, ORANGE_NDX, YELLOW_NDX, PINK_NDX, GREY_NDX
|
|
|
|
};
|
|
|
|
|
|
|
|
/* This array defines each color supported in the luminance model */
|
|
|
|
|
|
|
|
const color_lum_t g_unit_vector[NUNIT_VECTORS] =
|
|
|
|
{
|
2016-11-10 19:21:47 +01:00
|
|
|
{0.5773503, 0.5773503, 0.5773503, 441.672932,}, /* GREY_NDX */
|
|
|
|
|
|
|
|
{0.0, 0.0, 1.0, 255.0}, /* BLUE_NDX */
|
|
|
|
{0.0, 0.4841229, 0.875, 291.428571}, /* GREENERBLUE_NDX */
|
|
|
|
{0.0, 0.7071068, 0.7071068, 360.624445}, /* BLUEGREEN_NDX */
|
|
|
|
{0.4841229, 0.0, 0.875, 291.428571}, /* BLUEVIOLET_NDX */
|
|
|
|
{0.7071068, 0.0, 0.7071068, 360.624445}, /* VIOLET_NDX */
|
|
|
|
{0.5270463, 0.5270463, 0.6666667, 382.499981}, /* LIGHTBLUE_NDX */
|
|
|
|
|
|
|
|
{0.0, 1.0, 0.0, 255.0}, /* GREEN_NDX */
|
|
|
|
{0.0, 0.875, 0.4841229, 291.428571}, /* BLUERGREN_NDX */
|
|
|
|
{0.4841229, 0.875, 0.0, 291.428571}, /* YELLOWGREEN_NDX */
|
|
|
|
{0.7071068, 0.7071068, 0.0, 360.624445}, /* YELLOW_NDX */
|
|
|
|
{0.5270463, 0.6666667, 0.5270463, 382.499981}, /* LIGHTGREEN_NDX */
|
|
|
|
|
|
|
|
{1.0, 0.0, 0.0, 255.0}, /* RED_NDX */
|
|
|
|
{0.875, 0.0, 0.4841229, 291.428571}, /* REDVIOLET_NDX */
|
|
|
|
{0.875, 0.4841229, 0.0, 291.428571}, /* ORANGE_NDX */
|
|
|
|
{0.6666667, 0.5270463, 0.5270463, 382.499981}, /* PINK_NDX */
|
2016-11-10 18:42:37 +01:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Public Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: wld_rgblookup_allocate
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
void wld_rgblookup_allocate(void)
|
|
|
|
{
|
|
|
|
#if RGB_CUBE_SIZE < MIN_LUM_LEVELS
|
2016-11-11 14:04:01 +01:00
|
|
|
color_rgb_t *lut;
|
2016-11-10 18:42:37 +01:00
|
|
|
int uvndx;
|
|
|
|
int lumndx;
|
|
|
|
int index;
|
|
|
|
|
|
|
|
/* Check if a color lookup table has been allocated */
|
|
|
|
|
2016-11-11 14:04:01 +01:00
|
|
|
g_rgb_lut = (color_rgb_t *)
|
|
|
|
wld_malloc(sizeof(color_rgb_t) * (NUNIT_VECTORS * NLUMINANCES));
|
2016-11-10 18:42:37 +01:00
|
|
|
|
2016-11-11 14:04:01 +01:00
|
|
|
if (!g_rgb_lut)
|
2016-11-10 18:42:37 +01:00
|
|
|
{
|
|
|
|
wld_fatal_error("ERROR: Failed to allocate color lookup table\n");
|
|
|
|
}
|
|
|
|
|
2016-11-11 14:04:01 +01:00
|
|
|
lut = g_rgb_lut;
|
2016-11-10 18:42:37 +01:00
|
|
|
|
2016-11-10 19:21:47 +01:00
|
|
|
/* Save the color information and color lookup table for use in color mapping
|
|
|
|
* below. */
|
2016-11-10 18:42:37 +01:00
|
|
|
|
2016-11-11 14:04:01 +01:00
|
|
|
g_lum_lut = (color_lum_t *)
|
2016-11-10 19:21:47 +01:00
|
|
|
wld_malloc(sizeof(color_lum_t) * (NUNIT_VECTORS * NLUMINANCES));
|
2016-11-10 18:42:37 +01:00
|
|
|
|
2016-11-11 14:04:01 +01:00
|
|
|
if (!g_lum_lut)
|
2016-11-10 18:42:37 +01:00
|
|
|
{
|
|
|
|
wld_fatal_error("ERROR: Failed to allocate luminance table\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Allocate each color at each luminance value */
|
|
|
|
|
|
|
|
index = 0;
|
|
|
|
for (uvndx = 0; uvndx < NUNIT_VECTORS; uvndx++)
|
|
|
|
{
|
|
|
|
for (lumndx = 0; lumndx < NLUMINANCES; lumndx++)
|
|
|
|
{
|
2016-11-10 19:21:47 +01:00
|
|
|
color_lum_t *lum;
|
2016-11-10 18:42:37 +01:00
|
|
|
|
|
|
|
/* Get a convenience pointer to the lookup table entry */
|
|
|
|
|
2016-11-11 14:04:01 +01:00
|
|
|
lum = &g_lum_lut[index];
|
2016-11-10 18:42:37 +01:00
|
|
|
*lum = g_unit_vector[uvndx];
|
|
|
|
|
2016-11-10 19:21:47 +01:00
|
|
|
/* Get the luminance associated with this lum for this unit vector. */
|
2016-11-10 18:42:37 +01:00
|
|
|
|
|
|
|
lum->luminance = (lum->luminance * (float)(lumndx + 1)) / NLUMINANCES;
|
|
|
|
|
2016-11-11 14:04:01 +01:00
|
|
|
/* Convert to RGB in lookup table */
|
2016-11-10 18:42:37 +01:00
|
|
|
|
2016-11-11 14:04:01 +01:00
|
|
|
lut[index].red = (short)(lum->red * lum->luminance);
|
|
|
|
lut[index].green = (short)(lum->green * lum->luminance);
|
|
|
|
lut[index].blue = (short)(lum->blue * lum->luminance);
|
2016-11-10 18:42:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
2016-11-11 14:04:01 +01:00
|
|
|
color_rgb_t *lut;
|
2016-11-10 18:42:37 +01:00
|
|
|
int index;
|
|
|
|
color_rgb_t rgb;
|
|
|
|
|
|
|
|
/* Check if a color lookup table has been allocated */
|
|
|
|
|
2016-11-11 14:04:01 +01:00
|
|
|
g_rgb_lut = (color_rgb_t *)
|
|
|
|
wld_malloc(sizeof(color_rgb_t) * (WLD_PIXEL_MAX + 1));
|
2016-11-10 18:42:37 +01:00
|
|
|
|
2016-11-11 14:04:01 +01:00
|
|
|
if (!g_rgb_lut)
|
2016-11-10 18:42:37 +01:00
|
|
|
{
|
|
|
|
wld_fatal_error("ERROR: Failed to allocate color lookup table\n");
|
|
|
|
}
|
|
|
|
|
2016-11-10 19:21:47 +01:00
|
|
|
/* Save the color information and color lookup table for use in subsequent
|
|
|
|
* color mapping. */
|
2016-11-10 18:42:37 +01:00
|
|
|
|
2016-11-11 14:04:01 +01:00
|
|
|
lut = g_rgb_lut;
|
2016-11-10 18:42:37 +01:00
|
|
|
|
|
|
|
/* Check if a Pixel-to-RGB color mapping table has been allocated */
|
|
|
|
|
2016-11-11 14:04:01 +01:00
|
|
|
g_rgb_lut = (color_rgb_t *)
|
2016-11-10 19:21:47 +01:00
|
|
|
wld_malloc(sizeof(color_rgb_t) * (WLD_PIXEL_MAX + 1));
|
2016-11-10 18:42:37 +01:00
|
|
|
|
2016-11-11 14:04:01 +01:00
|
|
|
if (!g_rgb_lut)
|
2016-11-10 18:42:37 +01:00
|
|
|
{
|
|
|
|
wld_fatal_error("ERROR: Failed to allocate luminance table\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (index = 0; index <= WLD_PIXEL_MAX; index++)
|
|
|
|
{
|
2016-11-11 14:04:01 +01:00
|
|
|
g_rgb_lut[index].red
|
|
|
|
= g_rgb_lut[index].green = g_rgb_lut[index].blue = 0;
|
2016-11-10 18:42:37 +01:00
|
|
|
}
|
|
|
|
|
2016-11-11 15:43:48 +01:00
|
|
|
/* Calculate the cube to wld_pixel_t scale factor. This factor will convert
|
2016-11-10 19:21:47 +01:00
|
|
|
* an RGB component in the range {0..RGB_CUBE_SIZE-1} to a value in the range
|
|
|
|
* {0..WLD_PIXEL_MAX}. */
|
2016-11-10 18:42:37 +01:00
|
|
|
|
2016-11-10 19:21:47 +01:00
|
|
|
g_wld_cube2pixel = (float)WLD_PIXEL_MAX / (float)(RGB_CUBE_SIZE - 1);
|
2016-11-10 18:42:37 +01:00
|
|
|
|
|
|
|
/* Allocate each color in the RGB Cube */
|
|
|
|
|
2016-11-10 19:21:47 +01:00
|
|
|
for (rgb.red = 0; rgb.red < RGB_CUBE_SIZE; rgb.red++)
|
2016-11-11 14:04:01 +01:00
|
|
|
{
|
|
|
|
for (rgb.green = 0; rgb.green < RGB_CUBE_SIZE; rgb.green++)
|
2016-11-10 18:42:37 +01:00
|
|
|
{
|
2016-11-11 14:04:01 +01:00
|
|
|
for (rgb.blue = 0; rgb.blue < RGB_CUBE_SIZE; rgb.blue++)
|
2016-11-10 19:21:47 +01:00
|
|
|
{
|
2016-11-11 14:04:01 +01:00
|
|
|
/* Save the RGB to pixel lookup data */
|
|
|
|
|
|
|
|
lut[index].red = (short)(rgb.red * 65535 / (RGB_CUBE_SIZE - 1));
|
|
|
|
lut[index].green = (short)(rgb.green * 65535 / (RGB_CUBE_SIZE - 1));
|
|
|
|
lut[index].blue = (short)(rgb.blue * 65535 / (RGB_CUBE_SIZE - 1));
|
2016-11-10 19:21:47 +01:00
|
|
|
}
|
2016-11-10 18:42:37 +01:00
|
|
|
}
|
2016-11-11 14:04:01 +01:00
|
|
|
}
|
2016-11-10 18:42:37 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: wld_color_endmapping
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* When all color mapping has been performed, this function should be
|
|
|
|
* called to release all resources dedicated to color mapping.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
void wld_color_endmapping(void)
|
|
|
|
{
|
|
|
|
#if RGB_CUBE_SIZE < MIN_LUM_LEVELS
|
2016-11-11 14:04:01 +01:00
|
|
|
if (g_lum_lut)
|
2016-11-10 18:42:37 +01:00
|
|
|
{
|
2016-11-11 14:04:01 +01:00
|
|
|
wld_free(g_lum_lut);
|
|
|
|
g_lum_lut = NULL;
|
2016-11-10 18:42:37 +01:00
|
|
|
}
|
|
|
|
#else
|
2016-11-11 14:04:01 +01:00
|
|
|
if (g_rgb_lut)
|
2016-11-10 18:42:37 +01:00
|
|
|
{
|
2016-11-11 14:04:01 +01:00
|
|
|
wld_free(g_rgb_lut);
|
|
|
|
g_rgb_lut = NULL;
|
2016-11-10 18:42:37 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: wld_rgblookup_free
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Free the color lookup table
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
void wld_rgblookup_free(void)
|
|
|
|
{
|
2016-11-11 14:04:01 +01:00
|
|
|
if (g_rgb_lut)
|
2016-11-10 18:42:37 +01:00
|
|
|
{
|
2016-11-11 14:04:01 +01:00
|
|
|
wld_free(g_rgb_lut);
|
|
|
|
g_rgb_lut = NULL;
|
2016-11-10 18:42:37 +01:00
|
|
|
}
|
|
|
|
}
|