NetSurf
webp.c
Go to the documentation of this file.
1/*
2 * Copyright 2019 Vincent Sanders <vince@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * \file
21 * implementation of content handling for image/webp
22 *
23 * This implementation uses the google webp library.
24 * Image cache handling is performed by the generic NetSurf handler.
25 */
26
27#include <stdbool.h>
28#include <stdlib.h>
29#include <setjmp.h>
30
31#include <webp/decode.h>
32
33#include "utils/utils.h"
34#include "utils/log.h"
35#include "utils/messages.h"
36#include "netsurf/bitmap.h"
37#include "content/llcache.h"
41#include "desktop/bitmap.h"
42
43#include "image/image_cache.h"
44
45#include "webp.h"
46
47/**
48 * Content create entry point.
49 *
50 * create a content object for the webp
51 */
52static nserror
54 lwc_string *imime_type,
55 const struct http_parameter *params,
57 const char *fallback_charset,
58 bool quirks,
59 struct content **c)
60{
61 struct content *webp_c; /* webp content object */
62 nserror res;
63
64 webp_c = calloc(1, sizeof(struct content));
65 if (webp_c == NULL) {
66 return NSERROR_NOMEM;
67 }
68
69 res = content__init(webp_c,
70 handler,
71 imime_type,
72 params,
73 llcache,
75 quirks);
76 if (res != NSERROR_OK) {
77 free(webp_c);
78 return res;
79 }
80
81 *c = webp_c;
82
83 return NSERROR_OK;
84}
85
86/**
87 * create a bitmap from webp content.
88 */
89static struct bitmap *
91{
92 const uint8_t *source_data; /* webp source data */
93 size_t source_size; /* length of webp source data */
94 VP8StatusCode webpres;
95 WebPBitstreamFeatures webpfeatures;
96 unsigned int bmap_flags;
97 uint8_t *pixels = NULL;
98 uint8_t *decoded;
99 size_t rowstride;
100 struct bitmap *bitmap = NULL;
101 bitmap_fmt_t webp_fmt = {
103 };
104
105 source_data = content__get_source_data(c, &source_size);
106
107 webpres = WebPGetFeatures(source_data, source_size, &webpfeatures);
108
109 if (webpres != VP8_STATUS_OK) {
110 return NULL;
111 }
112
113 if (webpfeatures.has_alpha == 0) {
114 bmap_flags = BITMAP_OPAQUE;
115 /* Image has no alpha. Premultiplied alpha makes no difference.
116 * Optimisation: Avoid unnecessary conversion by copying format.
117 */
118 webp_fmt.pma = bitmap_fmt.pma;
119 } else {
120 bmap_flags = BITMAP_NONE;
121 }
122
123 /* create bitmap */
124 bitmap = guit->bitmap->create(webpfeatures.width,
125 webpfeatures.height,
126 bmap_flags);
127 if (bitmap == NULL) {
128 /* empty bitmap could not be created */
129 return NULL;
130 }
131
132 pixels = guit->bitmap->get_buffer(bitmap);
133 if (pixels == NULL) {
134 /* bitmap with no buffer available */
136 return NULL;
137 }
138
140
141 switch (webp_fmt.layout) {
142 default:
143 /* WebP has no ABGR function, fall back to default. */
147 decoded = WebPDecodeRGBAInto(source_data, source_size, pixels,
148 rowstride * webpfeatures.height, rowstride);
149 break;
150
152 decoded = WebPDecodeBGRAInto(source_data, source_size, pixels,
153 rowstride * webpfeatures.height, rowstride);
154 break;
155
157 decoded = WebPDecodeARGBInto(source_data, source_size, pixels,
158 rowstride * webpfeatures.height, rowstride);
159 break;
160 }
161 if (decoded == NULL) {
162 /* decode failed */
164 return NULL;
165 }
166
169
170 return bitmap;
171}
172
173/**
174 * Convert the webp source data content.
175 *
176 * This ensures there is valid webp source data in the content object
177 * and then adds it to the image cache ready to be converted on
178 * demand.
179 *
180 * \param c The webp content object
181 * \return true on successful processing of teh webp content else false
182 */
183static bool webp_convert(struct content *c)
184{
185 int res;
186 const uint8_t* data;
187 size_t data_size;
188 int width;
189 int height;
190
191 data = content__get_source_data(c, &data_size);
192
193 res = WebPGetInfo(data, data_size, &width, &height);
194 if (res == 0) {
195 NSLOG(netsurf, INFO, "WebPGetInfo failed:%p", c);
196 return false;
197 }
198
199 c->width = width;
200 c->height = height;
201 c->size = c->width * c->height * 4;
202
204
207
208 return true;
209}
210
211/**
212 * Clone content.
213 */
214static nserror webp_clone(const struct content *old, struct content **new_c)
215{
216 struct content *webp_c; /* cloned webp content */
217 nserror res;
218
219 webp_c = calloc(1, sizeof(struct content));
220 if (webp_c == NULL) {
221 return NSERROR_NOMEM;
222 }
223
224 res = content__clone(old, webp_c);
225 if (res != NSERROR_OK) {
226 content_destroy(webp_c);
227 return res;
228 }
229
230 /* re-convert if the content is ready */
231 if ((old->status == CONTENT_STATUS_READY) ||
232 (old->status == CONTENT_STATUS_DONE)) {
233 if (webp_convert(webp_c) == false) {
234 content_destroy(webp_c);
236 }
237 }
238
239 *new_c = webp_c;
240
241 return NSERROR_OK;
242}
243
246 .data_complete = webp_convert,
247 .destroy = image_cache_destroy,
248 .redraw = image_cache_redraw,
249 .clone = webp_clone,
250 .get_internal = image_cache_get_internal,
252 .is_opaque = image_cache_is_opaque,
253 .no_share = false,
254};
255
256static const char *webp_types[] = {
257 "image/webp"
258};
259
void content_destroy(struct content *c)
Destroy and free a content.
Definition: content.c:354
void content_set_done(struct content *c)
Put a content in status CONTENT_STATUS_DONE.
Definition: content.c:299
nserror content__init(struct content *c, const content_handler *handler, lwc_string *imime_type, const struct http_parameter *params, llcache_handle *llcache, const char *fallback_charset, bool quirks)
Definition: content.c:190
const uint8_t * content__get_source_data(struct content *c, size_t *size)
Retrieve source of content.
Definition: content.c:1216
nserror content__clone(const struct content *c, struct content *nc)
Clone a content's data members.
Definition: content.c:1382
void content_set_ready(struct content *c)
Put a content in status CONTENT_STATUS_READY and unlock the content.
Definition: content.c:285
Protected interface to Content handling.
@ CONTENT_STATUS_READY
Some parts of content still being loaded, but can be displayed.
Definition: content_type.h:92
@ CONTENT_STATUS_DONE
Content has completed all processing.
Definition: content_type.h:95
Internal core bitmap interface.
static void bitmap_format_to_client(void *bitmap, const bitmap_fmt_t *current_fmt)
Convert a bitmap to the client bitmap format.
Definition: bitmap.h:117
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_NOMEM
Memory exhaustion.
Definition: errors.h:32
@ NSERROR_CLONE_FAILED
Failed to clone handle.
Definition: errors.h:37
@ NSERROR_OK
No error.
Definition: errors.h:30
struct netsurf_table * guit
The global interface table.
Definition: gui_factory.c:50
Interface to core interface table.
content_type image_cache_content_type(void)
Definition: image_cache.c:873
void * image_cache_get_internal(const struct content *c, void *context)
Definition: image_cache.c:856
bool image_cache_redraw(struct content *c, struct content_redraw_data *data, const struct rect *clip, const struct redraw_context *ctx)
Generic content redraw callback.
Definition: image_cache.c:798
void image_cache_destroy(struct content *content)
Definition: image_cache.c:841
nserror image_cache_add(struct content *content, struct bitmap *bitmap, image_cache_convert_fn *convert)
adds an image content to be cached.
Definition: image_cache.c:510
bool image_cache_is_opaque(struct content *c)
Definition: image_cache.c:862
The image content handler intermediate image cache.
Generic bitmap handling interface.
@ BITMAP_OPAQUE
image is opaque
Definition: bitmap.h:38
@ BITMAP_NONE
Definition: bitmap.h:37
@ BITMAP_LAYOUT_B8G8R8A8
Bite-wise BGRA: Byte order: 0xBB, 0xGG, 0xRR, 0xAA.
Definition: bitmap.h:53
@ BITMAP_LAYOUT_R8G8B8A8
Bite-wise RGBA: Byte order: 0xRR, 0xGG, 0xBB, 0xAA.
Definition: bitmap.h:50
@ BITMAP_LAYOUT_A8R8G8B8
Bite-wise ARGB: Byte order: 0xAA, 0xRR, 0xGG, 0xBB.
Definition: bitmap.h:56
static struct llcache_s * llcache
low level cache state
Definition: llcache.c:267
Low-level resource cache (interface)
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
Localised message support (interface).
int width
Definition: gui.c:160
int height
Definition: gui.c:161
Bitmap format specifier.
Definition: bitmap.h:95
bool pma
Premultiplied alpha.
Definition: bitmap.h:97
enum bitmap_layout layout
Colour component layout.
Definition: bitmap.h:96
RISC OS wimp toolkit bitmap.
Definition: bitmap.c:68
size_t rowstride
Definition: bitmap.h:65
Content operation function table.
nserror(* create)(const struct content_handler *handler, lwc_string *imime_type, const struct http_parameter *params, struct llcache_handle *llcache, const char *fallback_charset, bool quirks, struct content **c)
Content which corresponds to a single URL.
bool quirks
Content is in quirks mode.
int height
Height dimension, if applicable.
char * fallback_charset
Fallback charset, or NULL.
int width
Width dimension, if applicable.
const struct content_handler * handler
Handler for content.
content_status status
Current status.
unsigned int size
Estimated size of all data associated with this content.
void(* destroy)(void *bitmap)
Destroy a bitmap.
Definition: bitmap.h:143
void *(* create)(int width, int height, enum gui_bitmap_flags flags)
Create a new bitmap.
Definition: bitmap.h:136
size_t(* get_rowstride)(void *bitmap)
Get the number of bytes per row of the image.
Definition: bitmap.h:177
void(* modified)(void *bitmap)
Marks a bitmap as modified.
Definition: bitmap.h:200
unsigned char *(* get_buffer)(void *bitmap)
Get the image buffer from a bitmap.
Definition: bitmap.h:169
Representation of an HTTP parameter.
Definition: parameter.c:31
Handle to low-level cache object.
Definition: llcache.c:76
struct gui_bitmap_table * bitmap
Bitmap table.
Definition: gui_table.h:153
Interface to a number of general purpose functionality.
#define fallthrough
switch fall through
Definition: utils.h:119
static bool webp_convert(struct content *c)
Convert the webp source data content.
Definition: webp.c:183
static const content_handler webp_content_handler
Definition: webp.c:244
static struct bitmap * webp_cache_convert(struct content *c)
create a bitmap from webp content.
Definition: webp.c:90
static nserror webp_clone(const struct content *old, struct content **new_c)
Clone content.
Definition: webp.c:214
static nserror webp_create(const content_handler *handler, lwc_string *imime_type, const struct http_parameter *params, llcache_handle *llcache, const char *fallback_charset, bool quirks, struct content **c)
Content create entry point.
Definition: webp.c:53
static const char * webp_types[]
Definition: webp.c:256
CONTENT_FACTORY_REGISTER_TYPES(nswebp, webp_types, webp_content_handler)
Interface to image/webp content handlers.
static nserror bitmap(const struct redraw_context *ctx, struct bitmap *bitmap, int x, int y, int width, int height, colour bg, bitmap_flags_t flags)
Plot a bitmap.
Definition: plot.c:857