Skip to content

Fixes to bitmask - #250

Merged
TrevorBurgoyne merged 11 commits into
mainfrom
fix/bitmask-filter
Aug 11, 2026
Merged

Fixes to bitmask#250
TrevorBurgoyne merged 11 commits into
mainfrom
fix/bitmask-filter

Conversation

@TrevorBurgoyne

@TrevorBurgoyne TrevorBurgoyne commented Aug 5, 2026

Copy link
Copy Markdown
Member

Bitmask fixes

Description

  • The ConfidenceSlider toolbox item now also filters bitmask annotations
  • The set_annotations() and swap_frame_image() public API methods now display the loading spinner while they run and return a Promise
  • Bitmask brush overlap modes (exclude / overwrite) now resolve against bitmask annotations across all subtasks, not just the active one.
  • Performance improvements for jobs with many large bitmask annotations:
    • Overlap resolution (exclude / overwrite) now uses a bounding-box pre-filter and box-limited pixel operations, so its cost scales with the size of the brush stroke rather than the number and size of existing masks.
    • Moving a bitmask renders only the moving mask over a cached snapshot of the others (throttled to one render per animation frame) instead of re-rasterizing every mask on the canvas each frame.
    • Each bitmask caches a pre-tinted render that is reused across redraws (brush dabs, moves, pan, zoom) and rebuilt only when the mask or its color changes, removing per-frame pixel-by-pixel rasterization.

PR Checklist

  • Merged latest main
  • Version number in package.json has been bumped since last release
  • Version numbers match between package package.json and src/version.js
  • Updated documentation if necessary (currently just in api_spec.md)
  • Added changes to changelog.md

Breaking API Changes

No

@TrevorBurgoyne
TrevorBurgoyne requested a balanced review from Copilot August 10, 2026 18:33
@TrevorBurgoyne
TrevorBurgoyne marked this pull request as ready for review August 10, 2026 18:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Improves bitmask overlap handling, rendering performance, confidence filtering, and asynchronous loading behavior.

Changes:

  • Adds cross-subtask, bounding-box-limited bitmask overlap resolution.
  • Introduces cached bitmask rendering and throttled move overlays.
  • Makes annotation/image replacement asynchronous and expands test coverage.

Reviewed changes

Copilot reviewed 15 out of 17 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/index.js Implements overlap, rendering, movement, and async API changes.
src/mask_utils.ts Adds mask versions and box-limited operations.
src/actions.ts Adds optimized bitmask move rendering.
src/loader.ts Adds render-waiting support.
src/version.js Bumps the library version.
index.d.ts Updates public API types.
package.json Bumps package version.
package-lock.json Synchronizes package version.
api_spec.md Documents filtering and async APIs.
CHANGELOG.md Records the release changes.
demo/bitmask-e2e.html Adds a bitmask test fixture.
tests/mask_utils.test.js Tests mask operations and versioning.
tests/bitmask_overlap.test.js Tests overlap semantics.
tests/e2e/bitmask.spec.js Tests integrated bitmask behavior.
tests/e2e/confidence-slider.spec.js Awaits asynchronous annotation replacement.
tests/confidence_slider.test.js Tests bitmask confidence filtering.
tests/annotation_operators.test.js Verifies bitmask filter eligibility.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/index.js Outdated
Comment thread src/loader.ts
Comment thread demo/bitmask-e2e.html
Comment thread CHANGELOG.md Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 17 changed files in this pull request and generated 1 comment.

Suppressed comments (5)

demo/bitmask-e2e.html:23

  • This newly introduced console.log violates the repository logging rule. The e2e fixture does not use submission output, so make the callback a no-op; if logging is needed, route it through log_message instead.
                function on_submit(annotations) {
                    console.log("submit", annotations);
                }

src/index.js:4856

  • frame is compared strictly here, but draw_annotation_from_id treats numeric frame strings as visible via loose equality. Imported annotations are assigned from JSON without coercing frame, so an annotation with frame: "0" is rendered on frame 0 but skipped by overlap resolution, allowing masks to overlap. Normalize the frame value while preserving the renderer's special "undefined" handling.
                const frame = ann["frame"];
                if (frame != null && frame !== current_frame) continue;

src/index.js:4898

  • This re-encodes the entire existing mask before every carve, which is especially costly for the large masks this optimization targets. The annotation's current spatial_payload is already the pre-edit RLE, so reuse it for undo instead of performing this redundant full-image scan.
            const before_rle = other_mask.to_rle();

src/index.js:6846

  • Changing this method from returning the old source synchronously to returning Promise<string> breaks callers that consume the return value directly, despite the PR declaring no breaking API changes. Either preserve the synchronous API (for example via a separate async loading method) or mark and version this as a breaking change with migration guidance.
    async swap_frame_image(new_src, frame = 0) {

src/index.js:6947

  • The new await makes annotation replacement asynchronous even for callers that ignore the return value: code immediately after set_annotations() now observes the old annotations. That is a behavioral breaking change, contrary to the PR's “Breaking API Changes: No”. Preserve synchronous semantics via a separate async API, or explicitly classify/version/document this migration as breaking.
    async set_annotations(new_annotations, subtask) {
        // Show the loader while re-initializing annotations, since this is similar to a new init
        const container = document.getElementById(this.config["container_id"]);
        ULabelLoader.add_loader_div(container);
        // Yield so the browser can paint the loader before the heavy synchronous work below
        await ULabelLoader.wait_for_render();

Comment thread src/index.js

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 17 changed files in this pull request and generated no new comments.

Suppressed comments (3)

demo/bitmask-e2e.html:22

  • Avoid writing submitted annotation payloads to the browser console from this fixture. It creates noisy test output and exposes annotation data when the fixture is opened manually; this callback can be a no-op because submission is not exercised here.
                    console.log("submit", annotations);

src/index.js:4856

  • This frame filter does not match draw_annotation_from_id(): that render gate deliberately treats the legacy literal "undefined" and numerically equivalent frame values as visible. Those bitmasks can therefore be rendered while being skipped by overlap resolution, leaving visible masks overlapping. Mirror the render gate here (or normalize frame values during import).
                if (frame != null && frame !== current_frame) continue;

package.json:4

  • This patch version conflicts with the PR's “Breaking API Changes: No” claim: swap_frame_image() now returns a Promise instead of the old source string, and set_annotations() now defers its mutation until after an await. Existing callers that consume the return value or immediately read annotations will break. Either preserve synchronous compatibility or release/document these as breaking API changes with an appropriate synchronized version bump.
  "version": "0.25.1",

@TrevorBurgoyne
TrevorBurgoyne merged commit 7591f0e into main Aug 11, 2026
5 checks passed
@TrevorBurgoyne
TrevorBurgoyne deleted the fix/bitmask-filter branch August 11, 2026 14:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants