Select › Color Range: sampled colours, Fuzziness, Invert, a live preview and the panel (13.3b)
This commit is contained in:
1 parent
462fe805b1
commit
0b7eb6cb6f
29 files changed
+1535
-71
No files matched your search
@@ -172,3 +172,34 @@ fail:
|
||||
free(lens);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int color_near(const int *rgb, const uint8_t *colors, int count, int fuzziness) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
const uint8_t *c = colors + i * 3;
|
||||
if (abs(rgb[0] - c[0]) <= fuzziness && abs(rgb[1] - c[1]) <= fuzziness && abs(rgb[2] - c[2]) <= fuzziness) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
long color_range_mask(const uint8_t *rgba, size_t width, size_t height, size_t stride,
|
||||
const uint8_t *include, int includeCount, const uint8_t *exclude, int excludeCount,
|
||||
int fuzziness, int invert, uint8_t *mask) {
|
||||
long count = 0;
|
||||
for (size_t y = 0; y < height; ++y) {
|
||||
const uint8_t *row = rgba + y * stride;
|
||||
uint8_t *out = mask + y * width;
|
||||
for (size_t x = 0; x < width; ++x) {
|
||||
const uint8_t *px = row + x * 4;
|
||||
int matches = 0;
|
||||
if (px[3]) {
|
||||
int rgb[3];
|
||||
for (int c = 0; c < 3; ++c) rgb[c] = (px[c] * 255 + px[3] / 2) / px[3];
|
||||
matches = color_near(rgb, include, includeCount, fuzziness) && !color_near(rgb, exclude, excludeCount, fuzziness);
|
||||
}
|
||||
if (invert) matches = !matches;
|
||||
out[x] = matches ? 255 : 0;
|
||||
count += matches;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
@@ -10,6 +10,13 @@
|
||||
// `mask` (width * height bytes). Returns the number selected, or -1 when memory runs out.
|
||||
long wand_mask(const uint8_t *rgba, size_t width, size_t height, size_t stride,
|
||||
size_t seedX, size_t seedY, size_t radius, int tolerance, int contiguous, uint8_t *mask);
|
||||
// Select > Color Range over premultiplied RGBA (as above). A pixel matches when every color channel is within
|
||||
// `fuzziness` of one of the `includeCount` colors in `include` and of none in `exclude` (straight sRGB, 3 bytes
|
||||
// each). Transparent pixels never match. With `invert`, the pixels that don't match are selected instead. Writes
|
||||
// 255 for selected, 0 elsewhere, into `mask`, and returns the number selected.
|
||||
long color_range_mask(const uint8_t *rgba, size_t width, size_t height, size_t stride,
|
||||
const uint8_t *include, int includeCount, const uint8_t *exclude, int excludeCount,
|
||||
int fuzziness, int invert, uint8_t *mask);
|
||||
// Outline of the nonzero pixels of `mask`, along pixel edges, as closed loops of corner points
|
||||
// (x, y pairs in pixel-edge coordinates). Outer boundaries run clockwise and holes
|
||||
// counterclockwise in top-left coordinates, so the winding rule fills exactly those pixels.
|
||||
|
||||
Reference in new issue
Block a user