Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
2484f15
feat!: add Codec interface
bogovicj Jun 5, 2025
1a58d7b
BREAKING!: remove DefaultBlockReader/Writer
bogovicj Jun 5, 2025
8dafdc9
doc: Codec, ArrayCodec, and BytesCodec
bogovicj Jun 5, 2025
c8cac8c
refactor: remove BlockHeader methods from AbstractDataBlockCodec
bogovicj Jun 10, 2025
df49f87
doc: n5 serialization annotations
bogovicj Jun 11, 2025
f978d9e
doc: javadoc fixes
bogovicj Jun 11, 2025
2a72632
doc: even more javadoc fixes
bogovicj Jun 11, 2025
b20ebdf
doc: fix errors
bogovicj Jun 11, 2025
4f36daa
Merge remote-tracking branch 'origin/master' into wip/codecs
bogovicj Jun 13, 2025
322b2b7
doc: javadoc fixes
bogovicj Jun 13, 2025
f30c539
Merge branch 'master' into wip/codecs
cmhulbert Jun 24, 2025
503e287
refactor: better align with recent merges to master
cmhulbert Jun 24, 2025
3d83479
fix: partial code when migrating to ReadData for GsonUtils.readAttrib…
cmhulbert Jun 24, 2025
e06b337
fix: some regressions from merging; Also HttpURLConnection throws Fil…
cmhulbert Jun 25, 2025
760b1a3
chore: fix javadoc
cmhulbert Jun 26, 2025
bd92d78
feat: add NameConfigAdapter and update GsonUtils
bogovicj Jun 27, 2025
16258a5
Merge branch 'wip/codecs' of github.com:saalfeldlab/n5 into wip/codecs
bogovicj Jun 27, 2025
f8ba742
fix: dont add NameConfig and Codec serializers to default N5
cmhulbert Jun 27, 2025
b59b1a7
Merge branch 'master' into wip/codecs
cmhulbert Jun 27, 2025
bfad2a9
feat!: simpler, more contrained DatasetAttributes constructor
bogovicj Jul 28, 2025
2de7803
Merge branch 'wip/codecs' of github.com:saalfeldlab/n5 into wip/codecs
bogovicj Jul 28, 2025
fd42a86
Remove unnecessary class AbstractDataBlockCodec
tpietzsch Jul 28, 2025
52b5f18
Remove redundant overrides
tpietzsch Jul 28, 2025
5e34016
Use private instead of protected
tpietzsch Jul 28, 2025
76a2883
Revise Codec naming, refactor
tpietzsch Jul 29, 2025
db42883
ArrayCodec produces DataBlockSerializer
tpietzsch Jul 29, 2025
b2eaa62
refactor
tpietzsch Jul 29, 2025
5598f3d
fix: DatasetAttributes arrayCodec init
bogovicj Jul 29, 2025
2229bcc
fix: GsonUtils import
bogovicj Jul 29, 2025
c20f596
doc: Describe the purpose of the Compression interface
bogovicj Jul 29, 2025
39d677e
rm DeterministicSizeCodec interface
bogovicj Jul 29, 2025
e51f40a
doc: BytesCodec javadoc fix
bogovicj Jul 29, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,22 @@
package org.janelia.saalfeldlab.n5;

import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;
import org.janelia.saalfeldlab.n5.Compression.CompressionType;
import org.janelia.saalfeldlab.n5.N5Exception.N5IOException;
import org.janelia.saalfeldlab.n5.readdata.ReadData;
import org.janelia.saalfeldlab.n5.serialization.NameConfig;

@CompressionType("bzip2")
@NameConfig.Name("bzip2")
public class Bzip2Compression implements Compression {

private static final long serialVersionUID = -4873117458390529118L;

@CompressionParameter
@NameConfig.Parameter
private final int blockSize;

public Bzip2Compression(final int blockSize) {
Expand Down
55 changes: 13 additions & 42 deletions src/main/java/org/janelia/saalfeldlab/n5/Compression.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,24 +53,31 @@
*/
package org.janelia.saalfeldlab.n5;

import java.io.IOException;
import java.io.Serializable;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.janelia.saalfeldlab.n5.N5Exception.N5IOException;
import org.janelia.saalfeldlab.n5.readdata.ReadData;
import org.janelia.saalfeldlab.n5.codec.BytesCodec;
import org.janelia.saalfeldlab.n5.codec.Codec;
import org.scijava.annotations.Indexable;

/**
* Compression scheme interface.
* This interface is used to indicate that a {@link BytesCodec} can be
* serialized as a "compression" for the N5 format (using the N5 API).
* <p>
* N5Readers and N5Writers for the N5 format can declare BytesCodecs that
* implement this interface so that the {@link CompressionAdapter} is used for
* serialization.
* <p>
* See also: an alternative method for serializing general {@link Codec}s is
* with the {@link NameConfigAdapter}.
*
* @author Stephan Saalfeld
*/
public interface Compression extends Serializable {
public interface Compression extends Serializable, BytesCodec {

/**
* Annotation for runtime discovery of compression schemes.
Expand All @@ -94,6 +101,7 @@ public interface Compression extends Serializable {
@Target(ElementType.FIELD)
@interface CompressionParameter {}

@Override
default String getType() {

final CompressionType compressionType = getClass().getAnnotation(CompressionType.class);
Expand All @@ -102,41 +110,4 @@ default String getType() {
else
return compressionType.value();
}

// --------------------------------------------------
//

/**
* Decode the given {@code readData}.
* <p>
* The returned decoded {@code ReadData} reports {@link ReadData#length()
* length()}{@code == decodedLength}. Decoding may be lazy or eager,
* depending on the {@code BytesCodec} implementation.
*
* @param readData
* data to decode
*
* @return decoded ReadData
*
* @throws N5IOException
* if any I/O error occurs
*/
ReadData decode(ReadData readData) throws N5IOException;

/**
* Encode the given {@code readData}.
* <p>
* Encoding may be lazy or eager, depending on the {@code BytesCodec}
* implementation.
*
* @param readData
* data to encode
*
* @return encoded ReadData
*
* @throws N5IOException
* if any I/O error occurs
*/
ReadData encode(ReadData readData) throws N5IOException;

}
94 changes: 43 additions & 51 deletions src/main/java/org/janelia/saalfeldlab/n5/DatasetAttributes.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,6 @@
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* #L%
*/
/**
* Copyright (c) 2017, Stephan Saalfeld
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
Expand All @@ -42,23 +16,27 @@
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* #L%
*/
package org.janelia.saalfeldlab.n5;

import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;

import org.janelia.saalfeldlab.n5.codec.DataBlockCodec;
import org.janelia.saalfeldlab.n5.codec.N5Codecs;
import org.janelia.saalfeldlab.n5.codec.Codec;
import org.janelia.saalfeldlab.n5.codec.ArrayCodec;
import org.janelia.saalfeldlab.n5.codec.BytesCodec;
import org.janelia.saalfeldlab.n5.codec.DataBlockSerializer;
import org.janelia.saalfeldlab.n5.codec.N5ArrayCodec;

/**
* Mandatory dataset attributes:
Expand Down Expand Up @@ -88,30 +66,39 @@ public class DatasetAttributes implements Serializable {
private final long[] dimensions;
private final int[] blockSize;
private final DataType dataType;
private final DataBlockCodec<?> dataBlockCodec;
private final Compression compression;

private final ArrayCodec arrayCodec;
private final BytesCodec[] byteCodecs;

private final DataBlockSerializer<?> dataBlockSerializer;

public DatasetAttributes(
final long[] dimensions,
final int[] blockSize,
final DataType dataType,
final Compression compression) {
final ArrayCodec arrayCodec,
final BytesCodec... codecs) {

this.dimensions = dimensions;
this.blockSize = blockSize;
this.dataType = dataType;

this(dimensions, blockSize, dataType, compression, N5Codecs.createDataBlockCodec(dataType, compression));
this.arrayCodec = arrayCodec == null ? defaultArrayCodec() : arrayCodec;
byteCodecs = Arrays.stream(codecs).filter(it -> !(it instanceof RawCompression)).toArray(BytesCodec[]::new);
dataBlockSerializer = this.arrayCodec.initialize(this, byteCodecs);
}

protected DatasetAttributes(
public DatasetAttributes(
final long[] dimensions,
final int[] blockSize,
final DataType dataType,
final Compression compression,
final DataBlockCodec<?> dataBlockCodec) {
final BytesCodec compression) {

this.dimensions = dimensions;
this.blockSize = blockSize;
this.dataType = dataType;
this.compression = compression;
this.dataBlockCodec = dataBlockCodec;
this(dimensions, blockSize, dataType, null, compression);
}

protected ArrayCodec defaultArrayCodec() {
return new N5ArrayCodec();
}

public long[] getDimensions() {
Expand All @@ -131,7 +118,11 @@ public int[] getBlockSize() {

public Compression getCompression() {

return compression;
return Arrays.stream(byteCodecs)
.filter(it -> it instanceof Compression)
.map(it -> (Compression)it)
.findFirst()
.orElse(new RawCompression());
}

public DataType getDataType() {
Expand All @@ -140,17 +131,18 @@ public DataType getDataType() {
}

/**
* Get the {@link DataBlockCodec} for this dataset.
* Get the {@link ArrayCodec} for this dataset.
*
* @param <T>
* the returned codec is cast to {@code DataBlockCodec<T>} for convenience
* (that is, the caller doesn't have to do the cast explicitly).
* @return the {@code DataBlockCodec} for this dataset
* @return the {@code ArrayCodec} for this dataset
*/
@SuppressWarnings("unchecked")
public <T> DataBlockCodec<T> getDataBlockCodec() {
public ArrayCodec getArrayCodec() {

return (DataBlockCodec<T>) dataBlockCodec;
return arrayCodec;
}

@SuppressWarnings("unchecked")
<T> DataBlockSerializer<T> getDataBlockSerializer() {
return (DataBlockSerializer<T>) dataBlockSerializer;
}

public HashMap<String, Object> asMap() {
Expand All @@ -159,7 +151,7 @@ public HashMap<String, Object> asMap() {
map.put(DIMENSIONS_KEY, dimensions);
map.put(BLOCK_SIZE_KEY, blockSize);
map.put(DATA_TYPE_KEY, dataType);
map.put(COMPRESSION_KEY, compression);
map.put(COMPRESSION_KEY, getCompression());
return map;
}

Expand Down
92 changes: 0 additions & 92 deletions src/main/java/org/janelia/saalfeldlab/n5/DefaultBlockReader.java

This file was deleted.

Loading