Changeset 238


Ignore:
Timestamp:
Nov 30, 2003, 4:01:55 PM (16 years ago)
Author:
Sam Hocevar
Message:
  • src/bitmap.c: + Fixed an endianness issue in the byte reader. + Decreased precision in RGB and HSV values to avoid overflows. + New dithering method: 2x2 ordered. + New renderer, with background colour awareness.
  • configure.ac: + Check for <endian.h>.
  • examples/demo.c examples/view.c: + Fixed an endianness issue in cacaview. + Adapted code to the additional dithering method.
Location:
libcaca/trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • libcaca/trunk/configure.ac

    r231 r238  
    77AC_CANONICAL_SYSTEM
    88
    9 AM_INIT_AUTOMAKE(libcaca, 0.1)
     9AM_INIT_AUTOMAKE(libcaca, 0.2)
    1010AM_CONFIG_HEADER(config.h)
    1111
     
    2525  [  --enable-conio          DOS conio.h graphics support (default disabled)])
    2626
    27 AC_CHECK_HEADERS(inttypes.h)
     27AC_CHECK_HEADERS(inttypes.h endian.h)
    2828AC_CHECK_FUNCS(vsnprintf getenv putenv)
    2929
  • libcaca/trunk/examples/demo.c

    r235 r238  
    101101            case 'd':
    102102            case 'D':
    103                 dithering = (dithering + 1) % 4;
     103                dithering = (dithering + 1) % 5;
    104104                caca_set_dithering(dithering);
    105105                display_menu();
  • libcaca/trunk/examples/view.c

    r237 r238  
    2929#include <unistd.h>
    3030
     31#ifdef HAVE_ENDIAN_H
     32#   include <endian.h>
     33#endif
     34
    3135#include <Imlib2.h>
    3236
     
    3741struct caca_bitmap *bitmap = NULL;
    3842int x, y, w, h;
     43unsigned int rmask, gmask, bmask;
    3944
    4045int dithering = CACA_DITHERING_ORDERED4;
     
    4954    char **list = NULL;
    5055    int current = 0, items = 0, opts = 1;
     56
     57#ifdef HAVE_ENDIAN_H
     58    if(__BYTE_ORDER == __BIG_ENDIAN)
     59#else
     60    rmask = 0x12345678;
     61    if(*(char *)&rmask == 0x12)
     62#endif
     63    {
     64        rmask = 0x00ff0000; gmask = 0x0000ff00; bmask = 0x000000ff;
     65    }
     66    else
     67    {
     68        rmask = 0x0000ff00; gmask = 0x00ff0000; bmask = 0xff000000;
     69    }
    5170
    5271    /* Initialise libcaca */
     
    102121                break;
    103122            case CACA_EVENT_KEY_PRESS | 'd':
    104                 dithering = (dithering + 1) % 4;
     123                dithering = (dithering + 1) % 5;
    105124                update = 1;
    106125                break;
    107126            case CACA_EVENT_KEY_PRESS | 'D':
    108                 dithering = (dithering - 1) % 4;
     127                dithering = (dithering + 4) % 5;
    109128                update = 1;
    110129                break;
     
    216235            if(yn + y > h) y = h - yn;
    217236            newbitmap = caca_create_bitmap(32, 2 * xn, 2 * yn, 4 * w,
    218                                        0x0000ff00, 0x00ff0000, 0xff000000);
     237                                           rmask, gmask, bmask);
    219238            caca_draw_bitmap(0, 0, ww - 1, wh - 1, newbitmap,
    220239                             pixels + 4 * (x - xn) + 4 * w * (y - yn));
     
    298317
    299318    /* Create the libcaca bitmap */
    300     bitmap = caca_create_bitmap(32, w, h, 4 * w,
    301                                 0x0000ff00, 0x00ff0000, 0xff000000);
     319    bitmap = caca_create_bitmap(32, w, h, 4 * w, rmask, gmask, bmask);
    302320    if(!bitmap)
    303321    {
  • libcaca/trunk/src/bitmap.c

    r237 r238  
    5454static void increment_no_dither(void);
    5555
     56static void init_ordered2_dither(int);
     57static unsigned int get_ordered2_dither(void);
     58static void increment_ordered2_dither(void);
     59
    5660static void init_ordered4_dither(int);
    5761static unsigned int get_ordered4_dither(void);
     
    8185        _get_dither = get_no_dither;
    8286        _increment_dither = increment_no_dither;
     87        break;
     88
     89    case CACA_DITHERING_ORDERED2:
     90        _init_dither = init_ordered2_dither;
     91        _get_dither = get_ordered2_dither;
     92        _increment_dither = increment_ordered2_dither;
    8393        break;
    8494
     
    141151        lshift++;
    142152    }
    143     *left = 16 - lshift;
    144 }
    145 
    146 #include <stdio.h>
     153    *left = 12 - lshift;
     154}
     155
    147156struct caca_bitmap *caca_create_bitmap(int bpp, int w, int h, int pitch,
    148157                                       int rmask, int gmask, int bmask)
     
    176185        mask2shift(bmask, &bitmap->bright, &bitmap->bleft);
    177186    }
    178 fprintf(stderr, "shifts: %i %i %i %i %i %i\n", bitmap->rright, bitmap->rleft, bitmap->gright, bitmap->gleft, bitmap->bright, bitmap->bleft);
    179187
    180188    /* In 8 bpp mode, default to a grayscale palette */
     
    185193        for(i = 0; i < 256; i++)
    186194        {
    187             bitmap->red[i] = i * 0x100;
    188             bitmap->green[i] = i * 0x100;
    189             bitmap->blue[i] = i * 0x100;
     195            bitmap->red[i] = i * 0x10;
     196            bitmap->green[i] = i * 0x10;
     197            bitmap->blue[i] = i * 0x10;
    190198        }
    191199    }
     
    204212    for(i = 0; i < 256; i++)
    205213    {
    206         if(red[i] >= 0 && red[i] < 65536 &&
    207            green[i] >= 0 && green[i] < 65536 &&
    208            blue[i] >= 0 && blue[i] < 65536)
     214        if(red[i] >= 0 && red[i] < 0x1000 &&
     215           green[i] >= 0 && green[i] < 0x1000 &&
     216           blue[i] >= 0 && blue[i] < 0x1000)
    209217        {
    210218            bitmap->red[i] = red[i];
     
    281289    if(delta)
    282290    {
    283         *sat = 0x1000 * delta / max * 0x10; /* 0 - 0xffff */
    284 
    285         /* Generate *hue between 0 and 0x5ffff */
     291        *sat = 0x1000 * delta / max; /* 0 - 0xfff */
     292
     293        /* Generate *hue between 0 and 0x5fff */
    286294        if( r == max )
    287             *hue = 0x10000 + 0x100 * (g - b) / delta * 0x100;
     295            *hue = 0x1000 + 0x1000 * (g - b) / delta;
    288296        else if( g == max )
    289             *hue = 0x30000 + 0x100 * (b - r) / delta * 0x100;
     297            *hue = 0x3000 + 0x1000 * (b - r) / delta;
    290298        else
    291             *hue = 0x50000 + 0x100 * (r - g) / delta * 0x100;
     299            *hue = 0x5000 + 0x1000 * (r - g) / delta;
    292300    }
    293301    else
     
    304312    static int white_colors[] =
    305313    {
     314        CACA_COLOR_BLACK,
    306315        CACA_COLOR_DARKGRAY,
    307316        CACA_COLOR_LIGHTGRAY,
     
    331340    };
    332341
    333     static char foo[] =
     342    /* FIXME: choose better characters! */
     343#   define DENSITY_CHARS 13
     344    static char density_chars[] =
    334345        "    "
    335         " ,' "
     346        "    "
     347        ".`  "
    336348        ",`.'"
    337         "i-:^"
    338         "|/;\\"
    339         "=+ox"
    340         "<x%>"
    341         "&z$w"
     349        "i:-^"
     350        "|=+;"
     351        "ox/\\"
     352        "<>x%"
     353        "&$zw"
    342354        "WXKM"
    343355        "#8##"
    344356        "8@8#"
    345         "@8@8";
     357        "@8@8"
     358        "????";
    346359
    347360    int x, y, w, h, pitch;
     
    365378
    366379    for(y = y1 > 0 ? y1 : 0; y <= y2 && y <= (int)caca_get_height(); y++)
    367     {
    368         /* Initialize dither tables for the current line */
    369         _init_dither(y);
    370 
    371         /* Dither the current line */
    372         for(x = x1 > 0 ? x1 : 0; x <= x2 && x <= (int)caca_get_width(); x++)
    373         {
    374             int ch;
    375             unsigned int hue, sat, val, r, g, b, R, G, B;
    376             int fromx = w * (x - x1) / (x2 - x1 + 1);
    377             int fromy = h * (y - y1) / (y2 - y1 + 1);
    378 
    379             /* Clip values (yuck) */
    380             if(fromx == 0) fromx = 1;
    381             if(fromy == 0) fromy = 1;
    382 
    383             /* First get RGB */
    384             R = 0, G = 0, B = 0;
    385             get_rgb_default(bitmap, pixels, fromx, fromy, &r, &g, &b);
    386             R += r; G += g; B += b;
    387             get_rgb_default(bitmap, pixels, fromx - 1, fromy, &r, &g, &b);
    388             R += r; G += g; B += b;
    389             get_rgb_default(bitmap, pixels, fromx, fromy - 1, &r, &g, &b);
    390             R += r; G += g; B += b;
    391             get_rgb_default(bitmap, pixels, fromx + 1, fromy, &r, &g, &b);
    392             R += r; G += g; B += b;
    393             get_rgb_default(bitmap, pixels, fromx, fromy + 1, &r, &g, &b);
    394             R += r; G += g; B += b;
    395             R /= 5; G /= 5; B /= 5;
    396 
    397             /* Now get HSV from RGB */
    398             rgb2hsv_default(R, G, B, &hue, &sat, &val);
    399 
    400             if(sat < 0x2000 + _get_dither() * 0x80)
    401                 caca_set_color(white_colors[val * 3 / 0x10000], CACA_COLOR_BLACK);
    402             else if(val > 0x8000 + _get_dither() * 0x40)
    403                 caca_set_color(light_colors[(hue + _get_dither() * 0x100) / 0x10000], CACA_COLOR_BLACK);
    404             else
    405                 caca_set_color(dark_colors[(hue + _get_dither() * 0x100) / 0x10000], CACA_COLOR_BLACK);
    406 
    407             /* FIXME: choose better characters! */
    408             ch = (val + 0x20 * _get_dither() - 0x1000 /*???*/) * 10 / 0x10000;
    409             ch = 4 * ch + (_get_dither() + 8) / 0x40;
    410             caca_putchar(x, y, foo[ch]);
    411 
    412             _increment_dither();
    413         }
     380        for(x = x1 > 0 ? x1 : 0, _init_dither(y);
     381            x <= x2 && x <= (int)caca_get_width();
     382            x++)
     383    {
     384        int ch;
     385        unsigned int r, g, b, R, G, B;
     386        int hue, sat, val;
     387        int fromx = w * (x - x1) / (x2 - x1 + 1);
     388        int fromy = h * (y - y1) / (y2 - y1 + 1);
     389        enum caca_color outfg, outbg;
     390        char outch;
     391#define NEW_DITHERER 1
     392#ifdef NEW_DITHERER
     393        int distbg, distfg, dist;
     394#endif
     395
     396        /* Clip values (yuck) */
     397        if(fromx == 0) fromx = 1;
     398        if(fromy == 0) fromy = 1;
     399
     400        /* First get RGB */
     401        R = 0, G = 0, B = 0;
     402        get_rgb_default(bitmap, pixels, fromx, fromy, &r, &g, &b);
     403#if 0
     404        R += r; G += g; B += b;
     405        get_rgb_default(bitmap, pixels, fromx - 1, fromy, &r, &g, &b);
     406        R += r; G += g; B += b;
     407        get_rgb_default(bitmap, pixels, fromx, fromy - 1, &r, &g, &b);
     408        R += r; G += g; B += b;
     409        get_rgb_default(bitmap, pixels, fromx + 1, fromy, &r, &g, &b);
     410        R += r; G += g; B += b;
     411        get_rgb_default(bitmap, pixels, fromx, fromy + 1, &r, &g, &b);
     412        R += r; G += g; B += b;
     413        R /= 5; G /= 5; B /= 5;
     414#else
     415        R += r; G += g; B += b;
     416#endif
     417
     418        /* Now get HSV from RGB */
     419        rgb2hsv_default(R, G, B, &hue, &sat, &val);
     420
     421        /* The hard work: calculate foreground and background colours,
     422         * as well as the most appropriate character to output. */
     423#if NEW_DITHERER
     424#define XRATIO 5*5
     425#define YRATIO 3*3
     426        /* distance to black */
     427        distbg = XRATIO * val * val;
     428        distbg += XRATIO * 0x1000 * _get_dither() - XRATIO * 0x8000;
     429        outbg = CACA_COLOR_BLACK;
     430
     431        /* distance to 30% */
     432        dist = XRATIO * (val - 0x600) * (val - 0x600)
     433             + YRATIO * sat * sat;
     434        dist += XRATIO * 0x1000 * _get_dither() - XRATIO * 0x8000;
     435        if(dist <= distbg)
     436        {
     437            outfg = outbg;
     438            distfg = distbg;
     439            outbg = CACA_COLOR_DARKGRAY;
     440            distbg = dist;
     441        }
     442        else
     443        {
     444            outfg = CACA_COLOR_DARKGRAY;
     445            distfg = dist;
     446        }
     447
     448        /* check dist to 70% */
     449        dist = XRATIO * (val - 0xa00) * (val - 0xa00)
     450             + YRATIO * sat * sat;
     451        dist += XRATIO * 0x1000 * _get_dither() - XRATIO * 0x8000;
     452        if(dist <= distbg)
     453        {
     454            outfg = outbg;
     455            distfg = distbg;
     456            outbg = CACA_COLOR_LIGHTGRAY;
     457            distbg = dist;
     458        }
     459        else if(dist <= distfg)
     460        {
     461            outfg = CACA_COLOR_LIGHTGRAY;
     462            distfg = dist;
     463        }
     464
     465        /* check dist to white */
     466        dist = XRATIO * (val - 0x1000) * (val - 0x1000)
     467             + YRATIO * sat * sat;
     468        dist += XRATIO * 0x1000 * _get_dither() - XRATIO * 0x8000;
     469        if(dist <= distbg)
     470        {
     471            outfg = outbg;
     472            distfg = distbg;
     473            outbg = CACA_COLOR_WHITE;
     474            distbg = dist;
     475        }
     476        else if(dist <= distfg)
     477        {
     478            outfg = CACA_COLOR_WHITE;
     479            distfg = dist;
     480        }
     481
     482        /* check dist to dark */
     483        dist = XRATIO * (val - 0x600) * (val - 0x600)
     484             + YRATIO * (sat - 0x1000) * (sat - 0x1000);
     485        dist += XRATIO * 0x1000 * _get_dither() - XRATIO * 0x8000;
     486        dist = dist * 3 / 4;
     487        if(dist <= distbg)
     488        {
     489            outfg = outbg;
     490            distfg = distbg;
     491            outbg = dark_colors[(hue + _get_dither() * 0x10) / 0x1000];
     492            distbg = dist;
     493        }
     494        else if(dist <= distfg)
     495        {
     496            outfg = dark_colors[(hue + _get_dither() * 0x10) / 0x1000];
     497            distfg = dist;
     498        }
     499
     500        /* check dist to light */
     501        dist = XRATIO * (val - 0x1000) * (val - 0x1000)
     502             + YRATIO * (sat - 0x1000) * (sat - 0x1000);
     503        dist += XRATIO * 0x1000 * _get_dither() - XRATIO * 0x8000;
     504        dist = dist / 2;
     505        if(dist <= distbg)
     506        {
     507            outfg = outbg;
     508            distfg = distbg;
     509            outbg = light_colors[(hue + _get_dither() * 0x10) / 0x1000];
     510            distbg = dist;
     511        }
     512        else if(dist <= distfg)
     513        {
     514            outfg = light_colors[(hue + _get_dither() * 0x10) / 0x1000];
     515            distfg = dist;
     516        }
     517
     518        if(distbg <= 0) distbg = 1;
     519        if(distfg <= 0) distfg = 1;
     520
     521        /* distbg can be > distfg because of dithering fuzziness */
     522        ch = distbg * 2 * (DENSITY_CHARS - 1) / (distbg + distfg);
     523        ch = 4 * ch /*+ _get_dither() / 0x40*/;
     524        outch = density_chars[ch];
     525
     526#else
     527        outbg = CACA_COLOR_BLACK;
     528        if(sat < 0x200 + _get_dither() * 0x8)
     529            outfg = white_colors[1 + (val * 2 + _get_dither() * 0x10) / 0x1000];
     530        else if(val > 0x800 + _get_dither() * 0x4)
     531            outfg = light_colors[(hue + _get_dither() * 0x10) / 0x1000];
     532        else
     533            outfg = dark_colors[(hue + _get_dither() * 0x10) / 0x1000];
     534
     535        ch = (val + 0x2 * _get_dither()) * 10 / 0x1000;
     536        ch = 4 * ch + _get_dither() / 0x40;
     537        outch = density_chars[ch];
     538
     539#endif
     540
     541        /* Now output the character */
     542        caca_set_color(outfg, outbg);
     543        caca_putchar(x, y, outch);
     544
     545        _increment_dither();
    414546    }
    415547}
     
    435567{
    436568    return;
     569}
     570
     571/*
     572 * Ordered 2 dithering
     573 */
     574static unsigned int *ordered2_table;
     575static unsigned int ordered2_index;
     576
     577static void init_ordered2_dither(int line)
     578{
     579    static unsigned int dither2x2[] =
     580    {
     581        0x00, 0x80,
     582        0xc0, 0x40,
     583    };
     584
     585    ordered2_table = dither2x2 + (line % 2) * 2;
     586    ordered2_index = 0;
     587}
     588
     589static unsigned int get_ordered2_dither(void)
     590{
     591    return ordered2_table[ordered2_index];
     592}
     593
     594static void increment_ordered2_dither(void)
     595{
     596    ordered2_index = (ordered2_index + 1) % 2;
    437597}
    438598
  • libcaca/trunk/src/caca.c

    r236 r238  
    186186    {
    187187        "no",
     188        "2x2 ordered",
    188189        "4x4 ordered",
    189190        "8x8 ordered",
     
    191192    };
    192193
    193     if(dithering < 0 || dithering > 3)
     194    if(dithering < 0 || dithering > 4)
    194195        return "unknown";
    195196
  • libcaca/trunk/src/caca.h

    r235 r238  
    9090{
    9191    CACA_DITHERING_NONE = 0,
    92     CACA_DITHERING_ORDERED4 = 1,
    93     CACA_DITHERING_ORDERED8 = 2,
    94     CACA_DITHERING_RANDOM = 3
     92    CACA_DITHERING_ORDERED2 = 1,
     93    CACA_DITHERING_ORDERED4 = 2,
     94    CACA_DITHERING_ORDERED8 = 3,
     95    CACA_DITHERING_RANDOM = 4
    9596};
    9697
Note: See TracChangeset for help on using the changeset viewer.