Changeset 221


Ignore:
Timestamp:
Nov 26, 2003, 9:58:30 PM (17 years ago)
Author:
Sam Hocevar
Message:
  • src/bitmap.c: Support for more colour depths.
File:
1 edited

Legend:

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

    r214 r221  
    4141#include "caca_internals.h"
    4242
     43static void mask2shift(int, int *, int *);
     44
     45static void get_rgb_default(struct caca_bitmap *, unsigned char *,
     46                            int, int, int *, int *, int *);
     47static void rgb2hsv_default(int, int, int, int *, int *, int *);
     48
    4349/* Dithering methods */
    4450static void init_no_dither(int);
     
    9298struct caca_bitmap
    9399{
    94     int bpp;
     100    int bpp, palette;
    95101    int w, h, pitch;
    96102    int rmask, gmask, bmask;
     103    int rright, gright, bright;
     104    int rleft, gleft, bleft;
     105    void (*get_hsv)(struct caca_bitmap *, char *, int, int);
     106    int red[256], green[256], blue[256];
    97107};
     108
     109static void mask2shift(int mask, int *right, int *left)
     110{
     111    int rshift = 0, lshift = 0;
     112    *right = *left = 0;
     113
     114    if(!mask)
     115        return;
     116
     117    while(!(mask & 1))
     118    {
     119        mask >>= 1;
     120        rshift++;
     121    }
     122    *right = rshift;
     123
     124    while(mask & 1)
     125    {
     126        mask >>= 1;
     127        lshift++;
     128    }
     129    *left = 16 - lshift;
     130}
    98131
    99132struct caca_bitmap *caca_create_bitmap(int bpp, int w, int h, int pitch,
     
    103136
    104137    /* Currently only this format is supported. Will improve later. */
    105     if(!w || !h || !pitch || bpp != 32 ||
    106        rmask != 0x00ff0000 || gmask != 0x0000ff00 || bmask != 0x000000ff)
     138    if(!w || !h || !pitch || bpp > 32 || bpp < 8)
    107139        return NULL;
    108140
     
    112144
    113145    bitmap->bpp = bpp;
     146    bitmap->palette = 0;
    114147
    115148    bitmap->w = w;
     
    121154    bitmap->bmask = bmask;
    122155
     156    /* Load bitmasks */
     157    if(rmask || gmask || bmask)
     158    {
     159        mask2shift(rmask, &bitmap->rright, &bitmap->rleft);
     160        mask2shift(gmask, &bitmap->gright, &bitmap->gleft);
     161        mask2shift(bmask, &bitmap->bright, &bitmap->bleft);
     162    }
     163
     164    /* In 8 bpp mode, default to a grayscale palette */
     165    if(bpp == 8)
     166    {
     167        int i;
     168        bitmap->palette = 1;
     169        for(i = 0; i < 256; i++)
     170        {
     171            bitmap->red[i] = i * 0x100;
     172            bitmap->green[i] = i * 0x100;
     173            bitmap->blue[i] = i * 0x100;
     174        }
     175    }
     176
    123177    return bitmap;
     178}
     179
     180void caca_set_bitmap_palette(struct caca_bitmap *bitmap,
     181                             int red[], int green[], int blue[])
     182{
     183    int i;
     184
     185    if(bitmap->bpp != 8)
     186        return;
     187
     188    for(i = 0; i < 256; i++)
     189    {
     190        if(red[i] >= 0 && red[i] < 65536 &&
     191           green[i] >= 0 && green[i] < 65536 &&
     192           blue[i] >= 0 && blue[i] < 65536)
     193        {
     194            bitmap->red[i] = red[i];
     195            bitmap->green[i] = green[i];
     196            bitmap->blue[i] = blue[i];
     197        }
     198    }
    124199}
    125200
     
    132207}
    133208
     209static void get_rgb_default(struct caca_bitmap *bitmap, unsigned char *pixels,
     210                            int x, int y, int *r, int *g, int *b)
     211{
     212    int bits;
     213
     214    pixels += (bitmap->bpp / 8) * x + bitmap->pitch * y;
     215
     216    switch(bitmap->bpp / 8)
     217    {
     218        case 4:
     219            bits = *(uint32_t *)(pixels + 0);
     220            break;
     221        case 3:
     222            bits = (pixels[0] << 16)
     223                    | (pixels[1] << 8)
     224                    | (pixels[2]);
     225            break;
     226        case 2:
     227            bits = *(uint16_t *)(pixels + 0);
     228            break;
     229        case 1:
     230        default:
     231            bits = pixels[0];
     232            break;
     233    }
     234
     235    if(bitmap->palette)
     236    {
     237        *r = bitmap->red[bits];
     238        *g = bitmap->green[bits];
     239        *b = bitmap->blue[bits];
     240    }
     241    else
     242    {
     243        *r = ((bits & bitmap->rmask) >> bitmap->rright) << bitmap->rleft;
     244        *g = ((bits & bitmap->gmask) >> bitmap->gright) << bitmap->gleft;
     245        *b = ((bits & bitmap->bmask) >> bitmap->bright) << bitmap->bleft;
     246    }
     247}
     248
     249static void rgb2hsv_default(int r, int g, int b, int *hue, int *sat, int *val)
     250{
     251    int min, max, delta;
     252
     253    min = r; max = r;
     254    if(min > g) min = g; if(max < g) max = g;
     255    if(min > b) min = b; if(max < b) max = b;
     256
     257    delta = max - min; /* 0 - 65535 */
     258    *val = max; /* 0 - 65535 */
     259    *sat = max ? 0x100 * delta / max * 0x100: 0; /* 0 - 65536 */
     260
     261    if(*sat > (_get_dither() + 24) * 0x400)
     262    {
     263        /* XXX: Values should be between 1 and 6, but since we
     264         * are dithering, there may be overflows, hence our bigger
     265         * *_colors[] tables. */
     266        if( r == max )
     267            *hue = 0x10000 + 0x100 * (g - b) / delta * 0x100;
     268        else if( g == max )
     269            *hue = 0x30000 + 0x100 * (b - r) / delta * 0x100;
     270        else
     271            *hue = 0x50000 + 0x100 * (r - g) / delta * 0x100;
     272
     273        *hue = (*hue + 0x8000 + 0x1000 * _get_dither()) / 0x10000;
     274    }
     275    else
     276    {
     277        *sat = 0;
     278    }
     279}
     280
    134281void caca_draw_bitmap(int x1, int y1, int x2, int y2,
    135282                      struct caca_bitmap *bitmap, char *pixels)
    136283{
    137284    /* FIXME: this code is shite! */
    138     static int white_colors[] = {CACA_COLOR_DARKGRAY, CACA_COLOR_LIGHTGRAY, CACA_COLOR_WHITE};
    139     static int light_colors[] = {CACA_COLOR_LIGHTMAGENTA, CACA_COLOR_LIGHTRED, CACA_COLOR_YELLOW, CACA_COLOR_LIGHTGREEN, CACA_COLOR_LIGHTCYAN, CACA_COLOR_LIGHTBLUE, CACA_COLOR_LIGHTMAGENTA};
    140     static int dark_colors[] = {CACA_COLOR_MAGENTA, CACA_COLOR_RED, CACA_COLOR_BROWN, CACA_COLOR_GREEN, CACA_COLOR_CYAN, CACA_COLOR_BLUE, CACA_COLOR_MAGENTA};
    141     static char foo[] = { ' ', '.', ':', ';', '=', '%', '$', 'W', '#', '8', '@' };
     285    static int white_colors[] =
     286    {
     287        CACA_COLOR_DARKGRAY,
     288        CACA_COLOR_LIGHTGRAY,
     289        CACA_COLOR_WHITE
     290    };
     291
     292    static int light_colors[] =
     293    {
     294        CACA_COLOR_LIGHTMAGENTA,
     295        CACA_COLOR_LIGHTRED,
     296        CACA_COLOR_YELLOW,
     297        CACA_COLOR_LIGHTGREEN,
     298        CACA_COLOR_LIGHTCYAN,
     299        CACA_COLOR_LIGHTBLUE,
     300        CACA_COLOR_LIGHTMAGENTA
     301    };
     302
     303    static int dark_colors[] =
     304    {
     305        CACA_COLOR_MAGENTA,
     306        CACA_COLOR_RED,
     307        CACA_COLOR_BROWN,
     308        CACA_COLOR_GREEN,
     309        CACA_COLOR_CYAN,
     310        CACA_COLOR_BLUE,
     311        CACA_COLOR_MAGENTA
     312    };
     313
     314    static char foo[] =
     315    {
     316        ' ', ' ', ' ', ' ',
     317        ',', '`', '.', '\'',
     318        'i', '-', ':', '^',
     319        '|', '/', ';', '\\',
     320        '=', '+', 'o', 'x',
     321        '<', 'x', '%', '>',
     322        '&', 'z', '$', '§',
     323        'W', 'X', 'K', 'M',
     324        '#', '8', '#', '#',
     325        '8', '@', '8', '#',
     326        '@', '8', '@', '8',
     327    };
     328
    142329    int x, y, w, h, pitch;
    143330
     
    167354        for(x = x1 > 0 ? x1 : 0; x <= x2 && x <= (int)caca_get_width(); x++)
    168355        {
     356            int ch;
     357            int hue, sat, val, r, g, b, R, G, B;
    169358            int fromx = w * (x - x1) / (x2 - x1 + 1);
    170359            int fromy = h * (y - y1) / (y2 - y1 + 1);
    171             /* FIXME: bwahaaa, we don't even respect masks */
    172             int b = ((unsigned char *)pixels)[4 * fromx + pitch * fromy];
    173             int g = ((unsigned char *)pixels)[4 * fromx + 1 + pitch * fromy];
    174             int r = ((unsigned char *)pixels)[4 * fromx + 2 + pitch * fromy];
    175             int hue, sat, val;
    176 
    177             int min = r, max = r, delta;
    178             if(min > g) min = g; if(max < g) max = g;
    179             if(min > b) min = b; if(max < b) max = b;
    180 
    181             delta = max - min;
    182             val = max; /* 0 - 255 */
    183             sat = max ? 256 * delta / max : 0; /* 0 - 255 */
    184 
    185             if(sat > (_get_dither() + 24) * 4)
    186             {
    187                 /* XXX: Values should be between 1 and 6, but since we
    188                  * are dithering, there may be overflows, hence our bigger
    189                  * *_colors[] tables. */
    190                 if( r == max )
    191                     hue = 256 + 256 * (g - b) / delta;
    192                 else if( g == max )
    193                     hue = 768 + 256 * (b - r) / delta;
    194                 else
    195                     hue = 1280 + 256 * (r - g) / delta;
    196 
    197                 hue = (hue + 128 + 16 * _get_dither()) / 256;
    198 
    199                 if(val > (_get_dither() + 40) * 4)
    200                     caca_set_color(light_colors[hue]);
    201                 else
    202                     caca_set_color(dark_colors[hue]);
    203             }
     360
     361            /* First get RGB */
     362            R = 0, G = 0, B = 0;
     363            get_rgb_default(bitmap, pixels, fromx, fromy, &r, &g, &b);
     364            R += r; G += g; B += b;
     365            get_rgb_default(bitmap, pixels, fromx - 1, fromy, &r, &g, &b);
     366            R += r; G += g; B += b;
     367            get_rgb_default(bitmap, pixels, fromx, fromy - 1, &r, &g, &b);
     368            R += r; G += g; B += b;
     369            get_rgb_default(bitmap, pixels, fromx + 1, fromy, &r, &g, &b);
     370            R += r; G += g; B += b;
     371            get_rgb_default(bitmap, pixels, fromx, fromy + 1, &r, &g, &b);
     372            R += r; G += g; B += b;
     373            R /= 5; G /= 5; B /= 5;
     374
     375            /* Now get HSV from RGB */
     376            rgb2hsv_default(R, G, B, &hue, &sat, &val);
     377
     378            if(!sat)
     379                caca_set_color(white_colors[val * 3 / 0x10000], CACA_COLOR_BLACK);
     380            else if(val > (_get_dither() + 40) * 0x400)
     381                caca_set_color(light_colors[hue], CACA_COLOR_BLACK);
    204382            else
    205             {
    206                 caca_set_color(white_colors[max * 3 / 256]);
    207             }
    208 
    209             caca_putchar(x, y, foo[(r + g + b + 2 * _get_dither()) / 3 / 25]);
     383                caca_set_color(dark_colors[hue], CACA_COLOR_BLACK);
     384
     385            /* FIXME: choose better characters! */
     386            ch = (val + 0x200 * _get_dither()) * 10 / 0x10000;
     387            ch = 4 * ch + (_get_dither() + 8) / 4;
     388            caca_putchar(x, y, foo[ch]);
    210389
    211390            _increment_dither();
Note: See TracChangeset for help on using the changeset viewer.