Ignore:
Timestamp:
Dec 12, 2003, 3:49:41 PM (19 years ago)
Author:
Sam Hocevar
Message:
  • src/bitmap.c: + Added antialiasing support. + Dithering, antialiasing and background mode can now be selected at

runtime.

  • src/caca.c src/caca.h: + Renamed caca_dithering into caca_feature and extended the type to

express background colour and antialiasing mode.

  • examples/demo.c: + Fixed a bug that disabled the sprite demo. + Draw solid flares.
  • examples/view.c: + Select antialiasing and background mode at runtime.
File:
1 edited

Legend:

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

    r247 r249  
    4747#include "caca_internals.h"
    4848
    49 #define NEW_RENDERER 1
    50 
     49/*
     50 * Global variables
     51 */
     52enum caca_feature _caca_background;
     53enum caca_feature _caca_dithering;
     54enum caca_feature _caca_antialiasing;
     55
     56/*
     57 * Local prototypes
     58 */
    5159static void mask2shift(unsigned int, int *, int *);
    5260
     
    7684static unsigned int get_random_dither(void);
    7785static void increment_random_dither(void);
    78 
    79 /* Current dithering method */
    80 static enum caca_dithering _caca_dithering = CACA_DITHERING_NONE;
    81 
    82 static void (*_init_dither) (int) = init_no_dither;
    83 static unsigned int (*_get_dither) (void) = get_no_dither;
    84 static void (*_increment_dither) (void) = increment_no_dither;
    85 
    86 void caca_set_dithering(enum caca_dithering dither)
    87 {
    88     switch(dither)
    89     {
    90     case CACA_DITHERING_NONE:
    91         _init_dither = init_no_dither;
    92         _get_dither = get_no_dither;
    93         _increment_dither = increment_no_dither;
    94         break;
    95 
    96     case CACA_DITHERING_ORDERED2:
    97         _init_dither = init_ordered2_dither;
    98         _get_dither = get_ordered2_dither;
    99         _increment_dither = increment_ordered2_dither;
    100         break;
    101 
    102     case CACA_DITHERING_ORDERED4:
    103         _init_dither = init_ordered4_dither;
    104         _get_dither = get_ordered4_dither;
    105         _increment_dither = increment_ordered4_dither;
    106         break;
    107 
    108     case CACA_DITHERING_ORDERED8:
    109         _init_dither = init_ordered8_dither;
    110         _get_dither = get_ordered8_dither;
    111         _increment_dither = increment_ordered8_dither;
    112         break;
    113 
    114     case CACA_DITHERING_RANDOM:
    115         _init_dither = init_random_dither;
    116         _get_dither = get_random_dither;
    117         _increment_dither = increment_random_dither;
    118         break;
    119 
    120     default:
    121         return;
    122     }
    123 
    124     _caca_dithering = dither;
    125 }
    12686
    12787struct caca_bitmap
     
    288248    if(bitmap->palette)
    289249    {
    290         *r = bitmap->red[bits];
    291         *g = bitmap->green[bits];
    292         *b = bitmap->blue[bits];
    293         *a = bitmap->alpha[bits];
     250        *r += bitmap->red[bits];
     251        *g += bitmap->green[bits];
     252        *b += bitmap->blue[bits];
     253        *a += bitmap->alpha[bits];
    294254    }
    295255    else
    296256    {
    297         *r = ((bits & bitmap->rmask) >> bitmap->rright) << bitmap->rleft;
    298         *g = ((bits & bitmap->gmask) >> bitmap->gright) << bitmap->gleft;
    299         *b = ((bits & bitmap->bmask) >> bitmap->bright) << bitmap->bleft;
    300         *a = ((bits & bitmap->amask) >> bitmap->aright) << bitmap->aleft;
     257        *r += ((bits & bitmap->rmask) >> bitmap->rright) << bitmap->rleft;
     258        *g += ((bits & bitmap->gmask) >> bitmap->gright) << bitmap->gleft;
     259        *b += ((bits & bitmap->bmask) >> bitmap->bright) << bitmap->bleft;
     260        *a += ((bits & bitmap->amask) >> bitmap->aright) << bitmap->aleft;
    301261    }
    302262}
     
    335295                      const struct caca_bitmap *bitmap, void *pixels)
    336296{
    337 #if !NEW_RENDERER
     297    /* Current dithering method */
     298    void (*_init_dither) (int);
     299    unsigned int (*_get_dither) (void);
     300    void (*_increment_dither) (void);
     301
     302    /* Only used when background is black */
    338303    static const int white_colors[] =
    339304    {
     
    343308        CACA_COLOR_WHITE
    344309    };
    345 #endif
    346310
    347311    static const int light_colors[] =
     
    404368    }
    405369
     370    switch(_caca_dithering)
     371    {
     372    case CACA_DITHERING_NONE:
     373        _init_dither = init_no_dither;
     374        _get_dither = get_no_dither;
     375        _increment_dither = increment_no_dither;
     376        break;
     377
     378    case CACA_DITHERING_ORDERED2:
     379        _init_dither = init_ordered2_dither;
     380        _get_dither = get_ordered2_dither;
     381        _increment_dither = increment_ordered2_dither;
     382        break;
     383
     384    case CACA_DITHERING_ORDERED4:
     385        _init_dither = init_ordered4_dither;
     386        _get_dither = get_ordered4_dither;
     387        _increment_dither = increment_ordered4_dither;
     388        break;
     389
     390    case CACA_DITHERING_ORDERED8:
     391        _init_dither = init_ordered8_dither;
     392        _get_dither = get_ordered8_dither;
     393        _increment_dither = increment_ordered8_dither;
     394        break;
     395
     396    case CACA_DITHERING_RANDOM:
     397        _init_dither = init_random_dither;
     398        _get_dither = get_random_dither;
     399        _increment_dither = increment_random_dither;
     400        break;
     401
     402    default:
     403        /* Something wicked happened! */
     404        return;
     405    }
     406
    406407    for(y = y1 > 0 ? y1 : 0; y <= y2 && y <= (int)_caca_height; y++)
    407408        for(x = x1 > 0 ? x1 : 0, _init_dither(y);
     
    410411    {
    411412        int ch;
    412         unsigned int r, g, b, a, R, G, B;
     413        unsigned int r, g, b, a;
    413414        int hue, sat, val;
    414         int fromx = w * (x - x1) / (x2 - x1 + 1);
    415         int fromy = h * (y - y1) / (y2 - y1 + 1);
     415        int fromx, fromy, tox, toy, myx, myy, dots;
    416416        enum caca_color outfg, outbg;
    417417        char outch;
    418 #if NEW_RENDERER
     418
     419        /* Only used by coloured background */
    419420        int distbg, distfg, dist, hue1, hue2;
    420 #endif
    421 
    422         /* Clip values (yuck) */
    423         if(fromx == 0) fromx = 1;
    424         if(fromy == 0) fromy = 1;
     421
     422        r = g = b = a = 0;
    425423
    426424        /* First get RGB */
    427         R = 0, G = 0, B = 0;
    428         get_rgba_default(bitmap, pixels, fromx, fromy, &r, &g, &b, &a);
    429         if(a == 0)
    430             continue;
    431 #if 1
    432         R += r; G += g; B += b;
    433 #else
    434         R += r; G += g; B += b;
    435         get_rgba_default(bitmap, pixels, fromx - 1, fromy, &r, &g, &b, &a);
    436         R += r; G += g; B += b;
    437         get_rgba_default(bitmap, pixels, fromx, fromy - 1, &r, &g, &b, &a);
    438         R += r; G += g; B += b;
    439         get_rgba_default(bitmap, pixels, fromx + 1, fromy, &r, &g, &b, &a);
    440         R += r; G += g; B += b;
    441         get_rgba_default(bitmap, pixels, fromx, fromy + 1, &r, &g, &b, &a);
    442         R += r; G += g; B += b;
    443         R /= 5; G /= 5; B /= 5;
    444 #endif
    445 
    446         /* Now get HSV from RGB */
    447         rgb2hsv_default(R, G, B, &hue, &sat, &val);
    448 
    449         /* The hard work: calculate foreground and background colours,
    450          * as well as the most appropriate character to output. */
    451 #if NEW_RENDERER
    452 #       define XRATIO 5*5
    453 #       define YRATIO 3*3
    454 #       define HRATIO 2*2
    455 #       define FUZZINESS XRATIO * 0x800
    456 
    457         /* distance to black */
    458         distbg = XRATIO * val * val;
    459         distbg += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
    460         distbg = distbg * 2 / 4;
    461         outbg = CACA_COLOR_BLACK;
    462 
    463         /* distance to 30% */
    464         dist = XRATIO * (val - 0x600) * (val - 0x600)
    465              + YRATIO * sat * sat;
    466         dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
    467         dist = dist * 3 / 2;
    468         if(dist <= distbg)
     425        if(_caca_antialiasing == CACA_ANTIALIASING_PREFILTER)
    469426        {
    470             outfg = outbg;
    471             distfg = distbg;
    472             outbg = CACA_COLOR_DARKGRAY;
    473             distbg = dist;
     427            fromx = ((x - x1) * (w - 1)) / (x2 - x1 + 1);
     428            fromy = ((y - y1) * (h - 1)) / (y2 - y1 + 1);
     429            tox = ((x - x1 + 1) * (w - 1)) / (x2 - x1 + 1);
     430            toy = ((y - y1 + 1) * (h - 1)) / (y2 - y1 + 1);
     431            dots = 0;
     432
     433            for(myx = fromx; myx <= tox; myx++)
     434                for(myy = fromy; myy <= toy; myy++)
     435                {
     436                    dots++;
     437                    get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a);
     438                }
     439
     440            /* Normalize */
     441            r /= dots;
     442            g /= dots;
     443            b /= dots;
     444            a /= dots;
    474445        }
    475446        else
    476447        {
    477             outfg = CACA_COLOR_DARKGRAY;
    478             distfg = dist;
     448            fromx = ((x - x1) * (w - 1)) / (x2 - x1 + 1);
     449            fromy = ((y - y1) * (h - 1)) / (y2 - y1 + 1);
     450            tox = ((x - x1 + 1) * (w - 1)) / (x2 - x1 + 1);
     451            toy = ((y - y1 + 1) * (h - 1)) / (y2 - y1 + 1);
     452
     453            myx = (fromx + tox) / 2;
     454            myy = (fromy + toy) / 2;
     455
     456            get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a);
    479457        }
    480458
    481         /* check dist to 70% */
    482         dist = XRATIO * (val - 0xa00) * (val - 0xa00)
    483              + YRATIO * sat * sat;
    484         dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
    485         dist = dist * 3 / 2;
    486         if(dist <= distbg)
     459        if(a < 0x100)
     460            continue;
     461
     462        /* Now get HSV from RGB */
     463        rgb2hsv_default(r, g, b, &hue, &sat, &val);
     464
     465        /* The hard work: calculate foreground and background colours,
     466         * as well as the most appropriate character to output. */
     467        if(_caca_background == CACA_BACKGROUND_SOLID)
    487468        {
    488             outfg = outbg;
    489             distfg = distbg;
    490             outbg = CACA_COLOR_LIGHTGRAY;
    491             distbg = dist;
     469#           define XRATIO 5*5
     470#           define YRATIO 3*3
     471#           define HRATIO 2*2
     472#           define FUZZINESS XRATIO * 0x800
     473
     474            /* distance to black */
     475            distbg = XRATIO * val * val;
     476            distbg += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
     477            distbg = distbg * 2 / 4;
     478            outbg = CACA_COLOR_BLACK;
     479
     480            /* distance to 30% */
     481            dist = XRATIO * (val - 0x600) * (val - 0x600)
     482                 + YRATIO * sat * sat;
     483            dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
     484            dist = dist * 3 / 2;
     485            if(dist <= distbg)
     486            {
     487                outfg = outbg;
     488                distfg = distbg;
     489                outbg = CACA_COLOR_DARKGRAY;
     490                distbg = dist;
     491            }
     492            else
     493            {
     494                outfg = CACA_COLOR_DARKGRAY;
     495                distfg = dist;
     496            }
     497
     498            /* check dist to 70% */
     499            dist = XRATIO * (val - 0xa00) * (val - 0xa00)
     500                 + YRATIO * sat * sat;
     501            dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
     502            dist = dist * 3 / 2;
     503            if(dist <= distbg)
     504            {
     505                outfg = outbg;
     506                distfg = distbg;
     507                outbg = CACA_COLOR_LIGHTGRAY;
     508                distbg = dist;
     509            }
     510            else if(dist <= distfg)
     511            {
     512                outfg = CACA_COLOR_LIGHTGRAY;
     513                distfg = dist;
     514            }
     515
     516            /* check dist to white */
     517            dist = XRATIO * (val - 0x1000) * (val - 0x1000)
     518                 + YRATIO * sat * sat;
     519            dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
     520            if(dist <= distbg)
     521            {
     522                outfg = outbg;
     523                distfg = distbg;
     524                outbg = CACA_COLOR_WHITE;
     525                distbg = dist;
     526            }
     527            else if(dist <= distfg)
     528            {
     529                outfg = CACA_COLOR_WHITE;
     530                distfg = dist;
     531            }
     532
     533            hue1 = (hue + 0x800) & ~0xfff;
     534            if(hue > hue1)
     535                hue2 = (hue + 0x1800) & ~0xfff;
     536            else
     537                hue2 = (hue - 0x800) & ~0xfff;
     538
     539            /* check dist to 2nd closest dark color */
     540            dist = XRATIO * (val - 0x600) * (val - 0x600)
     541                 + YRATIO * (sat - 0x1000) * (sat - 0x1000)
     542                 + HRATIO * (hue - hue2) * (hue - hue2);
     543            dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
     544            //dist = dist * 3 / 4;
     545            if(dist <= distbg)
     546            {
     547                outfg = outbg;
     548                distfg = distbg;
     549                outbg = dark_colors[hue2 / 0x1000];
     550                distbg = dist;
     551            }
     552            else if(dist <= distfg)
     553            {
     554                outfg = dark_colors[hue2 / 0x1000];
     555                distfg = dist;
     556            }
     557
     558            /* check dist to 2nd closest light color */
     559            dist = XRATIO * (val - 0x1000) * (val - 0x1000)
     560                 + YRATIO * (sat - 0x1000) * (sat - 0x1000)
     561                 + HRATIO * (hue - hue2) * (hue - hue2);
     562            dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
     563            //dist = dist * 3 / 4;
     564            //dist = dist / 2;
     565            if(dist <= distbg)
     566            {
     567                outfg = outbg;
     568                distfg = distbg;
     569                outbg = light_colors[hue2 / 0x1000];
     570                distbg = dist;
     571            }
     572            else if(dist <= distfg)
     573            {
     574                outfg = light_colors[hue2 / 0x1000];
     575                distfg = dist;
     576            }
     577
     578            /* check dist to closest dark color */
     579            dist = XRATIO * (val - 0x600) * (val - 0x600)
     580                 + YRATIO * (sat - 0x1000) * (sat - 0x1000)
     581                 + HRATIO * (hue - hue1) * (hue - hue1);
     582            dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
     583            dist = dist * 3 / 4;
     584            if(dist <= distbg)
     585            {
     586                outfg = outbg;
     587                distfg = distbg;
     588                outbg = dark_colors[hue1 / 0x1000];
     589                distbg = dist;
     590            }
     591            else if(dist <= distfg)
     592            {
     593                outfg = dark_colors[hue1 / 0x1000];
     594                distfg = dist;
     595            }
     596
     597            /* check dist to closest light color */
     598            dist = XRATIO * (val - 0x1000) * (val - 0x1000)
     599                 + YRATIO * (sat - 0x1000) * (sat - 0x1000)
     600                 + HRATIO * (hue - hue1) * (hue - hue1);
     601            dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
     602            dist = dist / 2;
     603            if(dist <= distbg)
     604            {
     605                outfg = outbg;
     606                distfg = distbg;
     607                outbg = light_colors[hue1 / 0x1000];
     608                distbg = dist;
     609            }
     610            else if(dist <= distfg)
     611            {
     612                outfg = light_colors[hue1 / 0x1000];
     613                distfg = dist;
     614            }
     615
     616            if(distbg <= 0) distbg = 1;
     617            if(distfg <= 0) distfg = 1;
     618
     619            /* distbg can be > distfg because of dithering fuzziness */
     620            ch = distbg * 2 * (DENSITY_CHARS - 1) / (distbg + distfg);
     621            ch = 4 * ch + _get_dither() / 0x40;
     622            outch = density_chars[ch];
    492623        }
    493         else if(dist <= distfg)
     624        else
    494625        {
    495             outfg = CACA_COLOR_LIGHTGRAY;
    496             distfg = dist;
     626            outbg = CACA_COLOR_BLACK;
     627            if((unsigned int)sat < 0x200 + _get_dither() * 0x8)
     628                outfg = white_colors[1 + (val * 2 + _get_dither() * 0x10)
     629                                       / 0x1000];
     630            else if((unsigned int)val > 0x800 + _get_dither() * 0x4)
     631                outfg = light_colors[(hue + _get_dither() * 0x10) / 0x1000];
     632            else
     633                outfg = dark_colors[(hue + _get_dither() * 0x10) / 0x1000];
     634
     635            ch = (val + 0x2 * _get_dither()) * 10 / 0x1000;
     636            ch = 4 * ch + _get_dither() / 0x40;
     637            outch = density_chars[ch];
    497638        }
    498 
    499         /* check dist to white */
    500         dist = XRATIO * (val - 0x1000) * (val - 0x1000)
    501              + YRATIO * sat * sat;
    502         dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
    503         if(dist <= distbg)
    504         {
    505             outfg = outbg;
    506             distfg = distbg;
    507             outbg = CACA_COLOR_WHITE;
    508             distbg = dist;
    509         }
    510         else if(dist <= distfg)
    511         {
    512             outfg = CACA_COLOR_WHITE;
    513             distfg = dist;
    514         }
    515 
    516         hue1 = (hue + 0x800) & ~0xfff;
    517         if(hue > hue1)
    518             hue2 = (hue + 0x1800) & ~0xfff;
    519         else
    520             hue2 = (hue - 0x800) & ~0xfff;
    521 
    522         /* check dist to 2nd closest dark color */
    523         dist = XRATIO * (val - 0x600) * (val - 0x600)
    524              + YRATIO * (sat - 0x1000) * (sat - 0x1000)
    525              + HRATIO * (hue - hue2) * (hue - hue2);
    526         dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
    527 //        dist = dist * 3 / 4;
    528         if(dist <= distbg)
    529         {
    530             outfg = outbg;
    531             distfg = distbg;
    532             outbg = dark_colors[hue2 / 0x1000];
    533             distbg = dist;
    534         }
    535         else if(dist <= distfg)
    536         {
    537             outfg = dark_colors[hue2 / 0x1000];
    538             distfg = dist;
    539         }
    540 
    541         /* check dist to 2nd closest light color */
    542         dist = XRATIO * (val - 0x1000) * (val - 0x1000)
    543              + YRATIO * (sat - 0x1000) * (sat - 0x1000)
    544              + HRATIO * (hue - hue2) * (hue - hue2);
    545         dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
    546         //dist = dist * 3 / 4;
    547         //dist = dist / 2;
    548         if(dist <= distbg)
    549         {
    550             outfg = outbg;
    551             distfg = distbg;
    552             outbg = light_colors[hue2 / 0x1000];
    553             distbg = dist;
    554         }
    555         else if(dist <= distfg)
    556         {
    557             outfg = light_colors[hue2 / 0x1000];
    558             distfg = dist;
    559         }
    560 
    561         /* check dist to closest dark color */
    562         dist = XRATIO * (val - 0x600) * (val - 0x600)
    563              + YRATIO * (sat - 0x1000) * (sat - 0x1000)
    564              + HRATIO * (hue - hue1) * (hue - hue1);
    565         dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
    566         dist = dist * 3 / 4;
    567         if(dist <= distbg)
    568         {
    569             outfg = outbg;
    570             distfg = distbg;
    571             outbg = dark_colors[hue1 / 0x1000];
    572             distbg = dist;
    573         }
    574         else if(dist <= distfg)
    575         {
    576             outfg = dark_colors[hue1 / 0x1000];
    577             distfg = dist;
    578         }
    579 
    580         /* check dist to closest light color */
    581         dist = XRATIO * (val - 0x1000) * (val - 0x1000)
    582              + YRATIO * (sat - 0x1000) * (sat - 0x1000)
    583              + HRATIO * (hue - hue1) * (hue - hue1);
    584         dist += FUZZINESS * _get_dither() - 0x80 * FUZZINESS;
    585         dist = dist / 2;
    586         if(dist <= distbg)
    587         {
    588             outfg = outbg;
    589             distfg = distbg;
    590             outbg = light_colors[hue1 / 0x1000];
    591             distbg = dist;
    592         }
    593         else if(dist <= distfg)
    594         {
    595             outfg = light_colors[hue1 / 0x1000];
    596             distfg = dist;
    597         }
    598 
    599         if(distbg <= 0) distbg = 1;
    600         if(distfg <= 0) distfg = 1;
    601 
    602         /* distbg can be > distfg because of dithering fuzziness */
    603         ch = distbg * 2 * (DENSITY_CHARS - 1) / (distbg + distfg);
    604         ch = 4 * ch + _get_dither() / 0x40;
    605         outch = density_chars[ch];
    606 
    607 #else
    608         outbg = CACA_COLOR_BLACK;
    609         if((unsigned int)sat < 0x200 + _get_dither() * 0x8)
    610             outfg = white_colors[1 + (val * 2 + _get_dither() * 0x10) / 0x1000];
    611         else if((unsigned int)val > 0x800 + _get_dither() * 0x4)
    612             outfg = light_colors[(hue + _get_dither() * 0x10) / 0x1000];
    613         else
    614             outfg = dark_colors[(hue + _get_dither() * 0x10) / 0x1000];
    615 
    616         ch = (val + 0x2 * _get_dither()) * 10 / 0x1000;
    617         ch = 4 * ch + _get_dither() / 0x40;
    618         outch = density_chars[ch];
    619 
    620 #endif
    621639
    622640        /* Now output the character */
Note: See TracChangeset for help on using the changeset viewer.