Graphviz 12.0.1~dev.20240716.0800
Loading...
Searching...
No Matches
gvloadimage_webp.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 <cgraph/prisize_t.h>
14#include <stdbool.h>
15#include <stdlib.h>
16#include <string.h>
17
19#include <gvc/gvio.h>
20
21#ifdef HAVE_WEBP
22#ifdef HAVE_PANGOCAIRO
23#include <cairo.h>
24#include <webp/decode.h>
25
26#ifdef _MSC_VER //*dependencies
27 #pragma comment( lib, "gvc.lib" )
28 #pragma comment( lib, "glib-2.0.lib" )
29 #pragma comment( lib, "pango-1.0.lib" )
30 #pragma comment( lib, "pangocairo-1.0.lib" )
31 #pragma comment( lib, "libcairo-2.lib" )
32 #pragma comment( lib, "gobject-2.0.lib" )
33 #pragma comment( lib, "graph.lib" )
34 #pragma comment( lib, "webp.lib" )
35#endif
36
37static const char* const kStatusMessages[] = {
38 "OK", "OUT_OF_MEMORY", "INVALID_PARAM", "BITSTREAM_ERROR",
39 "UNSUPPORTED_FEATURE", "SUSPENDED", "USER_ABORT", "NOT_ENOUGH_DATA"
40};
41
42typedef enum {
43 FORMAT_WEBP_CAIRO,
45
46static void webp_freeimage(usershape_t *us)
47{
48 cairo_surface_destroy(us->data);
49}
50
51static cairo_surface_t* webp_really_loadimage(const char *in_file, FILE* const in)
52{
53 WebPDecoderConfig config;
54 WebPDecBuffer* const output_buffer = &config.output;
55 WebPBitstreamFeatures* const bitstream = &config.input;
56 VP8StatusCode status = VP8_STATUS_OK;
57 cairo_surface_t *surface = NULL; /* source surface */
58 int ok;
59 void* data = NULL;
60
61 if (!WebPInitDecoderConfig(&config)) {
62 fprintf(stderr, "Error: WebP library version mismatch!\n");
63 return NULL;
64 }
65
66 fseek(in, 0, SEEK_END);
67 long size = ftell(in);
68 if (size < 0) {
69 fprintf(stderr, "Error: WebP could not determine %s size\n", in_file);
70 return NULL;
71 }
72 size_t data_size = (size_t)size;
73 fseek(in, 0, SEEK_SET);
74 data = malloc(data_size);
75 ok = fread(data, data_size, 1, in) == 1;
76 if (!ok) {
77 fprintf(stderr, "Error: WebP could not read %" PRISIZE_T
78 " bytes of data from %s\n", data_size, in_file);
79 free(data);
80 return NULL;
81 }
82
83 status = WebPGetFeatures(data, data_size, bitstream);
84 if (status != VP8_STATUS_OK) {
85 goto end;
86 }
87
88 output_buffer->colorspace = MODE_RGBA;
89 status = WebPDecode(data, data_size, &config);
90
91 /* FIXME - this is ugly */
92 if (! bitstream->has_alpha) {
93 int x, y;
94 unsigned char *p, t;
95
96 for (y = 0; y < output_buffer->height; y++) {
97 p = output_buffer->u.RGBA.rgba + output_buffer->u.RGBA.stride * y;
98 for (x = 0; x < output_buffer->width; x++) {
99 t = p[0]; /* swap red/blue */
100 p[0] = p[2];
101 p[2] = t;
102 p += 4;
103 }
104 }
105 }
106
107end:
108 free(data);
109 ok = status == VP8_STATUS_OK;
110 if (!ok) {
111 fprintf(stderr, "Error: WebP decoding of %s failed.\n", in_file);
112 fprintf(stderr, "Status: %d (%s)\n", status, kStatusMessages[status]);
113 return NULL;
114 }
115
116 surface = cairo_image_surface_create_for_data (
117 output_buffer->u.RGBA.rgba,
118 CAIRO_FORMAT_ARGB32,
119 output_buffer->width,
120 output_buffer->height,
121 output_buffer->u.RGBA.stride);
122
123 return surface;
124}
125
126/* get image either from cached surface, or from freskly loaded surface */
127static cairo_surface_t* webp_loadimage(GVJ_t * job, usershape_t *us)
128{
129 cairo_surface_t *surface = NULL; /* source surface */
130
131 assert(job);
132 assert(us);
133 assert(us->name);
134
135 if (us->data) {
136 if (us->datafree == webp_freeimage)
137 surface = us->data; /* use cached data */
138 else {
139 us->datafree(us); /* free incompatible cache data */
140 us->datafree = NULL;
141 us->data = NULL;
142 }
143 }
144 if (!surface) { /* read file into cache */
146 return NULL;
147 switch (us->type) {
148 case FT_WEBP:
149 if ((surface = webp_really_loadimage(us->name, us->f)))
150 cairo_surface_reference(surface);
151 break;
152 default:
153 surface = NULL;
154 }
155 if (surface) {
156 us->data = surface;
157 us->datafree = webp_freeimage;
158 }
160 }
161 return surface;
162}
163
164/* paint image into required location in graph */
165static void webp_loadimage_cairo(GVJ_t * job, usershape_t *us, boxf b, bool filled)
166{
167 (void)filled;
168
169 cairo_t *cr = job->context; /* target context */
170 cairo_surface_t *surface; /* source surface */
171
172 surface = webp_loadimage(job, us);
173 if (surface) {
174 cairo_save(cr);
175 cairo_translate(cr, b.LL.x, -b.UR.y);
176 cairo_scale(cr, (b.UR.x - b.LL.x) / us->w, (b.UR.y - b.LL.y) / us->h);
177 cairo_set_source_surface (cr, surface, 0, 0);
178 cairo_paint (cr);
179 cairo_restore(cr);
180 }
181}
182
183static gvloadimage_engine_t engine_webp = {
184 webp_loadimage_cairo
185};
186#endif
187#endif
188
190#ifdef HAVE_WEBP
191#ifdef HAVE_PANGOCAIRO
192 {FORMAT_WEBP_CAIRO, "webp:cairo", 1, &engine_webp, NULL},
193#endif
194#endif
195 {0, NULL, 0, NULL, NULL}
196};
void * malloc(YYSIZE_T)
void free(void *)
node NULL
Definition grammar.y:149
void gvusershape_file_release(usershape_t *us)
bool gvusershape_file_access(usershape_t *us)
bool ok(Agraph_t *g)
Definition gv.cpp:368
format_type
gvplugin_installed_t gvloadimage_webp_types[]
#define PRISIZE_T
PRIu64 alike for printing size_t
Definition prisize_t.h:27
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_WEBP
Definition usershape.h:27