Test/node_modules/pica/lib/mm_resize/convolve.c
2026-04-09 22:54:00 +07:00

80 lines
2.6 KiB
C

#include <stdint.h>
inline uint8_t clampTo8(int32_t i) {
return i < 0 ? 0 : (i > 255 ? 255 : i);
}
#define R(x) ((uint8_t)(x))
#define G(x) ((uint8_t)((x) >> 8))
#define B(x) ((uint8_t)((x) >> 16))
#define A(x) ((uint8_t)((x) >> 24))
#define RGBA(r, g, b, a) ((r) | ((g) << 8) | ((b) << 16) | ((a) << 24))
void convolve(uint32_t *src, uint32_t *dest, uint32_t srcW, uint32_t srcH, uint32_t destW, int16_t *filters)
{
int32_t r, g, b, a;
uint32_t rgba;
uint32_t filterPtr, filterShift, filterSize;
uint32_t srcPtr, srcY, destX;
int32_t filterVal;
uint32_t srcOffset = 0, destOffset = 0;
//
for (srcY=0; srcY < srcH; srcY++) {
filterPtr = 0;
// Apply precomputed filters to each destination row point
for (destX = 0; destX < destW; destX++) {
// Get the filter that determines the current output pixel.
filterShift = filters[filterPtr++];
srcPtr = srcOffset + filterShift;
filterSize = filters[filterPtr++];
r = g = b = a = 0;
// Apply the filter to the row to get the destination pixel r, g, b, a
for (; filterSize > 0; filterSize--) {
filterVal = filters[filterPtr++];
rgba = src[srcPtr++];
r += filterVal * R(rgba);
g += filterVal * G(rgba);
b += filterVal * B(rgba);
a += filterVal * A(rgba);
};
// Bring this value back in range. All of the filter scaling factors
// are in fixed point with FIXED_FRAC_BITS bits of fractional part.
//
// (!) Add 1/2 of value before clamping to get proper rounding. In other
// case brightness loss will be noticeable if you resize image with white
// border and place it on white background.
dest[destOffset] = RGBA(
clampTo8((r + (1<<13))>>14 /*FIXED_FRAC_BITS*/),
clampTo8((g + (1<<13))>>14 /*FIXED_FRAC_BITS*/),
clampTo8((b + (1<<13))>>14 /*FIXED_FRAC_BITS*/),
clampTo8((a + (1<<13))>>14 /*FIXED_FRAC_BITS*/));
destOffset += srcH;
};
destOffset = srcY + 1;
srcOffset = (srcY + 1) * srcW;
};
}
void convolveHV(uint32_t filtersX_offset,
uint32_t filtersY_offset,
uint32_t tmp_offset,
uint32_t srcW,
uint32_t srcH,
uint32_t destW,
uint32_t destH)
{
uint8_t *memory = 0;
uint32_t *src = (uint32_t *)memory;
int16_t *filterX = (int16_t *)(memory + filtersX_offset);
int16_t *filterY = (int16_t *)(memory + filtersY_offset);
uint32_t *tmp = (uint32_t *)(memory + tmp_offset);
convolve(src, tmp, srcW, srcH, destW, filterX);
convolve(tmp, src, srcH, destW, destH, filterY);
}