Skip to content

Commit

Permalink
Merge pull request #12 from lincbrain/ak-merge
Browse files Browse the repository at this point in the history
merge upstream changes from neuroglancer main
  • Loading branch information
aaronkanzer authored Nov 14, 2024
2 parents 093a603 + 30adf68 commit 8c42da2
Show file tree
Hide file tree
Showing 45 changed files with 1,860 additions and 325 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ jobs:
# - name: Setup tmate session
# uses: mxschmitt/action-tmate@v3
- name: Install Python packaging/test tools
run: pip install --upgrade pip tox nox wheel numpy -r python/requirements-test.txt
run: pip install tox nox wheel numpy -r python/requirements-test.txt
- uses: ./.github/actions/setup-firefox
- run: nox -s lint format mypy
- name: Check for dirty working directory
Expand Down Expand Up @@ -296,5 +296,6 @@ jobs:
- run: ./src/mesh/draco/build.sh
- run: ./src/sliceview/compresso/build.sh
- run: ./src/sliceview/png/build.sh
- run: ./src/sliceview/jxl/build.sh
# Check that there are no differences.
- run: git diff --exit-code
9 changes: 5 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
"ikonate": "github:mikolajdobrucki/ikonate#a86b4107c6ec717e7877f880a930d1ccf0b59d89",
"lodash-es": "^4.17.21",
"nifti-reader-js": "^0.6.8",
"numcodecs": "^0.3.1",
"numcodecs": "^0.3.2",
"pako": "^2.1.0"
},
"overrides": {
Expand Down
2 changes: 1 addition & 1 deletion python/neuroglancer/json_wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ class _Map(Map):


def typed_set(wrapped_type: Callable[[Any], T]):
def wrapper(x, _readonly=False) -> Callable[[Any], Union[set[T], frozenset[T]]]:
def wrapper(x, _readonly=False) -> Union[set[T], frozenset[T]]:
set_type = frozenset if _readonly else set
kwargs: dict[str, Any] = dict()
if hasattr(wrapped_type, "supports_readonly"):
Expand Down
9 changes: 5 additions & 4 deletions src/async_computation/decode_jpeg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,22 @@ registerAsyncComputation(
data: Uint8Array,
width: number | undefined,
height: number | undefined,
area: number | undefined,
numComponents: number | undefined,
convertToGrayscale: boolean,
) => {
const parser = new JpegDecoder();
parser.parse(data);
// Just check that the total number pixels matches the expected value.
if (
width !== undefined &&
height !== undefined &&
parser.width * parser.height !== width * height
(width !== undefined && width !== parser.width) ||
(height !== undefined && height !== parser.height) ||
(area !== undefined && parser.width * parser.height !== area)
) {
throw new Error(
"JPEG data does not have the expected dimensions: " +
`width=${parser.width}, height=${parser.height}, ` +
`expected width=${width}, expected height=${height}`,
`expected width=${width}, expected height=${height}, expected area=${area}`,
);
}
width = parser.width;
Expand Down
21 changes: 11 additions & 10 deletions src/async_computation/decode_jpeg_request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@
import type { DecodedImage } from "#src/async_computation/decode_png_request.js";
import { asyncComputation } from "#src/async_computation/index.js";

export const decodeJpeg =
asyncComputation<
(
data: Uint8Array,
width: number | undefined,
height: number | undefined,
numComponents: number | undefined,
convertToGrayscale: boolean,
) => DecodedImage
>("decodeJpeg");
export const decodeJpeg = asyncComputation<
(
data: Uint8Array,
width: number | undefined,
height: number | undefined,
// Expected width * height
area: number | undefined,
numComponents: number | undefined,
convertToGrayscale: boolean,
) => DecodedImage
>("decodeJpeg");
37 changes: 37 additions & 0 deletions src/async_computation/decode_jxl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* @license
* Copyright 2024 William Silversmith
* 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.
*/

import { decodeJxl } from "#src/async_computation/decode_jxl_request.js";
import { registerAsyncComputation } from "#src/async_computation/handler.js";
import { decompressJxl } from "#src/sliceview/jxl/index.js";

registerAsyncComputation(
decodeJxl,
async (
data: Uint8Array,
area: number | undefined,
numComponents: number | undefined,
bytesPerPixel: number,
) => {
const result = await decompressJxl(
data,
area,
numComponents,
bytesPerPixel,
);
return { value: result, transfer: [result.uint8Array.buffer] };
},
);
27 changes: 27 additions & 0 deletions src/async_computation/decode_jxl_request.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* @license
* Copyright 2024 William Silversmith
* 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.
*/
import type { DecodedImage } from "#src/async_computation/decode_png_request.js";
import { asyncComputation } from "#src/async_computation/index.js";

export const decodeJxl =
asyncComputation<
(
data: Uint8Array,
area: number | undefined,
numComponents: number | undefined,
bytesPerPixel: number,
) => DecodedImage
>("decodeJxl");
3 changes: 3 additions & 0 deletions src/async_computation/decode_png.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ registerAsyncComputation(
data: Uint8Array,
width: number | undefined,
height: number | undefined,
// Expected width * height
area: number | undefined,
numComponents: number | undefined,
bytesPerPixel: number,
convertToGrayscale: boolean,
Expand All @@ -32,6 +34,7 @@ registerAsyncComputation(
data,
width,
height,
area,
numComponents,
bytesPerPixel,
convertToGrayscale,
Expand Down
23 changes: 12 additions & 11 deletions src/async_computation/decode_png_request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ export interface DecodedImage {
uint8Array: Uint8Array;
}

export const decodePng =
asyncComputation<
(
data: Uint8Array,
width: number | undefined,
height: number | undefined,
numComponents: number | undefined,
bytesPerPixel: number,
convertToGrayscale: boolean,
) => DecodedImage
>("decodePng");
export const decodePng = asyncComputation<
(
data: Uint8Array,
width: number | undefined,
height: number | undefined,
// Expected width * height
area: number | undefined,
numComponents: number | undefined,
bytesPerPixel: number,
convertToGrayscale: boolean,
) => DecodedImage
>("decodePng");
2 changes: 2 additions & 0 deletions src/datasource/deepzoom/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export class DeepzoomImageTileSource extends WithParameters(
new Uint8Array(responseBuffer),
undefined,
undefined,
undefined,
3,
1,
false,
Expand All @@ -133,6 +134,7 @@ export class DeepzoomImageTileSource extends WithParameters(
new Uint8Array(responseBuffer),
undefined,
undefined,
undefined,
3,
false,
);
Expand Down
1 change: 1 addition & 0 deletions src/datasource/precomputed/async_computation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "#src/async_computation/decode_jpeg.js";
import "#src/async_computation/decode_jxl.js";
import "#src/async_computation/decode_gzip.js";
import "#src/async_computation/decode_compresso.js";
import "#src/async_computation/decode_png.js";
2 changes: 2 additions & 0 deletions src/datasource/precomputed/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import { decodeCompressedSegmentationChunk } from "#src/sliceview/backend_chunk_
import { decodeCompressoChunk } from "#src/sliceview/backend_chunk_decoders/compresso.js";
import type { ChunkDecoder } from "#src/sliceview/backend_chunk_decoders/index.js";
import { decodeJpegChunk } from "#src/sliceview/backend_chunk_decoders/jpeg.js";
import { decodeJxlChunk } from "#src/sliceview/backend_chunk_decoders/jxl.js";
import { decodePngChunk } from "#src/sliceview/backend_chunk_decoders/png.js";
import { decodeRawChunk } from "#src/sliceview/backend_chunk_decoders/raw.js";
import type { VolumeChunk } from "#src/sliceview/volume/backend.js";
Expand Down Expand Up @@ -380,6 +381,7 @@ chunkDecoders.set(
);
chunkDecoders.set(VolumeChunkEncoding.COMPRESSO, decodeCompressoChunk);
chunkDecoders.set(VolumeChunkEncoding.PNG, decodePngChunk);
chunkDecoders.set(VolumeChunkEncoding.JXL, decodeJxlChunk);

@registerSharedObject()
export class PrecomputedVolumeChunkSource extends WithParameters(
Expand Down
1 change: 1 addition & 0 deletions src/datasource/precomputed/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export enum VolumeChunkEncoding {
COMPRESSED_SEGMENTATION = 2,
COMPRESSO = 3,
PNG = 4,
JXL = 5,
}

export class VolumeChunkSourceParameters {
Expand Down
5 changes: 3 additions & 2 deletions src/datasource/render/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ chunkDecoders.set(
cancellationToken,
[response],
new Uint8Array(response),
chunkDataSize[0],
chunkDataSize[1] * chunkDataSize[2],
undefined,
undefined,
chunkDataSize[0] * chunkDataSize[1] * chunkDataSize[2],
3,
true,
);
Expand Down
5 changes: 3 additions & 2 deletions src/display_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ export class DisplayContext extends RefCounted implements FrameNumberCounter {
rootRect: DOMRect | undefined;
resizeGeneration = 0;
boundsGeneration = -1;
force3DHistogramForAutoRange = false;
private framerateMonitor = new FramerateMonitor();

private continuousCameraMotionInProgress = false;
Expand Down Expand Up @@ -587,7 +588,7 @@ export class DisplayContext extends RefCounted implements FrameNumberCounter {
this.updateStarted.dispatch();
const gl = this.gl;
const ext = this.framerateMonitor.getTimingExtension(gl);
const query = this.framerateMonitor.startFrameTimeQuery(gl, ext);
this.framerateMonitor.startFrameTimeQuery(gl, ext, this.frameNumber);
this.ensureBoundsUpdated();
this.gl.clearColor(0.0, 0.0, 0.0, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
Expand All @@ -611,7 +612,7 @@ export class DisplayContext extends RefCounted implements FrameNumberCounter {
gl.clear(gl.COLOR_BUFFER_BIT);
this.gl.colorMask(true, true, true, true);
this.updateFinished.dispatch();
this.framerateMonitor.endFrameTimeQuery(gl, ext, query);
this.framerateMonitor.endLastTimeQuery(gl, ext);
this.framerateMonitor.grabAnyFinishedQueryResults(gl);
}

Expand Down
1 change: 1 addition & 0 deletions src/perspective_view/panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,7 @@ export class PerspectivePanel extends RenderedDataPanel {
sliceViewsPresent: this.sliceViews.size > 0,
isContinuousCameraMotionInProgress:
this.isContinuousCameraMotionInProgress,
force3DHistogramForAutoRange: this.context.force3DHistogramForAutoRange,
};

mat4.copy(
Expand Down
6 changes: 6 additions & 0 deletions src/perspective_view/render_layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ export interface PerspectiveViewRenderContext
*/
isContinuousCameraMotionInProgress: boolean;

/**
* Usually, the histogram in 3D is disabled during camera movement
* This flag is used to force 3D histogram rendering during camera movement
*/
force3DHistogramForAutoRange: boolean;

/**
* Specifices how to bind the max projection buffer
*/
Expand Down
5 changes: 3 additions & 2 deletions src/sliceview/backend_chunk_decoders/jpeg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ export async function decodeJpegChunk(
cancellationToken,
[response],
new Uint8Array(response),
chunkDataSize[0],
chunkDataSize[1] * chunkDataSize[2],
undefined,
undefined,
chunkDataSize[0] * chunkDataSize[1] * chunkDataSize[2],
chunkDataSize[3] || 1,
false,
);
Expand Down
39 changes: 39 additions & 0 deletions src/sliceview/backend_chunk_decoders/jxl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* @license
* Copyright 2016 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.
*/

import { decodeJxl } from "#src/async_computation/decode_jxl_request.js";
import { requestAsyncComputation } from "#src/async_computation/request.js";
import { postProcessRawData } from "#src/sliceview/backend_chunk_decoders/postprocess.js";
import type { VolumeChunk } from "#src/sliceview/volume/backend.js";
import type { CancellationToken } from "#src/util/cancellation.js";

export async function decodeJxlChunk(
chunk: VolumeChunk,
cancellationToken: CancellationToken,
response: ArrayBuffer,
) {
const chunkDataSize = chunk.chunkDataSize!;
const { uint8Array: decoded } = await requestAsyncComputation(
decodeJxl,
cancellationToken,
[response],
new Uint8Array(response),
chunkDataSize[0] * chunkDataSize[1] * chunkDataSize[2],
chunkDataSize[3] || 1,
1, // bytesPerPixel
);
await postProcessRawData(chunk, cancellationToken, decoded);
}
5 changes: 3 additions & 2 deletions src/sliceview/backend_chunk_decoders/png.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ export async function decodePngChunk(
cancellationToken,
[response],
/*buffer=*/ new Uint8Array(response),
/*width=*/ chunkDataSize[0],
/*height=*/ chunkDataSize[1] * chunkDataSize[2],
/*width=*/ undefined,
/*height=*/ undefined,
/*area=*/ chunkDataSize[0] * chunkDataSize[1] * chunkDataSize[2],
/*numComponents=*/ chunkDataSize[3] || 1,
/*bytesPerPixel=*/ DATA_TYPE_BYTES[dataType],
/*convertToGrayscale=*/ false,
Expand Down
Loading

0 comments on commit 8c42da2

Please sign in to comment.