Blender V5.0
grease_pencil_trace_util.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
7#include "BLI_color_types.hh"
10#include "BLI_span.hh"
11#include "BLI_string_ref.hh"
12#include "BLI_task.hh"
13
14#include "IMB_imbuf_types.hh"
15
16#ifdef WITH_POTRACE
17# include "potracelib.h"
18#endif
19
20namespace blender::bke {
21class CurvesGeometry;
22}
23
25
26#ifdef WITH_POTRACE
27using Bitmap = potrace_bitmap_t;
28using Trace = potrace_state_t;
29#else
30struct Bitmap;
31struct Trace;
32#endif
33
34Bitmap *create_bitmap(const int2 &size);
35void free_bitmap(Bitmap *bm);
36
43template<typename ThresholdFn> Bitmap *image_to_bitmap(const ImBuf &ibuf, ThresholdFn fn);
44ImBuf *bitmap_to_image(const Bitmap &bm);
45
46/* Policy for resolving ambiguity during decomposition of bitmaps into paths. */
47enum class TurnPolicy : int8_t {
48 /* Prefers to connect foreground pixels. */
50 /* Prefers to connect background pixels. */
52 /* Always take a left turn. */
53 Left = 2,
54 /* Always take a right turn. */
55 Right = 3,
56 /* Prefers to connect minority color in the neighborhood. */
58 /* Prefers to connect majority color in the neighborhood. */
60 /* Chose direction randomly. */
61 Random = 6,
62};
63
65 /* Area of the largest path to be ignored. */
67 /* Resolves ambiguous turns in path decomposition. */
69 /* Corner threshold. */
70 float alpha_max = 1.0f;
71 /* True to enable curve optimization. */
72 bool optimize_curves = true;
73 /* Curve optimization tolerance. */
74 float optimize_tolerance = 0.2f;
75};
76
80Trace *trace_bitmap(const TraceParams &params, Bitmap &bm);
81void free_trace(Trace *trace);
82
88 StringRef hole_attribute_id,
89 const float4x4 &transform);
95 StringRef hole_attribute_id,
96 FunctionRef<float3(const int2 &)> pixel_to_position);
97
98/* Inline functions. */
99
104template<typename ThresholdFn> Bitmap *image_to_bitmap(const ImBuf &ibuf, ThresholdFn fn)
105{
106#ifdef WITH_POTRACE
107 constexpr int BM_WORDSIZE = int(sizeof(potrace_word));
108 constexpr int BM_WORDBITS = 8 * BM_WORDSIZE;
109 constexpr potrace_word BM_HIBIT = potrace_word(1) << (BM_WORDBITS - 1);
110
111 potrace_bitmap_t *bm = create_bitmap({ibuf.x, ibuf.y});
112 const int num_words = bm->dy * bm->h;
113 const int words_per_scanline = bm->dy;
114 /* Note: bitmap stores one bit per pixel, but can't easily use a BitSpan, because the bit order
115 * is reversed in each word (most-significant bit is on the left). */
116 MutableSpan<potrace_word> words = {bm->map, num_words};
117
118 if (ibuf.float_buffer.data) {
119 const Span<ColorGeometry4f> colors = {
120 reinterpret_cast<ColorGeometry4f *>(ibuf.float_buffer.data), ibuf.x * ibuf.y};
121 threading::parallel_for(IndexRange(ibuf.y), 4096, [&](const IndexRange range) {
122 /* Use callback with the correct color conversion. */
123 constexpr bool is_float_color_fn =
124 std::is_invocable_r_v<void, ThresholdFn, const ColorGeometry4f &>;
125 for (const int y : range) {
126 MutableSpan<potrace_word> scanline_words = words.slice(
127 IndexRange(words_per_scanline * y, words_per_scanline));
128 const Span<ColorGeometry4f> scanline_colors = colors.slice(IndexRange(y * ibuf.x, ibuf.x));
129 for (int x = 0; x < ibuf.x; x++) {
130 potrace_word &word = scanline_words[x / BM_WORDBITS];
131 const potrace_word mask = BM_HIBIT >> (x & (BM_WORDBITS - 1));
132
133 const ColorGeometry4f &fcolor = scanline_colors[x];
134 bool is_foreground;
135 if constexpr (!is_float_color_fn) {
136 is_foreground = fn(
137 ColorGeometry4b(fcolor.r * 255, fcolor.g * 255, fcolor.b * 255, fcolor.a * 255));
138 }
139 else {
140 is_foreground = fn(fcolor);
141 }
142
143 if (is_foreground) {
144 word |= mask;
145 }
146 else {
147 word &= ~mask;
148 }
149 }
150 }
151 });
152 return bm;
153 }
154
155 const Span<ColorGeometry4b> colors = {reinterpret_cast<ColorGeometry4b *>(ibuf.byte_buffer.data),
156 ibuf.x * ibuf.y};
157 threading::parallel_for(IndexRange(ibuf.y), 4096, [&](const IndexRange range) {
158 /* Use callback with the correct color conversion. */
159 constexpr bool is_float_color_fn =
160 std::is_invocable_r_v<void, ThresholdFn, const ColorGeometry4f &>;
161 for (const int y : range) {
162 MutableSpan<potrace_word> scanline_words = words.slice(
163 IndexRange(words_per_scanline * y, words_per_scanline));
164 const Span<ColorGeometry4b> scanline_colors = colors.slice(IndexRange(y * ibuf.x, ibuf.x));
165 for (uint32_t x = 0; x < ibuf.x; x++) {
166 potrace_word &word = scanline_words[x / BM_WORDBITS];
167 const potrace_word mask = BM_HIBIT >> (x & (BM_WORDBITS - 1));
168
169 const ColorGeometry4b bcolor = scanline_colors[x];
170 bool is_foreground;
171 if constexpr (is_float_color_fn) {
172 is_foreground = fn(ColorGeometry4f(
173 bcolor.r / 255.0f, bcolor.r / 255.0f, bcolor.r / 255.0f, bcolor.r / 255.0f));
174 }
175 else {
176 is_foreground = fn(bcolor);
177 }
178
179 if (is_foreground) {
180 word |= mask;
181 }
182 else {
183 word &= ~mask;
184 }
185 }
186 }
187 });
188 return bm;
189#else
190 UNUSED_VARS(ibuf, fn);
191 return nullptr;
192#endif
193}
194
195} // namespace blender::ed::image_trace
#define UNUSED_VARS(...)
BMesh * bm
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void free_bitmap(Bitmap *bm)
Bitmap * create_bitmap(const int2 &size)
Bitmap * image_to_bitmap(const ImBuf &ibuf, ThresholdFn fn)
bke::CurvesGeometry trace_to_curves(const Trace &trace, StringRef hole_attribute_id, const float4x4 &transform)
void free_trace(Trace *trace)
Trace * trace_bitmap(const TraceParams &params, Bitmap &bm)
ImBuf * bitmap_to_image(const Bitmap &bm)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
MatBase< float, 4, 4 > float4x4
VecBase< int32_t, 2 > int2
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
VecBase< float, 3 > float3
ColorSceneLinearByteEncoded4b< eAlpha::Premultiplied > ColorGeometry4b
ImBufFloatBuffer float_buffer