Leptonica 1.82.0
Image processing and image analysis suite
webpanimio.c
Go to the documentation of this file.
1/*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 -
4 - Redistribution and use in source and binary forms, with or without
5 - modification, are permitted provided that the following conditions
6 - are met:
7 - 1. Redistributions of source code must retain the above copyright
8 - notice, this list of conditions and the following disclaimer.
9 - 2. Redistributions in binary form must reproduce the above
10 - copyright notice, this list of conditions and the following
11 - disclaimer in the documentation and/or other materials
12 - provided with the distribution.
13 -
14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *====================================================================*/
26
38#ifdef HAVE_CONFIG_H
39#include <config_auto.h>
40#endif /* HAVE_CONFIG_H */
41
42#include "allheaders.h"
43
44/* -----------------------------------------------*/
45#if HAVE_LIBWEBP_ANIM /* defined in environ.h */
46/* -----------------------------------------------*/
47#include "webp/decode.h"
48#include "webp/encode.h"
49#include "webp/mux.h"
50#include "webp/demux.h"
51
52/*---------------------------------------------------------------------*
53 * Writing animated WebP *
54 *---------------------------------------------------------------------*/
71l_ok
72pixaWriteWebPAnim(const char *filename,
73 PIXA *pixa,
74 l_int32 loopcount,
75 l_int32 duration,
76 l_int32 quality,
77 l_int32 lossless)
78{
79l_int32 ret;
80FILE *fp;
81
82 PROCNAME("pixaWriteWebPAnim");
83
84 if (!filename)
85 return ERROR_INT("filename not defined", procName, 1);
86 if (!pixa)
87 return ERROR_INT("pixa not defined", procName, 1);
88
89 if ((fp = fopenWriteStream(filename, "wb+")) == NULL)
90 return ERROR_INT("stream not opened", procName, 1);
91 ret = pixaWriteStreamWebPAnim(fp, pixa, loopcount, duration,
92 quality, lossless);
93 fclose(fp);
94 if (ret)
95 return ERROR_INT("pixs not compressed to stream", procName, 1);
96 return 0;
97}
98
99
118l_ok
119pixaWriteStreamWebPAnim(FILE *fp,
120 PIXA *pixa,
121 l_int32 loopcount,
122 l_int32 duration,
123 l_int32 quality,
124 l_int32 lossless)
125{
126l_uint8 *filedata;
127size_t filebytes, nbytes;
128
129 PROCNAME("pixaWriteStreamWebpAnim");
130
131 if (!fp)
132 return ERROR_INT("stream not open", procName, 1);
133 if (!pixa)
134 return ERROR_INT("pixa not defined", procName, 1);
135
136 filedata = NULL;
137 pixaWriteMemWebPAnim(&filedata, &filebytes, pixa, loopcount,
138 duration, quality, lossless);
139 rewind(fp);
140 if (!filedata)
141 return ERROR_INT("filedata not made", procName, 1);
142 nbytes = fwrite(filedata, 1, filebytes, fp);
143 free(filedata);
144 if (nbytes != filebytes)
145 return ERROR_INT("Write error", procName, 1);
146 return 0;
147}
148
149
167l_ok
168pixaWriteMemWebPAnim(l_uint8 **pencdata,
169 size_t *pencsize,
170 PIXA *pixa,
171 l_int32 loopcount,
172 l_int32 duration,
173 l_int32 quality,
174 l_int32 lossless)
175{
176l_int32 i, n, same, w, h, wpl, ret;
177l_uint8 *data;
178PIX *pix1, *pix2;
179WebPAnimEncoder *enc;
180WebPAnimEncoderOptions enc_options;
181WebPConfig config;
182WebPData webp_data;
183WebPMux *mux = NULL;
184WebPMuxAnimParams newparams;
185WebPPicture frame;
186
187 PROCNAME("pixaWriteMemWebPAnim");
188
189 if (!pencdata)
190 return ERROR_INT("&encdata not defined", procName, 1);
191 *pencdata = NULL;
192 if (!pencsize)
193 return ERROR_INT("&encsize not defined", procName, 1);
194 *pencsize = 0;
195 if (!pixa)
196 return ERROR_INT("&pixa not defined", procName, 1);
197 if ((n = pixaGetCount(pixa)) == 0)
198 return ERROR_INT("no images in pixa", procName, 1);
199 if (loopcount < 0) loopcount = 0;
200 if (lossless == 0 && (quality < 0 || quality > 100))
201 return ERROR_INT("quality not in [0 ... 100]", procName, 1);
202
203 pixaVerifyDimensions(pixa, &same, &w, &h);
204 if (!same)
205 return ERROR_INT("sizes of all pix are not the same", procName, 1);
206
207 /* Set up the encoder */
208 WebPAnimEncoderOptionsInit(&enc_options);
209 enc = WebPAnimEncoderNew(w, h, &enc_options);
210
211 for (i = 0; i < n; i++) {
212 /* Make a frame for each image. Convert the pix to RGBA with
213 * an opaque alpha layer, and put the raster data in the frame. */
214 pix1 = pixaGetPix(pixa, i, L_CLONE);
215 pix2 = pixConvertTo32(pix1);
217 pixEndianByteSwap(pix2);
218 data = (l_uint8 *)pixGetData(pix2);
219 wpl = pixGetWpl(pix2);
220 WebPPictureInit(&frame);
221 frame.width = w;
222 frame.height = h;
223 WebPPictureImportRGBA(&frame, data, 4 * wpl);
224 pixDestroy(&pix1);
225 pixDestroy(&pix2);
226
227 /* Add the frame data to the encoder, and clear its memory */
228 WebPConfigInit(&config);
229 config.lossless = lossless;
230 config.quality = quality;
231 WebPAnimEncoderAdd(enc, &frame, duration * i, &config);
232 WebPPictureFree(&frame);
233 }
234 WebPAnimEncoderAdd(enc, NULL, duration * i, NULL); /* add a blank frame */
235 WebPAnimEncoderAssemble(enc, &webp_data); /* encode the data */
236 WebPAnimEncoderDelete(enc);
237
238 /* Set the loopcount if requested. Note that when you make a mux,
239 * it imports the webp_data that was previously made, including
240 * the webp encoded images. Before you re-export that data using
241 * WebPMuxAssemble(), free the heap data in webp_data. There is an
242 * example for setting the loop count in the webp distribution;
243 * see gif2webp.c. */
244 if (loopcount > 0) {
245 mux = WebPMuxCreate(&webp_data, 1);
246 if (!mux) {
247 L_ERROR("could not re-mux to add loop count\n", procName);
248 } else {
249 ret = WebPMuxGetAnimationParams(mux, &newparams);
250 if (ret != WEBP_MUX_OK) {
251 L_ERROR("failed to get loop count\n", procName);
252 } else {
253 newparams.loop_count = loopcount;
254 ret = WebPMuxSetAnimationParams(mux, &newparams);
255 if (ret != WEBP_MUX_OK)
256 L_ERROR("failed to set loop count\n", procName);
257 }
258 WebPDataClear(&webp_data);
259 WebPMuxAssemble(mux, &webp_data);
260 WebPMuxDelete(mux);
261 }
262 }
263
264 *pencdata = (l_uint8 *)webp_data.bytes;
265 *pencsize = webp_data.size;
266 L_INFO("data size = %zu\n", procName, webp_data.size);
267 return 0;
268}
269
270
271/* --------------------------------------------*/
272#endif /* HAVE_LIBWEBP_ANIM */
273/* --------------------------------------------*/
void pixDestroy(PIX **ppix)
pixDestroy()
Definition: pix1.c:621
l_uint32 * pixGetData(PIX *pix)
pixGetData()
Definition: pix1.c:1763
l_ok pixEndianByteSwap(PIX *pixs)
pixEndianByteSwap()
Definition: pix2.c:3074
l_ok pixSetComponentArbitrary(PIX *pix, l_int32 comp, l_int32 val)
pixSetComponentArbitrary()
Definition: pix2.c:1068
@ L_ALPHA_CHANNEL
Definition: pix.h:207
@ L_CLONE
Definition: pix.h:713
l_int32 pixaGetCount(PIXA *pixa)
pixaGetCount()
Definition: pixabasic.c:650
PIX * pixaGetPix(PIXA *pixa, l_int32 index, l_int32 accesstype)
pixaGetPix()
Definition: pixabasic.c:691
l_ok pixaVerifyDimensions(PIXA *pixa, l_int32 *psame, l_int32 *pmaxw, l_int32 *pmaxh)
pixaVerifyDimensions()
Definition: pixabasic.c:1006
PIX * pixConvertTo32(PIX *pixs)
pixConvertTo32()
Definition: pixconv.c:3332
Definition: pix.h:139
Definition: pix.h:456
FILE * fopenWriteStream(const char *filename, const char *modestring)
fopenWriteStream()
Definition: utils2.c:1975