source: mainline/uspace/lib/draw/codec/webp.c@ eec201d

Last change on this file since eec201d was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 6.7 KB
Line 
1/*
2 * Copyright (c) 2014 Martin Decky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup draw
30 * @{
31 */
32/**
33 * @file
34 */
35
36#include <stdlib.h>
37#include <byteorder.h>
38#include <align.h>
39#include <stdbool.h>
40#include <pixconv.h>
41#include <fourcc.h>
42#include <stdint.h>
43#include <abi/fourcc.h>
44#include "webp.h"
45
46/** Check for input buffer overrun condition */
47#define CHECK_OVERRUN(state, retval) \
48 do { \
49 if ((state).overrun) \
50 return (retval); \
51 } while (false)
52
53#define SIGNATURE_WEBP_LOSSLESS UINT8_C(0x2f)
54
55enum {
56 FOURCC_RIFF = FOURCC('R', 'I', 'F', 'F'),
57 FOURCC_WEBP = FOURCC('W', 'E', 'B', 'P'),
58 FOURCC_WEBP_LOSSLESS = FOURCC('V', 'P', '8', 'L')
59};
60
61typedef enum {
62 TRANSFORM_PREDICTOR = 0,
63 TRANSFORM_COLOR = 1,
64 TRANSFORM_SUBTRACT = 2,
65 TRANSFORM_COLOR_INDEXING = 3
66} webp_transform_t;
67
68typedef struct {
69 fourcc_t fourcc;
70 uint32_t payload_size;
71} __attribute__((packed)) riff_header_t;
72
73typedef struct {
74 fourcc_t fourcc;
75 fourcc_t encoding;
76 uint32_t stream_size;
77 uint8_t signature;
78} __attribute__((packed)) webp_header_t;
79
80typedef struct {
81 uint32_t stream_size;
82 uint16_t width;
83 uint16_t height;
84 bool alpha_used;
85 uint8_t version;
86
87 uint8_t *src; /**< Input buffer */
88 size_t srclen; /**< Input buffer size */
89 size_t srccnt; /**< Position in the input buffer */
90
91 uint32_t bitbuf; /**< Bit buffer */
92 size_t bitlen; /**< Number of bits in the bit buffer */
93
94 bool overrun; /**< Overrun condition */
95} webp_t;
96
97/** Get bits from the bit buffer
98 *
99 * @param state WebP state.
100 * @param cnt Number of bits to return (at most 32).
101 *
102 * @return Returned bits.
103 *
104 */
105static inline uint32_t get_bits(webp_t *state, size_t cnt)
106{
107 /* Bit accumulator for at least 36 bits */
108 uint64_t val = state->bitbuf;
109
110 while (state->bitlen < cnt) {
111 if (state->srccnt == state->srclen) {
112 state->overrun = true;
113 return 0;
114 }
115
116 /* Load 8 more bits */
117 val |= ((uint64_t) state->src[state->srccnt]) << state->bitlen;
118 state->srccnt++;
119 state->bitlen += 8;
120 }
121
122 /* Update bits in the buffer */
123 state->bitbuf = (uint32_t) (val >> cnt);
124 state->bitlen -= cnt;
125
126 return ((uint32_t) (val & ((1 << cnt) - 1)));
127}
128
129/** Decode WebP header
130 *
131 * @param[in] data Memory representation of WebP.
132 * @param[in] size Size of the representation (in bytes).
133 * @param[out] webp Decoded WebP.
134 *
135 * @return True on succesful decoding.
136 * @return False on failure.
137 *
138 */
139static bool decode_webp_header(void *data, size_t size, webp_t *webp)
140{
141 /* Headers sanity check */
142 if ((size < sizeof(riff_header_t)) ||
143 (size - sizeof(riff_header_t) < sizeof(webp_header_t)))
144 return false;
145
146 riff_header_t *riff_header = (riff_header_t *) data;
147 if (riff_header->fourcc != FOURCC_RIFF)
148 return false;
149
150 /* Check payload size */
151 size_t payload_size = uint32_t_le2host(riff_header->payload_size);
152 if (payload_size + sizeof(riff_header_t) > size)
153 return false;
154
155 data += sizeof(riff_header_t);
156 webp_header_t *webp_header = (webp_header_t *) data;
157 if (webp_header->fourcc != FOURCC_WEBP)
158 return false;
159
160 /* Only lossless encoding supported so far */
161 if (webp_header->encoding != FOURCC_WEBP_LOSSLESS)
162 return false;
163
164 webp->stream_size = uint32_t_le2host(webp_header->stream_size);
165 if (webp->stream_size + sizeof(riff_header_t) +
166 sizeof(webp_header_t) > size)
167 return false;
168
169 if (webp_header->signature != SIGNATURE_WEBP_LOSSLESS)
170 return false;
171
172 data += sizeof(webp_header_t);
173
174 /* Setup decoding state */
175 webp->src = (uint8_t *) data;
176 webp->srclen = webp->stream_size - 1;
177 webp->srccnt = 0;
178 webp->bitbuf = 0;
179 webp->bitlen = 0;
180 webp->overrun = false;
181
182 /* Decode the rest of the metadata */
183 webp->width = get_bits(webp, 14) + 1;
184 CHECK_OVERRUN(*webp, false);
185
186 webp->height = get_bits(webp, 14) + 1;
187 CHECK_OVERRUN(*webp, false);
188
189 webp->alpha_used = get_bits(webp, 1);
190 CHECK_OVERRUN(*webp, false);
191
192 webp->version = get_bits(webp, 3);
193 CHECK_OVERRUN(*webp, false);
194
195 if (webp->version != 0)
196 return false;
197
198 return true;
199}
200
201/** Decode WebP format
202 *
203 * Decode WebP format and create a surface from it. The supported
204 * variants of WebP are currently limited to losslessly compressed
205 * ARGB images.
206 *
207 * @param[in] data Memory representation of WebP.
208 * @param[in] size Size of the representation (in bytes).
209 * @param[in] flags Surface creation flags.
210 *
211 * @return Newly allocated surface with the decoded content.
212 * @return NULL on error or unsupported format.
213 *
214 */
215surface_t *decode_webp(void *data, size_t size, surface_flags_t flags)
216{
217 webp_t webp;
218 if (!decode_webp_header(data, size, &webp))
219 return NULL;
220
221 bool transform_present = false;
222
223 do {
224 transform_present = get_bits(&webp, 1);
225 CHECK_OVERRUN(webp, NULL);
226
227 if (transform_present) {
228 webp_transform_t transform = get_bits(&webp, 2);
229 CHECK_OVERRUN(webp, NULL);
230
231 if (transform == TRANSFORM_PREDICTOR) {
232 // FIXME TODO
233 } else
234 return NULL;
235
236 // FIXME: decode other transforms
237 }
238 } while (transform_present);
239
240 // FIXME: decode image data
241
242 return NULL;
243}
244
245/** Encode WebP format
246 *
247 * Encode WebP format into an array.
248 *
249 * @param[in] surface Surface to be encoded into WebP.
250 * @param[out] pdata Pointer to the resulting array.
251 * @param[out] psize Pointer to the size of the resulting array.
252 *
253 * @return True on succesful encoding.
254 * @return False on failure.
255 *
256 */
257bool encode_webp(surface_t *surface, void **pdata, size_t *psize)
258{
259 // TODO
260 return false;
261}
262
263/** @}
264 */
Note: See TracBrowser for help on using the repository browser.