Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/high resolution screenshot #37

Open
wants to merge 67 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
5bcb1ec
feat: simple screenshot button in settings
seankmartin Jul 12, 2024
5f296e8
poc: scalable screenshot
seankmartin Jul 12, 2024
c425f54
Merge branch 'master' into feature/high-resolution-screenshot
seankmartin Jul 29, 2024
a111495
feat(ui): add camera icon to top bar
seankmartin Aug 27, 2024
71b4ec7
refactor: pull viewer complexity for screenshot into new class
seankmartin Aug 27, 2024
0472c12
refactor: clarify variable
seankmartin Aug 27, 2024
e2b15b9
refactor: move interface for screenshot to utils
seankmartin Aug 28, 2024
504228a
fix: revert help menu change for temp testing
seankmartin Aug 28, 2024
e0b1504
feat(ui): add screenshot UI elements
seankmartin Aug 28, 2024
bd52bd7
fix: allow forcing screenshot if viewer not ready
seankmartin Aug 28, 2024
58deb88
feat: crop screenshot to view panels
seankmartin Aug 28, 2024
4ef21f4
refactor: clean up screenshot code
seankmartin Aug 28, 2024
ac9fe69
refactor: remove atob and btoa to reduce complexity of codebase
seankmartin Aug 28, 2024
0c219d3
fix(ui): remove SVG titles in buttons
seankmartin Aug 28, 2024
eac9be3
fix(ui): better icon fix
seankmartin Aug 29, 2024
17c8a88
feat: switch between buttons for save or force screenshot
seankmartin Aug 29, 2024
d651e55
refactor: remove event listener complexity from viewer
seankmartin Aug 29, 2024
570650a
feat: first version of screenshot statistics
seankmartin Aug 30, 2024
aed271e
feat: auto force screenshot if no updates
seankmartin Aug 30, 2024
3b87bee
refactor: simplify logic for object interaction
seankmartin Aug 30, 2024
e39740a
refactor: clean up screenshot menu
seankmartin Sep 2, 2024
3d2804b
feat: add minimal CSS styling for screenshot
seankmartin Sep 2, 2024
53b02e5
feat(ui): only show stats while in progress
seankmartin Sep 2, 2024
51e01c3
feat(ui): improve screenshot stats
seankmartin Sep 2, 2024
24b04a9
feat: hide screenshot controls when not in use and update stats with …
seankmartin Sep 3, 2024
d11dff2
feat(ui): improve table updating
seankmartin Sep 3, 2024
6bafc30
refactor: improve screenshot from viewer code
seankmartin Sep 3, 2024
81154b6
refactor: small rename for consistency
seankmartin Sep 3, 2024
aa4b419
feat: include state log for screenshot replication
seankmartin Sep 3, 2024
2d59788
refactor: change trackable screenshot from type to class
seankmartin Sep 3, 2024
f40c432
refactor: clarify force check for bool
seankmartin Sep 3, 2024
d666a3e
remove: is DataPanel flag in favour of checking instance
seankmartin Sep 3, 2024
7fbbf88
feat(ui): small UI improvements in screenshot menu
seankmartin Sep 3, 2024
c6dca6c
refactor: rename classes
seankmartin Sep 3, 2024
e0facf0
refactor: clarify interaction between screenshot objects
seankmartin Sep 3, 2024
f928d07
refactor: make viewer menu responsible for manipulating data from con…
seankmartin Sep 3, 2024
cf44402
refactor: rename screenshot manager file
seankmartin Sep 16, 2024
4fc91b8
feat: lock screenshot menu until cancelled or done
seankmartin Sep 16, 2024
a2d504b
feat: close tool menus before opening JSON state editor or screenshot…
seankmartin Sep 16, 2024
7f61396
feat: show indication of screenshot size, warning if big, don't hide …
seankmartin Sep 16, 2024
15bf297
feat: progress on image (slice and volume) res stats
seankmartin Sep 16, 2024
3e2afd8
feat: resolution from each layer type
seankmartin Sep 17, 2024
5d1a0ee
feat: add per panel resolution indicator
seankmartin Sep 17, 2024
7d2930b
feat: separate screenshot cancel button
seankmartin Sep 17, 2024
5f84eb6
feat: separate close button
seankmartin Sep 17, 2024
beeb355
feat(ui): show stats on menu even when screenshot not running
seankmartin Sep 17, 2024
949bcdf
feat: update resolution rounding for slices > 1px
seankmartin Sep 17, 2024
042ee62
feat: populate layer stats in menu as they laod
seankmartin Sep 19, 2024
b62fe06
feat: hide non-visible stats
seankmartin Sep 19, 2024
3289c2c
feat: reduce screenshot hang time
seankmartin Sep 19, 2024
bd91904
feat: improve stats display and checking for hanging screenshots
seankmartin Sep 20, 2024
bb07ae8
feat: detect ortographic view stats
seankmartin Sep 23, 2024
54a20d2
fix(ui): don't round resolution < 1 in display
seankmartin Sep 23, 2024
4230a4c
docs: note about why use debug close menu
seankmartin Sep 23, 2024
7f0d199
revert: don't grab JSON state with screenshot
seankmartin Sep 26, 2024
beab5f4
feat: include voxel resolution in screenshot
seankmartin Sep 26, 2024
681d923
feat: allow fixed 2D panel FOV in screenshots with checkbox
seankmartin Sep 26, 2024
7e5dda2
fix: formatting
seankmartin Sep 26, 2024
5862bf9
fix: possible race condition between screenshot taking and resetting …
seankmartin Sep 26, 2024
7ebf558
feat: add panel pixel sizes
seankmartin Sep 26, 2024
7e9404f
refactor: small changes for clarity
seankmartin Sep 27, 2024
461a79e
docs: add docstring for resolution functions
seankmartin Sep 27, 2024
970a3f7
docs, refactor: improve screenshot clarity
seankmartin Sep 27, 2024
0cb7ef2
docs: screenshot manager notes
seankmartin Sep 27, 2024
6c171df
feat: combine panel physical and pixel resolution in UI
seankmartin Sep 27, 2024
9b4c306
fix: handle correclty the pixel indicator on zoom in UI
seankmartin Sep 27, 2024
c9eb62a
feat(ui): initial version of tooltips
seankmartin Sep 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions src/display_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ import { FramerateMonitor } from "#src/util/framerate.js";
import type { mat4 } from "#src/util/geom.js";
import { parseFixedLengthArray, verifyFloat01 } from "#src/util/json.js";
import { NullarySignal } from "#src/util/signal.js";
import {
TrackableScreenshotMode,
ScreenshotMode,
} from "#src/util/trackable_screenshot_mode.js";
import type { WatchableVisibilityPriority } from "#src/visibility_priority/frontend.js";
import type { GL } from "#src/webgl/context.js";
import { initializeWebGL } from "#src/webgl/context.js";
Expand Down Expand Up @@ -221,8 +225,15 @@ export abstract class RenderedPanel extends RefCounted {
0,
clippedBottom - clippedTop,
));
viewport.logicalWidth = logicalWidth;
viewport.logicalHeight = logicalHeight;
if (this.context.screenshotMode.value !== ScreenshotMode.OFF) {
viewport.width = logicalWidth * screenToCanvasPixelScaleX;
viewport.height = logicalHeight * screenToCanvasPixelScaleY;
viewport.logicalWidth = logicalWidth * screenToCanvasPixelScaleX;
viewport.logicalHeight = logicalHeight * screenToCanvasPixelScaleY;
} else {
viewport.logicalWidth = logicalWidth;
viewport.logicalHeight = logicalHeight;
}
viewport.visibleLeftFraction = (clippedLeft - logicalLeft) / logicalWidth;
viewport.visibleTopFraction = (clippedTop - logicalTop) / logicalHeight;
viewport.visibleWidthFraction = clippedWidth / logicalWidth;
Expand Down Expand Up @@ -403,6 +414,9 @@ export class DisplayContext extends RefCounted implements FrameNumberCounter {
rootRect: DOMRect | undefined;
resizeGeneration = 0;
boundsGeneration = -1;
screenshotMode: TrackableScreenshotMode = new TrackableScreenshotMode(
ScreenshotMode.OFF,
);
private framerateMonitor = new FramerateMonitor();

private continuousCameraMotionInProgress = false;
Expand Down Expand Up @@ -575,8 +589,10 @@ export class DisplayContext extends RefCounted implements FrameNumberCounter {
const { resizeGeneration } = this;
if (this.boundsGeneration === resizeGeneration) return;
const { canvas } = this;
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
if (this.screenshotMode.value === ScreenshotMode.OFF) {
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
}
this.canvasRect = canvas.getBoundingClientRect();
this.rootRect = this.container.getBoundingClientRect();
this.boundsGeneration = resizeGeneration;
Expand Down
48 changes: 44 additions & 4 deletions src/python_integration/screenshots.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,49 @@ import { convertEndian32, Endianness } from "#src/util/endian.js";
import { verifyOptionalString } from "#src/util/json.js";
import { Signal } from "#src/util/signal.js";
import { getCachedJson } from "#src/util/trackable.js";
import { ScreenshotMode } from "#src/util/trackable_screenshot_mode.js";
import type { Viewer } from "#src/viewer.js";

export interface ScreenshotActionState {
viewerState: any;
selectedValues: any;
screenshot: {
id: string;
image: string;
imageType: string;
depthData: string | undefined;
width: number;
height: number;
};
}

export interface ScreenshotChunkStatistics {
downloadLatency: number;
visibleChunksDownloading: number;
visibleChunksFailed: number;
visibleChunksGpuMemory: number;
visibleChunksSystemMemory: number;
visibleChunksTotal: number;
visibleGpuMemory: number;
}

export interface StatisticsActionState {
viewerState: any;
selectedValues: any;
screenshotStatistics: {
id: string;
chunkSources: any[];
total: ScreenshotChunkStatistics;
};
}

export class ScreenshotHandler extends RefCounted {
sendScreenshotRequested = new Signal<(state: any) => void>();
sendStatisticsRequested = new Signal<(state: any) => void>();
sendScreenshotRequested = new Signal<
(state: ScreenshotActionState) => void
>();
sendStatisticsRequested = new Signal<
(state: StatisticsActionState) => void
>();
requestState = new TrackableValue<string | undefined>(
undefined,
verifyOptionalString,
Expand Down Expand Up @@ -124,12 +162,14 @@ export class ScreenshotHandler extends RefCounted {
return;
}
const { viewer } = this;
if (!viewer.isReady()) {
const shouldForceScreenshot =
this.viewer.display.screenshotMode.value === ScreenshotMode.FORCE;
if (!viewer.isReady() && !shouldForceScreenshot) {
this.wasAlreadyVisible = false;
this.throttledSendStatistics(requestState);
return;
}
if (!this.wasAlreadyVisible) {
if (!this.wasAlreadyVisible && !shouldForceScreenshot) {
this.throttledSendStatistics(requestState);
this.wasAlreadyVisible = true;
this.debouncedMaybeSendScreenshot();
Expand Down
14 changes: 14 additions & 0 deletions src/sliceview/volume/renderlayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ export abstract class SliceViewVolumeRenderLayer<
>;
private tempChunkPosition: Float32Array;
shaderParameters: WatchableValueInterface<ShaderParameters>;
highestResolutionLoadedVoxelSize: Float32Array | undefined;
private vertexIdHelper: VertexIdHelper;

constructor(
Expand Down Expand Up @@ -570,6 +571,7 @@ void main() {
this.chunkManager.chunkQueueManager.frameNumberCounter.frameNumber,
);
}
this.highestResolutionLoadedVoxelSize = undefined;

let shaderResult: ParameterizedShaderGetterResult<
ShaderParameters,
Expand Down Expand Up @@ -692,6 +694,18 @@ void main() {
effectiveVoxelSize[1],
effectiveVoxelSize[2],
);
if (presentCount > 0) {
const medianStoredVoxelSize = this.highestResolutionLoadedVoxelSize
? medianOf3(
this.highestResolutionLoadedVoxelSize[0],
this.highestResolutionLoadedVoxelSize[1],
this.highestResolutionLoadedVoxelSize[2],
)
: Infinity;
if (medianVoxelSize <= medianStoredVoxelSize) {
this.highestResolutionLoadedVoxelSize = effectiveVoxelSize;
}
}
renderScaleHistogram.add(
medianVoxelSize,
medianVoxelSize / projectionParameters.pixelSize,
Expand Down
83 changes: 83 additions & 0 deletions src/ui/screenshot_menu.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* @license
* Copyright 2024 Google Inc.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

.neuroglancer-screenshot-dialog {
width: 60%;
}

.neuroglancer-screenshot-scale-radio {
display: inline-block;
width: 20px;
margin-right: -2px;
cursor: pointer;
}

.neuroglancer-screenshot-filename-and-buttons {
margin-bottom: 5px;
}

.neuroglancer-screenshot-name-input {
width: 50%;
margin-right: 10px;
border: 1px solid #ccc;
}

.neuroglancer-screenshot-button {
cursor: pointer;
margin: 2px;
}

.neuroglancer-screenshot-close-button {
position: absolute;
right: 15px;
}

.neuroglancer-screenshot-statistics-title {
margin-top: 5px;
}

.neuroglancer-screenshot-statistics-table {
width: 100%;
border-collapse: collapse;
margin-top: 5px;
}

.neuroglancer-screenshot-statistics-table th,
.neuroglancer-screenshot-statistics-table td {
padding: 12px 15px;
text-align: left;
border-bottom: 1px solid #ddd;
}

.neuroglancer-screenshot-statistics-table th {
background-color: #f8f8f8;
font-weight: bold;
color: #555;
}

.neuroglancer-screenshot-warning {
color: red;
}

.neuroglancer-screenshot-tooltip {
user-select: none;
text-align: center;
padding: 0.1em;
border: 0.1em solid black;
width: 1.1em;
height: 1.1em;
border-radius: 100%;
}
Loading
Loading