eel-graphic-effects.c 5.61 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/* Eel - pixbuf manipulation routines for graphical effects.
 *
 * Copyright (C) 2000 Eazel, Inc
 *
 * Author: Andy Hertzfeld <andy@eazel.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
18
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 20 21
 */

/* This file contains pixbuf manipulation routines used for graphical effects like pre-lighting
22
 *  and selection hilighting */
23 24

#include <config.h>
25

26
#include "eel-graphic-effects.h"
27 28
#include "eel-glib-extensions.h"

29
#include <math.h>
30 31 32 33 34 35 36
#include <string.h>

/* shared utility to create a new pixbuf from the passed-in one */

static GdkPixbuf *
create_new_pixbuf (GdkPixbuf *src)
{
37 38 39 40 41 42 43 44 45 46 47
    g_assert (gdk_pixbuf_get_colorspace (src) == GDK_COLORSPACE_RGB);
    g_assert ((!gdk_pixbuf_get_has_alpha (src)
               && gdk_pixbuf_get_n_channels (src) == 3)
              || (gdk_pixbuf_get_has_alpha (src)
                  && gdk_pixbuf_get_n_channels (src) == 4));

    return gdk_pixbuf_new (gdk_pixbuf_get_colorspace (src),
                           gdk_pixbuf_get_has_alpha (src),
                           gdk_pixbuf_get_bits_per_sample (src),
                           gdk_pixbuf_get_width (src),
                           gdk_pixbuf_get_height (src));
48 49 50 51 52 53 54
}

/* utility routine to bump the level of a color component with pinning */

static guchar
lighten_component (guchar cur_value)
{
55 56 57 58 59 60 61
    int new_value = cur_value;
    new_value += 24 + (new_value >> 3);
    if (new_value > 255)
    {
        new_value = 255;
    }
    return (guchar) new_value;
62 63 64
}

GdkPixbuf *
65
eel_create_spotlight_pixbuf (GdkPixbuf *src)
66
{
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
    GdkPixbuf *dest;
    int i, j;
    int width, height, has_alpha, src_row_stride, dst_row_stride;
    guchar *target_pixels, *original_pixels;
    guchar *pixsrc, *pixdest;

    g_return_val_if_fail (gdk_pixbuf_get_colorspace (src) == GDK_COLORSPACE_RGB, NULL);
    g_return_val_if_fail ((!gdk_pixbuf_get_has_alpha (src)
                           && gdk_pixbuf_get_n_channels (src) == 3)
                          || (gdk_pixbuf_get_has_alpha (src)
                              && gdk_pixbuf_get_n_channels (src) == 4), NULL);
    g_return_val_if_fail (gdk_pixbuf_get_bits_per_sample (src) == 8, NULL);

    dest = create_new_pixbuf (src);

    has_alpha = gdk_pixbuf_get_has_alpha (src);
    width = gdk_pixbuf_get_width (src);
    height = gdk_pixbuf_get_height (src);
    dst_row_stride = gdk_pixbuf_get_rowstride (dest);
    src_row_stride = gdk_pixbuf_get_rowstride (src);
    target_pixels = gdk_pixbuf_get_pixels (dest);
    original_pixels = gdk_pixbuf_get_pixels (src);

    for (i = 0; i < height; i++)
    {
        pixdest = target_pixels + i * dst_row_stride;
        pixsrc = original_pixels + i * src_row_stride;
        for (j = 0; j < width; j++)
        {
            *pixdest++ = lighten_component (*pixsrc++);
            *pixdest++ = lighten_component (*pixsrc++);
            *pixdest++ = lighten_component (*pixsrc++);
            if (has_alpha)
            {
                *pixdest++ = *pixsrc++;
            }
        }
    }
    return dest;
106 107
}

108
/* This routine colorizes %src by multiplying each pixel with colors in %dest. */
109 110 111

GdkPixbuf *
eel_create_colorized_pixbuf (GdkPixbuf *src,
112
                             GdkPixbuf *dest)
113
{
114 115 116 117 118 119 120 121
    int i, j;
    int width, height, has_alpha, src_row_stride, dst_row_stride;
    guchar *target_pixels;
    guchar *original_pixels;
    guchar *pixsrc;
    guchar *pixdest;

    g_return_val_if_fail (gdk_pixbuf_get_colorspace (src) == GDK_COLORSPACE_RGB, NULL);
122 123
    g_return_val_if_fail (gdk_pixbuf_get_colorspace (dest) == GDK_COLORSPACE_RGB, NULL);

124 125 126 127
    g_return_val_if_fail ((!gdk_pixbuf_get_has_alpha (src)
                           && gdk_pixbuf_get_n_channels (src) == 3)
                          || (gdk_pixbuf_get_has_alpha (src)
                              && gdk_pixbuf_get_n_channels (src) == 4), NULL);
128 129 130 131
    g_return_val_if_fail ((!gdk_pixbuf_get_has_alpha (dest)
                           && gdk_pixbuf_get_n_channels (dest) == 3)
                          || (gdk_pixbuf_get_has_alpha (dest)
                              && gdk_pixbuf_get_n_channels (dest) == 4), NULL);
132

133 134
    g_return_val_if_fail (gdk_pixbuf_get_bits_per_sample (src) == 8, NULL);
    g_return_val_if_fail (gdk_pixbuf_get_bits_per_sample (dest) == 8, NULL);
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149

    has_alpha = gdk_pixbuf_get_has_alpha (src);
    width = gdk_pixbuf_get_width (src);
    height = gdk_pixbuf_get_height (src);
    src_row_stride = gdk_pixbuf_get_rowstride (src);
    dst_row_stride = gdk_pixbuf_get_rowstride (dest);
    target_pixels = gdk_pixbuf_get_pixels (dest);
    original_pixels = gdk_pixbuf_get_pixels (src);

    for (i = 0; i < height; i++)
    {
        pixdest = target_pixels + i * dst_row_stride;
        pixsrc = original_pixels + i * src_row_stride;
        for (j = 0; j < width; j++)
        {
150 151 152 153 154 155
            *pixdest = (*pixsrc++ * *pixdest) >> 8;
            pixdest++;
            *pixdest = (*pixsrc++ * *pixdest) >> 8;
            pixdest++;
            *pixdest = (*pixsrc++ * *pixdest) >> 8;
            pixdest++;
156 157 158 159 160 161 162
            if (has_alpha)
            {
                *pixdest++ = *pixsrc++;
            }
        }
    }
    return dest;
163
}