libpurple/purplegdkpixbuf.c

changeset 41319
04d027ed3d63
parent 41144
910bdda75c74
child 42182
3fc2d2b7b7a8
equal deleted inserted replaced
41318:56092ffeae95 41319:04d027ed3d63
1 /*
2 * Purple - Internet Messaging Library
3 * Copyright (C) Pidgin Developers <devel@pidgin.im>
4 *
5 * Purple is the legal property of its developers, whose names are too numerous
6 * to list here. Please refer to the COPYRIGHT file distributed with this
7 * source distribution.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, see <https://www.gnu.org/licenses/>.
21 */
22
23 #include "libpurple/purplegdkpixbuf.h"
24
25 #include "debug.h"
26
27 void purple_gdk_pixbuf_make_round(GdkPixbuf *pixbuf) {
28 gint width, height, rowstride;
29 guchar *pixels;
30
31 if (!gdk_pixbuf_get_has_alpha(pixbuf)) {
32 return;
33 }
34
35 width = gdk_pixbuf_get_width(pixbuf);
36 height = gdk_pixbuf_get_height(pixbuf);
37 rowstride = gdk_pixbuf_get_rowstride(pixbuf);
38 pixels = gdk_pixbuf_get_pixels(pixbuf);
39
40 if (width < 6 || height < 6) {
41 return;
42 }
43
44 /* The following code will convert the alpha of the pixel data in all
45 * corners to look something like the following diagram.
46 *
47 * 00 80 c0 FF FF c0 80 00
48 * 80 FF FF FF FF FF FF 80
49 * c0 FF FF FF FF FF FF c0
50 * FF FF FF FF FF FF FF FF
51 * FF FF FF FF FF FF FF FF
52 * c0 FF FF FF FF FF FF c0
53 * 80 FF FF FF FF FF FF 80
54 * 00 80 c0 FF FF c0 80 00
55 */
56
57 /* Top left */
58 pixels[3] = 0;
59 pixels[7] = 0x80;
60 pixels[11] = 0xC0;
61 pixels[rowstride + 3] = 0x80;
62 pixels[rowstride * 2 + 3] = 0xC0;
63
64 /* Top right */
65 pixels[width * 4 - 1] = 0;
66 pixels[width * 4 - 5] = 0x80;
67 pixels[width * 4 - 9] = 0xC0;
68 pixels[rowstride + (width * 4) - 1] = 0x80;
69 pixels[(2 * rowstride) + (width * 4) - 1] = 0xC0;
70
71 /* Bottom left */
72 pixels[(height - 1) * rowstride + 3] = 0;
73 pixels[(height - 1) * rowstride + 7] = 0x80;
74 pixels[(height - 1) * rowstride + 11] = 0xC0;
75 pixels[(height - 2) * rowstride + 3] = 0x80;
76 pixels[(height - 3) * rowstride + 3] = 0xC0;
77
78 /* Bottom right */
79 pixels[height * rowstride - 1] = 0;
80 pixels[(height - 1) * rowstride - 1] = 0x80;
81 pixels[(height - 2) * rowstride - 1] = 0xC0;
82 pixels[height * rowstride - 5] = 0x80;
83 pixels[height * rowstride - 9] = 0xC0;
84 }
85
86 gboolean
87 purple_gdk_pixbuf_is_opaque(GdkPixbuf *pixbuf) {
88 gint height, rowstride, i;
89 guchar *pixels;
90 guchar *row;
91
92 if (!gdk_pixbuf_get_has_alpha(pixbuf)) {
93 return TRUE;
94 }
95
96 height = gdk_pixbuf_get_height (pixbuf);
97 rowstride = gdk_pixbuf_get_rowstride (pixbuf);
98 pixels = gdk_pixbuf_get_pixels (pixbuf);
99
100 /* check the top row */
101 row = pixels;
102 for (i = 3; i < rowstride; i+=4) {
103 if (row[i] < 0xfe) {
104 return FALSE;
105 }
106 }
107
108 /* check the left and right sides */
109 for (i = 1; i < height - 1; i++) {
110 row = pixels + (i * rowstride);
111 if (row[3] < 0xfe || row[rowstride - 1] < 0xfe) {
112 return FALSE;
113 }
114 }
115
116 /* check the bottom */
117 row = pixels + ((height - 1) * rowstride);
118 for (i = 3; i < rowstride; i += 4) {
119 if (row[i] < 0xfe) {
120 return FALSE;
121 }
122 }
123
124 return TRUE;
125 }
126
127 static GObject *purple_gdk_pixbuf_from_data_helper(const guchar *buf, gsize count, gboolean animated)
128 {
129 GObject *pixbuf;
130 GdkPixbufLoader *loader;
131 GError *error = NULL;
132
133 loader = gdk_pixbuf_loader_new();
134
135 if (!gdk_pixbuf_loader_write(loader, buf, count, &error) || error) {
136 purple_debug_warning("gtkutils", "gdk_pixbuf_loader_write() "
137 "failed with size=%" G_GSIZE_FORMAT ": %s\n", count,
138 error ? error->message : "(no error message)");
139 if (error)
140 g_error_free(error);
141 g_object_unref(G_OBJECT(loader));
142 return NULL;
143 }
144
145 if (!gdk_pixbuf_loader_close(loader, &error) || error) {
146 purple_debug_warning("gtkutils", "gdk_pixbuf_loader_close() "
147 "failed for image of size %" G_GSIZE_FORMAT ": %s\n", count,
148 error ? error->message : "(no error message)");
149 if (error)
150 g_error_free(error);
151 g_object_unref(G_OBJECT(loader));
152 return NULL;
153 }
154
155 if (animated)
156 pixbuf = G_OBJECT(gdk_pixbuf_loader_get_animation(loader));
157 else
158 pixbuf = G_OBJECT(gdk_pixbuf_loader_get_pixbuf(loader));
159 if (!pixbuf) {
160 purple_debug_warning("gtkutils", "%s() returned NULL for image "
161 "of size %" G_GSIZE_FORMAT "\n",
162 animated ? "gdk_pixbuf_loader_get_animation"
163 : "gdk_pixbuf_loader_get_pixbuf", count);
164 g_object_unref(G_OBJECT(loader));
165 return NULL;
166 }
167
168 g_object_ref(pixbuf);
169 g_object_unref(G_OBJECT(loader));
170
171 return pixbuf;
172 }
173
174 GdkPixbuf *purple_gdk_pixbuf_from_data(const guchar *buf, gsize count)
175 {
176 return GDK_PIXBUF(purple_gdk_pixbuf_from_data_helper(buf, count, FALSE));
177 }
178
179 GdkPixbuf *
180 purple_gdk_pixbuf_from_image(PurpleImage *image)
181 {
182 return purple_gdk_pixbuf_from_data(purple_image_get_data(image),
183 purple_image_get_data_size(image));
184 }
185
186 GdkPixbuf *purple_gdk_pixbuf_new_from_file(const gchar *filename)
187 {
188 GdkPixbuf *pixbuf;
189 GError *error = NULL;
190
191 g_return_val_if_fail(filename != NULL, NULL);
192 g_return_val_if_fail(filename[0] != '\0', NULL);
193
194 pixbuf = gdk_pixbuf_new_from_file(filename, &error);
195 if (!pixbuf || error) {
196 purple_debug_warning("gtkutils", "gdk_pixbuf_new_from_file() "
197 "returned %s for file %s: %s\n",
198 pixbuf ? "something" : "nothing",
199 filename,
200 error ? error->message : "(no error message)");
201 if (error)
202 g_error_free(error);
203 if (pixbuf)
204 g_object_unref(G_OBJECT(pixbuf));
205 return NULL;
206 }
207
208 return pixbuf;
209 }
210
211 GdkPixbuf *purple_gdk_pixbuf_new_from_file_at_size(const char *filename, int width, int height)
212 {
213 GdkPixbuf *pixbuf;
214 GError *error = NULL;
215
216 g_return_val_if_fail(filename != NULL, NULL);
217 g_return_val_if_fail(filename[0] != '\0', NULL);
218
219 pixbuf = gdk_pixbuf_new_from_file_at_size(filename,
220 width, height, &error);
221 if (!pixbuf || error) {
222 purple_debug_warning("gtkutils", "gdk_pixbuf_new_from_file_at_size() "
223 "returned %s for file %s: %s\n",
224 pixbuf ? "something" : "nothing",
225 filename,
226 error ? error->message : "(no error message)");
227 if (error)
228 g_error_free(error);
229 if (pixbuf)
230 g_object_unref(G_OBJECT(pixbuf));
231 return NULL;
232 }
233
234 return pixbuf;
235 }

mercurial