* lib/text.h: Added text_get_line() declaration
[dia.git] / lib / dia_image.c
blob643465d1452f2950685ba18690d9c22befd7aea9
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.
19 #include <config.h>
20 #include <string.h> /* memmove */
22 #include "geometry.h"
23 #include "dia_image.h"
24 #include <gtk/gtkwidget.h>
25 #include <gdk-pixbuf/gdk-pixbuf.h>
27 #include "dia-lib-icons.h"
29 #define SCALING_CACHE
31 struct _DiaImage {
32 GdkPixbuf *image;
33 gchar *filename;
34 #ifdef SCALING_CACHE
35 GdkPixbuf *scaled; /* a cache of the last scaled version */
36 int scaled_width, scaled_height;
37 #endif
40 gboolean _dia_image_initialized = FALSE;
42 /** Perform required initialization to handle images with GDK.
43 * Should not be called in non-interactive use.
45 void
46 dia_image_init(void)
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.
57 DiaImage
58 dia_image_get_broken(void)
60 static DiaImage broken = NULL;
62 if (broken == NULL) {
63 broken = g_new(struct _DiaImage, 1);
64 broken->image = gdk_pixbuf_new_from_inline(-1, dia_broken_icon, FALSE, NULL);
65 } else {
66 gdk_pixbuf_ref(broken->image);
68 /* Kinda hard to export :) */
69 broken->filename = g_strdup("broken");
70 #ifdef SCALING_CACHE
71 broken->scaled = NULL;
72 #endif
73 return broken;
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.
81 DiaImage
82 dia_image_load(gchar *filename)
84 DiaImage dia_img;
85 GdkPixbuf *image;
86 GError *error = NULL;
88 image = gdk_pixbuf_new_from_file(filename, &error);
89 if (image == NULL) {
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);
96 g_error_free (error);
97 return NULL;
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);
104 #ifdef SCALING_CACHE
105 dia_img->scaled = NULL;
106 #endif
107 return dia_img;
110 /** Reference an image.
111 * @param image Image that we want a reference to.
113 void
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.
122 void
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.
136 void
137 dia_image_draw(DiaImage image, GdkWindow *window,
138 int x, int y, int width, int height)
140 GdkPixbuf *scaled;
142 if (width < 1 || height < 1)
143 return;
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 */
147 #ifdef SCALING_CACHE
148 if (image->scaled == NULL ||
149 image->scaled_width != width || image->scaled_height != height) {
150 if (image->scaled)
151 gdk_pixbuf_unref(image->scaled);
152 image->scaled = gdk_pixbuf_scale_simple(image->image, width, height,
153 GDK_INTERP_TILES);
154 image->scaled_width = width;
155 image->scaled_height = height;
157 scaled = image->scaled;
158 #else
159 scaled = gdk_pixbuf_scale_simple(image->image, width, height,
160 GDK_INTERP_TILES);
161 #endif
162 } else {
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);
173 #endif
176 /** Get the width of an image.
177 * @param image An image object
178 * @returns The natural width of the object in pixels.
180 int
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.
190 int
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.
211 guint8 *
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);
222 int i, j;
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];
230 return rgb_pixels;
231 } else {
232 guint8 *pixels = gdk_pixbuf_get_pixels(image->image);
234 g_memmove(rgb_pixels, pixels, height*rowstride);
235 return rgb_pixels;
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.
244 guint8 *
245 dia_image_mask_data(DiaImage image)
247 guint8 *pixels;
248 guint8 *mask;
249 int i, size;
251 if (!gdk_pixbuf_get_has_alpha(image->image)) {
252 return NULL;
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];
266 return mask;
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.
274 const guint8 *
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);
280 return pixels;
281 } else {
282 return NULL;
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.
291 const char *
292 dia_image_filename(DiaImage image)
294 if (!image->filename)
295 return "(null)";
296 return image->filename;