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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since aeba767 was 2bb6d04, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 6 years ago

Curb the proliferation of libdraw headers

libdraw provides a lot of ambiguously named headers, which makes it
confusing. This change merges the subdirectories into single headers,
and moves all headers into draw subdirectory, so that it's obvious
at a glance what library the header belongs to.

Compare:

#include <path.h>
#include <source.h>
#include <font/bitmap_backend.h>
#include <font/pcf.h>

vs.

#include <draw/path.h>
#include <draw/source.h>
#include <draw/font.h>

  • Property mode set to 100644
File size: 6.7 KB
RevLine 
[490e21b]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>
[e299dbe]41#include <fourcc.h>
[8d2dd7f2]42#include <stdint.h>
[abf2dfd]43#include <abi/fourcc.h>
[2bb6d04]44#include <draw/codec.h>
[490e21b]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;
[a35b458]86
[490e21b]87 uint8_t *src; /**< Input buffer */
88 size_t srclen; /**< Input buffer size */
89 size_t srccnt; /**< Position in the input buffer */
[a35b458]90
[490e21b]91 uint32_t bitbuf; /**< Bit buffer */
92 size_t bitlen; /**< Number of bits in the bit buffer */
[a35b458]93
[490e21b]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;
[a35b458]109
[490e21b]110 while (state->bitlen < cnt) {
111 if (state->srccnt == state->srclen) {
112 state->overrun = true;
113 return 0;
114 }
[a35b458]115
[490e21b]116 /* Load 8 more bits */
117 val |= ((uint64_t) state->src[state->srccnt]) << state->bitlen;
118 state->srccnt++;
119 state->bitlen += 8;
120 }
[a35b458]121
[490e21b]122 /* Update bits in the buffer */
123 state->bitbuf = (uint32_t) (val >> cnt);
124 state->bitlen -= cnt;
[a35b458]125
[490e21b]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;
[a35b458]145
[490e21b]146 riff_header_t *riff_header = (riff_header_t *) data;
147 if (riff_header->fourcc != FOURCC_RIFF)
148 return false;
[a35b458]149
[490e21b]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;
[a35b458]154
[490e21b]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;
[a35b458]159
[490e21b]160 /* Only lossless encoding supported so far */
161 if (webp_header->encoding != FOURCC_WEBP_LOSSLESS)
162 return false;
[a35b458]163
[490e21b]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;
[a35b458]168
[490e21b]169 if (webp_header->signature != SIGNATURE_WEBP_LOSSLESS)
170 return false;
[a35b458]171
[490e21b]172 data += sizeof(webp_header_t);
[a35b458]173
[490e21b]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;
[a35b458]181
[490e21b]182 /* Decode the rest of the metadata */
183 webp->width = get_bits(webp, 14) + 1;
184 CHECK_OVERRUN(*webp, false);
[a35b458]185
[490e21b]186 webp->height = get_bits(webp, 14) + 1;
187 CHECK_OVERRUN(*webp, false);
[a35b458]188
[490e21b]189 webp->alpha_used = get_bits(webp, 1);
190 CHECK_OVERRUN(*webp, false);
[a35b458]191
[490e21b]192 webp->version = get_bits(webp, 3);
193 CHECK_OVERRUN(*webp, false);
[a35b458]194
[490e21b]195 if (webp->version != 0)
196 return false;
[a35b458]197
[490e21b]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;
[a35b458]220
[490e21b]221 bool transform_present = false;
[a35b458]222
[490e21b]223 do {
224 transform_present = get_bits(&webp, 1);
225 CHECK_OVERRUN(webp, NULL);
[a35b458]226
[490e21b]227 if (transform_present) {
228 webp_transform_t transform = get_bits(&webp, 2);
229 CHECK_OVERRUN(webp, NULL);
[a35b458]230
[490e21b]231 if (transform == TRANSFORM_PREDICTOR) {
232 // FIXME TODO
233 } else
234 return NULL;
[a35b458]235
[490e21b]236 // FIXME: decode other transforms
237 }
238 } while (transform_present);
[a35b458]239
[490e21b]240 // FIXME: decode image data
[a35b458]241
[490e21b]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.