Coverage Report

Created: 2026-10-28 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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.90k
#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
13.6k
                          int x_step, ptrdiff_t y_step) {
43
13.6k
  if (alpha == NULL) return 0;
44
9.56k
  WebPInitAlphaProcessing();
45
9.56k
  if (x_step == 1) {
46
7.06k
    for (; height-- > 0; alpha += y_step) {
47
7.06k
      if (WebPHasAlpha8b(alpha, width)) return 1;
48
7.06k
    }
49
5.21k
  } else {
50
475k
    for (; height-- > 0; alpha += y_step) {
51
474k
      if (WebPHasAlpha32b(alpha, width)) return 1;
52
474k
    }
53
5.21k
  }
54
868
  return 0;
55
9.56k
}
56
57
// Checking for the presence of non-opaque alpha.
58
6.80k
int WebPPictureHasTransparency(const WebPPicture* picture) {
59
6.80k
  if (picture == NULL) return 0;
60
6.80k
  if (picture->use_argb) {
61
0
    if (picture->argb != NULL) {
62
0
      return CheckNonOpaque(
63
0
          (const uint8_t*)picture->argb + ALPHA_OFFSET, picture->width,
64
0
          picture->height, 4,
65
0
          (ptrdiff_t)picture->argb_stride * sizeof(*picture->argb));
66
0
    }
67
0
    return 0;
68
0
  }
69
6.80k
  return CheckNonOpaque(picture->a, picture->width, picture->height, 1,
70
6.80k
                        picture->a_stride);
71
6.80k
}
72
73
extern VP8CPUInfo VP8GetCPUInfo;
74
75
//------------------------------------------------------------------------------
76
// Sharp RGB->YUV conversion
77
78
static const int kMinDimensionIterativeConversion = 4;
79
80
//------------------------------------------------------------------------------
81
// Main function
82
83
WEBP_NODISCARD static int PreprocessARGB(const uint8_t* r_ptr,
84
                                         const uint8_t* g_ptr,
85
                                         const uint8_t* b_ptr, int step,
86
                                         int rgb_stride,
87
0
                                         WebPPicture* const picture) {
88
0
  const int ok = SharpYuvConvert(
89
0
      r_ptr, g_ptr, b_ptr, step, rgb_stride, /*rgb_bit_depth=*/8, picture->y,
90
0
      picture->y_stride, picture->u, picture->uv_stride, picture->v,
91
0
      picture->uv_stride, /*yuv_bit_depth=*/8, picture->width, picture->height,
92
0
      SharpYuvGetConversionMatrix(kSharpYuvMatrixWebp));
93
0
  if (!ok) {
94
0
    return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
95
0
  }
96
0
  return ok;
97
0
}
98
99
static WEBP_INLINE void ConvertRowToY(const uint8_t* const r_ptr,
100
                                      const uint8_t* const g_ptr,
101
                                      const uint8_t* const b_ptr, int step,
102
                                      uint8_t* const dst_y, int width,
103
0
                                      VP8Random* const rg) {
104
0
  int i, j;
105
0
  for (i = 0, j = 0; i < width; i += 1, j += step) {
106
0
    dst_y[i] =
107
0
        VP8RGBToY(r_ptr[j], g_ptr[j], b_ptr[j], VP8RandomBits(rg, YUV_FIX));
108
0
  }
109
0
}
110
111
static WEBP_INLINE void ConvertRowsToUV(const uint16_t* rgb,
112
                                        uint8_t* const dst_u,
113
                                        uint8_t* const dst_v, int width,
114
0
                                        VP8Random* const rg) {
115
0
  int i;
116
0
  for (i = 0; i < width; i += 1, rgb += 4) {
117
0
    const int r = rgb[0], g = rgb[1], b = rgb[2];
118
0
    dst_u[i] = VP8RGBToU(r, g, b, VP8RandomBits(rg, YUV_FIX + 2));
119
0
    dst_v[i] = VP8RGBToV(r, g, b, VP8RandomBits(rg, YUV_FIX + 2));
120
0
  }
121
0
}
122
123
extern void SharpYuvInit(VP8CPUInfo cpu_info_func);
124
125
WEBP_NODISCARD static int ImportYUVAFromRGBA(
126
    const uint8_t* r_ptr, const uint8_t* g_ptr, const uint8_t* b_ptr,
127
    const uint8_t* a_ptr,
128
    int step,        // bytes per pixel
129
    int rgb_stride,  // bytes per scanline
130
6.80k
    float dithering, int use_iterative_conversion, WebPPicture* const picture) {
131
6.80k
  int y;
132
6.80k
  const int width = picture->width;
133
6.80k
  const int height = picture->height;
134
6.80k
  const int has_alpha = CheckNonOpaque(a_ptr, width, height, step, rgb_stride);
135
6.80k
  const WebPEncCSP orig_colorspace = picture->colorspace;
136
6.80k
  const int orig_use_argb = picture->use_argb;
137
138
6.80k
  picture->colorspace = has_alpha ? WEBP_YUV420A : WEBP_YUV420;
139
6.80k
  picture->use_argb = 0;
140
141
  // disable smart conversion if source is too small (overkill).
142
6.80k
  if (width < kMinDimensionIterativeConversion ||
143
5.66k
      height < kMinDimensionIterativeConversion) {
144
1.40k
    use_iterative_conversion = 0;
145
1.40k
  }
146
147
6.80k
  if (!WebPPictureAllocYUVA(picture)) {
148
0
    picture->colorspace = orig_colorspace;
149
0
    picture->use_argb = orig_use_argb;
150
0
    return 0;
151
0
  }
152
6.80k
  if (has_alpha) {
153
4.34k
    assert(step == 4);
154
4.34k
  }
155
156
6.80k
  if (use_iterative_conversion) {
157
0
    SharpYuvInit(VP8GetCPUInfo);
158
0
    if (!PreprocessARGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, picture)) {
159
0
      WebPSafeFree(picture->memory_);
160
0
      picture->memory_ = NULL;
161
0
      picture->y = picture->u = picture->v = picture->a = NULL;
162
0
      picture->y_stride = picture->uv_stride = picture->a_stride = 0;
163
0
      picture->colorspace = orig_colorspace;
164
0
      picture->use_argb = orig_use_argb;
165
0
      return 0;
166
0
    }
167
0
    if (has_alpha) {
168
0
      WebPExtractAlpha(a_ptr, rgb_stride, width, height, picture->a,
169
0
                       picture->a_stride);
170
0
    }
171
6.80k
  } else {
172
6.80k
    const int uv_width = (width + 1) >> 1;
173
    // temporary storage for accumulated R/G/B values during conversion to U/V
174
6.80k
    uint16_t* const tmp_rgb =
175
6.80k
        (uint16_t*)WebPSafeMalloc(4 * uv_width, sizeof(*tmp_rgb));
176
6.80k
    uint8_t* dst_y = picture->y;
177
6.80k
    uint8_t* dst_u = picture->u;
178
6.80k
    uint8_t* dst_v = picture->v;
179
6.80k
    uint8_t* dst_a = picture->a;
180
181
6.80k
    VP8Random base_rg;
182
6.80k
    VP8Random* rg = NULL;
183
6.80k
    if (dithering > 0.) {
184
0
      VP8InitRandom(&base_rg, dithering);
185
0
      rg = &base_rg;
186
0
    }
187
6.80k
    WebPInitConvertARGBToYUV();
188
6.80k
    WebPInitGammaTables();
189
190
6.80k
    if (tmp_rgb == NULL) {
191
0
      WebPSafeFree(picture->memory_);
192
0
      picture->memory_ = NULL;
193
0
      picture->y = picture->u = picture->v = picture->a = NULL;
194
0
      picture->y_stride = picture->uv_stride = picture->a_stride = 0;
195
0
      picture->colorspace = orig_colorspace;
196
0
      picture->use_argb = orig_use_argb;
197
0
      return WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY);
198
0
    }
199
200
6.80k
    if (rg == NULL) {
201
      // Downsample Y/U/V planes, two rows at a time
202
6.80k
      WebPImportYUVAFromRGBA(
203
6.80k
          r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride, has_alpha, width,
204
6.80k
          height, tmp_rgb, picture->y_stride, picture->uv_stride,
205
6.80k
          picture->uv_stride, picture->a_stride, dst_y, dst_u, dst_v, dst_a);
206
6.80k
      if (height & 1) {
207
2.29k
        dst_y += (height - 1) * (ptrdiff_t)picture->y_stride;
208
2.29k
        dst_u += (height >> 1) * (ptrdiff_t)picture->uv_stride;
209
2.29k
        dst_v += (height >> 1) * (ptrdiff_t)picture->uv_stride;
210
2.29k
        r_ptr += (height - 1) * (ptrdiff_t)rgb_stride;
211
2.29k
        b_ptr += (height - 1) * (ptrdiff_t)rgb_stride;
212
2.29k
        g_ptr += (height - 1) * (ptrdiff_t)rgb_stride;
213
2.29k
        if (has_alpha) {
214
1.06k
          dst_a += (height - 1) * (ptrdiff_t)picture->a_stride;
215
1.06k
          a_ptr += (height - 1) * (ptrdiff_t)rgb_stride;
216
1.06k
        }
217
2.29k
        WebPImportYUVAFromRGBALastLine(r_ptr, g_ptr, b_ptr, a_ptr, step,
218
2.29k
                                       has_alpha, width, tmp_rgb, dst_y, dst_u,
219
2.29k
                                       dst_v, dst_a);
220
2.29k
      }
221
6.80k
    } else {
222
      // Copy of WebPImportYUVAFromRGBA/WebPImportYUVAFromRGBALastLine,
223
      // but with dithering.
224
0
      for (y = 0; y < (height >> 1); ++y) {
225
0
        int rows_have_alpha = has_alpha;
226
0
        ConvertRowToY(r_ptr, g_ptr, b_ptr, step, dst_y, width, rg);
227
0
        ConvertRowToY(r_ptr + rgb_stride, g_ptr + rgb_stride,
228
0
                      b_ptr + rgb_stride, step, dst_y + picture->y_stride,
229
0
                      width, rg);
230
0
        dst_y += 2 * (ptrdiff_t)picture->y_stride;
231
0
        if (has_alpha) {
232
0
          rows_have_alpha &= !WebPExtractAlpha(a_ptr, rgb_stride, width, 2,
233
0
                                               dst_a, picture->a_stride);
234
0
          dst_a += 2 * (ptrdiff_t)picture->a_stride;
235
0
        }
236
        // Collect averaged R/G/B(/A)
237
0
        if (!rows_have_alpha) {
238
0
          WebPAccumulateRGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, tmp_rgb,
239
0
                            width);
240
0
        } else {
241
0
          WebPAccumulateRGBA(r_ptr, g_ptr, b_ptr, a_ptr, rgb_stride, tmp_rgb,
242
0
                             width);
243
0
        }
244
        // Convert to U/V
245
0
        ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg);
246
0
        dst_u += picture->uv_stride;
247
0
        dst_v += picture->uv_stride;
248
0
        r_ptr += 2 * (ptrdiff_t)rgb_stride;
249
0
        b_ptr += 2 * (ptrdiff_t)rgb_stride;
250
0
        g_ptr += 2 * (ptrdiff_t)rgb_stride;
251
0
        if (has_alpha) a_ptr += 2 * (ptrdiff_t)rgb_stride;
252
0
      }
253
0
      if (height & 1) {  // extra last row
254
0
        int row_has_alpha = has_alpha;
255
0
        ConvertRowToY(r_ptr, g_ptr, b_ptr, step, dst_y, width, rg);
256
0
        if (row_has_alpha) {
257
0
          row_has_alpha &= !WebPExtractAlpha(a_ptr, 0, width, 1, dst_a, 0);
258
0
        }
259
        // Collect averaged R/G/B(/A)
260
0
        if (!row_has_alpha) {
261
          // Collect averaged R/G/B
262
0
          WebPAccumulateRGB(r_ptr, g_ptr, b_ptr, step, /*rgb_stride=*/0,
263
0
                            tmp_rgb, width);
264
0
        } else {
265
0
          WebPAccumulateRGBA(r_ptr, g_ptr, b_ptr, a_ptr, /*rgb_stride=*/0,
266
0
                             tmp_rgb, width);
267
0
        }
268
0
        ConvertRowsToUV(tmp_rgb, dst_u, dst_v, uv_width, rg);
269
0
      }
270
0
    }
271
272
6.80k
    WebPSafeFree(tmp_rgb);
273
6.80k
  }
274
6.80k
  return 1;
275
6.80k
}
276
277
#undef SUM4
278
#undef SUM2
279
#undef SUM4ALPHA
280
#undef SUM2ALPHA
281
282
//------------------------------------------------------------------------------
283
// call for ARGB->YUVA conversion
284
285
// Validates that the source buffer of 'picture' (ARGB if 'use_argb' is true,
286
// YUVA otherwise) is allocated and within bounds, regardless of the current
287
// value of 'picture->use_argb', while preserving 'picture->use_argb'.
288
WEBP_NODISCARD static int ValidateAllocatedPicture(WebPPicture* const picture,
289
2.46k
                                                   int use_argb) {
290
2.46k
  int orig_use_argb, ok;
291
2.46k
  if (picture == NULL) return 0;
292
2.46k
  orig_use_argb = picture->use_argb;
293
2.46k
  picture->use_argb = use_argb;
294
2.46k
  ok = WebPValidateAllocatedPicture(picture);
295
2.46k
  picture->use_argb = orig_use_argb;
296
2.46k
  return ok;
297
2.46k
}
298
299
WEBP_NODISCARD static int PictureARGBToYUVA(WebPPicture* picture,
300
                                            WebPEncCSP colorspace,
301
                                            float dithering,
302
2.46k
                                            int use_iterative_conversion) {
303
2.46k
  if (!ValidateAllocatedPicture(picture, /*use_argb=*/1)) return 0;
304
2.46k
  if ((colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) {
305
0
    return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION);
306
2.46k
  } else {
307
2.46k
    const uint8_t* const argb = (const uint8_t*)picture->argb;
308
2.46k
    const uint8_t* const a = argb + CHANNEL_OFFSET(0);
309
2.46k
    const uint8_t* const r = argb + CHANNEL_OFFSET(1);
310
2.46k
    const uint8_t* const g = argb + CHANNEL_OFFSET(2);
311
2.46k
    const uint8_t* const b = argb + CHANNEL_OFFSET(3);
312
313
2.46k
    return ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride,
314
2.46k
                              dithering, use_iterative_conversion, picture);
315
2.46k
  }
316
2.46k
}
317
318
int WebPPictureARGBToYUVADithered(WebPPicture* picture, WebPEncCSP colorspace,
319
2.46k
                                  float dithering) {
320
2.46k
  return PictureARGBToYUVA(picture, colorspace, dithering, 0);
321
2.46k
}
322
323
0
int WebPPictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace) {
324
0
  return PictureARGBToYUVA(picture, colorspace, 0.f, 0);
325
0
}
326
327
0
int WebPPictureSharpARGBToYUVA(WebPPicture* picture) {
328
0
  return PictureARGBToYUVA(picture, WEBP_YUV420, 0.f, 1);
329
0
}
330
// for backward compatibility
331
0
int WebPPictureSmartARGBToYUVA(WebPPicture* picture) {
332
0
  return WebPPictureSharpARGBToYUVA(picture);
333
0
}
334
335
//------------------------------------------------------------------------------
336
// call for YUVA -> ARGB conversion
337
338
0
int WebPPictureYUVAToARGB(WebPPicture* picture) {
339
0
  if (!ValidateAllocatedPicture(picture, /*use_argb=*/0)) return 0;
340
  // Allocate a new argb buffer (discarding the previous one).
341
0
  if (!WebPPictureAllocARGB(picture)) return 0;
342
0
  picture->use_argb = 1;
343
344
  // Convert
345
0
  {
346
0
    int y;
347
0
    const int width = picture->width;
348
0
    const int height = picture->height;
349
0
    const ptrdiff_t argb_stride = 4 * (ptrdiff_t)picture->argb_stride;
350
0
    uint8_t* dst = (uint8_t*)picture->argb;
351
0
    const uint8_t *cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y;
352
0
    WebPUpsampleLinePairFunc upsample =
353
0
        WebPGetLinePairConverter(ALPHA_OFFSET > 0);
354
355
    // First row, with replicated top samples.
356
0
    upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width);
357
0
    cur_y += picture->y_stride;
358
0
    dst += argb_stride;
359
    // Center rows.
360
0
    for (y = 1; y + 1 < height; y += 2) {
361
0
      const uint8_t* const top_u = cur_u;
362
0
      const uint8_t* const top_v = cur_v;
363
0
      cur_u += picture->uv_stride;
364
0
      cur_v += picture->uv_stride;
365
0
      upsample(cur_y, cur_y + picture->y_stride, top_u, top_v, cur_u, cur_v,
366
0
               dst, dst + argb_stride, width);
367
0
      cur_y += 2 * (ptrdiff_t)picture->y_stride;
368
0
      dst += 2 * argb_stride;
369
0
    }
370
    // Last row (if needed), with replicated bottom samples.
371
0
    if (height > 1 && !(height & 1)) {
372
0
      upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width);
373
0
    }
374
    // Insert alpha values if needed, in replacement for the default 0xff ones.
375
0
    if (picture->colorspace & WEBP_CSP_ALPHA_BIT) {
376
0
      for (y = 0; y < height; ++y) {
377
0
        uint32_t* const argb_dst =
378
0
            picture->argb + (ptrdiff_t)y * picture->argb_stride;
379
0
        const uint8_t* const src =
380
0
            picture->a + (ptrdiff_t)y * picture->a_stride;
381
0
        int x;
382
0
        for (x = 0; x < width; ++x) {
383
0
          argb_dst[x] = (argb_dst[x] & 0x00ffffffu) | ((uint32_t)src[x] << 24);
384
0
        }
385
0
      }
386
0
    }
387
0
  }
388
0
  return 1;
389
0
}
390
391
//------------------------------------------------------------------------------
392
// automatic import / conversion
393
394
WEBP_NODISCARD static int Import(WebPPicture* const picture, const uint8_t* rgb,
395
                                 int rgb_stride, int step, int swap_rb,
396
6.80k
                                 int import_alpha) {
397
6.80k
  int y;
398
6.80k
  const uint8_t* r_ptr;
399
6.80k
  const uint8_t* g_ptr;
400
6.80k
  const uint8_t* b_ptr;
401
6.80k
  int width, height;
402
403
6.80k
  if (picture == NULL) return 0;
404
6.80k
  if (rgb == NULL) {
405
0
    return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER);
406
0
  }
407
6.80k
  r_ptr = rgb + (swap_rb ? 2 : 0);
408
6.80k
  g_ptr = rgb + 1;
409
6.80k
  b_ptr = rgb + (swap_rb ? 0 : 2);
410
411
6.80k
  WebPPictureFree(picture);
412
413
6.80k
  if (!WebPValidatePicture(picture)) return 0;
414
415
6.80k
  width = picture->width;
416
6.80k
  height = picture->height;
417
6.80k
  if (!CheckStride(rgb_stride, step, width)) {
418
0
    return WebPEncodingSetError(picture, VP8_ENC_ERROR_BAD_DIMENSION);
419
0
  }
420
421
6.80k
  if (!picture->use_argb) {
422
4.34k
    const uint8_t* a_ptr = import_alpha ? rgb + 3 : NULL;
423
4.34k
    return ImportYUVAFromRGBA(r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride,
424
4.34k
                              0.f /* no dithering */, 0, picture);
425
4.34k
  }
426
2.46k
  if (!WebPPictureAlloc(picture)) return 0;
427
428
2.46k
  VP8LDspInit();
429
2.46k
  WebPInitAlphaProcessing();
430
431
2.46k
  if (import_alpha) {
432
    // dst[] byte order is {a,r,g,b} for big-endian, {b,g,r,a} for little endian
433
1.90k
    uint32_t* dst = picture->argb;
434
1.90k
    const int do_copy = (ALPHA_OFFSET == 3) && swap_rb;
435
1.90k
    assert(step == 4);
436
1.90k
    if (do_copy) {
437
0
      for (y = 0; y < height; ++y) {
438
0
        memcpy(dst, rgb, width * 4);
439
0
        rgb += rgb_stride;
440
0
        dst += picture->argb_stride;
441
0
      }
442
1.90k
    } else {
443
1.44M
      for (y = 0; y < height; ++y) {
444
#ifdef WORDS_BIGENDIAN
445
        // BGRA or RGBA input order.
446
        const uint8_t* a_ptr = rgb + 3;
447
        WebPPackARGB(a_ptr, r_ptr, g_ptr, b_ptr, width, dst);
448
        r_ptr += rgb_stride;
449
        g_ptr += rgb_stride;
450
        b_ptr += rgb_stride;
451
#else
452
        // RGBA input order. Need to swap R and B.
453
1.44M
        if (WEBP_IS_ALIGNED(rgb, uint32_t)) {
454
1.44M
          VP8LConvertBGRAToRGBA((const uint32_t*)rgb, width, (uint8_t*)dst);
455
1.44M
        } else {
456
          // 'rgb' (or 'rgb_stride') is not 4-byte aligned: reading it through
457
          // a uint32_t* would be undefined behavior, so go through bytes.
458
0
          int x;
459
0
          for (x = 0; x < width; ++x) {
460
0
            const uint8_t* const p = rgb + 4 * x;
461
0
            dst[x] = ((uint32_t)p[3] << 24) | ((uint32_t)p[0] << 16) |
462
0
                     ((uint32_t)p[1] << 8) | (uint32_t)p[2];
463
0
          }
464
0
        }
465
1.44M
#endif
466
1.44M
        rgb += rgb_stride;
467
1.44M
        dst += picture->argb_stride;
468
1.44M
      }
469
1.90k
    }
470
1.90k
  } else {
471
559
    uint32_t* dst = picture->argb;
472
559
    assert(step >= 3);
473
111k
    for (y = 0; y < height; ++y) {
474
110k
      WebPPackRGB(r_ptr, g_ptr, b_ptr, width, step, dst);
475
110k
      r_ptr += rgb_stride;
476
110k
      g_ptr += rgb_stride;
477
110k
      b_ptr += rgb_stride;
478
110k
      dst += picture->argb_stride;
479
110k
    }
480
559
  }
481
2.46k
  return 1;
482
2.46k
}
483
484
// Public API
485
486
#if !defined(WEBP_REDUCE_CSP)
487
488
int WebPPictureImportBGR(WebPPicture* picture, const uint8_t* bgr,
489
0
                         int bgr_stride) {
490
0
  return Import(picture, bgr, bgr_stride, 3, 1, 0);
491
0
}
492
493
int WebPPictureImportBGRA(WebPPicture* picture, const uint8_t* bgra,
494
0
                          int bgra_stride) {
495
0
  return Import(picture, bgra, bgra_stride, 4, 1, 1);
496
0
}
497
498
int WebPPictureImportBGRX(WebPPicture* picture, const uint8_t* bgrx,
499
0
                          int bgrx_stride) {
500
0
  return Import(picture, bgrx, bgrx_stride, 4, 1, 0);
501
0
}
502
503
#endif  // WEBP_REDUCE_CSP
504
505
int WebPPictureImportRGB(WebPPicture* picture, const uint8_t* rgb,
506
2.15k
                         int rgb_stride) {
507
2.15k
  return Import(picture, rgb, rgb_stride, 3, 0, 0);
508
2.15k
}
509
510
int WebPPictureImportRGBA(WebPPicture* picture, const uint8_t* rgba,
511
4.65k
                          int rgba_stride) {
512
4.65k
  return Import(picture, rgba, rgba_stride, 4, 0, 1);
513
4.65k
}
514
515
int WebPPictureImportRGBX(WebPPicture* picture, const uint8_t* rgbx,
516
0
                          int rgbx_stride) {
517
0
  return Import(picture, rgbx, rgbx_stride, 4, 0, 0);
518
0
}
519
520
//------------------------------------------------------------------------------