2 * Copyright (c) 2014 Martin Decky
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
37 #include <byteorder.h>
43 #include <abi/fourcc.h>
46 /** Check for input buffer overrun condition */
47 #define CHECK_OVERRUN(state, retval) \
49 if ((state).overrun) \
53 #define SIGNATURE_WEBP_LOSSLESS UINT8_C(0x2f)
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')
62 TRANSFORM_PREDICTOR
= 0,
64 TRANSFORM_SUBTRACT
= 2,
65 TRANSFORM_COLOR_INDEXING
= 3
70 uint32_t payload_size
;
71 } __attribute__((packed
)) riff_header_t
;
78 } __attribute__((packed
)) webp_header_t
;
87 uint8_t *src
; /**< Input buffer */
88 size_t srclen
; /**< Input buffer size */
89 size_t srccnt
; /**< Position in the input buffer */
91 uint32_t bitbuf
; /**< Bit buffer */
92 size_t bitlen
; /**< Number of bits in the bit buffer */
94 bool overrun
; /**< Overrun condition */
97 /** Get bits from the bit buffer
99 * @param state WebP state.
100 * @param cnt Number of bits to return (at most 32).
102 * @return Returned bits.
105 static inline uint32_t get_bits(webp_t
*state
, size_t cnt
)
107 /* Bit accumulator for at least 36 bits */
108 uint64_t val
= state
->bitbuf
;
110 while (state
->bitlen
< cnt
) {
111 if (state
->srccnt
== state
->srclen
) {
112 state
->overrun
= true;
116 /* Load 8 more bits */
117 val
|= ((uint64_t) state
->src
[state
->srccnt
]) << state
->bitlen
;
122 /* Update bits in the buffer */
123 state
->bitbuf
= (uint32_t) (val
>> cnt
);
124 state
->bitlen
-= cnt
;
126 return ((uint32_t) (val
& ((1 << cnt
) - 1)));
129 /** Decode WebP header
131 * @param[in] data Memory representation of WebP.
132 * @param[in] size Size of the representation (in bytes).
133 * @param[out] webp Decoded WebP.
135 * @return True on succesful decoding.
136 * @return False on failure.
139 static bool decode_webp_header(void *data
, size_t size
, webp_t
*webp
)
141 /* Headers sanity check */
142 if ((size
< sizeof(riff_header_t
)) ||
143 (size
- sizeof(riff_header_t
) < sizeof(webp_header_t
)))
146 riff_header_t
*riff_header
= (riff_header_t
*) data
;
147 if (riff_header
->fourcc
!= FOURCC_RIFF
)
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
)
155 data
+= sizeof(riff_header_t
);
156 webp_header_t
*webp_header
= (webp_header_t
*) data
;
157 if (webp_header
->fourcc
!= FOURCC_WEBP
)
160 /* Only lossless encoding supported so far */
161 if (webp_header
->encoding
!= FOURCC_WEBP_LOSSLESS
)
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
)
169 if (webp_header
->signature
!= SIGNATURE_WEBP_LOSSLESS
)
172 data
+= sizeof(webp_header_t
);
174 /* Setup decoding state */
175 webp
->src
= (uint8_t *) data
;
176 webp
->srclen
= webp
->stream_size
- 1;
180 webp
->overrun
= false;
182 /* Decode the rest of the metadata */
183 webp
->width
= get_bits(webp
, 14) + 1;
184 CHECK_OVERRUN(*webp
, false);
186 webp
->height
= get_bits(webp
, 14) + 1;
187 CHECK_OVERRUN(*webp
, false);
189 webp
->alpha_used
= get_bits(webp
, 1);
190 CHECK_OVERRUN(*webp
, false);
192 webp
->version
= get_bits(webp
, 3);
193 CHECK_OVERRUN(*webp
, false);
195 if (webp
->version
!= 0)
201 /** Decode WebP format
203 * Decode WebP format and create a surface from it. The supported
204 * variants of WebP are currently limited to losslessly compressed
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.
211 * @return Newly allocated surface with the decoded content.
212 * @return NULL on error or unsupported format.
215 surface_t
*decode_webp(void *data
, size_t size
, surface_flags_t flags
)
218 if (!decode_webp_header(data
, size
, &webp
))
221 bool transform_present
= false;
224 transform_present
= get_bits(&webp
, 1);
225 CHECK_OVERRUN(webp
, NULL
);
227 if (transform_present
) {
228 webp_transform_t transform
= get_bits(&webp
, 2);
229 CHECK_OVERRUN(webp
, NULL
);
231 if (transform
== TRANSFORM_PREDICTOR
) {
236 // FIXME: decode other transforms
238 } while (transform_present
);
240 // FIXME: decode image data
245 /** Encode WebP format
247 * Encode WebP format into an array.
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.
253 * @return True on succesful encoding.
254 * @return False on failure.
257 bool encode_webp(surface_t
*surface
, void **pdata
, size_t *psize
)