Coverage Report

Created: 2026-09-14 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libavif/src/alpha.c
Line
Count
Source
1
// Copyright 2020 Joe Drago. All rights reserved.
2
// SPDX-License-Identifier: BSD-2-Clause
3
4
#include "avif/internal.h"
5
6
#include <assert.h>
7
#include <string.h>
8
9
void avifFillAlpha(const avifAlphaParams * params)
10
12.5k
{
11
12.5k
    if (params->dstDepth > 8) {
12
3.08k
        const uint16_t maxChannel = (uint16_t)((1 << params->dstDepth) - 1);
13
3.08k
        uint8_t * dstRow = &params->dstPlane[params->dstOffsetBytes];
14
2.29M
        for (uint32_t j = 0; j < params->height; ++j) {
15
2.29M
            uint8_t * dstPixel = dstRow;
16
432M
            for (uint32_t i = 0; i < params->width; ++i) {
17
430M
                *((uint16_t *)dstPixel) = maxChannel;
18
430M
                dstPixel += params->dstPixelBytes;
19
430M
            }
20
2.29M
            dstRow += params->dstRowBytes;
21
2.29M
        }
22
9.46k
    } else {
23
        // In this case, (1 << params->dstDepth) - 1 is always equal to 255.
24
9.46k
        const uint8_t maxChannel = 255;
25
9.46k
        uint8_t * dstRow = &params->dstPlane[params->dstOffsetBytes];
26
2.67M
        for (uint32_t j = 0; j < params->height; ++j) {
27
2.66M
            uint8_t * dstPixel = dstRow;
28
689M
            for (uint32_t i = 0; i < params->width; ++i) {
29
686M
                *dstPixel = maxChannel;
30
686M
                dstPixel += params->dstPixelBytes;
31
686M
            }
32
2.66M
            dstRow += params->dstRowBytes;
33
2.66M
        }
34
9.46k
    }
35
12.5k
}
36
37
void avifReformatAlpha(const avifAlphaParams * params)
38
251
{
39
251
    const int srcMaxChannel = (1 << params->srcDepth) - 1;
40
251
    const int dstMaxChannel = (1 << params->dstDepth) - 1;
41
251
    const float srcMaxChannelF = (float)srcMaxChannel;
42
251
    const float dstMaxChannelF = (float)dstMaxChannel;
43
44
251
    if (params->srcDepth == params->dstDepth) {
45
        // no depth rescale
46
47
168
        if (params->srcDepth > 8) {
48
            // no depth rescale, uint16_t -> uint16_t
49
50
0
            const uint8_t * srcRow = &params->srcPlane[params->srcOffsetBytes];
51
0
            uint8_t * dstRow = &params->dstPlane[params->dstOffsetBytes];
52
0
            for (uint32_t j = 0; j < params->height; ++j) {
53
0
                const uint8_t * srcPixel = srcRow;
54
0
                uint8_t * dstPixel = dstRow;
55
0
                for (uint32_t i = 0; i < params->width; ++i) {
56
0
                    *((uint16_t *)dstPixel) = *((const uint16_t *)srcPixel);
57
0
                    srcPixel += params->srcPixelBytes;
58
0
                    dstPixel += params->dstPixelBytes;
59
0
                }
60
0
                srcRow += params->srcRowBytes;
61
0
                dstRow += params->dstRowBytes;
62
0
            }
63
168
        } else {
64
            // no depth rescale, uint8_t -> uint8_t
65
66
168
            const uint8_t * srcRow = &params->srcPlane[params->srcOffsetBytes];
67
168
            uint8_t * dstRow = &params->dstPlane[params->dstOffsetBytes];
68
112k
            for (uint32_t j = 0; j < params->height; ++j) {
69
112k
                const uint8_t * srcPixel = srcRow;
70
112k
                uint8_t * dstPixel = dstRow;
71
10.0M
                for (uint32_t i = 0; i < params->width; ++i) {
72
9.91M
                    *dstPixel = *srcPixel;
73
9.91M
                    srcPixel += params->srcPixelBytes;
74
9.91M
                    dstPixel += params->dstPixelBytes;
75
9.91M
                }
76
112k
                srcRow += params->srcRowBytes;
77
112k
                dstRow += params->dstRowBytes;
78
112k
            }
79
168
        }
80
168
    } else {
81
        // depth rescale
82
83
83
        if (params->srcDepth > 8) {
84
83
            if (params->dstDepth > 8) {
85
                // depth rescale, uint16_t -> uint16_t
86
87
83
                const uint8_t * srcRow = &params->srcPlane[params->srcOffsetBytes];
88
83
                uint8_t * dstRow = &params->dstPlane[params->dstOffsetBytes];
89
63.3k
                for (uint32_t j = 0; j < params->height; ++j) {
90
63.2k
                    const uint8_t * srcPixel = srcRow;
91
63.2k
                    uint8_t * dstPixel = dstRow;
92
12.3M
                    for (uint32_t i = 0; i < params->width; ++i) {
93
12.3M
                        int srcAlpha = *((const uint16_t *)srcPixel);
94
12.3M
                        float alphaF = (float)srcAlpha / srcMaxChannelF;
95
12.3M
                        int dstAlpha = (int)(0.5f + (alphaF * dstMaxChannelF));
96
12.3M
                        dstAlpha = AVIF_CLAMP(dstAlpha, 0, dstMaxChannel);
97
12.3M
                        *((uint16_t *)dstPixel) = (uint16_t)dstAlpha;
98
12.3M
                        srcPixel += params->srcPixelBytes;
99
12.3M
                        dstPixel += params->dstPixelBytes;
100
12.3M
                    }
101
63.2k
                    srcRow += params->srcRowBytes;
102
63.2k
                    dstRow += params->dstRowBytes;
103
63.2k
                }
104
83
            } else {
105
                // depth rescale, uint16_t -> uint8_t
106
107
0
                const uint8_t * srcRow = &params->srcPlane[params->srcOffsetBytes];
108
0
                uint8_t * dstRow = &params->dstPlane[params->dstOffsetBytes];
109
0
                for (uint32_t j = 0; j < params->height; ++j) {
110
0
                    const uint8_t * srcPixel = srcRow;
111
0
                    uint8_t * dstPixel = dstRow;
112
0
                    for (uint32_t i = 0; i < params->width; ++i) {
113
0
                        int srcAlpha = *((const uint16_t *)srcPixel);
114
0
                        float alphaF = (float)srcAlpha / srcMaxChannelF;
115
0
                        int dstAlpha = (int)(0.5f + (alphaF * dstMaxChannelF));
116
0
                        dstAlpha = AVIF_CLAMP(dstAlpha, 0, dstMaxChannel);
117
0
                        *dstPixel = (uint8_t)dstAlpha;
118
0
                        srcPixel += params->srcPixelBytes;
119
0
                        dstPixel += params->dstPixelBytes;
120
0
                    }
121
0
                    srcRow += params->srcRowBytes;
122
0
                    dstRow += params->dstRowBytes;
123
0
                }
124
0
            }
125
83
        } else {
126
            // If (srcDepth == 8), dstDepth must be >8 otherwise we'd be in the (params->srcDepth == params->dstDepth) block above.
127
0
            assert(params->dstDepth > 8);
128
129
            // depth rescale, uint8_t -> uint16_t
130
0
            const uint8_t * srcRow = &params->srcPlane[params->srcOffsetBytes];
131
0
            uint8_t * dstRow = &params->dstPlane[params->dstOffsetBytes];
132
0
            for (uint32_t j = 0; j < params->height; ++j) {
133
0
                const uint8_t * srcPixel = srcRow;
134
0
                uint8_t * dstPixel = dstRow;
135
0
                for (uint32_t i = 0; i < params->width; ++i) {
136
0
                    int srcAlpha = *srcPixel;
137
0
                    float alphaF = (float)srcAlpha / srcMaxChannelF;
138
0
                    int dstAlpha = (int)(0.5f + (alphaF * dstMaxChannelF));
139
0
                    dstAlpha = AVIF_CLAMP(dstAlpha, 0, dstMaxChannel);
140
0
                    *((uint16_t *)dstPixel) = (uint16_t)dstAlpha;
141
0
                    srcPixel += params->srcPixelBytes;
142
0
                    dstPixel += params->dstPixelBytes;
143
0
                }
144
0
                srcRow += params->srcRowBytes;
145
0
                dstRow += params->dstRowBytes;
146
0
            }
147
0
        }
148
83
    }
149
251
}
150
151
avifResult avifRGBImagePremultiplyAlpha(avifRGBImage * rgb)
152
0
{
153
    // no data
154
0
    if (!rgb->pixels || !rgb->rowBytes) {
155
0
        return AVIF_RESULT_REFORMAT_FAILED;
156
0
    }
157
158
    // no alpha.
159
0
    if (!avifRGBFormatHasAlpha(rgb->format)) {
160
0
        return AVIF_RESULT_INVALID_ARGUMENT;
161
0
    }
162
163
0
    avifResult libyuvResult = avifRGBImagePremultiplyAlphaLibYUV(rgb);
164
0
    if (libyuvResult != AVIF_RESULT_NOT_IMPLEMENTED) {
165
0
        return libyuvResult;
166
0
    }
167
168
0
    assert(rgb->depth >= 8 && rgb->depth <= 16);
169
170
0
    uint32_t max = (1 << rgb->depth) - 1;
171
0
    float maxF = (float)max;
172
173
0
    if (rgb->depth > 8) {
174
0
        if (rgb->format == AVIF_RGB_FORMAT_RGBA || rgb->format == AVIF_RGB_FORMAT_BGRA) {
175
0
            uint8_t * row = rgb->pixels;
176
0
            for (uint32_t j = 0; j < rgb->height; ++j) {
177
0
                uint16_t * pixel = (uint16_t *)row;
178
0
                for (uint32_t i = 0; i < rgb->width; ++i) {
179
0
                    uint16_t a = pixel[3];
180
0
                    if (a >= max) {
181
                        // opaque is no-op
182
0
                    } else if (a == 0) {
183
                        // result must be zero
184
0
                        pixel[0] = 0;
185
0
                        pixel[1] = 0;
186
0
                        pixel[2] = 0;
187
0
                    } else {
188
                        // a < maxF is always true now, so we don't need clamp here
189
0
                        pixel[0] = (uint16_t)avifRoundf((float)pixel[0] * (float)a / maxF);
190
0
                        pixel[1] = (uint16_t)avifRoundf((float)pixel[1] * (float)a / maxF);
191
0
                        pixel[2] = (uint16_t)avifRoundf((float)pixel[2] * (float)a / maxF);
192
0
                    }
193
0
                    pixel += 4;
194
0
                }
195
0
                row += rgb->rowBytes;
196
0
            }
197
0
        } else if (rgb->format == AVIF_RGB_FORMAT_ARGB || rgb->format == AVIF_RGB_FORMAT_ABGR) {
198
0
            uint8_t * row = rgb->pixels;
199
0
            for (uint32_t j = 0; j < rgb->height; ++j) {
200
0
                uint16_t * pixel = (uint16_t *)row;
201
0
                for (uint32_t i = 0; i < rgb->width; ++i) {
202
0
                    uint16_t a = pixel[0];
203
0
                    if (a >= max) {
204
0
                    } else if (a == 0) {
205
0
                        pixel[1] = 0;
206
0
                        pixel[2] = 0;
207
0
                        pixel[3] = 0;
208
0
                    } else {
209
0
                        pixel[1] = (uint16_t)avifRoundf((float)pixel[1] * (float)a / maxF);
210
0
                        pixel[2] = (uint16_t)avifRoundf((float)pixel[2] * (float)a / maxF);
211
0
                        pixel[3] = (uint16_t)avifRoundf((float)pixel[3] * (float)a / maxF);
212
0
                    }
213
0
                    pixel += 4;
214
0
                }
215
0
                row += rgb->rowBytes;
216
0
            }
217
0
        } else if (rgb->format == AVIF_RGB_FORMAT_GRAYA) {
218
0
            uint8_t * row = rgb->pixels;
219
0
            for (uint32_t j = 0; j < rgb->height; ++j) {
220
0
                uint16_t * pixel = (uint16_t *)row;
221
0
                for (uint32_t i = 0; i < rgb->width; ++i) {
222
0
                    uint16_t a = pixel[1];
223
0
                    if (a >= max) {
224
                        // opaque is no-op
225
0
                    } else if (a == 0) {
226
                        // result must be zero
227
0
                        pixel[0] = 0;
228
0
                    } else {
229
                        // a < maxF is always true now, so we don't need clamp here
230
0
                        pixel[0] = (uint16_t)avifRoundf((float)pixel[0] * (float)a / maxF);
231
0
                    }
232
0
                    pixel += 2;
233
0
                }
234
0
                row += rgb->rowBytes;
235
0
            }
236
0
        } else if (rgb->format == AVIF_RGB_FORMAT_AGRAY) {
237
0
            uint8_t * row = rgb->pixels;
238
0
            for (uint32_t j = 0; j < rgb->height; ++j) {
239
0
                uint16_t * pixel = (uint16_t *)row;
240
0
                for (uint32_t i = 0; i < rgb->width; ++i) {
241
0
                    uint16_t a = pixel[0];
242
0
                    if (a >= max) {
243
0
                    } else if (a == 0) {
244
0
                        pixel[1] = 0;
245
0
                    } else {
246
0
                        pixel[1] = (uint16_t)avifRoundf((float)pixel[1] * (float)a / maxF);
247
0
                    }
248
0
                    pixel += 2;
249
0
                }
250
0
                row += rgb->rowBytes;
251
0
            }
252
0
        } else {
253
0
            return AVIF_RESULT_NOT_IMPLEMENTED;
254
0
        }
255
0
    } else {
256
0
        if (rgb->format == AVIF_RGB_FORMAT_RGBA || rgb->format == AVIF_RGB_FORMAT_BGRA) {
257
0
            uint8_t * row = rgb->pixels;
258
0
            for (uint32_t j = 0; j < rgb->height; ++j) {
259
0
                uint8_t * pixel = row;
260
0
                for (uint32_t i = 0; i < rgb->width; ++i) {
261
0
                    uint8_t a = pixel[3];
262
                    // uint8_t can't exceed 255
263
0
                    if (a == max) {
264
0
                    } else if (a == 0) {
265
0
                        pixel[0] = 0;
266
0
                        pixel[1] = 0;
267
0
                        pixel[2] = 0;
268
0
                    } else {
269
0
                        pixel[0] = (uint8_t)avifRoundf((float)pixel[0] * (float)a / maxF);
270
0
                        pixel[1] = (uint8_t)avifRoundf((float)pixel[1] * (float)a / maxF);
271
0
                        pixel[2] = (uint8_t)avifRoundf((float)pixel[2] * (float)a / maxF);
272
0
                    }
273
0
                    pixel += 4;
274
0
                }
275
0
                row += rgb->rowBytes;
276
0
            }
277
0
        } else if (rgb->format == AVIF_RGB_FORMAT_ARGB || rgb->format == AVIF_RGB_FORMAT_ABGR) {
278
0
            uint8_t * row = rgb->pixels;
279
0
            for (uint32_t j = 0; j < rgb->height; ++j) {
280
0
                uint8_t * pixel = row;
281
0
                for (uint32_t i = 0; i < rgb->width; ++i) {
282
0
                    uint8_t a = pixel[0];
283
0
                    if (a == max) {
284
0
                    } else if (a == 0) {
285
0
                        pixel[1] = 0;
286
0
                        pixel[2] = 0;
287
0
                        pixel[3] = 0;
288
0
                    } else {
289
0
                        pixel[1] = (uint8_t)avifRoundf((float)pixel[1] * (float)a / maxF);
290
0
                        pixel[2] = (uint8_t)avifRoundf((float)pixel[2] * (float)a / maxF);
291
0
                        pixel[3] = (uint8_t)avifRoundf((float)pixel[3] * (float)a / maxF);
292
0
                    }
293
0
                    pixel += 4;
294
0
                }
295
0
                row += rgb->rowBytes;
296
0
            }
297
0
        } else if (rgb->format == AVIF_RGB_FORMAT_GRAYA) {
298
0
            uint8_t * row = rgb->pixels;
299
0
            for (uint32_t j = 0; j < rgb->height; ++j) {
300
0
                uint8_t * pixel = row;
301
0
                for (uint32_t i = 0; i < rgb->width; ++i) {
302
0
                    uint8_t a = pixel[1];
303
                    // uint8_t can't exceed 255
304
0
                    if (a == max) {
305
0
                    } else if (a == 0) {
306
0
                        pixel[0] = 0;
307
0
                    } else {
308
0
                        pixel[0] = (uint8_t)avifRoundf((float)pixel[0] * (float)a / maxF);
309
0
                    }
310
0
                    pixel += 2;
311
0
                }
312
0
                row += rgb->rowBytes;
313
0
            }
314
0
        } else if (rgb->format == AVIF_RGB_FORMAT_AGRAY) {
315
0
            uint8_t * row = rgb->pixels;
316
0
            for (uint32_t j = 0; j < rgb->height; ++j) {
317
0
                uint8_t * pixel = row;
318
0
                for (uint32_t i = 0; i < rgb->width; ++i) {
319
0
                    uint8_t a = pixel[0];
320
0
                    if (a == max) {
321
0
                    } else if (a == 0) {
322
0
                        pixel[1] = 0;
323
0
                    } else {
324
0
                        pixel[1] = (uint8_t)avifRoundf((float)pixel[1] * (float)a / maxF);
325
0
                    }
326
0
                    pixel += 2;
327
0
                }
328
0
                row += rgb->rowBytes;
329
0
            }
330
0
        } else {
331
0
            return AVIF_RESULT_NOT_IMPLEMENTED;
332
0
        }
333
0
    }
334
335
0
    return AVIF_RESULT_OK;
336
0
}
337
338
avifResult avifRGBImageUnpremultiplyAlpha(avifRGBImage * rgb)
339
0
{
340
    // no data
341
0
    if (!rgb->pixels || !rgb->rowBytes) {
342
0
        return AVIF_RESULT_REFORMAT_FAILED;
343
0
    }
344
345
    // no alpha.
346
0
    if (!avifRGBFormatHasAlpha(rgb->format)) {
347
0
        return AVIF_RESULT_REFORMAT_FAILED;
348
0
    }
349
350
0
    avifResult libyuvResult = avifRGBImageUnpremultiplyAlphaLibYUV(rgb);
351
0
    if (libyuvResult != AVIF_RESULT_NOT_IMPLEMENTED) {
352
0
        return libyuvResult;
353
0
    }
354
355
0
    assert(rgb->depth >= 8 && rgb->depth <= 16);
356
357
0
    uint32_t max = (1 << rgb->depth) - 1;
358
0
    float maxF = (float)max;
359
360
0
    if (rgb->depth > 8) {
361
0
        if (rgb->format == AVIF_RGB_FORMAT_RGBA || rgb->format == AVIF_RGB_FORMAT_BGRA) {
362
0
            uint8_t * row = rgb->pixels;
363
0
            for (uint32_t j = 0; j < rgb->height; ++j) {
364
0
                uint16_t * pixel = (uint16_t *)row;
365
0
                for (uint32_t i = 0; i < rgb->width; ++i) {
366
0
                    uint16_t a = pixel[3];
367
0
                    if (a >= max) {
368
                        // opaque is no-op
369
0
                    } else if (a == 0) {
370
                        // prevent division by zero
371
0
                        pixel[0] = 0;
372
0
                        pixel[1] = 0;
373
0
                        pixel[2] = 0;
374
0
                    } else {
375
0
                        float c1 = avifRoundf((float)pixel[0] * maxF / (float)a);
376
0
                        float c2 = avifRoundf((float)pixel[1] * maxF / (float)a);
377
0
                        float c3 = avifRoundf((float)pixel[2] * maxF / (float)a);
378
0
                        pixel[0] = (uint16_t)AVIF_MIN(c1, maxF);
379
0
                        pixel[1] = (uint16_t)AVIF_MIN(c2, maxF);
380
0
                        pixel[2] = (uint16_t)AVIF_MIN(c3, maxF);
381
0
                    }
382
0
                    pixel += 4;
383
0
                }
384
0
                row += rgb->rowBytes;
385
0
            }
386
0
        } else if (rgb->format == AVIF_RGB_FORMAT_ARGB || rgb->format == AVIF_RGB_FORMAT_ABGR) {
387
0
            uint8_t * row = rgb->pixels;
388
0
            for (uint32_t j = 0; j < rgb->height; ++j) {
389
0
                uint16_t * pixel = (uint16_t *)row;
390
0
                for (uint32_t i = 0; i < rgb->width; ++i) {
391
0
                    uint16_t a = pixel[0];
392
0
                    if (a >= max) {
393
0
                    } else if (a == 0) {
394
0
                        pixel[1] = 0;
395
0
                        pixel[2] = 0;
396
0
                        pixel[3] = 0;
397
0
                    } else {
398
0
                        float c1 = avifRoundf((float)pixel[1] * maxF / (float)a);
399
0
                        float c2 = avifRoundf((float)pixel[2] * maxF / (float)a);
400
0
                        float c3 = avifRoundf((float)pixel[3] * maxF / (float)a);
401
0
                        pixel[1] = (uint16_t)AVIF_MIN(c1, maxF);
402
0
                        pixel[2] = (uint16_t)AVIF_MIN(c2, maxF);
403
0
                        pixel[3] = (uint16_t)AVIF_MIN(c3, maxF);
404
0
                    }
405
0
                    pixel += 4;
406
0
                }
407
0
                row += rgb->rowBytes;
408
0
            }
409
0
        } else if (rgb->format == AVIF_RGB_FORMAT_GRAYA) {
410
0
            uint8_t * row = rgb->pixels;
411
0
            for (uint32_t j = 0; j < rgb->height; ++j) {
412
0
                uint16_t * pixel = (uint16_t *)row;
413
0
                for (uint32_t i = 0; i < rgb->width; ++i) {
414
0
                    uint16_t a = pixel[1];
415
0
                    if (a >= max) {
416
                        // opaque is no-op
417
0
                    } else if (a == 0) {
418
                        // prevent division by zero
419
0
                        pixel[0] = 0;
420
0
                    } else {
421
0
                        float c1 = avifRoundf((float)pixel[0] * maxF / (float)a);
422
0
                        pixel[0] = (uint16_t)AVIF_MIN(c1, maxF);
423
0
                    }
424
0
                    pixel += 2;
425
0
                }
426
0
                row += rgb->rowBytes;
427
0
            }
428
0
        } else if (rgb->format == AVIF_RGB_FORMAT_AGRAY) {
429
0
            uint8_t * row = rgb->pixels;
430
0
            for (uint32_t j = 0; j < rgb->height; ++j) {
431
0
                uint16_t * pixel = (uint16_t *)row;
432
0
                for (uint32_t i = 0; i < rgb->width; ++i) {
433
0
                    uint16_t a = pixel[0];
434
0
                    if (a >= max) {
435
0
                    } else if (a == 0) {
436
0
                        pixel[1] = 0;
437
0
                    } else {
438
0
                        float c1 = avifRoundf((float)pixel[1] * maxF / (float)a);
439
0
                        pixel[1] = (uint16_t)AVIF_MIN(c1, maxF);
440
0
                    }
441
0
                    pixel += 2;
442
0
                }
443
0
                row += rgb->rowBytes;
444
0
            }
445
0
        } else {
446
0
            return AVIF_RESULT_NOT_IMPLEMENTED;
447
0
        }
448
0
    } else {
449
0
        if (rgb->format == AVIF_RGB_FORMAT_RGBA || rgb->format == AVIF_RGB_FORMAT_BGRA) {
450
0
            uint8_t * row = rgb->pixels;
451
0
            for (uint32_t j = 0; j < rgb->height; ++j) {
452
0
                uint8_t * pixel = row;
453
0
                for (uint32_t i = 0; i < rgb->width; ++i) {
454
0
                    uint8_t a = pixel[3];
455
0
                    if (a == max) {
456
0
                    } else if (a == 0) {
457
0
                        pixel[0] = 0;
458
0
                        pixel[1] = 0;
459
0
                        pixel[2] = 0;
460
0
                    } else {
461
0
                        float c1 = avifRoundf((float)pixel[0] * maxF / (float)a);
462
0
                        float c2 = avifRoundf((float)pixel[1] * maxF / (float)a);
463
0
                        float c3 = avifRoundf((float)pixel[2] * maxF / (float)a);
464
0
                        pixel[0] = (uint8_t)AVIF_MIN(c1, maxF);
465
0
                        pixel[1] = (uint8_t)AVIF_MIN(c2, maxF);
466
0
                        pixel[2] = (uint8_t)AVIF_MIN(c3, maxF);
467
0
                    }
468
0
                    pixel += 4;
469
0
                }
470
0
                row += rgb->rowBytes;
471
0
            }
472
0
        } else if (rgb->format == AVIF_RGB_FORMAT_ARGB || rgb->format == AVIF_RGB_FORMAT_ABGR) {
473
0
            uint8_t * row = rgb->pixels;
474
0
            for (uint32_t j = 0; j < rgb->height; ++j) {
475
0
                uint8_t * pixel = row;
476
0
                for (uint32_t i = 0; i < rgb->width; ++i) {
477
0
                    uint8_t a = pixel[0];
478
0
                    if (a == max) {
479
0
                    } else if (a == 0) {
480
0
                        pixel[1] = 0;
481
0
                        pixel[2] = 0;
482
0
                        pixel[3] = 0;
483
0
                    } else {
484
0
                        float c1 = avifRoundf((float)pixel[1] * maxF / (float)a);
485
0
                        float c2 = avifRoundf((float)pixel[2] * maxF / (float)a);
486
0
                        float c3 = avifRoundf((float)pixel[3] * maxF / (float)a);
487
0
                        pixel[1] = (uint8_t)AVIF_MIN(c1, maxF);
488
0
                        pixel[2] = (uint8_t)AVIF_MIN(c2, maxF);
489
0
                        pixel[3] = (uint8_t)AVIF_MIN(c3, maxF);
490
0
                    }
491
0
                    pixel += 4;
492
0
                }
493
0
                row += rgb->rowBytes;
494
0
            }
495
0
        } else if (rgb->format == AVIF_RGB_FORMAT_GRAYA) {
496
0
            uint8_t * row = rgb->pixels;
497
0
            for (uint32_t j = 0; j < rgb->height; ++j) {
498
0
                uint8_t * pixel = row;
499
0
                for (uint32_t i = 0; i < rgb->width; ++i) {
500
0
                    uint8_t a = pixel[1];
501
0
                    if (a == max) {
502
0
                    } else if (a == 0) {
503
0
                        pixel[0] = 0;
504
0
                    } else {
505
0
                        float c1 = avifRoundf((float)pixel[0] * maxF / (float)a);
506
0
                        pixel[0] = (uint8_t)AVIF_MIN(c1, maxF);
507
0
                    }
508
0
                    pixel += 2;
509
0
                }
510
0
                row += rgb->rowBytes;
511
0
            }
512
0
        } else if (rgb->format == AVIF_RGB_FORMAT_AGRAY) {
513
0
            uint8_t * row = rgb->pixels;
514
0
            for (uint32_t j = 0; j < rgb->height; ++j) {
515
0
                uint8_t * pixel = row;
516
0
                for (uint32_t i = 0; i < rgb->width; ++i) {
517
0
                    uint8_t a = pixel[0];
518
0
                    if (a == max) {
519
0
                    } else if (a == 0) {
520
0
                        pixel[1] = 0;
521
0
                    } else {
522
0
                        float c1 = avifRoundf((float)pixel[1] * maxF / (float)a);
523
0
                        pixel[1] = (uint8_t)AVIF_MIN(c1, maxF);
524
0
                    }
525
0
                    pixel += 2;
526
0
                }
527
0
                row += rgb->rowBytes;
528
0
            }
529
0
        } else {
530
0
            return AVIF_RESULT_NOT_IMPLEMENTED;
531
0
        }
532
0
    }
533
534
0
    return AVIF_RESULT_OK;
535
0
}