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

Screenshot for 3D view #5324

Merged
merged 7 commits into from
Apr 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released

### Added
- Upgraded UI library antd to version 4, creating a slightly more modern look and behavior of many UI elements. [#5350](https://github.com/scalableminds/webknossos/pull/5350)
- Added a screenshot of the 3D view when using the screenshot functionality in the tracing view. [#5324](https://github.com/scalableminds/webknossos/pull/5324)

### Changed
- webKnossos is now part of the [image.sc support community](https://forum.image.sc/tag/webknossos). [#5332](https://github.com/scalableminds/webknossos/pull/5332)
Expand All @@ -22,6 +23,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
- Fixed that editing a task type would always re-add the default values to the recommended configuration (if enabled). [#5341](https://github.com/scalableminds/webknossos/pull/5341)
- Fixed a bug where tasks created from existing volume annotations that did not have a specified bounding box were broken. [#5362](https://github.com/scalableminds/webknossos/pull/5361)
- Fixed a bug in Safari which could cause an error message (which is safe to ignore). [#5373](https://github.com/scalableminds/webknossos/pull/5373)
- Fixed artifacts in screenshots near the dataset border. [#5324](https://github.com/scalableminds/webknossos/pull/5324)

### Removed
-
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ ${compileShader(
void main() {
vec3 worldCoordUVW = getWorldCoordUVW();
if (isOutsideOfBoundingBox(worldCoordUVW)) {
gl_FragColor = vec4(0.0);
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
Copy link
Member Author

Choose a reason for hiding this comment

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

@philippotto Setting the alpha value to 1 for pixels outside of the bounding box, fixes both the mirroring issue (described in the PR description - would make my earlier fix obsolete) as well as the other transparency issue (see Michaels screenshot). Do you see any harm in that? I checked that the node picking is not affected.

Copy link
Member

Choose a reason for hiding this comment

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

Sounds perfectly fine to me 👍 I don't think that a lot of reasoning went into this line when it was written. The result probably behaved like "black" in the critical use case (viewport is out of bounds) which was considered good enough. Cool that you found this solution :)

Copy link
Contributor

Choose a reason for hiding this comment

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

I can't find any case where it would result in a 🐛 too.

return;
}
vec3 relativeCoords = getRelativeCoords(worldCoordUVW, zoomStep);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import { Button, Dropdown, Menu, Modal, Tooltip } from "antd";
import {
BarsOutlined,
CameraOutlined,
CheckCircleOutlined,
CheckOutlined,
CodeSandboxOutlined,
Expand Down Expand Up @@ -53,7 +52,7 @@ import Store, { type OxalisState, type RestrictionsAndSettings, type Task } from
import UserScriptsModalView from "oxalis/view/action-bar/user_scripts_modal_view";
import api from "oxalis/api/internal_api";
import messages from "messages";
import { downloadScreenshot } from "oxalis/view/rendering_utils";
import { screenshotMenuItem } from "oxalis/view/action-bar/view_dataset_actions_view";
import UserLocalStorage from "libs/user_local_storage";
import features from "features";

Expand Down Expand Up @@ -465,12 +464,7 @@ class TracingActionsView extends React.PureComponent<Props, State> {
annotationId={annotationId}
/>,
);
elements.push(
<Menu.Item key="screenshot-button" onClick={downloadScreenshot}>
<CameraOutlined />
Screenshot (Q)
</Menu.Item>,
);
elements.push(screenshotMenuItem);
elements.push(
<Menu.Item key="user-scripts-button" onClick={this.handleUserScriptsOpen}>
<SettingOutlined />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
// @flow
import React, { useState, type Node } from "react";
import { Dropdown, Menu } from "antd";
import { ShareAltOutlined, DownOutlined } from "@ant-design/icons";
import { ShareAltOutlined, DownOutlined, CameraOutlined } from "@ant-design/icons";
import ButtonComponent from "oxalis/view/components/button_component";
import ShareViewDatasetModalView from "oxalis/view/action-bar/share_view_dataset_modal_view";
import { downloadScreenshot } from "oxalis/view/rendering_utils";

type Props = {
layoutMenu: Node,
};

export const screenshotMenuItem = (
<Menu.Item key="screenshot-button" onClick={downloadScreenshot}>
<CameraOutlined />
Screenshot (Q)
</Menu.Item>
);

export default function ViewDatasetActionsView(props: Props) {
const [shareDatasetModalVisibility, setShareDatasetModalVisibility] = useState(false);
const modal = (
Expand All @@ -19,11 +27,12 @@ export default function ViewDatasetActionsView(props: Props) {
);
const overlayMenu = (
<Menu>
{props.layoutMenu}
<Menu.Item key="share-button" onClick={() => setShareDatasetModalVisibility(true)}>
<ShareAltOutlined />
Share
</Menu.Item>
{screenshotMenuItem}
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice addition 👍

{props.layoutMenu}
</Menu>
);

Expand Down
13 changes: 9 additions & 4 deletions frontend/javascripts/oxalis/view/rendering_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import Store from "oxalis/store";
import constants, {
type OrthoView,
ArbitraryViewport,
OrthoViewValuesWithoutTDView,
OrthoViewColors,
OrthoViewValues,
} from "oxalis/constants";
import { getInputCatcherRect } from "oxalis/model/accessors/view_mode_accessor";
import getSceneController from "oxalis/controller/scene_controller_provider";
Expand Down Expand Up @@ -39,11 +40,13 @@ export function renderToTexture(
plane: OrthoView | typeof ArbitraryViewport,
scene?: typeof THREE.Scene,
camera?: typeof THREE.Camera,
clearColor?: number,
): Uint8Array {
const SceneController = getSceneController();
const { renderer, scene: defaultScene } = SceneController;
scene = scene || defaultScene;
camera = camera || scene.getObjectByName(plane);
clearColor = clearColor != null ? clearColor : 0x000000;

renderer.autoClear = true;
let { width, height } = getInputCatcherRect(Store.getState(), plane);
Expand All @@ -52,7 +55,7 @@ export function renderToTexture(

renderer.setViewport(0, 0 + height, width, height);
renderer.setScissorTest(false);
renderer.setClearColor(0x000000, 1);
renderer.setClearColor(clearColor, 1);

const renderTarget = new THREE.WebGLRenderTarget(width, height);
const buffer = new Uint8Array(width * height * 4);
Expand All @@ -77,13 +80,15 @@ export async function downloadScreenshot() {
const baseName = `${datasetName}__${x}_${y}_${z}`;

const planeIds =
viewMode === constants.MODE_PLANE_TRACING ? OrthoViewValuesWithoutTDView : [ArbitraryViewport];
viewMode === constants.MODE_PLANE_TRACING ? OrthoViewValues : [ArbitraryViewport];

for (const planeId of planeIds) {
const { width, height } = getInputCatcherRect(Store.getState(), planeId);
if (width === 0 || height === 0) continue;

const buffer = renderToTexture(planeId);
// $FlowIssue[prop-missing] planeId cannot be arbitraryViewport in OrthoViewColors access
const clearColor = OrthoViewValues.includes(planeId) ? OrthoViewColors[planeId] : 0xffffff;
const buffer = renderToTexture(planeId, null, null, clearColor);

// eslint-disable-next-line no-await-in-loop
const blob = await convertBufferToImage(buffer, width, height);
Expand Down