tryLevelsOwned - multiple declarations

Function tryLevelsOwned

Create one independently owned ROI-local Levels result without an edit mask.

LevelsError tryLevelsOwned(T)(
  scope RasterView!T pixels,
  Region2D roi,
  scope const(bool)[] affected,
  Levels settings,
  size_t maxResultBytes,
  ref RasterLease!float published
) @safe
if (is(T == ubyte) || is(T == ushort) || is(T == float));

Each selected finite input channel is transformed by t = clamp((v-inputBlack)/(inputWhite-inputBlack), 0, 1) and outputBlack + pow(t, 1/gamma)*(outputWhite-outputBlack). Unselected channels are copied as normalized float samples; float NaN and infinities pass through unchanged. ubyte/ushort inputs are normalized by 255/65535. Alpha is never inferred or protected automatically; callers must leave its channel unselected when needed. No colour transfer or NoData handling occurs.

This candidate is @safe through an audited, private, minimal @trusted malloc/resource-adoption boundary. The public overload accepts only raster-d borrowed, validated sample views and publishes a new raster-d-owned lease; no raw storage address is exposed. The @safe attribute is a compiler-checked source contract, not a nothrow or @nogc promise. Fatal OOM/Error unwind is not guaranteed. Neither borrower nor output may be concurrently mutated.

The output is an interleaved RasterLease!float, sized exactly to the ROI, with the same channel count as the input. Source and mask (if any) are borrowed; published is replaced only after full success. Previously published ownership is unchanged on **returned** failures, including late sample failures; no guarantee is made for exceptions or OOM Errors.

maxResultBytes caps **only new pixel payload**, exactly ROI width * height * channel count * float.sizeof; it does not cover source, prior output, metadata, allocator/GC overhead or app I/O. Size/stride overflow is checked before output allocation. The operation may allocate and throw; no @nogc or nothrow claim is made.

Complexity

O(ROI pixels * input channels), O(ROI pixels * channels) new owned float payload plus descriptor metadata.

Parameters

NameDescription
pixels Borrowed source view, ubyte, ushort or float.
roi Nonempty source-local region fully inside the source.
affected One Boolean per source channel; true applies Levels.
settings Finite Levels settings; Levels.init is invalid.
maxResultBytes Maximum new float output pixel payload, in bytes.
published Existing or empty RasterLease!float, replaced only on successful completion. Must remain live throughout the call.

Returns

LevelsError.none on success. Structural/parameter/ROI errors and a too-small budget are classified before allocation; allocation/import failure returns allocationFailure when it is returned normally. No status implies success except none. In particular, LevelsError.init == LevelsError.notAttempted is NOT a success.

Examples

import core.stdc.stdlib : malloc;
import raster : OwnedByteResource, PlaneByteLayout, RasterLease,
                Region2D, tryAdoptMallocResource, tryImportOwnedRaster;
auto memory = cast(ubyte*)malloc(1);
assert(memory !is null);
OwnedByteResource backing;
assert(tryAdoptMallocResource(memory, 1, backing));
PlaneByteLayout[] layout = [PlaneByteLayout(0, 1, 1)];
RasterLease!ubyte input;
assert(tryImportOwnedRaster!ubyte(
    backing, layout, Region2D(0, 0, 1, 1), input).ok);
bool writable;
{
    scope auto writer = input.tryWritableView(writable);
    assert(writable && writer.trySetSample(0, 0, 0, 128));
}
bool[1] chosen = [true];
RasterLease!float output;
auto status = tryLevelsOwned!ubyte(
    input.view(), Region2D(0, 0, 1, 1), chosen[],
    Levels(0, 1, 1, 0, 1), float.sizeof, output);
assert(status == LevelsError.none);
scope auto view = output.view();
float result;
assert(view.trySample(0, 0, 0, result));
assert(result > 0.501f && result < 0.503f);

Function tryLevelsOwned

Apply the same owned scalar Levels operation with a graded edit mask.

LevelsError tryLevelsOwned(T)(
  scope RasterView!T pixels,
  Region2D roi,
  scope const(bool)[] affected,
  Levels settings,
  scope RasterView!ubyte selection,
  size_t maxResultBytes,
  ref RasterLease!float published
) @safe
if (is(T == ubyte) || is(T == ushort) || is(T == float));

The selection view must be one-plane RasterView!ubyte with the **full source dimensions**. Every byte defines weight mask/255.0 and the result is original + weight * (adjusted-original). A zero weight copies the input unchanged (normalized for integers). A RasterView!ubyte.init mask is rejected as invalidMask before output allocation. This is an editing-selection mask, not validity, NoData, opacity or an alpha-association rule.

Parameters

NameDescription
pixels Borrowed input source view of ubyte, ushort or float.
roi Nonempty source-local region.
affected One Boolean per input channel.
settings Valid finite Levels parameters.
selection Explicit single-plane, full-source-sized byte edit mask.
maxResultBytes Maximum new result float pixel payload in bytes.
published Live previous/empty output owner; replaced only on success.

Returns

LevelsError.none on success; other returned errors preserve published. Same ownership, resource, nonfinite and exception limitations as the unmasked overload.