]> Pileus Git - ~andy/gtk/blob - gdk/gdkpixbuf-render.c
New function to threshold a pixbuf's alpha channel into a bitmap.
[~andy/gtk] / gdk / gdkpixbuf-render.c
1 /* GdkPixbuf library - Rendering functions
2  *
3  * Copyright (C) 1999 The Free Software Foundation
4  *
5  * Author: Federico Mena-Quintero <federico@gimp.org>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <config.h>
24 #include <gdk/gdk.h>
25 #include <libart_lgpl/art_rect.h>
26 #include "gdk-pixbuf.h"
27
28 \f
29
30 /**
31  * gdk_pixbuf_render_threshold_alpha:
32  * @pixbuf: A pixbuf.
33  * @bitmap: Bitmap where the bilevel mask will be painted to.
34  * @src_x: Source X coordinate.
35  * @src_y: source Y coordinate.
36  * @dest_x: Destination X coordinate.
37  * @dest_y: Destination Y coordinate.
38  * @width: Width of region to threshold.
39  * @height: Height of region to threshold.
40  * @alpha_threshold: Opacity values below this will be painted as zero; all
41  * other values will be painted as one.
42  * 
43  * Takes the opacity values in a pixbuf and thresholds them to produce a
44  * bi-level alpha mask that can be used as a clipping mask for a drawable.
45  **/
46 void
47 gdk_pixbuf_render_threshold_alpha (GdkPixbuf *pixbuf, GdkBitmap *bitmap,
48                                    int src_x, int src_y,
49                                    int dest_x, int dest_y,
50                                    int width, int height,
51                                    int alpha_threshold)
52 {
53         ArtPixBuf *apb;
54         GdkGC *gc;
55         GdkColor color;
56         int x, y;
57         guchar *p;
58         int start, start_status;
59         int status;
60
61         g_return_if_fail (pixbuf != NULL);
62         apb = pixbuf->art_pixbuf;
63
64         g_return_if_fail (apb->format == ART_PIX_RGB);
65         g_return_if_fail (apb->n_channels == 3 || apb->n_channels == 4);
66         g_return_if_fail (apb->bits_per_sample == 8);
67
68         g_return_if_fail (bitmap != NULL);
69         g_return_if_fail (src_x >= 0 && src_x + width <= apb->width);
70         g_return_if_fail (src_y >= 0 && src_y + height <= apb->height);
71
72         g_return_if_fail (alpha_threshold >= 0 && alpha_threshold <= 255);
73
74         gc = gdk_gc_new (bitmap);
75
76         if (!apb->has_alpha) {
77                 color.pixel = (alpha_threshold == 255) ? 0 : 1;
78                 gdk_gc_set_foreground (gc, &color);
79                 gdk_draw_rectangle (bitmap, gc, TRUE, dest_x, dest_y, width, height);
80                 gdk_gc_unref (gc);
81                 return;
82         }
83
84         color.pixel = 0;
85         gdk_gc_set_foreground (gc, &color);
86         gdk_draw_rectangle (bitmap, gc, TRUE, dest_x, dest_y, width, height);
87
88         for (y = 0; y < height; y++) {
89                 p = (apb->pixels + (y + src_y) * apb->rowstride + src_x * apb->n_channels
90                      + apb->n_channels - 1);
91
92                 start = 0;
93                 start_status = *p < alpha_threshold;
94
95                 for (x = 0; x < width; x++) {
96                         status = *p < alpha_threshold;
97
98                         if (status != start_status) {
99                                 color.pixel = start_status ? 0 : 1;
100                                 gdk_gc_set_foreground (gc, &color);
101                                 gdk_draw_line (bitmap, gc,
102                                                start + dest_x, y + dest_y,
103                                                x - 1 + dest_x, y + dest_y);
104
105                                 start = x;
106                                 start_status = status;
107                         }
108
109                         p += apb->n_channels;
110                 }
111
112                 color.pixel = start_status ? 0 : 1;
113                 gdk_gc_set_foreground (gc, &color);
114                 gdk_draw_line (bitmap, gc,
115                                start + dest_x, y + dest_y,
116                                x - 1 + dest_x, y + dest_y);
117         }
118
119         gdk_gc_unref (gc);
120 }
121
122 void
123 gdk_pixbuf_render_to_drawable (GdkPixbuf *pixbuf, GdkDrawable *drawable,
124                                int src_x, int src_y,
125                                int dest_x, int dest_y,
126                                int width, int height,
127                                GdkPixbufAlphaMode alpha_mode,
128                                int alpha_threshold,
129                                GdkRgbDither dither,
130                                int x_dither, int y_dither)
131 {
132         ArtPixBuf *apb;
133         ArtIRect dest_rect, req_rect, area_rect;
134         GdkBitmap *bitmap;
135
136         g_return_if_fail (pixbuf != NULL);
137         apb = pixbuf->art_pixbuf;
138
139         g_return_if_fail (apb->format == ART_PIX_RGB);
140         g_return_if_fail (apb->n_channels == 3 || apb->n_channels == 4);
141         g_return_if_fail (apb->bits_per_sample == 8);
142
143         g_return_if_fail (drawable != NULL);
144         g_return_if_fail (src_x >= 0 && src_x + width <= apb->width);
145         g_return_if_fail (src_y >= 0 && src_y + height <= apb->height);
146
147
148         bitmap = gdk_pixmap_new (NULL, width, height, 1);
149 }