renderer

package
v0.0.0-...-508dbe3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 26, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// TerminationRefillLimit reports that batch mode exhausted its bounded
	// replacement attempts before every requested slot became useful.
	TerminationRefillLimit opt.Termination = "refill_limit"
	// MaxExtraBatchStages is the bounded number of residual-refill attempts
	// available after the initially planned batch stages.
	MaxExtraBatchStages = 3
)
View Source
const TerminationStageConvergence opt.Termination = "stage_convergence"

TerminationStageConvergence reports that the stage-level convergence tracker stopped a sequential or batch run before its circle budget was consumed. It is a pipeline outcome rather than an optimizer outcome, so it is defined here instead of in the opt package.

Variables

View Source
var (
	// ErrUnknownBackend is returned when the name does not match a known backend.
	ErrUnknownBackend = errors.New("unknown renderer backend")
	// ErrBackendUnavailable indicates the backend is not available in this build.
	ErrBackendUnavailable = errors.New("renderer backend unavailable")
	// ErrBackendNotImplemented indicates the backend is known but not yet implemented.
	ErrBackendNotImplemented = errors.New("renderer backend not implemented")
)
View Source
var (
	// ErrStagedOptimizationUnsupported indicates that a renderer cannot create
	// same-backend sessions while preserving its initial canvas.
	ErrStagedOptimizationUnsupported = errors.New("renderer does not support sequential or batch optimization")
	// ErrInvalidOptimizationInput indicates invalid pipeline dimensions or results.
	ErrInvalidOptimizationInput = errors.New("invalid optimization input")
)

Functions

func CompositingBackend

func CompositingBackend() string

CompositingBackend names the kernel the default, exact compositor uses.

func ConfigureCPUCompositing

func ConfigureCPUCompositing(cpu *CPURenderer, fastCompositing bool)

ConfigureCPUCompositing selects the span compositor and says out loud what the process will actually run.

The warning is the point. On a target with no float32 kernel the fast path falls back to a float32 scalar loop that is both less accurate and slower than the exact compositor it replaces, so the flag is a pure loss there - and a log line reading only "fastCompositing=true" would hide that completely.

func ConfigureCPUParallelism

func ConfigureCPUParallelism(cpu *CPURenderer, threads, evaluationWorkers int, parallelEvaluation bool)

ConfigureCPUParallelism applies both parallelism settings a job configuration carries. They are independent knobs: threads shards the rows of one render, while evaluationWorkers runs whole independent renders side by side, and the two compete for the same cores.

Evaluation width is left alone unless parallelEvaluation is set, so the setting is inert until it is opted into. Every entry point that builds a CPU renderer from a configuration goes through here, so the two settings cannot drift apart between the CLI, resume, and the server.

func EvaluationWidth

func EvaluationWidth(base Renderer) int

EvaluationWidth reports how many cost evaluations the pipeline will actually run concurrently for base, which is one for any backend that cannot hand out independent sessions. Callers use it to report the width they really got rather than the width they asked for.

func FastCompositingBackend

func FastCompositingBackend() string

FastCompositingBackend names the kernel the fast compositor would use on this host. Callers that log the flag should log this too: on a build with no fast kernel the flag is a pure pessimisation, and "fastCompositing=true" on its own hides that.

func LogCPURendererConfiguration

func LogCPURendererConfiguration(cpu *CPURenderer)

LogCPURendererConfiguration records the settings that change what a run computes or how fast it computes it, including which kernels were installed. A run's log should be enough to tell whether two runs are comparable.

func ParallelEvaluationOption

func ParallelEvaluationOption(base Renderer, enabled bool) (opt.MayflyOption, bool)

ParallelEvaluationOption returns the optimizer option matching what base can actually deliver, and reports whether parallel evaluation was enabled.

It is the single place that decides this, because the decision is only safe when made from the renderer's own reported width. Configuring the optimizer from a requested worker count instead would let a backend without independent sessions -- OpenCL today -- run the optimizer's parallel path against a one-slot pool: every evaluation goroutine would queue on that slot for no throughput at all, while the run still paid the altered search trajectory that parallel evaluation implies. Callers must therefore configure the renderer first, then derive the option from the renderer.

A false second result with enabled set means the request could not be honored, which is worth a warning rather than silence.

func ParallelEvaluationWidth

func ParallelEvaluationWidth(base Renderer, enabled bool) (int, bool)

ParallelEvaluationWidth reports the concurrent evaluation width base can actually deliver when enabled, and whether parallel evaluation was granted. A false second result means the run evaluates serially, whatever it asked for, and the width is one.

It exists because ParallelEvaluationOption can only speak for one optimizer library. The decision itself -- what the renderer can really hand out -- is the same for every optimizer, so callers configuring a different adapter take the width from here rather than from the requested worker count. See ParallelEvaluationOption for why deriving it from the renderer is the only safe order.

func PlanContiguousWindows

func PlanContiguousWindows(circleCount, activeSetSize, maxSweeps int, initialVisitCounts []int) ([][]int, []int, error)

PlanContiguousWindows returns the deterministic active sets and resulting visit counts for a contiguous-window polishing call. It is shared with the server's continuation reconstruction so persisted lineage cannot drift from the renderer's selector. Active sets contain zero-based draw slots.

func SeedCirclesFromResidual

func SeedCirclesFromResidual(canvas, reference *image.NRGBA, count int, options ResidualSeedOptions) ([]fit.Circle, error)

SeedCirclesFromResidual places replacement circles at separated high-error pixels. Their colors compensate for the configured opacity so compositing moves the current pixel toward the reference pixel.

func SeedParamsFromResidual

func SeedParamsFromResidual(canvas, reference *image.NRGBA, count int, options ResidualSeedOptions) ([]float64, error)

SeedParamsFromResidual is the flat-vector form used by optimizer candidates.

Types

type Backend

type Backend string

Backend identifies a renderer implementation.

const (
	BackendCPU    Backend = "cpu"
	BackendOpenCL Backend = "opencl"
)

func NormalizeBackend

func NormalizeBackend(name string) Backend

NormalizeBackend maps arbitrary user input to a canonical backend identifier.

func SupportedBackends

func SupportedBackends() []Backend

SupportedBackends returns the list of backends understood by the factory.

type BatchAudit

type BatchAudit struct {
	MSE     float64
	Circles []CircleAudit
}

BatchAudit is a post-optimization diagnostic. MSEContribution is positive when removing a circle makes the result worse, zero when it has no effect, and negative when the image improves without it.

func AuditCircleBatch

func AuditCircleBatch(r Renderer, params []float64) (BatchAudit, error)

AuditCircleBatch measures a batch against the renderer's configured base canvas and reference. It deliberately runs outside the optimizer hot path: each circle is rendered incrementally and once with that circle omitted.

type BatchPolishEpoch

type BatchPolishEpoch struct {
	Sweep       int
	Epoch       int
	BestParams  []float64
	BestCost    float64
	Iterations  int
	Evaluations int
}

BatchPolishEpoch reports a durable full-vector optimizer epoch boundary.

type BatchPolishOptions

type BatchPolishOptions struct {
	ActiveSetSize int
	MaxSweeps     int
	Strategy      BatchPolishStrategy
	// InitialVisitCounts carries zero-based draw-slot selection counts from
	// compatible completed polishing calls. The slice is copied, never mutated.
	InitialVisitCounts []int
	Observer           opt.Observer
	OnEpoch            func(BatchPolishEpoch) error
	OnSweep            func(BatchPolishProgress) error
}

BatchPolishOptions controls transactional active-set polishing after a complete batch solution has been found. Selected circles are optimized together while every other circle remains fixed in its original draw slot.

type BatchPolishProgress

type BatchPolishProgress struct {
	Sweep       int
	Accepted    bool
	Region      image.Rectangle
	ActiveSet   []int
	BestParams  []float64
	BestCost    float64
	Iterations  int
	Evaluations int
}

BatchPolishProgress is emitted after each committed or rejected sweep. BestParams always describes the complete image, never only the active set.

type BatchPolishResult

type BatchPolishResult struct {
	BestParams     []float64
	BestCost       float64
	BestImage      *image.NRGBA
	Iterations     int
	Evaluations    int
	Sweeps         int
	AcceptedSweeps int
}

BatchPolishResult is the best complete solution retained by active-set polishing. A rejected sweep is never reflected in BestParams or BestImage.

func PolishCircleBatchContext

func PolishCircleBatchContext(
	ctx context.Context,
	base Renderer,
	optimizer opt.Optimizer,
	initialParams []float64,
	options BatchPolishOptions,
) (*BatchPolishResult, error)

PolishCircleBatchContext repeatedly re-optimizes coverage-aware circle groups. Each sweep is transactional: it is committed only when every circle remains useful and the cost of the complete, original-order parameter vector falls. Rejected groups are rolled back, but do not prevent later sweeps from visiting other circles.

type BatchPolishStrategy

type BatchPolishStrategy string

BatchPolishStrategy selects how a polishing active set and its population are formed.

const (
	// BatchPolishWeakestReplacement replaces the weakest circles with residual
	// seeds. It preserves the original polishing behavior.
	BatchPolishWeakestReplacement BatchPolishStrategy = "replacement"
	// BatchPolishHybridOverlap retains weak anchors, adds their strongest
	// overlap partners, and mixes incumbent-local and residual populations.
	BatchPolishHybridOverlap BatchPolishStrategy = "hybrid-overlap"
	// BatchPolishResidualRegion visits high-error image regions, retaining the
	// circles that influence each region while residual-seeding weak draw slots.
	BatchPolishResidualRegion BatchPolishStrategy = "residual-region"
	// BatchPolishContiguousWindow polishes a contiguous run of circles in draw
	// order. Full-coverage budgets start at the front of the vector, where a
	// greedy fit leaves the most value; partial budgets retain the cheaper
	// latest-first traversal.
	//
	// The other strategies pick circles by image-space merit, which scatters the
	// active set through the draw order. Because only the circles before the
	// first active slot can be baked into a reusable canvas, an active set that
	// contains an early circle bakes nothing and every candidate rasterizes the
	// whole image. Selecting a contiguous window instead makes the baked prefix
	// exactly the window start, so per-candidate render cost is
	// circleCount-windowStart rather than always circleCount.
	BatchPolishContiguousWindow BatchPolishStrategy = "contiguous-window"
)

type CPURenderer

type CPURenderer struct {
	// contains filtered or unexported fields
}

CPURenderer implements software rendering of circles.

func NewCPURenderer

func NewCPURenderer(reference *image.NRGBA, k int) *CPURenderer

NewCPURenderer creates a CPU-based renderer with a white background.

func NewCPURendererWithCanvas

func NewCPURendererWithCanvas(reference *image.NRGBA, canvas *image.NRGBA, k int) *CPURenderer

NewCPURendererWithCanvas creates a CPU-based renderer with a custom initial canvas. This is useful for continuing optimization from a previous result (e.g., adding circles to an existing partial solution). The canvas parameter is copied, so the original image is not modified.

func (*CPURenderer) Bounds

func (r *CPURenderer) Bounds() (lower, upper []float64)

Bounds returns lower and upper bounds for parameters.

func (*CPURenderer) Cost

func (r *CPURenderer) Cost(params []float64) float64

Cost computes error between params and reference.

func (*CPURenderer) Dim

func (r *CPURenderer) Dim() int

Dim returns the dimensionality of the parameter space.

func (*CPURenderer) FastCompositing

func (r *CPURenderer) FastCompositing() bool

FastCompositing reports whether the reduced-precision span compositor is selected.

func (*CPURenderer) ParallelEvaluationWorkers

func (r *CPURenderer) ParallelEvaluationWorkers() int

ParallelEvaluationWorkers reports the configured concurrent evaluation width.

func (*CPURenderer) Reference

func (r *CPURenderer) Reference() *image.NRGBA

Reference returns the reference image.

func (*CPURenderer) Render

func (r *CPURenderer) Render(params []float64) *image.NRGBA

Render creates an image from parameter vector.

func (*CPURenderer) SetCostFunc

func (r *CPURenderer) SetCostFunc(costFunc fit.CostFunc)

SetCostFunc sets the cost function used for evaluation.

func (*CPURenderer) SetFastCompositing

func (r *CPURenderer) SetFastCompositing(enabled bool)

SetFastCompositing selects the reduced-precision float32 SIMD span compositor. Rendered output then differs from the exact float64 path by up to one unit per channel, so callers opt in explicitly.

func (*CPURenderer) SetParallelEvaluationWorkers

func (r *CPURenderer) SetParallelEvaluationWorkers(workers int)

SetParallelEvaluationWorkers configures how many concurrent cost evaluations the optimization pipeline may run. The pipeline then creates that many independent sessions, each with its own canvas, and gives every session a single rendering thread: with many evaluations in flight the row-band fan-out inside one render is pure overhead. Call it before starting an optimization.

Non-positive values select GOMAXPROCS, matching SetThreads. The two setters must agree on what zero means: they are fed from adjacent configuration fields, and a setter that read zero as "one" would silently disable evaluation parallelism for any caller that had not filled the field in.

The value is capped at GOMAXPROCS, which is the documented contract of the --threads flag. The cap is not merely advisory: every worker above one costs a full extra session with its own canvas and background copy (about 2*W*H*4 bytes), so an unclamped --threads 10000 would try to allocate hundreds of gigabytes at HD resolution. The cap deliberately does not reuse effectiveThreadCount, which additionally clamps to the image height: that is right for row sharding but wrong here, because evaluation concurrency is unrelated to how many rows a single render can split into.

func (*CPURenderer) SetThreads

func (r *CPURenderer) SetThreads(threads int)

SetThreads configures CPU rendering parallelism. Non-positive values select GOMAXPROCS. Values above GOMAXPROCS or the image height are capped to avoid oversubscription and empty row shards. Call SetThreads before starting an optimization; changing renderer settings concurrently with Render is unsupported.

func (*CPURenderer) Threads

func (r *CPURenderer) Threads() int

Threads returns the effective number of rendering workers.

func (*CPURenderer) UseFastCost

func (r *CPURenderer) UseFastCost()

UseFastCost restores the runtime-dispatched SIMD cost implementation after a custom cost function has been selected. New CPU renderers use this by default.

type CircleAudit

type CircleAudit struct {
	Circle                  int
	OriginalCircle          int
	IntroducedChangedPixels int
	FinalChangedPixels      int
	CostWithout             float64
	MSEContribution         float64
	Valid                   bool
	ValidationError         string
}

CircleAudit describes both the raster visibility and objective usefulness of one circle in a completed batch. Circle and OriginalCircle are one-based.

type CircleCallback

type CircleCallback func(circleNum int, params []float64, cost float64, img image.Image)

CircleCallback is called after each circle is optimized in sequential mode. Parameters:

  • circleNum: 1-indexed circle number
  • params: all circle parameters up to and including this circle (7*circleNum floats)
  • cost: the best cost retained after this circle
  • img: a stable copy of the retained image

type CirclePruneOptions

type CirclePruneOptions struct {
	MinChangedPixels   int
	MinMSEContribution float64
	MaxRemoved         int
}

CirclePruneOptions controls iterative batch pruning. A circle is removed if it changes fewer than MinChangedPixels in the final image or contributes no more than MinMSEContribution to MSE. Zero-value options therefore remove zero-pixel and non-positive-contribution circles.

type CirclePruneResult

type CirclePruneResult struct {
	Params  []float64
	Removed []CircleRemoval
	Audit   BatchAudit
}

CirclePruneResult contains a pruned parameter vector in its original draw order and a fresh audit of the retained circles.

func PruneCircleBatch

func PruneCircleBatch(base Renderer, params []float64, options CirclePruneOptions) (CirclePruneResult, error)

PruneCircleBatch repeatedly removes the least useful eligible circle and re-audits the remaining batch. Re-auditing matters because overlapping circles can become useful after a later or redundant circle is removed.

type CircleRemoval

type CircleRemoval struct {
	OriginalCircle     int
	FinalChangedPixels int
	MSEContribution    float64
}

CircleRemoval records an iterative pruning decision. OriginalCircle refers to the input draw order even after earlier circles have been removed.

type CircleVisibility

type CircleVisibility struct {
	Circle          int
	ChangedPixels   int
	Valid           bool
	ValidationError string
}

CircleVisibility reports the number of canvas pixels changed when one circle is introduced in draw order. A zero count means that the circle is invisible at that point: for example, it may be transparent, outside the canvas, or indistinguishable from the canvas beneath it.

func AnalyzeCircleVisibility

func AnalyzeCircleVisibility(r Renderer, params []float64) ([]CircleVisibility, error)

AnalyzeCircleVisibility replays params incrementally and reports whether each circle changes the configured base canvas. It is intended for result diagnostics, not the optimizer's hot evaluation path: it performs one full render per circle.

type ConcurrentEvaluator

type ConcurrentEvaluator struct {
	// contains filtered or unexported fields
}

ConcurrentEvaluator exposes the pipeline's re-entrant cost evaluation to callers that drive an optimizer themselves instead of going through OptimizeJoint. A renderer's Cost writes its own reusable canvas and dirty span set, so calling it from several goroutines corrupts results silently. The evaluator leases one independent session per in-flight evaluation, which is exactly what OptimizeJointContext does.

It is required wherever an optimizer is configured with opt.WithParallelEvaluation. With a renderer that reports fewer than two evaluation workers, or a backend that cannot create sessions, the evaluator wraps the caller's renderer in a single slot: correct, and identical to the historical serial path.

func NewConcurrentEvaluator

func NewConcurrentEvaluator(base Renderer, circleCount int) *ConcurrentEvaluator

NewConcurrentEvaluator builds an evaluator over base sized by base's configured evaluation width. Close must be called when the run finishes.

func (*ConcurrentEvaluator) Close

func (e *ConcurrentEvaluator) Close()

Close releases the sessions the evaluator created. It must not run while an evaluation is in flight.

func (*ConcurrentEvaluator) Cost

func (e *ConcurrentEvaluator) Cost(params []float64) float64

Cost evaluates params on a leased session. It is safe for concurrent use.

func (*ConcurrentEvaluator) Evaluations

func (e *ConcurrentEvaluator) Evaluations() int

Evaluations reports how many evaluations the evaluator has served.

func (*ConcurrentEvaluator) Width

func (e *ConcurrentEvaluator) Width() int

Width reports how many evaluations run concurrently before callers queue.

type ConvergenceConfig

type ConvergenceConfig struct {
	// Enabled controls whether convergence detection is active
	Enabled bool

	// Patience is the number of circles/batches with no improvement before stopping
	// For sequential mode: number of circles with no improvement
	// For batch mode: number of batches with no improvement
	Patience int

	// Threshold is the minimum relative improvement required to count as progress
	// Example: 0.001 = 0.1% improvement required
	// Relative improvement = (oldCost - newCost) / oldCost
	Threshold float64
}

ConvergenceConfig defines parameters for detecting optimization convergence.

func DefaultConvergenceConfig

func DefaultConvergenceConfig() ConvergenceConfig

DefaultConvergenceConfig returns sensible defaults for convergence detection.

func DisabledConvergenceConfig

func DisabledConvergenceConfig() ConvergenceConfig

DisabledConvergenceConfig returns a config with convergence detection disabled.

type ConvergenceTracker

type ConvergenceTracker struct {
	// contains filtered or unexported fields
}

ConvergenceTracker tracks cost history and detects when optimization has converged.

func NewConvergenceTracker

func NewConvergenceTracker(config ConvergenceConfig) *ConvergenceTracker

NewConvergenceTracker creates a new convergence tracker with the given config.

func (*ConvergenceTracker) BestCost

func (c *ConvergenceTracker) BestCost() float64

BestCost returns the best cost seen so far.

func (*ConvergenceTracker) History

func (c *ConvergenceTracker) History() []float64

History returns the full cost history.

func (*ConvergenceTracker) Reset

func (c *ConvergenceTracker) Reset()

Reset clears the tracker's state.

func (*ConvergenceTracker) StaleCount

func (c *ConvergenceTracker) StaleCount() int

StaleCount returns the current number of iterations without improvement.

func (*ConvergenceTracker) Update

func (c *ConvergenceTracker) Update(cost float64) bool

Update records a new cost value and returns true if convergence is detected.

type OptimizationResult

type OptimizationResult struct {
	BestParams       []float64
	BestCost         float64
	InitialCost      float64
	Iterations       int // Exact when Optimizer implements opt.LifecycleOptimizer.
	Evaluations      int // Objective evaluations, including pipeline validation evaluations.
	Stages           int // Completed optimizer runs (one for joint, circles/batches for staged modes).
	OptimizedCircles int
	BestImage        *image.NRGBA

	// Termination reports why the run stopped. Joint mode reports the single
	// optimizer run's reason verbatim. Staged modes report
	// TerminationStageConvergence when the stage-level tracker stopped the loop
	// and opt.TerminationCompleted when the circle budget was consumed: an
	// individual stage that stopped early is not why the run ended, because the
	// loop went on to the next circle or batch.
	Termination opt.Termination
	// StagesStoppedEarly counts stages whose optimizer stopped before its own
	// iteration cap. It is diagnostic and never changes Termination.
	StagesStoppedEarly int
}

OptimizationResult holds the output of an optimization run.

func OptimizeBatch

func OptimizeBatch(base Renderer, optimizer opt.Optimizer, totalCircles, batchSize int, convergenceConfig ConvergenceConfig) (*OptimizationResult, error)

OptimizeBatch attempts totalCircles, adding at most batchSize circles per stage. Invalid or worsening batches are omitted, so a result can contain fewer circles than requested. The final stage uses the remaining budget.

func OptimizeBatchAppendContext

func OptimizeBatchAppendContext(ctx context.Context, base Renderer, optimizer opt.Optimizer, prefixParams []float64, totalCircles, batchSize int, convergenceConfig ConvergenceConfig) (*OptimizationResult, error)

OptimizeBatchAppendContext preserves an already-rendered prefix and appends circles after it. The prefix order is immutable: staged optimization only receives the remaining suffix dimensions, while progress and the final result contain the complete parameter vector.

func OptimizeBatchAppendFromCanvasContext

func OptimizeBatchAppendFromCanvasContext(
	ctx context.Context,
	base Renderer,
	optimizer opt.Optimizer,
	prefixParams []float64,
	prefixCanvas *image.NRGBA,
	prefixCost float64,
	totalCircles, batchSize int,
	convergenceConfig ConvergenceConfig,
) (*OptimizationResult, error)

OptimizeBatchAppendFromCanvasContext is OptimizeBatchAppendContext with an already-rendered prefix. A completed server checkpoint stores that exact image as best.png, so a one-circle extension can restore the retained canvas without replaying thousands of immutable circles. The supplied cost must be the cost of prefixCanvas against base.Reference(); callers that cannot prove that relationship should use OptimizeBatchAppendContext.

func OptimizeBatchContext

func OptimizeBatchContext(ctx context.Context, base Renderer, optimizer opt.Optimizer, totalCircles, batchSize int, convergenceConfig ConvergenceConfig) (*OptimizationResult, error)

OptimizeBatchContext is OptimizeBatch with cooperative cancellation when the optimizer implements opt.LifecycleOptimizer.

func OptimizeJoint

func OptimizeJoint(base Renderer, optimizer opt.Optimizer, circleCount int, convergenceConfig ConvergenceConfig) (*OptimizationResult, error)

OptimizeJoint optimizes all circles simultaneously.

func OptimizeJointContext

func OptimizeJointContext(ctx context.Context, base Renderer, optimizer opt.Optimizer, circleCount int, _ ConvergenceConfig) (*OptimizationResult, error)

OptimizeJointContext is OptimizeJoint with cooperative cancellation when the optimizer implements opt.LifecycleOptimizer.

func OptimizeSequential

func OptimizeSequential(base Renderer, optimizer opt.Optimizer, totalCircles int, convergenceConfig ConvergenceConfig, callback CircleCallback) (*OptimizationResult, error)

OptimizeSequential optimizes circles one at a time while retaining the best historical solution. Invalid or worsening candidates are omitted.

func OptimizeSequentialContext

func OptimizeSequentialContext(ctx context.Context, base Renderer, optimizer opt.Optimizer, totalCircles int, convergenceConfig ConvergenceConfig, callback CircleCallback) (*OptimizationResult, error)

OptimizeSequentialContext is OptimizeSequential with cooperative cancellation when the optimizer implements opt.LifecycleOptimizer.

type Renderer

type Renderer interface {
	// Render creates an image from parameter vector
	Render(params []float64) *image.NRGBA

	// Cost computes error between params and reference
	Cost(params []float64) float64

	// Dim returns the dimensionality of the parameter space
	Dim() int

	// Bounds returns lower and upper bounds for parameters
	Bounds() (lower, upper []float64)

	// Reference returns the reference image
	Reference() *image.NRGBA
}

Renderer renders circles to an image and computes cost.

func NewOpenCLRenderer

func NewOpenCLRenderer(_ *image.NRGBA, _ int) (Renderer, func(), error)

NewOpenCLRenderer creates an OpenCL GPU-based renderer (stub for non-GPU builds).

func NewRendererForBackend

func NewRendererForBackend(name string, reference *image.NRGBA, k int) (Renderer, func(), error)

NewRendererForBackend constructs the requested renderer and returns an optional cleanup hook.

type ResidualSeedOptions

type ResidualSeedOptions struct {
	Radius        float64
	Opacity       float64
	MinSeparation float64
	// Region restricts candidate centers to an image subregion. An empty region
	// uses the complete canvas.
	Region image.Rectangle
}

ResidualSeedOptions controls deterministic replacement-circle seeding. Radius, Opacity, and MinSeparation use useful image-relative defaults when zero. Explicit non-zero values are validated rather than silently repaired.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL