Logo Search packages:      
Sourcecode: libcaca version File versions  Download package

void caca_draw_bitmap ( int  x1,
int  y1,
int  x2,
int  y2,
struct caca_bitmap const *  bitmap,
void *  pixels 
)

Draw a bitmap on the screen.

Draw a bitmap at the given coordinates. The bitmap can be of any size and will be stretched to the text area.

Parameters:
x1 X coordinate of the upper-left corner of the drawing area.
y1 Y coordinate of the upper-left corner of the drawing area.
x2 X coordinate of the lower-right corner of the drawing area.
y2 Y coordinate of the lower-right corner of the drawing area.
bitmap Bitmap object to be drawn.
pixels Bitmap's pixels.

Definition at line 400 of file bitmap.c.

References CACA_ANTIALIASING_PREFILTER, CACA_BACKGROUND_SOLID, CACA_COLOR_BLACK, CACA_COLOR_BLUE, CACA_COLOR_BROWN, CACA_COLOR_CYAN, CACA_COLOR_DARKGRAY, CACA_COLOR_GREEN, CACA_COLOR_LIGHTBLUE, CACA_COLOR_LIGHTCYAN, CACA_COLOR_LIGHTGRAY, CACA_COLOR_LIGHTGREEN, CACA_COLOR_LIGHTMAGENTA, CACA_COLOR_LIGHTRED, CACA_COLOR_MAGENTA, CACA_COLOR_RED, CACA_COLOR_WHITE, CACA_COLOR_YELLOW, CACA_DITHERING_NONE, CACA_DITHERING_ORDERED2, CACA_DITHERING_ORDERED4, CACA_DITHERING_ORDERED8, CACA_DITHERING_RANDOM, caca_putchar(), and caca_set_color().

{
    /* Current dithering method */
    void (*_init_dither) (int);
    unsigned int (*_get_dither) (void);
    void (*_increment_dither) (void);

    /* Only used when background is black */
    static int const white_colors[] =
    {
        CACA_COLOR_BLACK,
        CACA_COLOR_DARKGRAY,
        CACA_COLOR_LIGHTGRAY,
        CACA_COLOR_WHITE
    };

    static int const light_colors[] =
    {
        CACA_COLOR_LIGHTMAGENTA,
        CACA_COLOR_LIGHTRED,
        CACA_COLOR_YELLOW,
        CACA_COLOR_LIGHTGREEN,
        CACA_COLOR_LIGHTCYAN,
        CACA_COLOR_LIGHTBLUE,
        CACA_COLOR_LIGHTMAGENTA
    };

    static int const dark_colors[] =
    {
        CACA_COLOR_MAGENTA,
        CACA_COLOR_RED,
        CACA_COLOR_BROWN,
        CACA_COLOR_GREEN,
        CACA_COLOR_CYAN,
        CACA_COLOR_BLUE,
        CACA_COLOR_MAGENTA
    };

    /* FIXME: choose better characters! */
#if !defined(_DOXYGEN_SKIP_ME)
#   define DENSITY_CHARS ((sizeof(density_chars)/sizeof(char const)/4)-1)
#endif
    static char const density_chars[] =
        "    "
        ".   "
        "..  "
        "...."
        "::::"
        ";=;="
        "tftf"
        "%$%$"
        "&KSZ"
        "WXGM"
        "@@@@"
        "8888"
        "####"
        "????";

    int x, y, w, h, pitch, deltax, deltay;

    if(!bitmap || !pixels)
        return;

    w = bitmap->w;
    h = bitmap->h;
    pitch = bitmap->pitch;

    if(x1 > x2)
    {
        int tmp = x2; x2 = x1; x1 = tmp;
    }

    if(y1 > y2)
    {
        int tmp = y2; y2 = y1; y1 = tmp;
    }

    deltax = x2 - x1 + 1;
    deltay = y2 - y1 + 1;

    switch(_caca_dithering)
    {
    case CACA_DITHERING_NONE:
        _init_dither = init_no_dither;
        _get_dither = get_no_dither;
        _increment_dither = increment_no_dither;
        break;

    case CACA_DITHERING_ORDERED2:
        _init_dither = init_ordered2_dither;
        _get_dither = get_ordered2_dither;
        _increment_dither = increment_ordered2_dither;
        break;

    case CACA_DITHERING_ORDERED4:
        _init_dither = init_ordered4_dither;
        _get_dither = get_ordered4_dither;
        _increment_dither = increment_ordered4_dither;
        break;

    case CACA_DITHERING_ORDERED8:
        _init_dither = init_ordered8_dither;
        _get_dither = get_ordered8_dither;
        _increment_dither = increment_ordered8_dither;
        break;

    case CACA_DITHERING_RANDOM:
        _init_dither = init_random_dither;
        _get_dither = get_random_dither;
        _increment_dither = increment_random_dither;
        break;

    default:
        /* Something wicked happened! */
        return;
    }

    for(y = y1 > 0 ? y1 : 0; y <= y2 && y <= (int)_caca_height; y++)
        for(x = x1 > 0 ? x1 : 0, _init_dither(y);
            x <= x2 && x <= (int)_caca_width;
            x++)
    {
        int ch;
        unsigned int r, g, b, a;
        int hue, sat, val;
        int fromx, fromy, tox, toy, myx, myy, dots;
        enum caca_color outfg, outbg;
        char outch;

        r = g = b = a = 0;

        /* First get RGB */
        if(_caca_antialiasing == CACA_ANTIALIASING_PREFILTER)
        {
            fromx = (x - x1) * w / deltax;
            fromy = (y - y1) * h / deltay;
            tox = (x - x1 + 1) * w / deltax;
            toy = (y - y1 + 1) * h / deltay;

            /* We want at least one pixel */
            if(tox == fromx) tox++;
            if(toy == fromy) toy++;

            dots = 0;

            for(myx = fromx; myx < tox; myx++)
                for(myy = fromy; myy < toy; myy++)
            {
                dots++;
                get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a);
            }

            /* Normalize */
            r /= dots;
            g /= dots;
            b /= dots;
            a /= dots;
        }
        else
        {
            fromx = (x - x1) * w / deltax;
            fromy = (y - y1) * h / deltay;
            tox = (x - x1 + 1) * w / deltax;
            toy = (y - y1 + 1) * h / deltay;

            /* tox and toy can overflow the screen, but they cannot overflow
             * when averaged with fromx and fromy because these are guaranteed
             * to be within the pixel boundaries. */
            myx = (fromx + tox) / 2;
            myy = (fromy + toy) / 2;

            get_rgba_default(bitmap, pixels, myx, myy, &r, &g, &b, &a);
        }

        if(bitmap->has_alpha && a < 0x800)
            continue;

        /* Now get HSV from RGB */
        rgb2hsv_default(r, g, b, &hue, &sat, &val);

        /* The hard work: calculate foreground and background colours,
         * as well as the most appropriate character to output. */
        if(_caca_background == CACA_BACKGROUND_SOLID)
        {
            unsigned char point;
            int distfg, distbg;

            lookup_colors[4] = dark_colors[1 + hue / 0x1000];
            lookup_colors[5] = light_colors[1 + hue / 0x1000];
            lookup_colors[6] = dark_colors[hue / 0x1000];
            lookup_colors[7] = light_colors[hue / 0x1000];

            point = hsv_distances[(val + _get_dither() * (0x1000 / LOOKUP_VAL)
                                    / 0x100) * (LOOKUP_VAL - 1) / 0x1000]
                                 [(sat + _get_dither() * (0x1000 / LOOKUP_SAT)
                                    / 0x100) * (LOOKUP_SAT - 1) / 0x1000]
                                 [((hue & 0xfff) + _get_dither()
                                            * (0x1000 / LOOKUP_HUE) / 0x100)
                                            * (LOOKUP_HUE - 1) / 0x1000];

            distfg = HSV_DISTANCE(hue % 0xfff, sat, val, (point >> 4));
            distbg = HSV_DISTANCE(hue % 0xfff, sat, val, (point & 0xf));

            /* Sanity check due to the lack of precision in hsv_distances,
             * and distbg can be > distfg because of dithering fuzziness. */
            if(distbg > distfg)
                distbg = distfg;

            outfg = lookup_colors[(point >> 4)];
            outbg = lookup_colors[(point & 0xf)];

            ch = distbg * 2 * (DENSITY_CHARS - 1) / (distbg + distfg);
            ch = 4 * ch + _get_dither() / 0x40;
            outch = density_chars[ch];
        }
        else
        {
            outbg = CACA_COLOR_BLACK;
            if((unsigned int)sat < 0x200 + _get_dither() * 0x8)
                outfg = white_colors[1 + (val * 2 + _get_dither() * 0x10)
                                       / 0x1000];
            else if((unsigned int)val > 0x800 + _get_dither() * 0x4)
                outfg = light_colors[(hue + _get_dither() * 0x10) / 0x1000];
            else
                outfg = dark_colors[(hue + _get_dither() * 0x10) / 0x1000];

            ch = (val + 0x2 * _get_dither()) * 10 / 0x1000;
            ch = 4 * ch + _get_dither() / 0x40;
            outch = density_chars[ch];
        }

        /* Now output the character */
        caca_set_color(outfg, outbg);
        caca_putchar(x, y, outch);

        _increment_dither();
    }
}


Generated by  Doxygen 1.6.0   Back to index