Skip to content

Commit 8dbc822

Browse files
authored
Merge pull request #157 from saalfeldlab/wip/codecs
Codecs and serialization
2 parents 3955cdf + e51f40a commit 8dbc822

29 files changed

Lines changed: 1158 additions & 479 deletions

src/main/java/org/janelia/saalfeldlab/n5/Bzip2Compression.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,22 @@
5454
package org.janelia.saalfeldlab.n5;
5555

5656
import java.io.IOException;
57-
import java.io.InputStream;
57+
5858
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
5959
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;
6060
import org.janelia.saalfeldlab.n5.Compression.CompressionType;
6161
import org.janelia.saalfeldlab.n5.N5Exception.N5IOException;
6262
import org.janelia.saalfeldlab.n5.readdata.ReadData;
63+
import org.janelia.saalfeldlab.n5.serialization.NameConfig;
6364

6465
@CompressionType("bzip2")
66+
@NameConfig.Name("bzip2")
6567
public class Bzip2Compression implements Compression {
6668

6769
private static final long serialVersionUID = -4873117458390529118L;
6870

6971
@CompressionParameter
72+
@NameConfig.Parameter
7073
private final int blockSize;
7174

7275
public Bzip2Compression(final int blockSize) {

src/main/java/org/janelia/saalfeldlab/n5/Compression.java

Lines changed: 13 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -53,24 +53,31 @@
5353
*/
5454
package org.janelia.saalfeldlab.n5;
5555

56-
import java.io.IOException;
5756
import java.io.Serializable;
5857
import java.lang.annotation.ElementType;
5958
import java.lang.annotation.Inherited;
6059
import java.lang.annotation.Retention;
6160
import java.lang.annotation.RetentionPolicy;
6261
import java.lang.annotation.Target;
6362

64-
import org.janelia.saalfeldlab.n5.N5Exception.N5IOException;
65-
import org.janelia.saalfeldlab.n5.readdata.ReadData;
63+
import org.janelia.saalfeldlab.n5.codec.BytesCodec;
64+
import org.janelia.saalfeldlab.n5.codec.Codec;
6665
import org.scijava.annotations.Indexable;
6766

6867
/**
69-
* Compression scheme interface.
68+
* This interface is used to indicate that a {@link BytesCodec} can be
69+
* serialized as a "compression" for the N5 format (using the N5 API).
70+
* <p>
71+
* N5Readers and N5Writers for the N5 format can declare BytesCodecs that
72+
* implement this interface so that the {@link CompressionAdapter} is used for
73+
* serialization.
74+
* <p>
75+
* See also: an alternative method for serializing general {@link Codec}s is
76+
* with the {@link NameConfigAdapter}.
7077
*
7178
* @author Stephan Saalfeld
7279
*/
73-
public interface Compression extends Serializable {
80+
public interface Compression extends Serializable, BytesCodec {
7481

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

104+
@Override
97105
default String getType() {
98106

99107
final CompressionType compressionType = getClass().getAnnotation(CompressionType.class);
@@ -102,41 +110,4 @@ default String getType() {
102110
else
103111
return compressionType.value();
104112
}
105-
106-
// --------------------------------------------------
107-
//
108-
109-
/**
110-
* Decode the given {@code readData}.
111-
* <p>
112-
* The returned decoded {@code ReadData} reports {@link ReadData#length()
113-
* length()}{@code == decodedLength}. Decoding may be lazy or eager,
114-
* depending on the {@code BytesCodec} implementation.
115-
*
116-
* @param readData
117-
* data to decode
118-
*
119-
* @return decoded ReadData
120-
*
121-
* @throws N5IOException
122-
* if any I/O error occurs
123-
*/
124-
ReadData decode(ReadData readData) throws N5IOException;
125-
126-
/**
127-
* Encode the given {@code readData}.
128-
* <p>
129-
* Encoding may be lazy or eager, depending on the {@code BytesCodec}
130-
* implementation.
131-
*
132-
* @param readData
133-
* data to encode
134-
*
135-
* @return encoded ReadData
136-
*
137-
* @throws N5IOException
138-
* if any I/O error occurs
139-
*/
140-
ReadData encode(ReadData readData) throws N5IOException;
141-
142113
}

src/main/java/org/janelia/saalfeldlab/n5/DatasetAttributes.java

Lines changed: 43 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,6 @@
66
* %%
77
* Redistribution and use in source and binary forms, with or without
88
* modification, are permitted provided that the following conditions are met:
9-
*
10-
* 1. Redistributions of source code must retain the above copyright notice,
11-
* this list of conditions and the following disclaimer.
12-
* 2. Redistributions in binary form must reproduce the above copyright notice,
13-
* this list of conditions and the following disclaimer in the documentation
14-
* and/or other materials provided with the distribution.
15-
*
16-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17-
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18-
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19-
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20-
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21-
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22-
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23-
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24-
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25-
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26-
* POSSIBILITY OF SUCH DAMAGE.
27-
* #L%
28-
*/
29-
/**
30-
* Copyright (c) 2017, Stephan Saalfeld
31-
* All rights reserved.
32-
*
33-
* Redistribution and use in source and binary forms, with or without
34-
* modification, are permitted provided that the following conditions are met:
359
*
3610
* 1. Redistributions of source code must retain the above copyright notice,
3711
* this list of conditions and the following disclaimer.
@@ -42,23 +16,27 @@
4216
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
4317
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4418
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45-
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
4620
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
4721
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
4822
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
4923
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
5024
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5125
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
5226
* POSSIBILITY OF SUCH DAMAGE.
27+
* #L%
5328
*/
5429
package org.janelia.saalfeldlab.n5;
5530

5631
import java.io.Serializable;
5732
import java.util.Arrays;
5833
import java.util.HashMap;
5934

60-
import org.janelia.saalfeldlab.n5.codec.DataBlockCodec;
61-
import org.janelia.saalfeldlab.n5.codec.N5Codecs;
35+
import org.janelia.saalfeldlab.n5.codec.Codec;
36+
import org.janelia.saalfeldlab.n5.codec.ArrayCodec;
37+
import org.janelia.saalfeldlab.n5.codec.BytesCodec;
38+
import org.janelia.saalfeldlab.n5.codec.DataBlockSerializer;
39+
import org.janelia.saalfeldlab.n5.codec.N5ArrayCodec;
6240

6341
/**
6442
* Mandatory dataset attributes:
@@ -88,30 +66,39 @@ public class DatasetAttributes implements Serializable {
8866
private final long[] dimensions;
8967
private final int[] blockSize;
9068
private final DataType dataType;
91-
private final DataBlockCodec<?> dataBlockCodec;
92-
private final Compression compression;
69+
70+
private final ArrayCodec arrayCodec;
71+
private final BytesCodec[] byteCodecs;
72+
73+
private final DataBlockSerializer<?> dataBlockSerializer;
9374

9475
public DatasetAttributes(
9576
final long[] dimensions,
9677
final int[] blockSize,
9778
final DataType dataType,
98-
final Compression compression) {
79+
final ArrayCodec arrayCodec,
80+
final BytesCodec... codecs) {
81+
82+
this.dimensions = dimensions;
83+
this.blockSize = blockSize;
84+
this.dataType = dataType;
9985

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

103-
protected DatasetAttributes(
91+
public DatasetAttributes(
10492
final long[] dimensions,
10593
final int[] blockSize,
10694
final DataType dataType,
107-
final Compression compression,
108-
final DataBlockCodec<?> dataBlockCodec) {
95+
final BytesCodec compression) {
10996

110-
this.dimensions = dimensions;
111-
this.blockSize = blockSize;
112-
this.dataType = dataType;
113-
this.compression = compression;
114-
this.dataBlockCodec = dataBlockCodec;
97+
this(dimensions, blockSize, dataType, null, compression);
98+
}
99+
100+
protected ArrayCodec defaultArrayCodec() {
101+
return new N5ArrayCodec();
115102
}
116103

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

132119
public Compression getCompression() {
133120

134-
return compression;
121+
return Arrays.stream(byteCodecs)
122+
.filter(it -> it instanceof Compression)
123+
.map(it -> (Compression)it)
124+
.findFirst()
125+
.orElse(new RawCompression());
135126
}
136127

137128
public DataType getDataType() {
@@ -140,17 +131,18 @@ public DataType getDataType() {
140131
}
141132

142133
/**
143-
* Get the {@link DataBlockCodec} for this dataset.
134+
* Get the {@link ArrayCodec} for this dataset.
144135
*
145-
* @param <T>
146-
* the returned codec is cast to {@code DataBlockCodec<T>} for convenience
147-
* (that is, the caller doesn't have to do the cast explicitly).
148-
* @return the {@code DataBlockCodec} for this dataset
136+
* @return the {@code ArrayCodec} for this dataset
149137
*/
150-
@SuppressWarnings("unchecked")
151-
public <T> DataBlockCodec<T> getDataBlockCodec() {
138+
public ArrayCodec getArrayCodec() {
152139

153-
return (DataBlockCodec<T>) dataBlockCodec;
140+
return arrayCodec;
141+
}
142+
143+
@SuppressWarnings("unchecked")
144+
<T> DataBlockSerializer<T> getDataBlockSerializer() {
145+
return (DataBlockSerializer<T>) dataBlockSerializer;
154146
}
155147

156148
public HashMap<String, Object> asMap() {
@@ -159,7 +151,7 @@ public HashMap<String, Object> asMap() {
159151
map.put(DIMENSIONS_KEY, dimensions);
160152
map.put(BLOCK_SIZE_KEY, blockSize);
161153
map.put(DATA_TYPE_KEY, dataType);
162-
map.put(COMPRESSION_KEY, compression);
154+
map.put(COMPRESSION_KEY, getCompression());
163155
return map;
164156
}
165157

src/main/java/org/janelia/saalfeldlab/n5/DefaultBlockReader.java

Lines changed: 0 additions & 92 deletions
This file was deleted.

0 commit comments

Comments
 (0)