1/* 2 * Copyright 2001-2006, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * DarkWyrm <bpmagic@columbus.rr.com> 7 * Stefano Ceccherini (burton666@libero.it) 8 */ 9 10//! Methods to initialize and get the system color_map. 11 12 13#include "SystemPalette.h" 14 15#include <stdio.h> 16#include <string.h> 17 18#include <Palette.h> 19 20// TODO: BWindowScreen has a method to set the palette. 21// maybe we should have a lock to protect this variable. 22static color_map sColorMap; 23 24 25// color_distance 26/*! \brief Returns the "distance" between two RGB colors. 27 28 This functions defines an metric on the RGB color space. The distance 29 between two colors is 0, if and only if the colors are equal. 30 31 \param red1 Red component of the first color. 32 \param green1 Green component of the first color. 33 \param blue1 Blue component of the first color. 34 \param red2 Red component of the second color. 35 \param green2 Green component of the second color. 36 \param blue2 Blue component of the second color. 37 \return The distance between the given colors. 38*/ 39static inline uint32 40color_distance(uint8 red1, uint8 green1, uint8 blue1, 41 uint8 red2, uint8 green2, uint8 blue2) 42{ 43 int rd = (int)red1 - (int)red2; 44 int gd = (int)green1 - (int)green2; 45 int bd = (int)blue1 - (int)blue2; 46 47 // distance according to psycho-visual tests 48 // algorithm taken from here: 49 // http://www.stud.uni-hannover.de/~michaelt/juggle/Algorithms.pdf 50 int rmean = ((int)red1 + (int)red2) / 2; 51 return (((512 + rmean) * rd * rd) >> 8) 52 + 4 * gd * gd 53 + (((767 - rmean) * bd * bd) >> 8); 54} 55 56 57static inline uint8 58FindClosestColor(const rgb_color &color, const rgb_color *palette) 59{ 60 uint8 closestIndex = 0; 61 unsigned closestDistance = UINT_MAX; 62 for (int32 i = 0; i < 256; i++) { 63 const rgb_color &c = palette[i]; 64 unsigned distance = color_distance(color.red, color.green, color.blue, 65 c.red, c.green, c.blue); 66 if (distance < closestDistance) { 67 closestIndex = (uint8)i; 68 closestDistance = distance; 69 } 70 } 71 return closestIndex; 72} 73 74 75static inline rgb_color 76InvertColor(const rgb_color &color) 77{ 78 // For some reason, Inverting (255, 255, 255) on beos 79 // results in the same color. 80 if (color.red == 255 && color.green == 255 81 && color.blue == 255) 82 return color; 83 84 rgb_color inverted; 85 inverted.red = 255 - color.red; 86 inverted.green = 255 - color.green; 87 inverted.blue = 255 - color.blue; 88 inverted.alpha = 255; 89 90 return inverted; 91} 92 93 94static void 95FillColorMap(const rgb_color *palette, color_map *map) 96{ 97 memcpy((void*)map->color_list, palette, sizeof(map->color_list)); 98 99 // init index map 100 for (int32 color = 0; color < 32768; color++) { 101 // get components 102 rgb_color rgbColor; 103 rgbColor.red = (color & 0x7c00) >> 7; 104 rgbColor.green = (color & 0x3e0) >> 2; 105 rgbColor.blue = (color & 0x1f) << 3; 106 107 map->index_map[color] = FindClosestColor(rgbColor, palette); 108 } 109 110 // init inversion map 111 for (int32 index = 0; index < 256; index++) { 112 rgb_color inverted = InvertColor(map->color_list[index]); 113 map->inversion_map[index] = FindClosestColor(inverted, palette); 114 } 115} 116 117 118/*! \brief Initializes the system color_map. 119*/ 120void 121InitializeColorMap() 122{ 123 FillColorMap(kSystemPalette, &sColorMap); 124} 125 126 127/*! \brief Returns a pointer to the system palette. 128 \return A pointer to the system palette. 129*/ 130const rgb_color * 131SystemPalette() 132{ 133 return sColorMap.color_list; 134} 135 136 137/*! \brief Returns a pointer to the system color_map structure. 138 \return A pointer to the system color_map. 139*/ 140const color_map * 141SystemColorMap() 142{ 143 return &sColorMap; 144} 145