LibGfx/ICC: In lerp_nd(), use VLAs for coordinates

`x.size()` is 3 or 4 in practice and at most 15 in theory
(cf `number_of_components_in_color_space()` in Profile.cpp),
so using a VLA for these should be fine from a stack size PoV.

It's only accessed through a span, so there's no additional
security risk.

Takes

    Build/lagom/bin/image --no-output \
        --assign-color-profile \
            Build/lagom/Root/res/icc/Adobe/CMYK/USWebCoatedSWOP.icc \
        --convert-to-color-profile serenity-sRGB.icc \
        cmyk.jpg

from 2.74s to 2.66s on my machine, almost 3% faster.

(Don't do this in LibPDF's SampledFunction::evaluate() since there's
no bound on the dimension of the input function. Realistically,
size of the table puts a pretty low bound on that dimension though,
so we should probably enforce some bound in SampledFunction::create()
and do this there too.)
This commit is contained in:
Nico Weber 2024-02-04 19:00:40 -05:00 committed by Andreas Kling
parent 9fc47345ce
commit cc083310a7

View file

@ -48,15 +48,15 @@ inline FloatVector3 lerp_nd(Function<unsigned(size_t)> size, Function<FloatVecto
FloatVector3 sample_output {};
// The i'th bit of mask indicates if the i'th coordinate is rounded up or down.
Vector<unsigned> coordinates;
coordinates.resize(x.size());
unsigned coordinates[x.size()];
ReadonlySpan<unsigned> coordinates_span { coordinates, x.size() };
for (size_t mask = 0; mask < (1u << x.size()); ++mask) {
float sample_weight = 1.0f;
for (size_t i = 0; i < x.size(); ++i) {
coordinates[i] = left_index[i] + ((mask >> i) & 1u);
sample_weight *= ((mask >> i) & 1u) ? factor[i] : 1.0f - factor[i];
}
sample_output += sample(coordinates) * sample_weight;
sample_output += sample(coordinates_span) * sample_weight;
}
return sample_output;