LCOV - code coverage report
Current view: top level - monetdb5/modules/atoms - color.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 132 177 74.6 %
Date: 2021-10-13 02:24:04 Functions: 19 22 86.4 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : /*
      10             :  * @f color
      11             :  * @t The color module
      12             :  * @a Alex van Ballegooij
      13             :  * @v 1.0
      14             :  * @* Introduction
      15             :  * The color atom is a simple 32bit (24bit+zeros) encoding of a standard RGB
      16             :  * color encoding, consisting of the red component in bits 16-23,
      17             :  * the green component in bits 8-15, and the blue component in bits 0-7.
      18             :  *
      19             :  * The module contains a number of color conversion methods to construct
      20             :  * colors in various colorspaces and extract relevant color channels.
      21             :  *
      22             :  * @enumerate
      23             :  * @item rgb
      24             :  * = (byte,byte,byte) colorspace r,g,b=[0..255]
      25             :  * @item hsv
      26             :  * = (flt,flt,flt) colorspace h=[0..360], s,v=[0..1]
      27             :  * @item ycc
      28             :  * = (byte,byte,byte) colorspace y,c,c=[0..255]
      29             :  * @end enumerate
      30             :  *
      31             :  */
      32             : 
      33             : #include "monetdb_config.h"
      34             : #include "mal.h"
      35             : #include "mal_exception.h"
      36             : #include "color.h"
      37             : 
      38             : /*
      39             :  * @- Atom commands
      40             :  */
      41             : 
      42             : static int
      43          12 : CLRhextoint(char h, char l)
      44             : {
      45             :         int r = 0;
      46             : 
      47          12 :         if (isdigit((unsigned char) h))
      48           9 :                 r = 16 * (int) (h - '0');
      49           3 :         else if (h >= 'a' && h <= 'f')
      50           2 :                 r = 16 * (int) (10 + h - 'a');
      51           1 :         else if (h >= 'A' && h <= 'F')
      52           1 :                 r = 16 * (int) (10 + h - 'A');
      53             :         else
      54             :                 return -1;
      55          12 :         if (isdigit((unsigned char) l))
      56           8 :                 r += (int) (l - '0');
      57           4 :         else if (l >= 'a' && l <= 'f')
      58           3 :                 r += (int) (10 + l - 'a');
      59           1 :         else if (l >= 'A' && l <= 'F')
      60           1 :                 r += (int) (10 + l - 'A');
      61             :         else
      62             :                 return -1;
      63             :         return r;
      64             : }
      65             : 
      66             : static ssize_t
      67           4 : color_fromstr(const char *colorStr, size_t *len, void **C, bool external)
      68             : {
      69             :         color **c = (color **) C;
      70             :         const char *p = colorStr;
      71             : 
      72           4 :         if (*len < sizeof(color) || *c == NULL) {
      73           0 :                 GDKfree(*c);
      74           0 :                 *c = GDKmalloc(sizeof(color));
      75           0 :                 if( *c == NULL)
      76             :                         return -1;
      77           0 :                 *len = sizeof(color);
      78             :         }
      79             : 
      80           4 :         if (strNil(colorStr)) {
      81           0 :                 **c = color_nil;
      82           0 :                 return 1;
      83             :         }
      84             : 
      85           4 :         while (GDKisspace(*p))
      86           0 :                 p++;
      87           4 :         if (external && strncmp(p, "nil", 3) == 0) {
      88           0 :                 **c = color_nil;
      89           0 :                 p += 3;
      90           4 :         } else if (strncmp(p, "0x00", 4) == 0) {
      91             :                 int r, g, b;
      92             : 
      93           4 :                 if ((r = CLRhextoint(p[4], p[5])) == -1 ||
      94           4 :                         (g = CLRhextoint(p[6], p[7])) == -1 ||
      95           4 :                         (b = CLRhextoint(p[8], p[9])) == -1) {
      96           0 :                         **c = color_nil;
      97           0 :                         return 0;
      98             :                 }
      99           4 :                 **c = (color) (r << 16 | g << 8 | b);
     100           4 :                 p += 10;
     101             :         } else {
     102           0 :                 **c = color_nil;
     103           0 :                 GDKerror("not a color\n");
     104           0 :                 return -1;
     105             :         }
     106           4 :         return (ssize_t) (p - colorStr);
     107             : }
     108             : 
     109             : static ssize_t
     110           8 : color_tostr(char **colorStr, size_t *len, const void *c, bool external)
     111             : {
     112           8 :         color sc = *(color*)c;
     113             : 
     114             :         /* allocate and fill a new string */
     115             : 
     116           8 :         if (*len < 11 || *colorStr == NULL) {
     117           5 :                 GDKfree(*colorStr);
     118           5 :                 *colorStr = GDKmalloc(11);
     119           5 :                 if( *colorStr == NULL)
     120             :                         return -1;
     121           5 :                 *len = 11;
     122             :         }
     123             : 
     124           8 :         if (is_color_nil(sc)) {
     125           0 :                 if (external) {
     126           0 :                         strcpy(*colorStr, "nil");
     127           0 :                         return 3;
     128             :                 }
     129           0 :                 strcpy(*colorStr, str_nil);
     130           0 :                 return 1;
     131             :         }
     132           8 :         snprintf(*colorStr, *len, "0x%08X", (unsigned int) sc);
     133             : 
     134           8 :         return (ssize_t) strlen(*colorStr);
     135             : }
     136             : 
     137             : str
     138           5 : CLRstr(str *s, const color *c)
     139             : {
     140           5 :         size_t len = 0;
     141           5 :         str t = 0;
     142             : 
     143           5 :         if (color_tostr(&t, &len, c, false) < 0)
     144           0 :                 throw(MAL, "color.str", GDK_EXCEPTION);
     145           5 :         *s = t;
     146           5 :         return MAL_SUCCEED;
     147             : }
     148             : 
     149             : str
     150           1 : CLRrgb(color *rgb, const int *r, const int *g, const int *b)
     151             : {
     152           4 :         *rgb = (color) (((*r & 0xFF) << 16) | ((*g & 0xFF) << 8) | (*b & 0xFF));
     153           1 :         return (MAL_SUCCEED);
     154             : }
     155             : 
     156             : str
     157           5 : CLRred(int *r, const color *c)
     158             : {
     159           5 :         *r = (int) ((*c >> 16) & 0xFF);
     160           5 :         return (MAL_SUCCEED);
     161             : }
     162             : 
     163             : str
     164           2 : CLRgreen(int *g, const color *c)
     165             : {
     166           2 :         *g = (int) ((*c >> 8) & 0xFF);
     167           2 :         return (MAL_SUCCEED);
     168             : }
     169             : 
     170             : str
     171           2 : CLRblue(int *b, const color *c)
     172             : {
     173           2 :         *b = (int) (*c & 0xFF);
     174           2 :         return (MAL_SUCCEED);
     175             : }
     176             : 
     177             : #define max2(a,b) ((a)>(b)?(a):(b))
     178             : #define max3(a,b,c) max2(max2(a,b),(c))
     179             : 
     180             : #define min2(a,b) ((a)<(b)?(a):(b))
     181             : #define min3(a,b,c) min2(min2(a,b),(c))
     182             : 
     183             : #define EPS 0.001f
     184             : 
     185             : static void
     186           3 : color_rgb2hsv(float *h, float *s, float *v, int R, int G, int B)
     187             : {
     188             :         register float H, S, V, max;
     189           3 :         register float Rtmp = ((float) (R)) / 255.0f;
     190           3 :         register float Gtmp = ((float) (G)) / 255.0f;
     191           3 :         register float Btmp = ((float) (B)) / 255.0f;
     192             : 
     193           6 :         max = max3(Rtmp, Gtmp, Btmp);
     194             :         V = max;
     195           3 :         if (fabs(max) <= EPS) {
     196             :                 S = 0;
     197             :                 H = 0;
     198             :         } else {
     199             :                 register float min, delta;
     200             : 
     201           3 :                 min = min3(Rtmp, Gtmp, Btmp);
     202           3 :                 delta = max - min;
     203           3 :                 S = delta / max;
     204           3 :                 if (Rtmp == max)
     205           0 :                         H = (Gtmp - Btmp) / delta;
     206           3 :                 else if (Gtmp == max)
     207           3 :                         H = 2 + (Btmp - Rtmp) / delta;
     208             :                 else            /* Btmp == max */
     209           0 :                         H = 4 + (Rtmp - Gtmp) / delta;
     210           3 :                 H *= 60;
     211           3 :                 if (H < 0)
     212           0 :                         H += 360;
     213             :         }
     214           3 :         *h = H;
     215           3 :         *s = S;
     216           3 :         *v = V;
     217           3 : }
     218             : 
     219             : str
     220           2 : CLRhsv(color *c, const flt *h, const flt *s, const flt *v)
     221             : {
     222             :         int r, g, b;
     223             :         float Rtmp, Gtmp, Btmp;
     224             : 
     225           2 :         if (fabs(*s) <= EPS) {
     226           0 :                 Rtmp = Gtmp = Btmp = (*v);
     227             :         } else {
     228           2 :                 float Htmp = (*h) / 60;
     229           2 :                 float f = Htmp - ((int) Htmp);
     230           2 :                 float p = (*v) * (1 - (*s));
     231           2 :                 float q = (*v) * (1 - (*s) * f);
     232           2 :                 float t = (*v) * (1 - (*s) * (1 - f));
     233             : 
     234           2 :                 switch ((int) floor(Htmp)) {
     235             :                 case 0:
     236             :                         Rtmp = *v;
     237             :                         Gtmp = t;
     238             :                         Btmp = p;
     239             :                         break;
     240           2 :                 case 1:
     241             :                         Rtmp = q;
     242             :                         Gtmp = *v;
     243             :                         Btmp = p;
     244           2 :                         break;
     245           0 :                 case 2:
     246             :                         Rtmp = p;
     247             :                         Gtmp = *v;
     248             :                         Btmp = t;
     249           0 :                         break;
     250           0 :                 case 3:
     251             :                         Rtmp = p;
     252             :                         Gtmp = q;
     253             :                         Btmp = *v;
     254           0 :                         break;
     255           0 :                 case 4:
     256             :                         Rtmp = t;
     257             :                         Gtmp = p;
     258             :                         Btmp = *v;
     259           0 :                         break;
     260           0 :                 default:        /* case 5: */
     261             :                         Rtmp = *v;
     262             :                         Gtmp = p;
     263             :                         Btmp = q;
     264           0 :                         break;
     265             :                 }
     266             :         }
     267           2 :         r = (int) ((Rtmp * 255.0f) + 0.5f);
     268           2 :         g = (int) ((Gtmp * 255.0f) + 0.5f);
     269           2 :         b = (int) ((Btmp * 255.0f) + 0.5f);
     270           2 :         return CLRrgb(c, &r, &g, &b);
     271             : }
     272             : 
     273             : str
     274           1 : CLRhue(flt *f, const color *c)
     275             : {
     276             :         float h, s, v;
     277             : 
     278           1 :         color_rgb2hsv(&h, &s, &v, (*c >> 16) & 0xFF, (*c >> 8) & 0xFF, (*c) & 0xFF);
     279           1 :         *f = h;
     280           1 :         return (MAL_SUCCEED);
     281             : }
     282             : 
     283             : str
     284           0 : CLRhueInt(int *f, const color *c)
     285             : {
     286             :         float h, s, v;
     287             : 
     288           0 :         color_rgb2hsv(&h, &s, &v, (*c >> 16) & 0xFF, (*c >> 8) & 0xFF, (*c) & 0xFF);
     289           0 :         *f = (int) h;
     290           0 :         return (MAL_SUCCEED);
     291             : }
     292             : 
     293             : str
     294           1 : CLRsaturation(flt *f, const color *c)
     295             : {
     296             :         float h, s, v;
     297             : 
     298           1 :         color_rgb2hsv(&h, &s, &v, (*c >> 16) & 0xFF, (*c >> 8) & 0xFF, (*c) & 0xFF);
     299           1 :         *f = s;
     300           1 :         return (MAL_SUCCEED);
     301             : }
     302             : 
     303             : str
     304           0 : CLRsaturationInt(int *f, const color *c)
     305             : {
     306             :         float h, s, v;
     307             : 
     308           0 :         color_rgb2hsv(&h, &s, &v, (*c >> 16) & 0xFF, (*c >> 8) & 0xFF, (*c) & 0xFF);
     309           0 :         *f = (int) s;
     310           0 :         return (MAL_SUCCEED);
     311             : }
     312             : 
     313             : str
     314           1 : CLRvalue(flt *f, const color *c)
     315             : {
     316             :         float h, s, v;
     317             : 
     318           1 :         color_rgb2hsv(&h, &s, &v, (*c >> 16) & 0xFF, (*c >> 8) & 0xFF, (*c) & 0xFF);
     319           1 :         *f = v;
     320           1 :         return (MAL_SUCCEED);
     321             : }
     322             : 
     323             : str
     324           0 : CLRvalueInt(int *f, const color *c)
     325             : {
     326             :         float h, s, v;
     327             : 
     328           0 :         color_rgb2hsv(&h, &s, &v, (*c >> 16) & 0xFF, (*c >> 8) & 0xFF, (*c) & 0xFF);
     329           0 :         *f = (int) v;
     330           0 :         return (MAL_SUCCEED);
     331             : }
     332             : 
     333             : 
     334             : #ifndef CLIP
     335             : #define CLIP(X)     ((unsigned char)(((X)&~0xFF)?(((X)<0x00)?0x00:0xFF):(X)))
     336             : #endif
     337             : 
     338             : str
     339           1 : CLRycc(color *c, const int *y, const int *cr, const int *cb)
     340             : {
     341             :         int r, g, b;
     342           1 :         float Y = (float) *y;
     343           1 :         float CR = (float) (*cr - 128);
     344           1 :         float CB = (float) (*cb - 128);
     345             : 
     346           1 :         r = (int) (Y + CR * 1.4022f);
     347           1 :         r = CLIP(r);
     348           1 :         g = (int) (Y - CB * 0.3456f - CR * 0.7145f);
     349           1 :         g = CLIP(g);
     350           1 :         b = (int) (Y + CB * 1.7710f);
     351           1 :         b = CLIP(b);
     352           1 :         return CLRrgb(c, &r, &g, &b);
     353             : }
     354             : 
     355             : str
     356           1 : CLRluminance(int *y, const color *c)
     357             : {
     358           1 :         int r = (int) ((*c >> 16) & 0xFF);
     359           1 :         int g = (int) ((*c >> 8) & 0xFF);
     360           1 :         int b = (int) (*c & 0xFF);
     361             : 
     362           1 :         *y = (int) (0.2989f * (float) (r) + 0.5866f * (float) (g) + 0.1145f * (float) (b));
     363           1 :         *y = CLIP(*y);
     364           1 :         return (MAL_SUCCEED);
     365             : }
     366             : 
     367             : str
     368           1 : CLRcr(int *cr, const color *c)
     369             : {
     370           1 :         int r = (int) ((*c >> 16) & 0xFF);
     371           1 :         int g = (int) ((*c >> 8) & 0xFF);
     372           1 :         int b = (int) (*c & 0xFF);
     373             : 
     374           1 :         *cr = (int) (0.5000f * (float) (r) - 0.4183f * (float) (g) - 0.0816f * (float) (b)) + 128;
     375           1 :         return (MAL_SUCCEED);
     376             : }
     377             : 
     378             : str
     379           1 : CLRcb(int *cb, const color *c)
     380             : {
     381           1 :         int r = (int) ((*c >> 16) & 0xFF);
     382           1 :         int g = (int) ((*c >> 8) & 0xFF);
     383           1 :         int b = (int) (*c & 0xFF);
     384             : 
     385           1 :         *cb = (int) (-0.1687f * (float) (r) - 0.3312f * (float) (g) + 0.5000f * (float) (b)) + 128;
     386           1 :         return (MAL_SUCCEED);
     387             : }
     388             : 
     389             : str
     390           1 : CLRcolor(color *c, const char **val)
     391             : {
     392           1 :         size_t len = sizeof(color);
     393             : 
     394           1 :         if (color_fromstr(*val, &len, (void**)&c, false) < 0)
     395           0 :                 throw(MAL, "color.color", GDK_EXCEPTION);
     396             :         return MAL_SUCCEED;
     397             : }
     398             : 
     399             : #include "mel.h"
     400             : mel_atom color_init_atoms[] = {
     401             :  { .name="color", .basetype="int", .size=sizeof(color), .tostr=color_tostr, .fromstr=color_fromstr, },  { .cmp=NULL }
     402             : };
     403             : mel_func color_init_funcs[] = {
     404             :  command("color", "str", CLRstr, false, "Converts color to string ", args(1,2, arg("",str),arg("s",color))),
     405             :  command("color", "color", CLRcolor, false, "Converts string to color", args(1,2, arg("",color),arg("s",str))),
     406             :  command("color", "rgb", CLRrgb, false, "Converts an RGB triplets to a color atom", args(1,4, arg("",color),arg("r",int),arg("g",int),arg("b",int))),
     407             :  command("color", "red", CLRred, false, "Extracts red component from a color atom", args(1,2, arg("",int),arg("c",color))),
     408             :  command("color", "green", CLRgreen, false, "Extracts green component from a color atom", args(1,2, arg("",int),arg("c",color))),
     409             :  command("color", "blue", CLRblue, false, "Extracts blue component from a color atom", args(1,2, arg("",int),arg("c",color))),
     410             :  command("color", "hue", CLRhueInt, false, "Extracts hue component from a color atom", args(1,2, arg("",int),arg("c",color))),
     411             :  command("color", "saturation", CLRsaturationInt, false, "Extracts saturation component from a color atom", args(1,2, arg("",int),arg("c",color))),
     412             :  command("color", "value", CLRvalueInt, false, "Extracts value component from a color atom", args(1,2, arg("",int),arg("c",color))),
     413             :  command("color", "hsv", CLRhsv, false, "Converts an HSV triplets to a color atom", args(1,4, arg("",color),arg("h",flt),arg("s",flt),arg("v",flt))),
     414             :  command("color", "hue", CLRhue, false, "Extracts hue component from a color atom", args(1,2, arg("",flt),arg("c",color))),
     415             :  command("color", "saturation", CLRsaturation, false, "Extracts saturation component from a color atom", args(1,2, arg("",flt),arg("c",color))),
     416             :  command("color", "value", CLRvalue, false, "Extracts value component from a color atom", args(1,2, arg("",flt),arg("c",color))),
     417             :  command("color", "ycc", CLRycc, false, "Converts an YCC triplets to a color atom", args(1,4, arg("",color),arg("y",int),arg("cr",int),arg("cb",int))),
     418             :  command("color", "luminance", CLRluminance, false, "Extracts Y(luminance) component from a color atom", args(1,2, arg("",int),arg("c",color))),
     419             :  command("color", "cr", CLRcr, false, "Extracts Cr(red color) component from a color atom", args(1,2, arg("",int),arg("c",color))),
     420             :  command("color", "cb", CLRcb, false, "Extracts Cb(blue color) component from a color atom", args(1,2, arg("",int),arg("c",color))),
     421             :  { .imp=NULL }
     422             : };
     423             : #include "mal_import.h"
     424             : #ifdef _MSC_VER
     425             : #undef read
     426             : #pragma section(".CRT$XCU",read)
     427             : #endif
     428         259 : LIB_STARTUP_FUNC(init_color_mal)
     429         259 : { mal_module("color", color_init_atoms, color_init_funcs); }

Generated by: LCOV version 1.14