]> Pileus Git - ~andy/gtk/blob - gdk-pixbuf/gdk-pixbuf-util.c
Added gdk_pixbuf_copy_area() to gdk-pixbuf-utils.c and gdk-pixbuf.h.
[~andy/gtk] / gdk-pixbuf / gdk-pixbuf-util.c
1 /* GdkPixbuf library - Utilities and miscellaneous convenience functions
2  *
3  * Copyright (C) 1999 The Free Software Foundation
4  *
5  * Authors: Federico Mena-Quintero <federico@gimp.org>
6  *          Cody Russell  <bratsche@dfw.net>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include <config.h>
25 #include "gdk-pixbuf.h"
26
27 \f
28
29 /**
30  * gdk_pixbuf_add_alpha:
31  * @pixbuf: A pixbuf.
32  * @substitute_color: Whether to substitute a color for zero opacity.  If this
33  * is #FALSE, then the (@r, @g, @b) arguments will be ignored.
34  * @r: Red value to substitute.
35  * @g: Green value to substitute.
36  * @b: Blue value to substitute.
37  *
38  * Takes an existing pixbuf and adds an alpha channel to it.  If the original
39  * pixbuf already had alpha information, then the contents of the new pixbuf are
40  * exactly the same as the original's.  Otherwise, the new pixbuf will have all
41  * pixels with full opacity if @substitute_color is #FALSE.  If
42  * @substitute_color is #TRUE, then the color specified by (@r, @g, @b) will be
43  * substituted for zero opacity.
44  *
45  * Return value: A newly-created pixbuf with a reference count of 1.
46  **/
47 GdkPixbuf *
48 gdk_pixbuf_add_alpha (GdkPixbuf *pixbuf, gboolean substitute_color, guchar r, guchar g, guchar b)
49 {
50         ArtPixBuf *apb;
51         ArtPixBuf *new_apb;
52         GdkPixbuf *new_pixbuf;
53         int x, y;
54
55         g_return_val_if_fail (pixbuf != NULL, NULL);
56
57         apb = pixbuf->art_pixbuf;
58         g_return_val_if_fail (apb->format == ART_PIX_RGB, NULL);
59         g_return_val_if_fail (apb->n_channels == 3 || apb->n_channels == 4, NULL);
60         g_return_val_if_fail (apb->bits_per_sample == 8, NULL);
61
62         if (apb->has_alpha) {
63                 new_apb = art_pixbuf_duplicate (apb);
64                 if (!new_apb)
65                         return NULL;
66
67                 return gdk_pixbuf_new_from_art_pixbuf (new_apb);
68         }
69
70         new_pixbuf = gdk_pixbuf_new (ART_PIX_RGB, TRUE, 8, apb->width, apb->height);
71         if (!new_pixbuf)
72                 return NULL;
73
74         new_apb = new_pixbuf->art_pixbuf;
75
76         for (y = 0; y < apb->height; y++) {
77                 guchar *src, *dest;
78                 guchar tr, tg, tb;
79
80                 src = apb->pixels + y * apb->rowstride;
81                 dest = new_apb->pixels + y * new_apb->rowstride;
82
83                 for (x = 0; x < apb->width; x++) {
84                         tr = *dest++ = *src++;
85                         tg = *dest++ = *src++;
86                         tb = *dest++ = *src++;
87
88                         if (substitute_color && tr == r && tg == g && tb == b)
89                                 *dest++ = 0;
90                         else
91                                 *dest++ = 255;
92                 }
93         }
94
95         return new_pixbuf;
96 }
97
98 /**
99  * gdk_pixbuf_copy_area:
100  * @src_pixbuf: The pixbuf to be copied.
101  * @src_x: The X coordinate of the upper left corner of the area to copy.
102  * @src_y: The Y coordinate of the upper left corner of the area to copy.
103  * @width: The width of the area to copy.
104  * @height: The height of the area to copy.
105  * @dest_pixbuf: The pixbuf to store the copy in.
106  * @dest_x: X coordinate for the upper left corner of the rectangle to draw to in @dest_pixbuf.
107  * @dest_y: Y coordinate for the upper left corner of the rectangle to draw to in @dest_pixbuf.
108  *
109  * Takes a rectangle area beginning at (@src_x, @src_y) @width pixels wide
110  * and @height pixels high from @src_pixbuf and copy it into @dest_pixbuf
111  * at (@dest_x, @dest_y). @dest_pixbuf must already be created and must be
112  * large enough to hold the requested area.
113  *
114  * Return value: void
115  **/
116 void gdk_pixbuf_copy_area(GdkPixbuf *src_pixbuf,
117                           gint src_x, gint src_y,
118                           gint width, gint height,
119                           GdkPixbuf *dest_pixbuf,
120                           gint dest_x, gint dest_y)
121 {
122         gint src_width, src_height, dest_width, dest_height;
123
124         /* Ensure that we have a source pixbuf, and that the requested
125          * area is not larger than that pixbuf.
126          */
127         g_return_if_fail(src_pixbuf != NULL);
128
129         src_width = gdk_pixbuf_get_width(src_pixbuf);
130         src_height = gdk_pixbuf_get_height(src_pixbuf);
131
132         g_return_if_fail(src_x >= 0 && width <= src_width);
133         g_return_if_fail(src_y >= 0 && height <= src_height);
134
135         /* Ensure that we have a destination pixbuf, and that the
136          * requested area is not larger than that pixbuf.
137          */
138         g_return_if_fail(dest_pixbuf != NULL);
139
140         dest_width = gdk_pixbuf_get_width(dest_pixbuf);
141         dest_height = gdk_pixbuf_get_height(dest_pixbuf);
142
143         g_return_if_fail(dest_x >= 0 && width <= dest_width);
144         g_return_if_fail(dest_y >= 0 && height <= dest_height);
145
146         /* Scale 1:1 the source pixbuf into the destination pixbuf. */
147         gdk_pixbuf_scale(src_pixbuf,
148                          dest_pixbuf,
149                          dest_x, dest_y,
150                          width, height,
151                          (double)(dest_x - src_x),
152                          (double)(dest_y - src_y),
153                          1., 1., ART_FILTER_NEAREST);
154 }