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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since abf2dfd was abf2dfd, checked in by Martin Decky <martin@…>, 10 years ago

preparations for interface types

  • 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 <sys/types.h>
42#include <abi/fourcc.h>
43#include "webp.h"
44
45/** Check for input buffer overrun condition */
46#define CHECK_OVERRUN(state, retval) \
47 do { \
48 if ((state).overrun) \
49 return (retval); \
50 } while (false)
51
52#define SIGNATURE_WEBP_LOSSLESS UINT8_C(0x2f)
53
54enum {
55 FOURCC_RIFF = FOURCC('R', 'I', 'F', 'F'),
56 FOURCC_WEBP = FOURCC('W', 'E', 'B', 'P'),
57 FOURCC_WEBP_LOSSLESS = FOURCC('V', 'P', '8', 'L')
58};
59
60typedef enum {
61 TRANSFORM_PREDICTOR = 0,
62 TRANSFORM_COLOR = 1,
63 TRANSFORM_SUBTRACT = 2,
64 TRANSFORM_COLOR_INDEXING = 3
65} webp_transform_t;
66
67typedef struct {
68 fourcc_t fourcc;
69 uint32_t payload_size;
70} __attribute__((packed)) riff_header_t;
71
72typedef struct {
73 fourcc_t fourcc;
74 fourcc_t encoding;
75 uint32_t stream_size;
76 uint8_t signature;
77} __attribute__((packed)) webp_header_t;
78
79typedef struct {
80 uint32_t stream_size;
81 uint16_t width;
82 uint16_t height;
83 bool alpha_used;
84 uint8_t version;
85
86 uint8_t *src; /**< Input buffer */
87 size_t srclen; /**< Input buffer size */
88 size_t srccnt; /**< Position in the input buffer */
89
90 uint32_t bitbuf; /**< Bit buffer */
91 size_t bitlen; /**< Number of bits in the bit buffer */
92
93 bool overrun; /**< Overrun condition */
94} webp_t;
95
96/** Get bits from the bit buffer
97 *
98 * @param state WebP state.
99 * @param cnt Number of bits to return (at most 32).
100 *
101 * @return Returned bits.
102 *
103 */
104static inline uint32_t get_bits(webp_t *state, size_t cnt)
105{
106 /* Bit accumulator for at least 36 bits */
107 uint64_t val = state->bitbuf;
108
109 while (state->bitlen < cnt) {
110 if (state->srccnt == state->srclen) {
111 state->overrun = true;
112 return 0;
113 }
114
115 /* Load 8 more bits */
116 val |= ((uint64_t) state->src[state->srccnt]) << state->bitlen;
117 state->srccnt++;
118 state->bitlen += 8;
119 }
120
121 /* Update bits in the buffer */
122 state->bitbuf = (uint32_t) (val >> cnt);
123 state->bitlen -= cnt;
124
125 return ((uint32_t) (val & ((1 << cnt) - 1)));
126}
127
128/** Decode WebP header
129 *
130 * @param[in] data Memory representation of WebP.
131 * @param[in] size Size of the representation (in bytes).
132 * @param[out] webp Decoded WebP.
133 *
134 * @return True on succesful decoding.
135 * @return False on failure.
136 *
137 */
138static bool decode_webp_header(void *data, size_t size, webp_t *webp)
139{
140 /* Headers sanity check */
141 if ((size < sizeof(riff_header_t)) ||
142 (size - sizeof(riff_header_t) < sizeof(webp_header_t)))
143 return false;
144
145 riff_header_t *riff_header = (riff_header_t *) data;
146 if (riff_header->fourcc != FOURCC_RIFF)
147 return false;
148
149 /* Check payload size */
150 size_t payload_size = uint32_t_le2host(riff_header->payload_size);
151 if (payload_size + sizeof(riff_header_t) > size)
152 return false;
153
154 data += sizeof(riff_header_t);
155 webp_header_t *webp_header = (webp_header_t *) data;
156 if (webp_header->fourcc != FOURCC_WEBP)
157 return false;
158
159 /* Only lossless encoding supported so far */
160 if (webp_header->encoding != FOURCC_WEBP_LOSSLESS)
161 return false;
162
163 webp->stream_size = uint32_t_le2host(webp_header->stream_size);
164 if (webp->stream_size + sizeof(riff_header_t) +
165 sizeof(webp_header_t) > size)
166 return false;
167
168 if (webp_header->signature != SIGNATURE_WEBP_LOSSLESS)
169 return false;
170
171 data += sizeof(webp_header_t);
172
173 /* Setup decoding state */
174 webp->src = (uint8_t *) data;
175 webp->srclen = webp->stream_size - 1;
176 webp->srccnt = 0;
177 webp->bitbuf = 0;
178 webp->bitlen = 0;
179 webp->overrun = false;
180
181 /* Decode the rest of the metadata */
182 webp->width = get_bits(webp, 14) + 1;
183 CHECK_OVERRUN(*webp, false);
184
185 webp->height = get_bits(webp, 14) + 1;
186 CHECK_OVERRUN(*webp, false);
187
188 webp->alpha_used = get_bits(webp, 1);
189 CHECK_OVERRUN(*webp, false);
190
191 webp->version = get_bits(webp, 3);
192 CHECK_OVERRUN(*webp, false);
193
194 if (webp->version != 0)
195 return false;
196
197 return true;
198}
199
200/** Decode WebP format
201 *
202 * Decode WebP format and create a surface from it. The supported
203 * variants of WebP are currently limited to losslessly compressed
204 * ARGB images.
205 *
206 * @param[in] data Memory representation of WebP.
207 * @param[in] size Size of the representation (in bytes).
208 * @param[in] flags Surface creation flags.
209 *
210 * @return Newly allocated surface with the decoded content.
211 * @return NULL on error or unsupported format.
212 *
213 */
214surface_t *decode_webp(void *data, size_t size, surface_flags_t flags)
215{
216 webp_t webp;
217 if (!decode_webp_header(data, size, &webp))
218 return NULL;
219
220 bool transform_present = false;
221
222 do {
223 transform_present = get_bits(&webp, 1);
224 CHECK_OVERRUN(webp, NULL);
225
226 if (transform_present) {
227 webp_transform_t transform = get_bits(&webp, 2);
228 CHECK_OVERRUN(webp, NULL);
229
230 if (transform == TRANSFORM_PREDICTOR) {
231 // FIXME TODO
232 } else
233 return NULL;
234
235 // FIXME: decode other transforms
236 }
237 } while (transform_present);
238
239 // FIXME: decode image data
240
241 return NULL;
242}
243
244/** Encode WebP format
245 *
246 * Encode WebP format into an array.
247 *
248 * @param[in] surface Surface to be encoded into WebP.
249 * @param[out] pdata Pointer to the resulting array.
250 * @param[out] psize Pointer to the size of the resulting array.
251 *
252 * @return True on succesful encoding.
253 * @return False on failure.
254 *
255 */
256bool encode_webp(surface_t *surface, void **pdata, size_t *psize)
257{
258 // TODO
259 return false;
260}
261
262/** @}
263 */
Note: See TracBrowser for help on using the repository browser.