/src/libwebp/src/enc/picture_csp_enc.c
Line | Count | Source |
1 | | // Copyright 2014 Google Inc. All Rights Reserved. |
2 | | // |
3 | | // Use of this source code is governed by a BSD-style license |
4 | | // that can be found in the COPYING file in the root of the source |
5 | | // tree. An additional intellectual property rights grant can be found |
6 | | // in the file PATENTS. All contributing project authors may |
7 | | // be found in the AUTHORS file in the root of the source tree. |
8 | | // ----------------------------------------------------------------------------- |
9 | | // |
10 | | // WebPPicture utils for colorspace conversion |
11 | | // |
12 | | // Author: Skal (pascal.massimino@gmail.com) |
13 | | |
14 | | #include <assert.h> |
15 | | #include <math.h> |
16 | | #include <stdlib.h> |
17 | | #include <string.h> |
18 | | |
19 | | #include "sharpyuv/sharpyuv.h" |
20 | | #include "sharpyuv/sharpyuv_csp.h" |
21 | | #include "src/dsp/cpu.h" |
22 | | #include "src/dsp/dsp.h" |
23 | | #include "src/dsp/lossless.h" |
24 | | #include "src/dsp/yuv.h" |
25 | | #include "src/enc/vp8i_enc.h" |
26 | | #include "src/utils/random_utils.h" |
27 | | #include "src/utils/utils.h" |
28 | | #include "src/webp/encode.h" |
29 | | #include "src/webp/types.h" |
30 | | |
31 | | #if defined(WEBP_USE_THREAD) && !defined(_WIN32) |
32 | | #include <pthread.h> |
33 | | #endif |
34 | | |
35 | 1.67k | #define ALPHA_OFFSET CHANNEL_OFFSET(0) |
36 | | |
37 | | //------------------------------------------------------------------------------ |
38 | | // Detection of non-trivial transparency |
39 | | |
40 | | // Returns true if alpha[] has non-0xff values. |
41 | | static int CheckNonOpaque(const uint8_t* alpha, int width, int height, |
42 | 6.32k | int x_step, int y_step) { |
43 | 6.32k | if (alpha == NULL) return 0; |
44 | 3.79k | WebPInitAlphaProcessing(); |
45 | 3.79k | if (x_step == 1) { |
46 | 2.17k | for (; height-- > 0; alpha += y_step) { |
47 | 2.17k | if (WebPHasAlpha8b(alpha, width)) return 1; |
48 | 2.17k | } |
49 | 2.17k | } else { |
50 | 143k | for (; height-- > 0; alpha += y_step) { |
51 | 143k | if (WebPHasAlpha32b(alpha, width)) return 1; |
52 | 143k | } |
53 | 2.17k | } |
54 | 554 | return 0; |
55 | 3.79k | } |
56 | | |
57 | | // Checking for the presence of non-opaque alpha. |
58 | 3.16k | int WebPPictureHasTransparency(const WebPPicture* picture) { |
59 | 3.16k | if (picture == NULL) return 0; |
60 | 3.16k | if (picture->use_argb) { |
61 | 0 | if (picture->argb != NULL) { |
62 | 0 | return CheckNonOpaque((const uint8_t*)picture->argb + ALPHA_OFFSET, |
63 | 0 | picture->width, picture->height, 4, |
64 | 0 | picture->argb_stride * sizeof(*picture->argb)); |
65 | 0 | } |
66 | 0 | return 0; |
67 | 0 | } |
68 | 3.16k | return CheckNonOpaque(picture->a, picture->width, picture->height, 1, |
69 | 3.16k | picture->a_stride); |
70 | 3.16k | } |
71 | | |
72 | | extern VP8CPUInfo VP8GetCPUInfo; |
73 | | |
74 | | //------------------------------------------------------------------------------ |
75 | | // Sharp RGB->YUV conversion |
76 | | |
77 | | static const int kMinDimensionIterativeConversion = 4; |
78 | | |
79 | | //------------------------------------------------------------------------------ |
80 | | // Main function |
81 | | |
82 | | static int PreprocessARGB(const uint8_t* r_ptr, const uint8_t* g_ptr, |
83 | | const uint8_t* b_ptr, int step, int rgb_stride, |
84 | 0 | WebPPicture* const picture) { |
85 | 0 | const int ok = SharpYuvConvert( |
86 | 0 | r_ptr, g_ptr, b_ptr, step, rgb_stride, /*rgb_bit_depth=*/8, picture->y, |
87 | 0 | picture->y_stride, picture->u, picture->uv_stride, picture->v, |
88 | 0 | picture->uv_stride, /*yuv_bit_depth=*/8, picture->width, picture->height, |
89 | 0 | SharpYuvGetConversionMatrix(kSharpYuvMatrixWebp)); |
90 | 0 | if (!ok) { |
91 | 0 | return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); |
92 | 0 | } |
93 | 0 | return ok; |
94 | 0 | } |
95 | | |
96 | | static WEBP_INLINE void ConvertRowToY(const uint8_t* const r_ptr, |
97 | | const uint8_t* const g_ptr, |
98 | | const uint8_t* const b_ptr, int step, |
99 | | uint8_t* const dst_y, int width, |
100 | 0 | VP8Random* const rg) { |
101 | 0 | int i, j; |
102 | 0 | for (i = 0, j = 0; i < width; i += 1, j += step) { |
103 | 0 | dst_y[i] = |
104 | 0 | VP8RGBToY(r_ptr[j], g_ptr[j], b_ptr[j], VP8RandomBits(rg, YUV_FIX)); |
105 | 0 | } |
106 | 0 | } |
107 | | |
108 | | static WEBP_INLINE void ConvertRowsToUV(const uint16_t* rgb, |
109 | | uint8_t* const dst_u, |
110 | | uint8_t* const dst_v, int width, |
111 | 0 | VP8Random* const rg) { |
112 | 0 | int i; |
113 | 0 | for (i = 0; i < width; i += 1, rgb += 4) { |
114 | 0 | const int r = rgb[0], g = rgb[1], b = rgb[2]; |
115 | 0 | dst_u[i] = VP8RGBToU(r, g, b, VP8RandomBits(rg, YUV_FIX + 2)); |
116 | 0 | dst_v[i] = VP8RGBToV(r, g, b, VP8RandomBits(rg, YUV_FIX + 2)); |
117 | 0 | } |
118 | 0 | } |
119 | | |
120 | | extern void SharpYuvInit(VP8CPUInfo cpu_info_func); |
121 | | |
122 | | static int ImportYUVAFromRGBA(const uint8_t* r_ptr, const uint8_t* g_ptr, |
123 | | const uint8_t* b_ptr, const uint8_t* a_ptr, |
124 | | int step, // bytes per pixel |
125 | | int rgb_stride, // bytes per scanline |
126 | | float dithering, int use_iterative_conversion, |
127 | 3.16k | WebPPicture* const picture) { |
128 | 3.16k | int y; |
129 | 3.16k | const int width = picture->width; |
130 | 3.16k | const int height = picture->height; |
131 | 3.16k | const int has_alpha = CheckNonOpaque(a_ptr, width, height, step, rgb_stride); |
132 | | |
133 | 3.16k | picture->colorspace = has_alpha ? WEBP_YUV420A : WEBP_YUV420; |
134 | 3.16k | picture->use_argb = 0; |
135 | | |
136 | | // disable smart conversion if source is too small (overkill). |
137 | 3.16k | if (width < kMinDimensionIterativeConversion || |
138 | 2.77k | height < kMinDimensionIterativeConversion) { |
139 | 569 | use_iterative_conversion = 0; |
140 | 569 | } |
141 | | |
142 | 3.16k | if (!WebPPictureAllocYUVA(picture)) { |
143 | 0 | return 0; |
144 | 0 | } |
145 | 3.16k | if (has_alpha) { |
146 | 1.62k | assert(step == 4); |
147 | 1.62k | } |
148 | | |
149 | 3.16k | if (use_iterative_conversion) { |
150 | 0 | SharpYuvInit(VP8GetCPUInfo); |
151 | 0 | if (!PreprocessARGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, picture)) { |
152 | 0 | return 0; |
153 | 0 | } |
154 | 0 | if (has_alpha) { |
155 | 0 | WebPExtractAlpha(a_ptr, rgb_stride, width, height, picture->a, |
156 | 0 | picture->a_stride); |
157 | 0 | } |
158 | 3.16k | } else { |
159 | 3.16k | const int uv_width = (width + 1) >> 1; |
160 | | // temporary storage for accumulated R/G/B values during conversion to U/V |
161 | 3.16k | uint16_t* const tmp_rgb = |
162 | 3.16k | (uint16_t*)WebPSafeMalloc(4 * uv_width, sizeof(*tmp_rgb)); |
163 | 3.16k | uint8_t* dst_y = picture->y; |
164 | 3.16k | uint8_t* dst_u = picture->u; |
165 | 3.16k | uint8_t* dst_v = picture->v; |
166 | 3.16k | uint8_t* dst_a = picture->a; |
167 | | |
168 | 3.16k | VP8Random base_rg; |
169 | 3.16k | VP8Random* rg = NULL; |
170 | 3.16k | if (dithering > 0.) { |
171 | 0 | VP8InitRandom(&base_rg, dithering); |
172 | 0 | rg = &base_rg; |
173 | 0 | } |
174 | 3.16k | WebPInitConvertARGBToYUV(); |
175 | 3.16k | WebPInitGammaTables(); |
176 | | |
177 | 3.16k | if (tmp_rgb == NULL) { |
178 | 0 | return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); |
179 | 0 | } |
180 | | |
181 | 3.16k | if (rg == NULL) { |
182 | | // Downsample Y/U/V planes, two rows at a time |
183 | 3.16k | WebPImportYUVAFromRGBA(r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride, |
184 | 3.16k | has_alpha, width, height, tmp_rgb, |
185 | 3.16k | picture->y_stride, picture->uv_stride, |
186 | 3.16k | picture->a_stride, dst_y, dst_u, dst_v, dst_a); |
187 | 3.16k | if (height & 1) { |
188 | 1.16k | dst_y += (height - 1) * (ptrdiff_t)picture->y_stride; |
189 | 1.16k | dst_u += (height >> 1) * (ptrdiff_t)picture->uv_stride; |
190 | 1.16k | dst_v += (height >> 1) * (ptrdiff_t)picture->uv_stride; |
191 | 1.16k | r_ptr += (height - 1) * (ptrdiff_t)rgb_stride; |
192 | 1.16k | b_ptr += (height - 1) * (ptrdiff_t)rgb_stride; |
193 | 1.16k | g_ptr += (height - 1) * (ptrdiff_t)rgb_stride; |
194 | 1.16k | if (has_alpha) { |
195 | 862 | dst_a += (height - 1) * (ptrdiff_t)picture->a_stride; |
196 | 862 | a_ptr += (height - 1) * (ptrdiff_t)rgb_stride; |
197 | 862 | } |
198 | 1.16k | WebPImportYUVAFromRGBALastLine(r_ptr, g_ptr, b_ptr, a_ptr, step, |
199 | 1.16k | has_alpha, width, tmp_rgb, dst_y, dst_u, |
200 | 1.16k | dst_v, dst_a); |
201 | 1.16k | } |
202 | 3.16k | } else { |
203 | | // Copy of WebPImportYUVAFromRGBA/WebPImportYUVAFromRGBALastLine, |
204 | | // but with dithering. |
205 | 0 | for (y = 0; y < (height >> 1); ++y) { |
206 | 0 | int rows_have_alpha = has_alpha; |
207 | 0 | ConvertRowToY(r_ptr, g_ptr, b_ptr, step, dst_y, width, rg); |
208 | 0 | ConvertRowToY(r_ptr + rgb_stride, g_ptr + rgb_stride, |
209 | 0 | b_ptr + rgb_stride, step, dst_y + picture->y_stride, |
210 | 0 | width, rg); |
211 | 0 | dst_y += 2 * picture->y_stride; |
212 | 0 | if (has_alpha) { |
213 | 0 | rows_have_alpha &= !WebPExtractAlpha(a_ptr, rgb_stride, width, 2, |
214 | 0 | dst_a, picture->a_stride); |
215 | 0 | dst_a += 2 * picture->a_stride; |
216 | 0 | } |
217 | | // Collect averaged R/G/B(/A) |
218 | 0 | if (!rows_have_alpha) { |
219 | 0 | WebPAccumulateRGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, tmp_rgb, |
220 | 0 | width); |
221 | 0 | } else { |
222 | 0 | WebPAccumulateRGBA(r_ptr, g_ptr, b_ptr, a_ptr, rgb_stride, tmp_rgb, |
223 | 0 | width); |
224 | 0 | } |
225 | | // Convert to U/V |
226 | 0 | ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg); |
227 | 0 | dst_u += picture->uv_stride; |
228 | 0 | dst_v += picture->uv_stride; |
229 | 0 | r_ptr += 2 * rgb_stride; |
230 | 0 | b_ptr += 2 * rgb_stride; |
231 | 0 | g_ptr += 2 * rgb_stride; |
232 | 0 | if (has_alpha) a_ptr += 2 * rgb_stride; |
233 | 0 | } |
234 | 0 | if (height & 1) { // extra last row |
235 | 0 | int row_has_alpha = has_alpha; |
236 | 0 | ConvertRowToY(r_ptr, g_ptr, b_ptr, step, dst_y, width, rg); |
237 | 0 | if (row_has_alpha) { |
238 | 0 | row_has_alpha &= !WebPExtractAlpha(a_ptr, 0, width, 1, dst_a, 0); |
239 | 0 | } |
240 | | // Collect averaged R/G/B(/A) |
241 | 0 | if (!row_has_alpha) { |
242 | | // Collect averaged R/G/B |
243 | 0 | WebPAccumulateRGB(r_ptr, g_ptr, b_ptr, step, /*rgb_stride=*/0, |
244 | 0 | tmp_rgb, width); |
245 | 0 | } else { |
246 | 0 | WebPAccumulateRGBA(r_ptr, g_ptr, b_ptr, a_ptr, /*rgb_stride=*/0, |
247 | 0 | tmp_rgb, width); |
248 | 0 | } |
249 | 0 | ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg); |
250 | 0 | } |
251 | 0 | } |
252 | | |
253 | 3.16k | WebPSafeFree(tmp_rgb); |
254 | 3.16k | } |
255 | 3.16k | return 1; |
256 | 3.16k | } |
257 | | |
258 | | #undef SUM4 |
259 | | #undef SUM2 |
260 | | #undef SUM4ALPHA |
261 | | #undef SUM2ALPHA |
262 | | |
263 | | //------------------------------------------------------------------------------ |
264 | | // call for ARGB->YUVA conversion |
265 | | |
266 | | static int PictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace, |
267 | 2.14k | float dithering, int use_iterative_conversion) { |
268 | 2.14k | if (picture == NULL) return 0; |
269 | 2.14k | if (picture->argb == NULL) { |
270 | 0 | return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); |
271 | 2.14k | } else if ((colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) { |
272 | 0 | return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION); |
273 | 2.14k | } else { |
274 | 2.14k | const uint8_t* const argb = (const uint8_t*)picture->argb; |
275 | 2.14k | const uint8_t* const a = argb + CHANNEL_OFFSET(0); |
276 | 2.14k | const uint8_t* const r = argb + CHANNEL_OFFSET(1); |
277 | 2.14k | const uint8_t* const g = argb + CHANNEL_OFFSET(2); |
278 | 2.14k | const uint8_t* const b = argb + CHANNEL_OFFSET(3); |
279 | | |
280 | 2.14k | picture->colorspace = WEBP_YUV420; |
281 | 2.14k | return ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride, |
282 | 2.14k | dithering, use_iterative_conversion, picture); |
283 | 2.14k | } |
284 | 2.14k | } |
285 | | |
286 | | int WebPPictureARGBToYUVADithered(WebPPicture* picture, WebPEncCSP colorspace, |
287 | 2.14k | float dithering) { |
288 | 2.14k | return PictureARGBToYUVA(picture, colorspace, dithering, 0); |
289 | 2.14k | } |
290 | | |
291 | 0 | int WebPPictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace) { |
292 | 0 | return PictureARGBToYUVA(picture, colorspace, 0.f, 0); |
293 | 0 | } |
294 | | |
295 | 0 | int WebPPictureSharpARGBToYUVA(WebPPicture* picture) { |
296 | 0 | return PictureARGBToYUVA(picture, WEBP_YUV420, 0.f, 1); |
297 | 0 | } |
298 | | // for backward compatibility |
299 | 0 | int WebPPictureSmartARGBToYUVA(WebPPicture* picture) { |
300 | 0 | return WebPPictureSharpARGBToYUVA(picture); |
301 | 0 | } |
302 | | |
303 | | //------------------------------------------------------------------------------ |
304 | | // call for YUVA -> ARGB conversion |
305 | | |
306 | 0 | int WebPPictureYUVAToARGB(WebPPicture* picture) { |
307 | 0 | if (picture == NULL) return 0; |
308 | 0 | if (picture->y == NULL || picture->u == NULL || picture->v == NULL) { |
309 | 0 | return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); |
310 | 0 | } |
311 | 0 | if ((picture->colorspace & WEBP_CSP_ALPHA_BIT) && picture->a == NULL) { |
312 | 0 | return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); |
313 | 0 | } |
314 | 0 | if ((picture->colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) { |
315 | 0 | return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION); |
316 | 0 | } |
317 | | // Allocate a new argb buffer (discarding the previous one). |
318 | 0 | if (!WebPPictureAllocARGB(picture)) return 0; |
319 | 0 | picture->use_argb = 1; |
320 | | |
321 | | // Convert |
322 | 0 | { |
323 | 0 | int y; |
324 | 0 | const int width = picture->width; |
325 | 0 | const int height = picture->height; |
326 | 0 | const int argb_stride = 4 * picture->argb_stride; |
327 | 0 | uint8_t* dst = (uint8_t*)picture->argb; |
328 | 0 | const uint8_t *cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y; |
329 | 0 | WebPUpsampleLinePairFunc upsample = |
330 | 0 | WebPGetLinePairConverter(ALPHA_OFFSET > 0); |
331 | | |
332 | | // First row, with replicated top samples. |
333 | 0 | upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width); |
334 | 0 | cur_y += picture->y_stride; |
335 | 0 | dst += argb_stride; |
336 | | // Center rows. |
337 | 0 | for (y = 1; y + 1 < height; y += 2) { |
338 | 0 | const uint8_t* const top_u = cur_u; |
339 | 0 | const uint8_t* const top_v = cur_v; |
340 | 0 | cur_u += picture->uv_stride; |
341 | 0 | cur_v += picture->uv_stride; |
342 | 0 | upsample(cur_y, cur_y + picture->y_stride, top_u, top_v, cur_u, cur_v, |
343 | 0 | dst, dst + argb_stride, width); |
344 | 0 | cur_y += 2 * picture->y_stride; |
345 | 0 | dst += 2 * argb_stride; |
346 | 0 | } |
347 | | // Last row (if needed), with replicated bottom samples. |
348 | 0 | if (height > 1 && !(height & 1)) { |
349 | 0 | upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width); |
350 | 0 | } |
351 | | // Insert alpha values if needed, in replacement for the default 0xff ones. |
352 | 0 | if (picture->colorspace & WEBP_CSP_ALPHA_BIT) { |
353 | 0 | for (y = 0; y < height; ++y) { |
354 | 0 | uint32_t* const argb_dst = picture->argb + y * picture->argb_stride; |
355 | 0 | const uint8_t* const src = picture->a + y * picture->a_stride; |
356 | 0 | int x; |
357 | 0 | for (x = 0; x < width; ++x) { |
358 | 0 | argb_dst[x] = (argb_dst[x] & 0x00ffffffu) | ((uint32_t)src[x] << 24); |
359 | 0 | } |
360 | 0 | } |
361 | 0 | } |
362 | 0 | } |
363 | 0 | return 1; |
364 | 0 | } |
365 | | |
366 | | //------------------------------------------------------------------------------ |
367 | | // automatic import / conversion |
368 | | |
369 | | static int Import(WebPPicture* const picture, const uint8_t* rgb, |
370 | 3.16k | int rgb_stride, int step, int swap_rb, int import_alpha) { |
371 | 3.16k | int y; |
372 | | // swap_rb -> b,g,r,a , !swap_rb -> r,g,b,a |
373 | 3.16k | const uint8_t* r_ptr = rgb + (swap_rb ? 2 : 0); |
374 | 3.16k | const uint8_t* g_ptr = rgb + 1; |
375 | 3.16k | const uint8_t* b_ptr = rgb + (swap_rb ? 0 : 2); |
376 | 3.16k | const int width = picture->width; |
377 | 3.16k | const int height = picture->height; |
378 | | |
379 | 3.16k | if (abs(rgb_stride) < (import_alpha ? 4 : 3) * width) return 0; |
380 | | |
381 | 3.16k | if (!picture->use_argb) { |
382 | 1.01k | const uint8_t* a_ptr = import_alpha ? rgb + 3 : NULL; |
383 | 1.01k | return ImportYUVAFromRGBA(r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride, |
384 | 1.01k | 0.f /* no dithering */, 0, picture); |
385 | 1.01k | } |
386 | 2.14k | if (!WebPPictureAlloc(picture)) return 0; |
387 | | |
388 | 2.14k | VP8LDspInit(); |
389 | 2.14k | WebPInitAlphaProcessing(); |
390 | | |
391 | 2.14k | if (import_alpha) { |
392 | | // dst[] byte order is {a,r,g,b} for big-endian, {b,g,r,a} for little endian |
393 | 1.67k | uint32_t* dst = picture->argb; |
394 | 1.67k | const int do_copy = (ALPHA_OFFSET == 3) && swap_rb; |
395 | 1.67k | assert(step == 4); |
396 | 1.67k | if (do_copy) { |
397 | 0 | for (y = 0; y < height; ++y) { |
398 | 0 | memcpy(dst, rgb, width * 4); |
399 | 0 | rgb += rgb_stride; |
400 | 0 | dst += picture->argb_stride; |
401 | 0 | } |
402 | 1.67k | } else { |
403 | 1.30M | for (y = 0; y < height; ++y) { |
404 | | #ifdef WORDS_BIGENDIAN |
405 | | // BGRA or RGBA input order. |
406 | | const uint8_t* a_ptr = rgb + 3; |
407 | | WebPPackARGB(a_ptr, r_ptr, g_ptr, b_ptr, width, dst); |
408 | | r_ptr += rgb_stride; |
409 | | g_ptr += rgb_stride; |
410 | | b_ptr += rgb_stride; |
411 | | #else |
412 | | // RGBA input order. Need to swap R and B. |
413 | 1.30M | VP8LConvertBGRAToRGBA((const uint32_t*)rgb, width, (uint8_t*)dst); |
414 | 1.30M | #endif |
415 | 1.30M | rgb += rgb_stride; |
416 | 1.30M | dst += picture->argb_stride; |
417 | 1.30M | } |
418 | 1.67k | } |
419 | 1.67k | } else { |
420 | 472 | uint32_t* dst = picture->argb; |
421 | 472 | assert(step >= 3); |
422 | 87.7k | for (y = 0; y < height; ++y) { |
423 | 87.2k | WebPPackRGB(r_ptr, g_ptr, b_ptr, width, step, dst); |
424 | 87.2k | r_ptr += rgb_stride; |
425 | 87.2k | g_ptr += rgb_stride; |
426 | 87.2k | b_ptr += rgb_stride; |
427 | 87.2k | dst += picture->argb_stride; |
428 | 87.2k | } |
429 | 472 | } |
430 | 2.14k | return 1; |
431 | 2.14k | } |
432 | | |
433 | | // Public API |
434 | | |
435 | | #if !defined(WEBP_REDUCE_CSP) |
436 | | |
437 | | int WebPPictureImportBGR(WebPPicture* picture, const uint8_t* bgr, |
438 | 0 | int bgr_stride) { |
439 | 0 | return (picture != NULL && bgr != NULL) |
440 | 0 | ? Import(picture, bgr, bgr_stride, 3, 1, 0) |
441 | 0 | : 0; |
442 | 0 | } |
443 | | |
444 | | int WebPPictureImportBGRA(WebPPicture* picture, const uint8_t* bgra, |
445 | 0 | int bgra_stride) { |
446 | 0 | return (picture != NULL && bgra != NULL) |
447 | 0 | ? Import(picture, bgra, bgra_stride, 4, 1, 1) |
448 | 0 | : 0; |
449 | 0 | } |
450 | | |
451 | | int WebPPictureImportBGRX(WebPPicture* picture, const uint8_t* bgrx, |
452 | 0 | int bgrx_stride) { |
453 | 0 | return (picture != NULL && bgrx != NULL) |
454 | 0 | ? Import(picture, bgrx, bgrx_stride, 4, 1, 0) |
455 | 0 | : 0; |
456 | 0 | } |
457 | | |
458 | | #endif // WEBP_REDUCE_CSP |
459 | | |
460 | | int WebPPictureImportRGB(WebPPicture* picture, const uint8_t* rgb, |
461 | 1.45k | int rgb_stride) { |
462 | 1.45k | return (picture != NULL && rgb != NULL) |
463 | 1.45k | ? Import(picture, rgb, rgb_stride, 3, 0, 0) |
464 | 1.45k | : 0; |
465 | 1.45k | } |
466 | | |
467 | | int WebPPictureImportRGBA(WebPPicture* picture, const uint8_t* rgba, |
468 | 1.70k | int rgba_stride) { |
469 | 1.70k | return (picture != NULL && rgba != NULL) |
470 | 1.70k | ? Import(picture, rgba, rgba_stride, 4, 0, 1) |
471 | 1.70k | : 0; |
472 | 1.70k | } |
473 | | |
474 | | int WebPPictureImportRGBX(WebPPicture* picture, const uint8_t* rgbx, |
475 | 0 | int rgbx_stride) { |
476 | 0 | return (picture != NULL && rgbx != NULL) |
477 | 0 | ? Import(picture, rgbx, rgbx_stride, 4, 0, 0) |
478 | 0 | : 0; |
479 | 0 | } |
480 | | |
481 | | //------------------------------------------------------------------------------ |