* added GDK_PIXBUF_LIBS in order to create pixbuf.dll
[dia.git] / lib / dia_image.c
blobf9abb6b6e7792bc94cf1a665c9ee891a74a1e42d
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 "pixmaps/broken.xpm"
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 void
41 dia_image_init(void)
43 gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
46 DiaImage
47 dia_image_get_broken(void)
49 static DiaImage broken = NULL;
51 if (broken == NULL) {
52 broken = g_new(struct _DiaImage, 1);
53 broken->image = gdk_pixbuf_new_from_xpm_data((const char **)broken_xpm);
54 } else {
55 gdk_pixbuf_ref(broken->image);
57 /* Kinda hard to export :) */
58 broken->filename = g_strdup("broken");
59 #ifdef SCALING_CACHE
60 broken->scaled = NULL;
61 #endif
62 return broken;
65 DiaImage
66 dia_image_load(gchar *filename)
68 DiaImage dia_img;
69 GdkPixbuf *image;
71 image = gdk_pixbuf_new_from_file(filename, NULL);
72 if (image == NULL)
73 return NULL;
75 dia_img = g_new(struct _DiaImage, 1);
76 dia_img->image = image;
77 /* We have a leak here, unless we add our own refcount */
78 dia_img->filename = g_strdup(filename);
79 #ifdef SCALING_CACHE
80 dia_img->scaled = NULL;
81 #endif
82 return dia_img;
85 void
86 dia_image_add_ref(DiaImage image)
88 gdk_pixbuf_ref(image->image);
91 void
92 dia_image_release(DiaImage image)
94 gdk_pixbuf_unref(image->image);
97 void
98 dia_image_draw(DiaImage image, GdkWindow *window,
99 int x, int y, int width, int height)
101 GdkPixbuf *scaled;
103 if (gdk_pixbuf_get_width(image->image) != width ||
104 gdk_pixbuf_get_height(image->image) != height) {
105 /* Using TILES to make it look more like PostScript */
106 #ifdef SCALING_CACHE
107 if (image->scaled == NULL ||
108 image->scaled_width != width || image->scaled_height != height) {
109 if (image->scaled)
110 gdk_pixbuf_unref(image->scaled);
111 image->scaled = gdk_pixbuf_scale_simple(image->image, width, height,
112 GDK_INTERP_TILES);
113 image->scaled_width = width;
114 image->scaled_height = height;
116 scaled = image->scaled;
117 #else
118 scaled = gdk_pixbuf_scale_simple(image->image, width, height,
119 GDK_INTERP_TILES);
120 #endif
121 } else {
122 scaled = image->image;
125 /* Once we can render Alpha, we'll do it! */
126 gdk_pixbuf_render_to_drawable_alpha(scaled, window,
127 0, 0, x, y, width, height,
128 GDK_PIXBUF_ALPHA_BILEVEL, 128,
129 GDK_RGB_DITHER_NORMAL, 0, 0);
130 #ifndef SCALING_CACHE
131 gdk_pixbuf_unref(scaled);
132 #endif
135 int
136 dia_image_width(DiaImage image)
138 return gdk_pixbuf_get_width(image->image);
141 int
142 dia_image_height(DiaImage image)
144 return gdk_pixbuf_get_height(image->image);
148 dia_image_rowstride(DiaImage image)
150 return gdk_pixbuf_get_rowstride(image->image);
153 guint8 *
154 dia_image_rgb_data(DiaImage image)
156 int width = dia_image_width(image);
157 int height = dia_image_height(image);
158 int rowstride = dia_image_rowstride(image);
159 int size = height*rowstride;
160 guint8 *rgb_pixels = g_malloc(size);
162 if (gdk_pixbuf_get_has_alpha(image->image)) {
163 guint8 *pixels = gdk_pixbuf_get_pixels(image->image);
164 int i, j;
165 for (i = 0; i < height; i++) {
166 for (j = 0; j < width; j++) {
167 rgb_pixels[i*rowstride+j*3] = pixels[i*rowstride+j*4];
168 rgb_pixels[i*rowstride+j*3+1] = pixels[i*rowstride+j*4+1];
169 rgb_pixels[i*rowstride+j*3+2] = pixels[i*rowstride+j*4+2];
172 return rgb_pixels;
173 } else {
174 guint8 *pixels = gdk_pixbuf_get_pixels(image->image);
176 g_memmove(rgb_pixels, pixels, height*rowstride);
177 return rgb_pixels;
181 guint8 *
182 dia_image_mask_data(DiaImage image)
184 guint8 *pixels;
185 guint8 *mask;
186 int i, size;
188 if (!gdk_pixbuf_get_has_alpha(image->image)) {
189 return NULL;
192 pixels = gdk_pixbuf_get_pixels(image->image);
194 size = gdk_pixbuf_get_width(image->image)*
195 gdk_pixbuf_get_height(image->image);
197 mask = g_malloc(size);
199 /* Pick every fourth byte (the alpha channel) into mask */
200 for (i = 0; i < size; i++)
201 mask[i] = pixels[i*4+3];
203 return mask;
206 guint8 *
207 dia_image_rgba_data(DiaImage image)
209 int size;
210 guint8 *rgb_pixels;
211 int width = dia_image_width(image);
212 int height = dia_image_height(image);
213 int rowstride = dia_image_rowstride(image);
215 if (gdk_pixbuf_get_has_alpha(image->image)) {
216 guint8 *pixels = gdk_pixbuf_get_pixels(image->image);
218 size = gdk_pixbuf_get_rowstride(image->image)*
219 gdk_pixbuf_get_height(image->image);
220 rgb_pixels = g_malloc(size);
222 g_memmove(rgb_pixels, pixels, size);
224 for(i = 0; i < height; i++) {
225 g_memmove(&rgb_pixels[i*width*4], &pixels[i*rowstride], width*4);
228 return rgb_pixels;
229 } else {
230 return NULL;
234 char *
235 dia_image_filename(DiaImage image)
237 return image->filename;