Graphviz 12.0.1~dev.20240716.0800
Loading...
Searching...
No Matches
gvloadimage_gd.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include "config.h"
12
13#include <stdbool.h>
14#include <stdlib.h>
15#include <stddef.h>
16#include <string.h>
17
18#ifdef HAVE_PANGOCAIRO
19#include <cairo.h>
20#endif
21
23#include <gvc/gvio.h>
24#include <gd.h>
25
31
32
33static void gd_freeimage(usershape_t *us)
34{
35 gdImageDestroy(us->data);
36}
37
38static gdImagePtr gd_loadimage(GVJ_t * job, usershape_t *us)
39{
40 assert(job);
41 assert(us);
42 assert(us->name);
43
44 if (us->data) {
45 if (us->datafree != gd_freeimage) {
46 us->datafree(us); /* free incompatible cache data */
47 us->data = NULL;
48 us->datafree = NULL;
49 }
50 }
51 if (!us->data) { /* read file into cache */
53 return NULL;
54 switch (us->type) {
55#ifdef HAVE_GD_PNG
56 case FT_PNG:
57 us->data = gdImageCreateFromPng(us->f);
58 break;
59#endif
60#ifdef HAVE_GD_GIF
61 case FT_GIF:
62 us->data = gdImageCreateFromGif(us->f);
63 break;
64#endif
65#ifdef HAVE_GD_JPEG
66 case FT_JPEG:
67 us->data = gdImageCreateFromJpeg(us->f);
68 break;
69#endif
70 default:
71 break;
72 }
73 if (us->data)
75
77 }
78 return us->data;
79}
80
81static gdImagePtr gd_rotateimage(gdImagePtr im, int rotation)
82{
83 gdImagePtr im2 = gdImageCreate(im->sy, im->sx);
84
85 gdImageCopyRotated(im2, im, im2->sx / 2., im2->sy / 2.,
86 0, 0, im->sx, im->sy, rotation);
87 gdImageDestroy(im);
88 return im2;
89}
90
91static void gd_loadimage_gd(GVJ_t * job, usershape_t *us, boxf b, bool filled)
92{
93 (void)filled;
94
95 gdImagePtr im2, im = job->context;
96
97 if ((im2 = gd_loadimage(job, us))) {
98 if (job->rotation)
99 im2 = gd_rotateimage(im2, job->rotation);
100 gdImageCopyResized(im, im2, ROUND(b.LL.x), ROUND(b.LL.y), 0, 0,
101 ROUND(b.UR.x - b.LL.x), ROUND(b.UR.y - b.LL.y), im2->sx, im2->sy);
102 }
103}
104
105#ifdef HAVE_PANGOCAIRO
106static void gd_loadimage_cairo(GVJ_t * job, usershape_t *us, boxf b, bool filled)
107{
108 (void)filled;
109
110 cairo_t *cr = job->context; /* target context */
111 int x, y, stride, width, height;
112 unsigned px;
113 unsigned char *data;
114 cairo_surface_t *surface; /* source surface */
115 gdImagePtr im;
116
117 if ((im = gd_loadimage(job, us))) {
118 width = im->sx;
119 height = im->sy;
120// cairo_format_stride_for_width() not available prior to cairo-1.6.4 or so (fc9)
121//stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width);
122 stride = width*4;
123 data = malloc (stride * height);
124 surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32,
125 width, height, stride);
126
127 if (im->trueColor) {
128 if (im->saveAlphaFlag) {
129 for (y = 0; y < height; y++) {
130 for (x = 0; x < width; x++) {
131 px = gdImageTrueColorPixel(im, x, y);
132 *data++ = gdTrueColorGetBlue(px);
133 *data++ = gdTrueColorGetGreen(px);
134 *data++ = gdTrueColorGetRed(px);
135 *data++ = (0x7F-gdTrueColorGetAlpha(px)) << 1;
136 }
137 }
138 }
139 else {
140 for (y = 0; y < height; y++) {
141 for (x = 0; x < width; x++) {
142 px = gdImageTrueColorPixel(im, x, y);
143 *data++ = gdTrueColorGetBlue(px);
144 *data++ = gdTrueColorGetGreen(px);
145 *data++ = gdTrueColorGetRed(px);
146 *data++ = 0xFF;
147 }
148 }
149 }
150 }
151 else {
152 for (y = 0; y < height; y++) {
153 for (x = 0; x < width; x++) {
154 px = gdImagePalettePixel(im, x, y);
155 *data++ = im->blue[px];
156 *data++ = im->green[px];
157 *data++ = im->red[px];
158 *data++ = (px==im->transparent)?0x00:0xff;
159 }
160 }
161 }
162
163 cairo_save(cr);
164 cairo_translate(cr, b.LL.x, -b.UR.y);
165 cairo_scale(cr, (b.UR.x - b.LL.x)/(us->w), (b.UR.y - b.LL.y)/(us->h));
166 cairo_set_source_surface (cr, surface, 0, 0);
167 cairo_paint (cr);
168 cairo_restore(cr);
169
170 cairo_surface_destroy(surface);
171 }
172}
173#endif
174
175static void gd_loadimage_ps(GVJ_t * job, usershape_t *us, boxf b, bool filled)
176{
177 (void)filled;
178
179 gdImagePtr im = NULL;
180 int X, Y, x, y, px;
181
182 if ((im = gd_loadimage(job, us))) {
183 X = im->sx;
184 Y = im->sy;
185
186 gvputs(job, "save\n");
187
188 /* define image data as string array (one per raster line) */
189 gvputs(job, "/myctr 0 def\n");
190 gvputs(job, "/myarray [\n");
191 if (im->trueColor) {
192 for (y = 0; y < Y; y++) {
193 gvputs(job, "<");
194 for (x = 0; x < X; x++) {
195 px = gdImageTrueColorPixel(im, x, y);
196 gvprintf(job, "%02x%02x%02x",
197 gdTrueColorGetRed(px),
198 gdTrueColorGetGreen(px),
199 gdTrueColorGetBlue(px));
200 }
201 gvputs(job, ">\n");
202 }
203 }
204 else {
205 for (y = 0; y < Y; y++) {
206 gvputs(job, "<");
207 for (x = 0; x < X; x++) {
208 px = gdImagePalettePixel(im, x, y);
209 gvprintf(job, "%02x%02x%02x",
210 im->red[px],
211 im->green[px],
212 im->blue[px]);
213 }
214 gvputs(job, ">\n");
215 }
216 }
217 gvputs(job, "] def\n");
218 gvputs(job,"/myproc { myarray myctr get /myctr myctr 1 add def } def\n");
219
220 /* this sets the position of the image */
221 gvprintf(job, "%g %g translate\n",
222 (b.LL.x + (b.UR.x - b.LL.x) * (1. - (job->dpi.x) / 96.) / 2.),
223 (b.LL.y + (b.UR.y - b.LL.y) * (1. - (job->dpi.y) / 96.) / 2.));
224
225 /* this sets the rendered size to fit the box */
226 gvprintf(job,"%g %g scale\n",
227 ((b.UR.x - b.LL.x) * (job->dpi.x) / 96.),
228 ((b.UR.y - b.LL.y) * (job->dpi.y) / 96.));
229
230 /* xsize ysize bits-per-sample [matrix] */
231 gvprintf(job, "%d %d 8 [%d 0 0 %d 0 %d]\n", X, Y, X, -Y, Y);
232
233 gvputs(job, "{myproc} false 3 colorimage\n");
234
235 gvputs(job, "restore\n");
236 }
237}
238
242
246
247#ifdef HAVE_PANGOCAIRO
249 gd_loadimage_cairo
250};
251#endif
252
254 {FORMAT_GD_GD, "gd:gd", 1, &engine, NULL},
255 {FORMAT_GD2_GD, "gd2:gd", 1, &engine, NULL},
256#ifdef HAVE_GD_GIF
257 {FORMAT_GIF_GD, "gif:gd", 1, &engine, NULL},
258#endif
259#ifdef HAVE_GD_JPEG
260 {FORMAT_JPG_GD, "jpeg:gd", 1, &engine, NULL},
261 {FORMAT_JPG_GD, "jpe:gd", 1, &engine, NULL},
262 {FORMAT_JPG_GD, "jpg:gd", 1, &engine, NULL},
263#endif
264#ifdef HAVE_GD_PNG
265 {FORMAT_PNG_GD, "png:gd", 1, &engine, NULL},
266#endif
267#ifdef HAVE_GD_WBMP
268 {FORMAT_WBMP_GD, "wbmp:gd", 1, &engine, NULL},
269#endif
270#ifdef HAVE_GD_XPM
271 {FORMAT_XBM_GD, "xbm:gd", 1, &engine, NULL},
272#endif
273
274 {FORMAT_GD_PS, "gd:ps", 1, &engine_ps, NULL},
275 {FORMAT_GD_PS, "gd:lasi", 1, &engine_ps, NULL},
276 {FORMAT_GD2_PS, "gd2:ps", 1, &engine_ps, NULL},
277 {FORMAT_GD2_PS, "gd2:lasi", 1, &engine_ps, NULL},
278#ifdef HAVE_GD_GIF
279 {FORMAT_GIF_PS, "gif:ps", 1, &engine_ps, NULL},
280 {FORMAT_GIF_PS, "gif:lasi", 1, &engine_ps, NULL},
281#endif
282#ifdef HAVE_GD_JPEG
283 {FORMAT_JPG_PS, "jpeg:ps", 1, &engine_ps, NULL},
284 {FORMAT_JPG_PS, "jpg:ps", 1, &engine_ps, NULL},
285 {FORMAT_JPG_PS, "jpe:ps", 1, &engine_ps, NULL},
286 {FORMAT_JPG_PS, "jpeg:lasi", 1, &engine_ps, NULL},
287 {FORMAT_JPG_PS, "jpg:lasi", 1, &engine_ps, NULL},
288 {FORMAT_JPG_PS, "jpe:lasi", 1, &engine_ps, NULL},
289#endif
290#ifdef HAVE_GD_PNG
291 {FORMAT_PNG_PS, "png:ps", 1, &engine_ps, NULL},
292 {FORMAT_PNG_PS, "png:lasi", 1, &engine_ps, NULL},
293#endif
294#ifdef HAVE_GD_WBMP
295 {FORMAT_WBMP_PS, "wbmp:ps", 1, &engine_ps, NULL},
296 {FORMAT_WBMP_PS, "wbmp:lasi", 1, &engine_ps, NULL},
297#endif
298#ifdef HAVE_GD_XPM
299 {FORMAT_XBM_PS, "xbm:ps", 1, &engine_ps, NULL},
300 {FORMAT_XBM_PS, "xbm:lasi", 1, &engine_ps, NULL},
301#endif
302
303#ifdef HAVE_PANGOCAIRO
304 {FORMAT_GD_CAIRO, "gd:cairo", 1, &engine_cairo, NULL},
305 {FORMAT_GD2_CAIRO, "gd2:cairo", 1, &engine_cairo, NULL},
306#ifdef HAVE_GD_GIF
307 {FORMAT_GIF_CAIRO, "gif:cairo", 1, &engine_cairo, NULL},
308#endif
309#ifdef HAVE_GD_JPEG
310 {FORMAT_JPG_CAIRO, "jpeg:cairo", 1, &engine_cairo, NULL},
311 {FORMAT_JPG_CAIRO, "jpg:cairo", 1, &engine_cairo, NULL},
312 {FORMAT_JPG_CAIRO, "jpe:cairo", 1, &engine_cairo, NULL},
313#endif
314#ifdef HAVE_GD_PNG
315 {FORMAT_PNG_CAIRO, "png:cairo", -1, &engine_cairo, NULL},
316#endif
317#ifdef HAVE_GD_WBMP
318 {FORMAT_WBMP_CAIRO, "wbmp:cairo", 1, &engine_cairo, NULL},
319#endif
320#ifdef HAVE_GD_XPM
321 {FORMAT_XBM_CAIRO, "xbm:cairo", 1, &engine_cairo, NULL},
322#endif
323#endif /* HAVE_PANGOCAIRO */
324 {0, NULL, 0, NULL, NULL}
325};
#define ROUND(f)
Definition arith.h:48
#define Y(i)
Definition gdefs.h:3
#define X(prefix, name, str, type, subtype,...)
Definition gdefs.h:14
void * malloc(YYSIZE_T)
node NULL
Definition grammar.y:149
void gvusershape_file_release(usershape_t *us)
bool gvusershape_file_access(usershape_t *us)
int gvputs(GVJ_t *job, const char *s)
Definition gvdevice.c:263
void gvprintf(GVJ_t *job, const char *format,...)
Definition gvdevice.c:394
static gvloadimage_engine_t engine_ps
static void gd_loadimage_ps(GVJ_t *job, usershape_t *us, boxf b, bool filled)
static void gd_freeimage(usershape_t *us)
static gvloadimage_engine_t engine
gvplugin_installed_t gvloadimage_gd_types[]
static void gd_loadimage_gd(GVJ_t *job, usershape_t *us, boxf b, bool filled)
static gdImagePtr gd_loadimage(GVJ_t *job, usershape_t *us)
format_type
@ FORMAT_JPG_PS
@ FORMAT_GD_GD
@ FORMAT_WBMP_PS
@ FORMAT_GIF_GD
@ FORMAT_XBM_PS
@ FORMAT_XBM_GD
@ FORMAT_XPM_GD
@ FORMAT_WBMP_CAIRO
@ FORMAT_GD_PS
@ FORMAT_JPG_GD
@ FORMAT_PNG_GD
@ FORMAT_WBMP_GD
@ FORMAT_GD_CAIRO
@ FORMAT_XBM_CAIRO
@ FORMAT_GD2_CAIRO
@ FORMAT_GIF_CAIRO
@ FORMAT_GIF_PS
@ FORMAT_JPG_CAIRO
@ FORMAT_GD2_GD
@ FORMAT_XPM_PS
@ FORMAT_PNG_PS
@ FORMAT_PNG_CAIRO
@ FORMAT_GD2_PS
@ FORMAT_XPM_CAIRO
static gdImagePtr gd_rotateimage(gdImagePtr im, int rotation)
static gvloadimage_engine_t engine_cairo
int rotation
Definition gvcjob.h:319
pointf dpi
Definition gvcjob.h:325
void * context
Definition gvcjob.h:295
Definition geom.h:41
pointf UR
Definition geom.h:41
pointf LL
Definition geom.h:41
Definition legal.c:50
ingroup plugin_api
Definition gvplugin.h:35
double x
Definition geom.h:29
double y
Definition geom.h:29
const char * name
Definition usershape.h:54
FILE * f
Definition usershape.h:58
void(* datafree)(usershape_t *us)
Definition usershape.h:65
void * data
Definition usershape.h:63
imagetype_t type
Definition usershape.h:59
double h
Definition usershape.h:61
double w
Definition usershape.h:61
@ FT_GIF
Definition usershape.h:25
@ FT_JPEG
Definition usershape.h:25
@ FT_PNG
Definition usershape.h:25