Changeset 306


Ignore:
Timestamp:
Jan 2, 2004, 7:09:29 PM (16 years ago)
Author:
Sam Hocevar
Message:
  • src/bitmap.c: + Fixed a minor overflow in the saturation computation. + Use a global lookup table for foreground/background colour selection

in the bitmap rendering routine. This broke dithering, sorry.

Location:
libcaca/trunk/src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • libcaca/trunk/src/bitmap.c

    r305 r306  
    5555
    5656/*
     57 * Local variables
     58 */
     59#define LOOKUP_VAL 32
     60#define LOOKUP_SAT 32
     61#define LOOKUP_HUE 16
     62static unsigned char lookup_table[LOOKUP_VAL][LOOKUP_SAT][LOOKUP_HUE];
     63static enum caca_color lookup_colors[8];
     64
     65static int const hsv_palette[] =
     66{
     67    /* hue, saturation, value */
     68    0x0,    0x0,    0x0,   /* black */
     69    0x0,    0x0,    0x5ff, /* 30% */
     70    0x0,    0x0,    0x9ff, /* 70% */
     71    0x0,    0x0,    0xfff, /* white */
     72    0x1000, 0xfff,  0x5ff, /* dark yellow */
     73    0x1000, 0xfff,  0xfff, /* light yellow */
     74    0x0,    0xfff,  0x5ff, /* dark red */
     75    0x0,    0xfff,  0xfff  /* light red */
     76};
     77
     78#define HSV_XRATIO (5*5)
     79#define HSV_YRATIO (3*3)
     80#define HSV_HRATIO (2*2)
     81
     82#define HSV_DISTANCE(h, s, v, index) \
     83    ((HSV_XRATIO * ((v) - hsv_palette[index * 3 + 2]) \
     84                 * ((v) - hsv_palette[index * 3 + 2])) \
     85    + (hsv_palette[index * 3 + 2] \
     86        ? (HSV_YRATIO * ((s) - hsv_palette[index * 3 + 1]) \
     87                      * ((s) - hsv_palette[index * 3 + 1])) \
     88        : 0) \
     89    + (hsv_palette[index * 3 + 1] \
     90        ? (HSV_HRATIO * ((h) - hsv_palette[index * 3 + 0]) \
     91                      * ((h) - hsv_palette[index * 3 + 0])) \
     92        : 0))
     93
     94/*
    5795 * Local prototypes
    5896 */
     
    62100                             unsigned int *, unsigned int *, unsigned int *,
    63101                             unsigned int *);
    64 static void rgb2hsv_default(int, int, int, int *, int *, int *);
     102static inline void rgb2hsv_default(int, int, int, int *, int *, int *);
    65103
    66104/* Dithering methods */
     
    298336}
    299337
    300 static void rgb2hsv_default(int r, int g, int b, int *hue, int *sat, int *val)
     338static inline void rgb2hsv_default(int r, int g, int b,
     339                                   int *hue, int *sat, int *val)
    301340{
    302341    int min, max, delta;
     
    306345    if(min > b) min = b; if(max < b) max = b;
    307346
    308     delta = max - min; /* 0 - 0xffff */
    309     *val = max; /* 0 - 0xffff */
     347    delta = max - min; /* 0 - 0xfff */
     348    *val = max; /* 0 - 0xfff */
    310349
    311350    if(delta)
    312351    {
    313         *sat = 0x1000 * delta / max; /* 0 - 0xfff */
     352        *sat = 0xfff * delta / max; /* 0 - 0xfff */
    314353
    315354        /* Generate *hue between 0 and 0x5fff */
     
    464503        char outch;
    465504
    466         /* Only used by coloured background */
    467         int distbg, distfg, dist, hue1, hue2;
    468 
    469505        r = g = b = a = 0;
    470506
     
    480516            for(myx = fromx; myx <= tox; myx++)
    481517                for(myy = fromy; myy <= toy; myy++)
    482                 {
    483                     dots++;
    484                     get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a);
    485                 }
     518            {
     519                dots++;
     520                get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a);
     521            }
    486522
    487523            /* Normalize */
     
    514550        if(_caca_background == CACA_BACKGROUND_SOLID)
    515551        {
    516 #           define XRATIO 5*5
    517 #           define YRATIO 3*3
    518 #           define HRATIO 2*2
    519 #           define FUZZINESS XRATIO * 0x800
    520 
    521             /* distance to black */
    522             distbg = XRATIO * val * val;
    523             distbg += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
    524             distbg = distbg * 2 / 4;
    525             outbg = CACA_COLOR_BLACK;
    526 
    527             /* distance to 30% */
    528             dist = XRATIO * (val - 0x600) * (val - 0x600)
    529                  + YRATIO * sat * sat;
    530             dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
    531             dist = dist * 3 / 2;
    532             if(dist <= distbg)
     552            unsigned char point;
     553            int distfg, distbg;
     554
     555            lookup_colors[4] = dark_colors[1 + hue / 0x1000];
     556            lookup_colors[5] = light_colors[1 + hue / 0x1000];
     557            lookup_colors[6] = dark_colors[hue / 0x1000];
     558            lookup_colors[7] = light_colors[hue / 0x1000];
     559
     560            point = lookup_table[val * LOOKUP_VAL / 0x1000]
     561                                [sat * LOOKUP_SAT / 0x1000]
     562                                [(hue & 0xfff) * LOOKUP_HUE / 0x1000];
     563
     564try_again:
     565            distfg = HSV_DISTANCE(hue % 0xfff, sat, val, (point >> 4));
     566            distbg = HSV_DISTANCE(hue % 0xfff, sat, val, (point & 0xf));
     567
     568            /* Sanity check due to the lack of precision in lookup_table */
     569#if 0
     570            if(distbg > distfg)
    533571            {
    534                 outfg = outbg;
    535                 distfg = distbg;
    536                 outbg = CACA_COLOR_DARKGRAY;
    537                 distbg = dist;
     572                point = ((point & 0xf) << 4) | (point >> 4);
     573                goto try_again;
    538574            }
    539             else
    540             {
    541                 outfg = CACA_COLOR_DARKGRAY;
    542                 distfg = dist;
    543             }
    544 
    545             /* check dist to 70% */
    546             dist = XRATIO * (val - 0xa00) * (val - 0xa00)
    547                  + YRATIO * sat * sat;
    548             dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
    549             dist = dist * 3 / 2;
    550             if(dist <= distbg)
    551             {
    552                 outfg = outbg;
    553                 distfg = distbg;
    554                 outbg = CACA_COLOR_LIGHTGRAY;
    555                 distbg = dist;
    556             }
    557             else if(dist <= distfg)
    558             {
    559                 outfg = CACA_COLOR_LIGHTGRAY;
    560                 distfg = dist;
    561             }
    562 
    563             /* check dist to white */
    564             dist = XRATIO * (val - 0x1000) * (val - 0x1000)
    565                  + YRATIO * sat * sat;
    566             dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
    567             if(dist <= distbg)
    568             {
    569                 outfg = outbg;
    570                 distfg = distbg;
    571                 outbg = CACA_COLOR_WHITE;
    572                 distbg = dist;
    573             }
    574             else if(dist <= distfg)
    575             {
    576                 outfg = CACA_COLOR_WHITE;
    577                 distfg = dist;
    578             }
    579 
    580             hue1 = (hue + 0x800) & ~0xfff;
    581             if(hue > hue1)
    582                 hue2 = (hue + 0x1800) & ~0xfff;
    583             else
    584                 hue2 = (hue - 0x800) & ~0xfff;
    585 
    586             /* check dist to 2nd closest dark color */
    587             dist = XRATIO * (val - 0x600) * (val - 0x600)
    588                  + YRATIO * (sat - 0x1000) * (sat - 0x1000)
    589                  + HRATIO * (hue - hue2) * (hue - hue2);
    590             dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
    591             //dist = dist * 3 / 4;
    592             if(dist <= distbg)
    593             {
    594                 outfg = outbg;
    595                 distfg = distbg;
    596                 outbg = dark_colors[hue2 / 0x1000];
    597                 distbg = dist;
    598             }
    599             else if(dist <= distfg)
    600             {
    601                 outfg = dark_colors[hue2 / 0x1000];
    602                 distfg = dist;
    603             }
    604 
    605             /* check dist to 2nd closest light color */
    606             dist = XRATIO * (val - 0x1000) * (val - 0x1000)
    607                  + YRATIO * (sat - 0x1000) * (sat - 0x1000)
    608                  + HRATIO * (hue - hue2) * (hue - hue2);
    609             dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
    610             //dist = dist * 3 / 4;
    611             //dist = dist / 2;
    612             if(dist <= distbg)
    613             {
    614                 outfg = outbg;
    615                 distfg = distbg;
    616                 outbg = light_colors[hue2 / 0x1000];
    617                 distbg = dist;
    618             }
    619             else if(dist <= distfg)
    620             {
    621                 outfg = light_colors[hue2 / 0x1000];
    622                 distfg = dist;
    623             }
    624 
    625             /* check dist to closest dark color */
    626             dist = XRATIO * (val - 0x600) * (val - 0x600)
    627                  + YRATIO * (sat - 0x1000) * (sat - 0x1000)
    628                  + HRATIO * (hue - hue1) * (hue - hue1);
    629             dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
    630             dist = dist * 3 / 4;
    631             if(dist <= distbg)
    632             {
    633                 outfg = outbg;
    634                 distfg = distbg;
    635                 outbg = dark_colors[hue1 / 0x1000];
    636                 distbg = dist;
    637             }
    638             else if(dist <= distfg)
    639             {
    640                 outfg = dark_colors[hue1 / 0x1000];
    641                 distfg = dist;
    642             }
    643 
    644             /* check dist to closest light color */
    645             dist = XRATIO * (val - 0x1000) * (val - 0x1000)
    646                  + YRATIO * (sat - 0x1000) * (sat - 0x1000)
    647                  + HRATIO * (hue - hue1) * (hue - hue1);
    648             dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
    649             dist = dist / 2;
    650             if(dist <= distbg)
    651             {
    652                 outfg = outbg;
    653                 distfg = distbg;
    654                 outbg = light_colors[hue1 / 0x1000];
    655                 distbg = dist;
    656             }
    657             else if(dist <= distfg)
    658             {
    659                 outfg = light_colors[hue1 / 0x1000];
    660                 distfg = dist;
    661             }
    662 
    663             if(distbg <= 0) distbg = 1;
    664             if(distfg <= 0) distfg = 1;
    665 
    666             /* distbg can be > distfg because of dithering fuzziness */
    667             ch = distbg * 2 * (DENSITY_CHARS - 1) / (distbg + distfg);
    668             ch = 4 * ch + _get_dither() / 0x40;
    669             outch = density_chars[ch];
     575#endif
     576            if(distbg > distfg)
     577                distbg = distfg;
     578
     579            outfg = lookup_colors[(point >> 4)];
     580            outbg = lookup_colors[(point & 0xf)];
     581
     582            outch = density_chars[4 * (distbg * (DENSITY_CHARS - 1) / distfg)];
    670583        }
    671584        else
     
    691604        _increment_dither();
    692605    }
     606}
     607
     608int _caca_init_bitmap(void)
     609{
     610    unsigned int v, s, h;
     611
     612    /* These ones are constant */
     613    lookup_colors[0] = CACA_COLOR_BLACK;
     614    lookup_colors[1] = CACA_COLOR_DARKGRAY;
     615    lookup_colors[2] = CACA_COLOR_LIGHTGRAY;
     616    lookup_colors[3] = CACA_COLOR_WHITE;
     617
     618    /* These ones will be overwritten */
     619    lookup_colors[4] = CACA_COLOR_MAGENTA;
     620    lookup_colors[5] = CACA_COLOR_LIGHTMAGENTA;
     621    lookup_colors[6] = CACA_COLOR_RED;
     622    lookup_colors[7] = CACA_COLOR_LIGHTRED;
     623
     624    for(v = 0; v < LOOKUP_VAL; v++)
     625        for(s = 0; s < LOOKUP_SAT; s++)
     626            for(h = 0; h < LOOKUP_HUE; h++)
     627    {
     628        int distbg, distfg, dist;
     629        int val, sat, hue;
     630        unsigned char outbg, outfg;
     631
     632        val = 0x1000 * v / LOOKUP_VAL;
     633        sat = 0x1000 * s / LOOKUP_SAT;
     634        hue = 0x1000 * h / LOOKUP_HUE;
     635
     636        /* distance to black */
     637        distbg = HSV_DISTANCE(hue, sat, val, 0);
     638        distbg = distbg * 2 / 4;
     639        outbg = 0;
     640
     641        /* distance to 30% */
     642        dist = HSV_DISTANCE(hue, sat, val, 1);
     643        dist = dist * 3 / 2;
     644        if(dist <= distbg)
     645        {
     646            outfg = outbg;
     647            distfg = distbg;
     648            outbg = 1;
     649            distbg = dist;
     650        }
     651        else
     652        {
     653            outfg = 1;
     654            distfg = dist;
     655        }
     656
     657        /* check dist to 70% */
     658        dist = HSV_DISTANCE(hue, sat, val, 2);
     659        dist = dist * 3 / 2;
     660        if(dist <= distbg)
     661        {
     662            outfg = outbg;
     663            distfg = distbg;
     664            outbg = 2;
     665            distbg = dist;
     666        }
     667        else if(dist <= distfg)
     668        {
     669            outfg = 2;
     670            distfg = dist;
     671        }
     672
     673        /* check dist to white */
     674        dist = HSV_DISTANCE(hue, sat, val, 3);
     675        if(dist <= distbg)
     676        {
     677            outfg = outbg;
     678            distfg = distbg;
     679            outbg = 3;
     680            distbg = dist;
     681        }
     682        else if(dist <= distfg)
     683        {
     684            outfg = 3;
     685            distfg = dist;
     686        }
     687
     688        /* check dist to 2nd closest dark color */
     689        dist = HSV_DISTANCE(hue, sat, val, 4);
     690        //dist = dist * 3 / 4;
     691        dist = dist * 3 / 4;
     692        if(dist <= distbg)
     693        {
     694            outfg = outbg;
     695            distfg = distbg;
     696            outbg = 4;
     697            distbg = dist;
     698        }
     699        else if(dist <= distfg)
     700        {
     701            outfg = 4;
     702            distfg = dist;
     703        }
     704
     705        /* check dist to 2nd closest light color */
     706        dist = HSV_DISTANCE(hue, sat, val, 5);
     707        dist = dist / 2;
     708        //dist = dist * 3 / 4;
     709        //dist = dist / 2;
     710        if(dist <= distbg)
     711        {
     712            outfg = outbg;
     713            distfg = distbg;
     714            outbg = 5;
     715            distbg = dist;
     716        }
     717        else if(dist <= distfg)
     718        {
     719            outfg = 5;
     720            distfg = dist;
     721        }
     722
     723        /* check dist to closest dark color */
     724        dist = HSV_DISTANCE(hue, sat, val, 6);
     725        dist = dist * 3 / 4;
     726        if(dist <= distbg)
     727        {
     728            outfg = outbg;
     729            distfg = distbg;
     730            outbg = 6;
     731            distbg = dist;
     732        }
     733        else if(dist <= distfg)
     734        {
     735            outfg = 6;
     736            distfg = dist;
     737        }
     738
     739        /* check dist to closest light color */
     740        dist = HSV_DISTANCE(hue, sat, val, 7);
     741        dist = dist / 2;
     742        if(dist <= distbg)
     743        {
     744            outfg = outbg;
     745            distfg = distbg;
     746            outbg = 7;
     747            distbg = dist;
     748        }
     749        else if(dist <= distfg)
     750        {
     751            outfg = 7;
     752            distfg = dist;
     753        }
     754
     755        lookup_table[v][s][h] = (outfg << 4) | outbg;
     756    }
     757
     758    return 0;
     759}
     760
     761int _caca_end_bitmap(void)
     762{
     763    return 0;
    693764}
    694765
  • libcaca/trunk/src/caca.c

    r305 r306  
    154154
    155155    if(_caca_init_graphics())
     156        return -1;
     157
     158    if(_caca_init_bitmap())
    156159        return -1;
    157160
     
    320323void caca_end(void)
    321324{
     325    _caca_end_bitmap();
    322326    _caca_end_graphics();
    323327
  • libcaca/trunk/src/caca_internals.h

    r273 r306  
    5454extern int _caca_init_graphics(void);
    5555extern int _caca_end_graphics(void);
     56extern int _caca_init_bitmap(void);
     57extern int _caca_end_bitmap(void);
    5658
    5759/* Cached screen size */
Note: See TracChangeset for help on using the changeset viewer.