14.2: RAW import rounds to 8 bits with fine noise, in the kernel; the develop sheet shows Importing… until the layer lands

This commit is contained in:
ZacharyZhang-NY committed 2026-10-11 02:38:04 -04:00
1 parent 5aad975e8b
commit c04d1fb6e4
14 files changed
+470 -65

No files matched your search

+35
View File
@@ -416,3 +416,38 @@ void dither_glow(uint8_t *rgba, const uint8_t *glow, size_t width, size_t height
glow_job glowing = { rgba, glow, width, stride, amount };
in_bands(height, glow_band, &glowing);
}
// A fixed pseudo-random value in [0, 1) for each pixel and draw.
static inline float hash_noise(size_t x, size_t y, uint32_t draw) {
uint32_t h = (uint32_t)x * 0x9E3779B1u ^ (uint32_t)y * 0x85EBCA77u ^ draw * 0xC2B2AE3Du;
h ^= h >> 15; h *= 0x2C1B3C6Du; h ^= h >> 12; h *= 0x297A2D39u; h ^= h >> 15;
return (float)(h >> 8) / (float)(1u << 24);
}
typedef struct { const uint16_t *wide; uint8_t *rgba; size_t width, stride; } quantize_job;
static void quantize_band(void *context, size_t first, size_t last) {
const quantize_job *job = context;
const uint16_t *wide = job->wide; uint8_t *rgba = job->rgba; size_t width = job->width, stride = job->stride;
for (size_t y = first; y < last; ++y) {
uint8_t *out = rgba + y * stride;
const uint16_t *in = wide + y * width * 4;
for (size_t x = 0; x < width; ++x) {
const uint16_t *p = in + x * 4;
long alpha = lroundf((float)p[3] * (255.0f / 65535.0f));
for (uint32_t c = 0; c < 3; ++c) {
// Two uniform draws added: noise that's strongest at zero and gone past one step.
float value = (float)p[c] * (255.0f / 65535.0f) + hash_noise(x, y, c) + hash_noise(x, y, c + 3) - 1.0f;
long rounded = lroundf(value);
// Premultiplied: the noise mustn't lift a color past its own alpha.
out[x * 4 + c] = (uint8_t)(rounded < 0 ? 0 : rounded > alpha ? alpha : rounded);
}
out[x * 4 + 3] = (uint8_t)alpha;
}
}
}
void dither_quantize16(const uint16_t *wide, uint8_t *rgba, size_t width, size_t height, size_t stride) {
quantize_job quantizing = { wide, rgba, width, stride };
in_bands(height, quantize_band, &quantizing);
}
+4
View File
@@ -51,4 +51,8 @@ int dither_apply(uint8_t *rgba, size_t width, size_t height, size_t stride, cons
void dither_dots(uint8_t *rgba, size_t width, size_t height, size_t stride, int block, const uint8_t *gap);
// Adds `glow` (premultiplied RGBA, same layout) over the pixels at `amount`, never past their own alpha.
void dither_glow(uint8_t *rgba, const uint8_t *glow, size_t width, size_t height, size_t stride, float amount);
// Rounds 16-bit premultiplied RGBA (`width` × `height`, tightly packed) to 8 bits into `rgba` (`stride` bytes per
// row), adding noise of about one 8-bit step first so smooth gradients don't come out in steps. The noise is fixed per
// pixel, so the same input always gives the same output.
void dither_quantize16(const uint16_t *wide, uint8_t *rgba, size_t width, size_t height, size_t stride);
#endif