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