1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1999 Alexander Larsson
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include <string.h> /* memmove */
23 #include "dia_image.h"
24 #include <gtk/gtkwidget.h>
25 #include <gdk-pixbuf/gdk-pixbuf.h>
27 #include "dia-lib-icons.h"
35 GdkPixbuf
*scaled
; /* a cache of the last scaled version */
36 int scaled_width
, scaled_height
;
40 gboolean _dia_image_initialized
= FALSE
;
42 /** Perform required initialization to handle images with GDK.
43 * Should not be called in non-interactive use.
48 if (!_dia_image_initialized
) {
49 gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
50 _dia_image_initialized
= TRUE
;
54 /** Get the image to put in place of a image that cannot be read.
55 * @returns A statically allocated image.
58 dia_image_get_broken(void)
60 static DiaImage broken
= NULL
;
63 broken
= g_new(struct _DiaImage
, 1);
64 broken
->image
= gdk_pixbuf_new_from_inline(-1, dia_broken_icon
, FALSE
, NULL
);
66 gdk_pixbuf_ref(broken
->image
);
68 /* Kinda hard to export :) */
69 broken
->filename
= g_strdup("broken");
71 broken
->scaled
= NULL
;
76 /** Load an image from file.
77 * @param filename Name of the file to load.
78 * @returns An image loaded from file, or NULL if an error occurred.
79 * Error messages will be displayed to the user.
82 dia_image_load(gchar
*filename
)
88 image
= gdk_pixbuf_new_from_file(filename
, &error
);
90 /* dia_image_load() function is also (mis)used to check file
91 * existance. Don't warn if the file is simply not there but
92 * only if there is something else wrong while loading it.
94 if (g_file_test(filename
, G_FILE_TEST_EXISTS
))
95 g_warning ("%s", error
->message
);
100 dia_img
= g_new(struct _DiaImage
, 1);
101 dia_img
->image
= image
;
102 /* We have a leak here, unless we add our own refcount */
103 dia_img
->filename
= g_strdup(filename
);
105 dia_img
->scaled
= NULL
;
110 /** Reference an image.
111 * @param image Image that we want a reference to.
114 dia_image_add_ref(DiaImage image
)
116 gdk_pixbuf_ref(image
->image
);
119 /** Release a reference to an image.
120 * @param image Image to unreference.
123 dia_image_release(DiaImage image
)
125 gdk_pixbuf_unref(image
->image
);
128 /** Render an image unto a window.
129 * @param image Image object to render.
130 * @param window The window to render the image into.
131 * @param x X position in window of place to render image.
132 * @param y Y position in window of place to render image.
133 * @param width Width in pixels of rendering in window.
134 * @param height Height in pixels of rendering in window.
137 dia_image_draw(DiaImage image
, GdkWindow
*window
,
138 int x
, int y
, int width
, int height
)
142 if (width
< 1 || height
< 1)
144 if (gdk_pixbuf_get_width(image
->image
) != width
||
145 gdk_pixbuf_get_height(image
->image
) != height
) {
146 /* Using TILES to make it look more like PostScript */
148 if (image
->scaled
== NULL
||
149 image
->scaled_width
!= width
|| image
->scaled_height
!= height
) {
151 gdk_pixbuf_unref(image
->scaled
);
152 image
->scaled
= gdk_pixbuf_scale_simple(image
->image
, width
, height
,
154 image
->scaled_width
= width
;
155 image
->scaled_height
= height
;
157 scaled
= image
->scaled
;
159 scaled
= gdk_pixbuf_scale_simple(image
->image
, width
, height
,
163 scaled
= image
->image
;
166 /* Once we can render Alpha, we'll do it! */
167 gdk_pixbuf_render_to_drawable_alpha(scaled
, window
,
168 0, 0, x
, y
, width
, height
,
169 GDK_PIXBUF_ALPHA_BILEVEL
, 128,
170 GDK_RGB_DITHER_NORMAL
, 0, 0);
171 #ifndef SCALING_CACHE
172 gdk_pixbuf_unref(scaled
);
176 /** Get the width of an image.
177 * @param image An image object
178 * @returns The natural width of the object in pixels.
181 dia_image_width(DiaImage image
)
183 return gdk_pixbuf_get_width(image
->image
);
186 /** Get the height of an image.
187 * @param image An image object
188 * @returns The natural height of the object in pixels.
191 dia_image_height(DiaImage image
)
193 return gdk_pixbuf_get_height(image
->image
);
196 /** Get the rowstride number of bytes per row, see gdk_pixbuf_get_rowstride.
197 * @param image An image object
198 * @returns The rowstride number of the image.
201 dia_image_rowstride(DiaImage image
)
203 return gdk_pixbuf_get_rowstride(image
->image
);
206 /** Get the raw RGB data from an image.
207 * @param image An image object.
208 * @returns An array of bytes (height*rowstride) containing the RGB data
209 * This array should be freed after use.
212 dia_image_rgb_data(DiaImage image
)
214 int width
= dia_image_width(image
);
215 int height
= dia_image_height(image
);
216 int rowstride
= dia_image_rowstride(image
);
217 int size
= height
*rowstride
;
218 guint8
*rgb_pixels
= g_malloc(size
);
220 if (gdk_pixbuf_get_has_alpha(image
->image
)) {
221 guint8
*pixels
= gdk_pixbuf_get_pixels(image
->image
);
223 for (i
= 0; i
< height
; i
++) {
224 for (j
= 0; j
< width
; j
++) {
225 rgb_pixels
[i
*rowstride
+j
*3] = pixels
[i
*rowstride
+j
*4];
226 rgb_pixels
[i
*rowstride
+j
*3+1] = pixels
[i
*rowstride
+j
*4+1];
227 rgb_pixels
[i
*rowstride
+j
*3+2] = pixels
[i
*rowstride
+j
*4+2];
232 guint8
*pixels
= gdk_pixbuf_get_pixels(image
->image
);
234 g_memmove(rgb_pixels
, pixels
, height
*rowstride
);
239 /** Get the mask data for an image.
240 * @param image An image object.
241 * @returns An array of bytes (width*height) with the alpha channel information
242 * from the image. This array should be freed after use.
245 dia_image_mask_data(DiaImage image
)
251 if (!gdk_pixbuf_get_has_alpha(image
->image
)) {
255 pixels
= gdk_pixbuf_get_pixels(image
->image
);
257 size
= gdk_pixbuf_get_width(image
->image
)*
258 gdk_pixbuf_get_height(image
->image
);
260 mask
= g_malloc(size
);
262 /* Pick every fourth byte (the alpha channel) into mask */
263 for (i
= 0; i
< size
; i
++)
264 mask
[i
] = pixels
[i
*4+3];
269 /** Get full RGBA data from an image.
270 * @param image An image object.
271 * @returns An array of pixels as delivered by gdk_pixbuf_get_pixels, or
272 * NULL if the image has no alpha channel.
275 dia_image_rgba_data(DiaImage image
)
277 if (gdk_pixbuf_get_has_alpha(image
->image
)) {
278 const guint8
*pixels
= gdk_pixbuf_get_pixels(image
->image
);
286 /** Return the filename associated with an image.
287 * @param image An image object
288 * @returns The filename associated with an image, or "(null)" if the image
289 * has no filename. This string should *not* be freed by the caller.
292 dia_image_filename(DiaImage image
)
294 if (!image
->filename
)
296 return image
->filename
;