Initial commit
This commit is contained in:
commit
378d929a00
36
ch.psi.imagej.cbf/.classpath
Normal file
36
ch.psi.imagej.cbf/.classpath
Normal file
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
1
ch.psi.imagej.cbf/.gitignore
vendored
Normal file
1
ch.psi.imagej.cbf/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target
|
23
ch.psi.imagej.cbf/.project
Normal file
23
ch.psi.imagej.cbf/.project
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>ch.psi.imagej.cbf</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
@ -0,0 +1,3 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding//src/main/java=UTF-8
|
||||
encoding//src/test/java=UTF-8
|
5
ch.psi.imagej.cbf/.settings/org.eclipse.jdt.core.prefs
Normal file
5
ch.psi.imagej.cbf/.settings/org.eclipse.jdt.core.prefs
Normal file
@ -0,0 +1,5 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
|
||||
org.eclipse.jdt.core.compiler.compliance=1.7
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.7
|
4
ch.psi.imagej.cbf/.settings/org.eclipse.m2e.core.prefs
Normal file
4
ch.psi.imagej.cbf/.settings/org.eclipse.m2e.core.prefs
Normal file
@ -0,0 +1,4 @@
|
||||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
6
ch.psi.imagej.cbf/Readme.md
Normal file
6
ch.psi.imagej.cbf/Readme.md
Normal file
@ -0,0 +1,6 @@
|
||||
Jcbf ([J]ava [C]rystallographic [B]inary [F]ile) is a pure Java library for
|
||||
reading and writing minimal CBF (miniCBF) image files using the MIME
|
||||
"mini-header" and the "none" or "byte_offset" compression algorithm, as
|
||||
produced by DECTRIS PILATUS detectors.
|
||||
|
||||
Written in March 2011 by J. Lewis Muir <jlmuir@imca.aps.anl.gov> (IMCA-CAT).
|
23
ch.psi.imagej.cbf/doc/developer.txt
Normal file
23
ch.psi.imagej.cbf/doc/developer.txt
Normal file
@ -0,0 +1,23 @@
|
||||
Code
|
||||
----
|
||||
* Follow style of existing code.
|
||||
* Max code line length: 100 characters.
|
||||
* Max comment line length: 76 characters.
|
||||
|
||||
Retrieve Library Dependencies
|
||||
-----------------------------
|
||||
* Required for compiling from source. Requires network connection. Only
|
||||
needs to be performed once, or after running the distclean target:
|
||||
$ ant fetch
|
||||
|
||||
Release
|
||||
-------
|
||||
* Change version property in build.properties.
|
||||
* Compile to update source with new version ID:
|
||||
$ ant compile
|
||||
* Check in any changes to version control system.
|
||||
* Run test cases:
|
||||
$ ant clean test
|
||||
* Make distribution (dist-bin for binary distribution):
|
||||
$ ant clean dist-src
|
||||
* Tag version in version control system.
|
48
ch.psi.imagej.cbf/pom.xml
Normal file
48
ch.psi.imagej.cbf/pom.xml
Normal file
@ -0,0 +1,48 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>ch.psi.imagej</groupId>
|
||||
<artifactId>ch.psi.imagej.cbf</artifactId>
|
||||
<version>0.0.1</version>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>gov.nih.imagej</groupId>
|
||||
<artifactId>imagej</artifactId>
|
||||
<version>1.46</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.3.2</version>
|
||||
<configuration>
|
||||
<encoding>UTF-8</encoding>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<configuration>
|
||||
<finalName>CBF_Viewer-${pom.version}</finalName>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
<archive />
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
100
ch.psi.imagej.cbf/src/main/java/imcacat/jcbf/Base64.java
Normal file
100
ch.psi.imagej.cbf/src/main/java/imcacat/jcbf/Base64.java
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* I am a base 64 codec implementing the "base64" encoding in RFC 4648. I do
|
||||
* not add line feeds to the encoded data.
|
||||
*/
|
||||
public class Base64 {
|
||||
private static final String ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
+ "abcdefghijklmnopqrstuvwxyz"
|
||||
+ "0123456789"
|
||||
+ "+/";
|
||||
private static final char PAD = '=';
|
||||
|
||||
public static String encode(byte[] value) {
|
||||
StringBuffer result = new StringBuffer(encodedSize(value));
|
||||
for (int i = 0; i < value.length; i += 3) {
|
||||
int octet1 = value[i] & 0xFF;
|
||||
int octet2 = (i + 1 < value.length) ? value[i + 1] & 0xFF : 0;
|
||||
int octet3 = (i + 2 < value.length) ? value[i + 2] & 0xFF : 0;
|
||||
int group = (octet1 << 16) | (octet2 << 8) | octet3;
|
||||
int sextetBitmask = 0x3F;
|
||||
int sextet1 = (group >> 18) & sextetBitmask;
|
||||
int sextet2 = (group >> 12) & sextetBitmask;
|
||||
int sextet3 = (group >> 6) & sextetBitmask;
|
||||
int sextet4 = group & sextetBitmask;
|
||||
result.append(encode(sextet1));
|
||||
result.append(encode(sextet2));
|
||||
result.append((i + 1 < value.length) ? encode(sextet3) : PAD);
|
||||
result.append((i + 2 < value.length) ? encode(sextet4) : PAD);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private static int encodedSize(byte[] value) {
|
||||
if ((value.length % 3) == 0) return value.length * 4 / 3;
|
||||
if ((value.length % 3) == 1) return (value.length + 2) * 4 / 3;
|
||||
return (value.length + 1) * 4 / 3;
|
||||
}
|
||||
|
||||
private static char encode(int sextet) {
|
||||
return ALPHABET.charAt(sextet);
|
||||
}
|
||||
|
||||
public static byte[] decode(String encoded) {
|
||||
ByteBuffer result = ByteBuffer.wrap(new byte[decodedSize(encoded)]);
|
||||
for (int i = 0; i < encoded.length(); i += 4) {
|
||||
boolean atEnd = i + 4 >= encoded.length();
|
||||
int sextet1 = decode(encoded.charAt(i));
|
||||
int sextet2 = decode(encoded.charAt(i + 1));
|
||||
int sextet3 = (atEnd && encoded.charAt(i + 2) == PAD) ? 0 : decode(encoded.charAt(i + 2));
|
||||
int sextet4 = (atEnd && encoded.charAt(i + 3) == PAD) ? 0 : decode(encoded.charAt(i + 3));
|
||||
int group = (sextet1 << 18) | (sextet2 << 12) | (sextet3 << 6) | sextet4;
|
||||
int octetBitmask = 0xFF;
|
||||
byte octet1 = (byte)((group >> 16) & octetBitmask);
|
||||
byte octet2 = (byte)((group >> 8) & octetBitmask);
|
||||
byte octet3 = (byte)(group & octetBitmask);
|
||||
result.put(octet1);
|
||||
if (!atEnd || encoded.charAt(i + 2) != PAD) result.put(octet2);
|
||||
if (!atEnd || encoded.charAt(i + 3) != PAD) result.put(octet3);
|
||||
}
|
||||
return result.array();
|
||||
}
|
||||
|
||||
private static int decodedSize(String encoded) {
|
||||
if ((encoded.length() % 4) != 0) {
|
||||
throw new IllegalArgumentException("Encoded string has invalid length");
|
||||
}
|
||||
String pad = String.valueOf(PAD);
|
||||
if (encoded.endsWith(pad + pad)) return (encoded.length() * 3 / 4) - 2;
|
||||
if (encoded.endsWith(pad)) return (encoded.length() * 3 / 4) - 1;
|
||||
return encoded.length() * 3 / 4;
|
||||
}
|
||||
|
||||
private static int decode(char encodedSextet) {
|
||||
if (encodedSextet >= 'A' && encodedSextet <= 'Z') return encodedSextet - 'A';
|
||||
if (encodedSextet >= 'a' && encodedSextet <= 'z') return encodedSextet - 'a' + 26;
|
||||
if (encodedSextet >= '0' && encodedSextet <= '9') return encodedSextet - '0' + 52;
|
||||
if (encodedSextet == '+') return 62;
|
||||
if (encodedSextet == '/') return 63;
|
||||
throw new IllegalArgumentException("Letter not in alphabet: '" + encodedSextet + "'");
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
/**
|
||||
* I am a <code>CbfData</code> backed by an array of bytes.
|
||||
*/
|
||||
public class ByteArrayCbfData implements CbfData {
|
||||
ByteBuffer data;
|
||||
|
||||
public ByteArrayCbfData(byte[] data) {
|
||||
this.data = ByteBuffer.wrap(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void order(ByteOrder bo) {
|
||||
data.order(bo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte() {
|
||||
return data.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getUbyte() {
|
||||
return (short)(data.get() & 0xFFFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort() {
|
||||
return data.getShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUshort() {
|
||||
return data.getShort() & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt() {
|
||||
return data.getInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getUint() {
|
||||
return data.getInt() & 0xFFFFFFFFL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong() {
|
||||
return data.getLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat() {
|
||||
return data.getFloat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble() {
|
||||
return data.getDouble();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skipBytes(int count) {
|
||||
data.position(data.position() + count);
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* I am the type of compression used to compress the data of a CBF image.
|
||||
*/
|
||||
public enum CbfCompression {
|
||||
/* @formatter:off */
|
||||
NONE( "x-CBF_NONE"),
|
||||
BYTE_OFFSET("x-CBF_BYTE_OFFSET");
|
||||
/* @formatter:on */
|
||||
|
||||
private String contentTypeConversions;
|
||||
|
||||
CbfCompression(String contentTypeConversions) {
|
||||
this.contentTypeConversions = contentTypeConversions;
|
||||
}
|
||||
|
||||
public boolean compatibleWith(CbfElementType type) {
|
||||
if (equals(NONE)) return true;
|
||||
return !CbfElementType.SIGNED_32_BIT_REAL_IEEE.equals(type)
|
||||
&& !CbfElementType.SIGNED_64_BIT_REAL_IEEE.equals(type);
|
||||
}
|
||||
|
||||
public String toContentTypeConversions() {
|
||||
return contentTypeConversions;
|
||||
}
|
||||
|
||||
public static CbfCompression parse(String contentTypeConversions) throws ParseException {
|
||||
String trimmed = contentTypeConversions.trim();
|
||||
for (CbfCompression each : values())
|
||||
if (each.toContentTypeConversions().equals(trimmed)) return each;
|
||||
throw new ParseException("Unsupported conversions: " + trimmed, 0);
|
||||
}
|
||||
}
|
47
ch.psi.imagej.cbf/src/main/java/imcacat/jcbf/CbfData.java
Normal file
47
ch.psi.imagej.cbf/src/main/java/imcacat/jcbf/CbfData.java
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
/**
|
||||
* I am an interface for reading CBF image data.
|
||||
*/
|
||||
public interface CbfData {
|
||||
void order(ByteOrder bo);
|
||||
|
||||
byte getByte() throws IOException;
|
||||
|
||||
short getUbyte() throws IOException;
|
||||
|
||||
short getShort() throws IOException;
|
||||
|
||||
int getUshort() throws IOException;
|
||||
|
||||
int getInt() throws IOException;
|
||||
|
||||
long getUint() throws IOException;
|
||||
|
||||
long getLong() throws IOException;
|
||||
|
||||
float getFloat() throws IOException;
|
||||
|
||||
double getDouble() throws IOException;
|
||||
|
||||
void skipBytes(int count) throws IOException;
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.text.ParseException;
|
||||
|
||||
/**
|
||||
* I am the type of an element in the data of a CBF image.
|
||||
*/
|
||||
public enum CbfElementType {
|
||||
/* @formatter:off */
|
||||
UNSIGNED_8_BIT_INTEGER( "unsigned 8-bit integer", false),
|
||||
SIGNED_8_BIT_INTEGER( "signed 8-bit integer", true),
|
||||
UNSIGNED_16_BIT_INTEGER("unsigned 16-bit integer", false),
|
||||
SIGNED_16_BIT_INTEGER( "signed 16-bit integer", true),
|
||||
UNSIGNED_32_BIT_INTEGER("unsigned 32-bit integer", false),
|
||||
SIGNED_32_BIT_INTEGER( "signed 32-bit integer", true),
|
||||
SIGNED_32_BIT_REAL_IEEE("signed 32-bit real IEEE", true),
|
||||
SIGNED_64_BIT_REAL_IEEE("signed 64-bit real IEEE", true);
|
||||
/* @formatter:on */
|
||||
|
||||
private String xBinaryElementType;
|
||||
private boolean signed;
|
||||
|
||||
CbfElementType(String xBinaryElementType, boolean signed) {
|
||||
this.xBinaryElementType = xBinaryElementType;
|
||||
this.signed = signed;
|
||||
}
|
||||
|
||||
public String toXBinaryElementType() {
|
||||
return xBinaryElementType;
|
||||
}
|
||||
|
||||
public boolean isSigned() {
|
||||
return signed;
|
||||
}
|
||||
|
||||
public static CbfElementType parse(String xBinaryElementType) throws ParseException {
|
||||
String trimmed = xBinaryElementType.trim();
|
||||
for (CbfElementType each : values())
|
||||
if (each.toXBinaryElementType().equals(trimmed)) return each;
|
||||
throw new ParseException("Unsupported type: " + trimmed, 0);
|
||||
}
|
||||
|
||||
public static CbfElementType fromDataBufferType(int dataBufferType) {
|
||||
switch (dataBufferType) {
|
||||
case DataBuffer.TYPE_BYTE:
|
||||
return UNSIGNED_8_BIT_INTEGER;
|
||||
case DataBuffer.TYPE_USHORT:
|
||||
return UNSIGNED_16_BIT_INTEGER;
|
||||
case DataBuffer.TYPE_SHORT:
|
||||
return SIGNED_16_BIT_INTEGER;
|
||||
case DataBuffer.TYPE_INT:
|
||||
return SIGNED_32_BIT_INTEGER;
|
||||
case DataBuffer.TYPE_FLOAT:
|
||||
return SIGNED_32_BIT_REAL_IEEE;
|
||||
case DataBuffer.TYPE_DOUBLE:
|
||||
return SIGNED_64_BIT_REAL_IEEE;
|
||||
default:
|
||||
return SIGNED_32_BIT_INTEGER;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import javax.imageio.ImageReadParam;
|
||||
|
||||
/**
|
||||
* I am an <code>ImageReadParam</code> for <code>CbfImageReader</code>.
|
||||
*/
|
||||
public class CbfImageReadParam extends ImageReadParam {
|
||||
private boolean minimizeMemoryUse = false;
|
||||
|
||||
@Override
|
||||
public boolean canSetSourceRenderSize() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether memory use during an image read should be minimized.
|
||||
*
|
||||
* @return <code>true</code> if memory use should be minimized;
|
||||
* <code>false</code> otherwise
|
||||
*
|
||||
* @see #setMinimizeMemoryUse(boolean)
|
||||
*/
|
||||
public boolean shouldMinimizeMemoryUse() {
|
||||
return minimizeMemoryUse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether memory use during an image read should be minimized.
|
||||
* Minimizing memory use will likely increase processor use and execution
|
||||
* time. However, if dealing with very large images or a system with very
|
||||
* little memory, this may be appropriate. The default is
|
||||
* <code>false</code>.
|
||||
*
|
||||
* @param minimizeMemoryUse whether memory use should be memorized
|
||||
*/
|
||||
public void setMinimizeMemoryUse(boolean minimizeMemoryUse) {
|
||||
this.minimizeMemoryUse = minimizeMemoryUse;
|
||||
}
|
||||
}
|
1386
ch.psi.imagej.cbf/src/main/java/imcacat/jcbf/CbfImageReader.java
Normal file
1386
ch.psi.imagej.cbf/src/main/java/imcacat/jcbf/CbfImageReader.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
|
||||
/**
|
||||
* I am a reader SPI for CBF images.
|
||||
*/
|
||||
public class CbfImageReaderSpi extends ImageReaderSpi {
|
||||
private static final String VENDOR_NAME = "IMCA-CAT";
|
||||
private static final String VERSION = Version.ID;
|
||||
private static final String[] FORMAT_NAMES = { "cbf", "CBF" };
|
||||
private static final String[] FORMAT_SUFFIXES = { "cbf" };
|
||||
private static final String[] MIME_TYPES = { "image/x-cbf" };
|
||||
private static final String READER_CLASS_NAME = "imcacat.jcbf.CbfImageReader";
|
||||
private static final String[] WRITER_SPI_CLASS_NAMES = { "imcacat.jcbf.CbfImageWriterSpi" };
|
||||
private static final String METADATA_FORMAT_NAME = "imcacat.jcbf.CbfMetadataFormat_1.0";
|
||||
private static final String METADATA_FORMAT_CLASS_NAME = "imcacat.jcbf.CbfMetadataFormat";
|
||||
|
||||
public CbfImageReaderSpi() {
|
||||
super(VENDOR_NAME, VERSION, FORMAT_NAMES, FORMAT_SUFFIXES, MIME_TYPES, READER_CLASS_NAME,
|
||||
STANDARD_INPUT_TYPE, WRITER_SPI_CLASS_NAMES, false, null, null, null, null, false,
|
||||
METADATA_FORMAT_NAME, METADATA_FORMAT_CLASS_NAME, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDecodeInput(Object source) throws IOException {
|
||||
if (!(source instanceof ImageInputStream)) return false;
|
||||
ImageInputStream stream = (ImageInputStream)source;
|
||||
String magicNumber = "###CBF: VERSION";
|
||||
byte[] expected = magicNumber.getBytes("US-ASCII");
|
||||
byte[] actual = new byte[expected.length];
|
||||
stream.mark();
|
||||
try {
|
||||
stream.readFully(actual);
|
||||
return Arrays.equals(expected, actual);
|
||||
} catch (EOFException e) {
|
||||
return false;
|
||||
} finally {
|
||||
stream.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageReader createReaderInstance(Object extension) throws IOException {
|
||||
return new CbfImageReader(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription(Locale locale) {
|
||||
return "CBF image reader";
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import javax.imageio.ImageWriteParam;
|
||||
|
||||
/**
|
||||
* I am an <code>ImageWriteParam</code> for <code>CbfImageWriter</code>.
|
||||
*/
|
||||
public class CbfImageWriteParam extends ImageWriteParam {
|
||||
public static final String COMPRESSION_NONE = "None";
|
||||
public static final String COMPRESSION_BYTE_OFFSET = "Byte_offset";
|
||||
|
||||
public CbfImageWriteParam() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWriteTiles() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canOffsetTiles() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWriteProgressive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWriteCompressed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getCompressionTypes() {
|
||||
return new String[] { COMPRESSION_NONE, COMPRESSION_BYTE_OFFSET };
|
||||
}
|
||||
}
|
773
ch.psi.imagej.cbf/src/main/java/imcacat/jcbf/CbfImageWriter.java
Normal file
773
ch.psi.imagej.cbf/src/main/java/imcacat/jcbf/CbfImageWriter.java
Normal file
@ -0,0 +1,773 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.IIOImage;
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.ImageWriteParam;
|
||||
import javax.imageio.ImageWriter;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.spi.ImageWriterSpi;
|
||||
import javax.imageio.stream.IIOByteBuffer;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
|
||||
/**
|
||||
* I write a minimal CBF (miniCBF) image like that produced by DECTRIS
|
||||
* PILATUS detectors. I only write images using the MIME mini-header and the
|
||||
* "none" or "byte_offset" compression algorithms. I do not support the
|
||||
* "unsigned 1-bit integer" and "signed 32-bit complex IEEE" data element
|
||||
* types.
|
||||
*/
|
||||
public class CbfImageWriter extends ImageWriter {
|
||||
public CbfImageWriter(ImageWriterSpi originatingProvider) {
|
||||
super(originatingProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IIOMetadata getDefaultStreamMetadata(ImageWriteParam param) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IIOMetadata getDefaultImageMetadata(ImageTypeSpecifier imageType, ImageWriteParam param) {
|
||||
CbfMetadata mdata = new CbfMetadata();
|
||||
|
||||
int bufferedImageType = imageType.getBufferedImageType();
|
||||
int dataBufferType = imageType.getSampleModel().getDataType();
|
||||
if (bufferedImageType == BufferedImage.TYPE_BYTE_BINARY) {
|
||||
mdata.setDataElementType(CbfElementType.UNSIGNED_8_BIT_INTEGER);
|
||||
} else if (bufferedImageType == BufferedImage.TYPE_BYTE_GRAY) {
|
||||
mdata.setDataElementType(CbfElementType.UNSIGNED_8_BIT_INTEGER);
|
||||
} else if (bufferedImageType == BufferedImage.TYPE_USHORT_GRAY) {
|
||||
mdata.setDataElementType(CbfElementType.UNSIGNED_16_BIT_INTEGER);
|
||||
} else if (dataBufferType == DataBuffer.TYPE_BYTE) {
|
||||
mdata.setDataElementType(CbfElementType.UNSIGNED_8_BIT_INTEGER);
|
||||
} else if (dataBufferType == DataBuffer.TYPE_SHORT) {
|
||||
mdata.setDataElementType(CbfElementType.SIGNED_16_BIT_INTEGER);
|
||||
} else if (dataBufferType == DataBuffer.TYPE_FLOAT) {
|
||||
mdata.setDataElementType(CbfElementType.SIGNED_32_BIT_REAL_IEEE);
|
||||
} else if (dataBufferType == DataBuffer.TYPE_INT) {
|
||||
mdata.setDataElementType(CbfElementType.SIGNED_32_BIT_INTEGER);
|
||||
} else if (dataBufferType == DataBuffer.TYPE_DOUBLE) {
|
||||
mdata.setDataElementType(CbfElementType.SIGNED_64_BIT_REAL_IEEE);
|
||||
}
|
||||
|
||||
int compressionMode = param.getCompressionMode();
|
||||
if (compressionMode == ImageWriteParam.MODE_DISABLED) {
|
||||
mdata.setDataCompression(CbfCompression.NONE);
|
||||
} else if (compressionMode == ImageWriteParam.MODE_EXPLICIT) {
|
||||
if (param.getCompressionType().equals(CbfImageWriteParam.COMPRESSION_BYTE_OFFSET)) {
|
||||
mdata.setDataCompression(CbfCompression.BYTE_OFFSET);
|
||||
} else if (param.getCompressionType().equals(CbfImageWriteParam.COMPRESSION_NONE)) {
|
||||
mdata.setDataCompression(CbfCompression.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
return mdata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageWriteParam getDefaultWriteParam() {
|
||||
return new CbfImageWriteParam();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IIOMetadata convertStreamMetadata(IIOMetadata inData, ImageWriteParam param) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IIOMetadata convertImageMetadata(IIOMetadata inData, ImageTypeSpecifier imageType,
|
||||
ImageWriteParam param) {
|
||||
return (inData instanceof CbfMetadata) ? inData : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(IIOMetadata streamMetadata, IIOImage image, ImageWriteParam iwparam)
|
||||
throws IOException {
|
||||
clearAbortRequest();
|
||||
processImageStarted(0);
|
||||
|
||||
RenderedImage srcImage = image.getRenderedImage();
|
||||
ImageWriteParam param = (iwparam == null) ? getDefaultWriteParam() : iwparam;
|
||||
|
||||
CbfMetadata mdata = null;
|
||||
IIOMetadata srcMetadata = image.getMetadata();
|
||||
if (srcMetadata != null) {
|
||||
mdata =
|
||||
(CbfMetadata)convertImageMetadata(srcMetadata,
|
||||
ImageTypeSpecifier.createFromRenderedImage(srcImage), param);
|
||||
}
|
||||
if (mdata == null) mdata =
|
||||
(CbfMetadata)getDefaultImageMetadata(ImageTypeSpecifier.createFromRenderedImage(srcImage),
|
||||
param);
|
||||
|
||||
IIOByteBuffer encodedImage = encode(image, mdata, param);
|
||||
if (encodedImage == null) return;
|
||||
|
||||
if (abortRequested()) {
|
||||
processWriteAborted();
|
||||
return;
|
||||
}
|
||||
|
||||
ImageOutputStream stream = getNonNullOutput();
|
||||
|
||||
stream.writeBytes(mdata.getIdentifier() + "\r\n");
|
||||
stream.writeBytes("\r\n");
|
||||
stream.writeBytes("data_" + mdata.getDataBlockName() + "\r\n");
|
||||
stream.writeBytes("\r\n");
|
||||
stream.writeBytes("_array_data.header_convention \"" + mdata.getHeaderConvention() + "\"\r\n");
|
||||
stream.writeBytes("_array_data.header_contents\r\n");
|
||||
stream.writeBytes(";\r\n");
|
||||
if (mdata.getHeaderDetector() != null) {
|
||||
stream.writeBytes("# Detector: ");
|
||||
stream.writeBytes(mdata.getHeaderDetector());
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderDate() != null) {
|
||||
stream.writeBytes("# ");
|
||||
DateFormat format = new SimpleDateFormat("yyyy-MMM-dd'T'HH:mm:ss.SSS", Locale.US);
|
||||
stream.writeBytes(format.format(mdata.getHeaderDate()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderPixelSize() != null) {
|
||||
stream.writeBytes("# Pixel_size ");
|
||||
float[] size = mdata.getHeaderPixelSize();
|
||||
size[0] *= 1e6f;
|
||||
size[1] *= 1e6f;
|
||||
stream.writeBytes(String.format(Locale.US, "%.0fe-6 m x %.0fe-6 m", size[0], size[1]));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderSensorType() != null && mdata.getHeaderSensorThickness() != null) {
|
||||
stream.writeBytes("# ");
|
||||
stream.writeBytes(mdata.getHeaderSensorType());
|
||||
stream.writeBytes(" sensor, thickness ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.6f m", mdata.getHeaderSensorThickness()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderExposureTime() != null) {
|
||||
stream.writeBytes("# Exposure_time ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.6f s", mdata.getHeaderExposureTime()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderExposurePeriod() != null) {
|
||||
stream.writeBytes("# Exposure_period ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.6f s", mdata.getHeaderExposurePeriod()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderTau() != null) {
|
||||
stream.writeBytes("# Tau = ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.1fe-09 s", 1e9f * mdata.getHeaderTau()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderCountCutoff() != null) {
|
||||
stream.writeBytes("# Count_cutoff ");
|
||||
stream.writeBytes(String.format(Locale.US, "%d counts", mdata.getHeaderCountCutoff()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderThreshold() != null) {
|
||||
stream.writeBytes("# Threshold_setting ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.0f eV", mdata.getHeaderThreshold()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderGainVrf() != null) {
|
||||
stream.writeBytes("# Gain_setting ");
|
||||
String type = mdata.getHeaderGainType();
|
||||
stream.writeBytes((type == null) ? "not implemented" : type);
|
||||
stream.writeBytes(String.format(Locale.US, " (vrf = %.3f)", mdata.getHeaderGainVrf()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderNumExcludedPixels() != null) {
|
||||
stream.writeBytes("# N_excluded_pixels = ");
|
||||
stream.writeBytes(String.format(Locale.US, "%d", mdata.getHeaderNumExcludedPixels()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderExcludedPixels() != null) {
|
||||
stream.writeBytes("# Excluded_pixels: ");
|
||||
stream.writeBytes(mdata.getHeaderExcludedPixels());
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderFlatField() != null) {
|
||||
stream.writeBytes("# Flat_field: ");
|
||||
stream.writeBytes(mdata.getHeaderFlatField());
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderTrim() != null) {
|
||||
stream.writeBytes("# Trim_directory: ");
|
||||
stream.writeBytes(mdata.getHeaderTrim());
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderWavelength() != null) {
|
||||
stream.writeBytes("# Wavelength ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.4f A", mdata.getHeaderWavelength()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderEnergyRange() != null) {
|
||||
stream.writeBytes("# Energy_range ");
|
||||
float[] range = mdata.getHeaderEnergyRange();
|
||||
stream.writeBytes(String.format(Locale.US, "(%.0f, %.0f) eV", range[0], range[1]));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderDetectorDistance() != null) {
|
||||
stream.writeBytes("# Detector_distance ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.5f m", mdata.getHeaderDetectorDistance()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderDetectorVOffset() != null) {
|
||||
stream.writeBytes("# Detector_Voffset ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.5f m", mdata.getHeaderDetectorVOffset()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderBeamXY() != null) {
|
||||
stream.writeBytes("# Beam_xy ");
|
||||
float[] beam = mdata.getHeaderBeamXY();
|
||||
stream.writeBytes(String.format(Locale.US, "(%.2f, %.2f) pixels", beam[0], beam[1]));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderFlux() != null) {
|
||||
stream.writeBytes("# Flux ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.4f ph/s", mdata.getHeaderFlux()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderFilterTransmission() != null) {
|
||||
stream.writeBytes("# Filter_transmission ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.4f", mdata.getHeaderFilterTransmission()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderStartAngle() != null) {
|
||||
stream.writeBytes("# Start_angle ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.4f deg.", mdata.getHeaderStartAngle()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderAngleIncrement() != null) {
|
||||
stream.writeBytes("# Angle_increment ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.4f deg.", mdata.getHeaderAngleIncrement()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderDetector2Theta() != null) {
|
||||
stream.writeBytes("# Detector_2theta ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.4f deg.", mdata.getHeaderDetector2Theta()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderPolarization() != null) {
|
||||
stream.writeBytes("# Polarization ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.3f", mdata.getHeaderPolarization()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderAlpha() != null) {
|
||||
stream.writeBytes("# Alpha ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.4f deg.", mdata.getHeaderAlpha()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderKappa() != null) {
|
||||
stream.writeBytes("# Kappa ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.4f deg.", mdata.getHeaderKappa()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderPhi() != null) {
|
||||
stream.writeBytes("# Phi ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.4f deg.", mdata.getHeaderPhi()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderChi() != null) {
|
||||
stream.writeBytes("# Chi ");
|
||||
stream.writeBytes(String.format(Locale.US, "%.4f deg.", mdata.getHeaderChi()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderOscillationAxis() != null) {
|
||||
stream.writeBytes("# Oscillation_axis ");
|
||||
stream.writeBytes(mdata.getHeaderOscillationAxis());
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderNumOscillations() != null) {
|
||||
stream.writeBytes("# N_oscillations ");
|
||||
stream.writeBytes(String.format(Locale.US, "%d", mdata.getHeaderNumOscillations()));
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
if (mdata.getHeaderComment() != null) {
|
||||
stream.writeBytes("# Comment: ");
|
||||
stream.writeBytes(mdata.getHeaderComment());
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
for (String each : mdata.getHeaderUnrecognizedLines()) {
|
||||
stream.writeBytes(each);
|
||||
stream.writeBytes("\r\n");
|
||||
}
|
||||
stream.writeBytes(";\r\n");
|
||||
stream.writeBytes("\r\n");
|
||||
|
||||
stream.writeBytes("_array_data.data\r\n");
|
||||
stream.writeBytes(";\r\n");
|
||||
|
||||
stream.writeBytes("--CIF-BINARY-FORMAT-SECTION--\r\n");
|
||||
stream.writeBytes("Content-Type: application/octet-stream;\r\n");
|
||||
stream.writeBytes(" conversions=\"");
|
||||
stream.writeBytes(mdata.getDataCompression().toContentTypeConversions());
|
||||
stream.writeBytes("\"\r\n");
|
||||
stream.writeBytes("Content-Transfer-Encoding: BINARY\r\n");
|
||||
stream.writeBytes("X-Binary-Size: ");
|
||||
stream.writeBytes(String.format(Locale.US, "%d", mdata.getDataSize()));
|
||||
stream.writeBytes("\r\n");
|
||||
stream.writeBytes("X-Binary-ID: ");
|
||||
stream.writeBytes(String.format(Locale.US, "%d", mdata.getDataId()));
|
||||
stream.writeBytes("\r\n");
|
||||
stream.writeBytes("X-Binary-Element-Type: \"");
|
||||
stream.writeBytes(mdata.getDataElementType().toXBinaryElementType());
|
||||
stream.writeBytes("\"\r\n");
|
||||
stream.writeBytes("X-Binary-Element-Byte-Order: ");
|
||||
stream.writeBytes(ByteOrder.LITTLE_ENDIAN.equals(mdata.getDataElementByteOrder())
|
||||
? "LITTLE_ENDIAN" : "BIG_ENDIAN");
|
||||
stream.writeBytes("\r\n");
|
||||
stream.writeBytes("Content-MD5: ");
|
||||
stream.writeBytes(Base64.encode(mdata.getDataMd5()));
|
||||
stream.writeBytes("\r\n");
|
||||
stream.writeBytes("X-Binary-Number-of-Elements: ");
|
||||
stream.writeBytes(String.format(Locale.US, "%d", mdata.getDataNumElements()));
|
||||
stream.writeBytes("\r\n");
|
||||
stream.writeBytes("X-Binary-Size-Fastest-Dimension: ");
|
||||
stream.writeBytes(String.format(Locale.US, "%d", mdata.getDataWidth()));
|
||||
stream.writeBytes("\r\n");
|
||||
stream.writeBytes("X-Binary-Size-Second-Dimension: ");
|
||||
stream.writeBytes(String.format(Locale.US, "%d", mdata.getDataHeight()));
|
||||
stream.writeBytes("\r\n");
|
||||
stream.writeBytes("X-Binary-Size-Padding: ");
|
||||
stream.writeBytes(String.format(Locale.US, "%d", mdata.getDataPadding()));
|
||||
stream.writeBytes("\r\n");
|
||||
stream.writeBytes("\r\n");
|
||||
stream.write(new byte[] { 0x0C, 0x1A, 0x04, (byte)0xD5 });
|
||||
stream.write(encodedImage.getData(), 0, encodedImage.getLength());
|
||||
stream.write(new byte[mdata.getDataPadding()]);
|
||||
stream.writeBytes("\r\n");
|
||||
stream.writeBytes("--CIF-BINARY-FORMAT-SECTION----\r\n");
|
||||
stream.writeBytes(";\r\n");
|
||||
stream.writeBytes("\r\n");
|
||||
stream.flush();
|
||||
|
||||
processImageComplete();
|
||||
}
|
||||
|
||||
/*
|
||||
* Ignores IIOMetadata of specified IIOImage; instead uses specified
|
||||
* CbfMetadata. Specified ImageWriteParam takes precedence over specified
|
||||
* CbfMetadata. Specified CbfMetadata will be modified as needed to match
|
||||
* the encoding.
|
||||
*/
|
||||
private IIOByteBuffer encode(IIOImage iimage, CbfMetadata mdata, ImageWriteParam param)
|
||||
throws IIOException {
|
||||
RenderedImage rimage = iimage.getRenderedImage();
|
||||
|
||||
int dataBufferType = rimage.getSampleModel().getDataType();
|
||||
CbfElementType elementType = mdata.getDataElementType();
|
||||
if (elementType == null) {
|
||||
elementType = CbfElementType.fromDataBufferType(dataBufferType);
|
||||
mdata.setDataElementType(elementType);
|
||||
}
|
||||
|
||||
CbfCompression compression = mdata.getDataCompression();
|
||||
if (compression == null) compression = CbfCompression.BYTE_OFFSET;
|
||||
if (param.getCompressionMode() == ImageWriteParam.MODE_DEFAULT) {
|
||||
compression = CbfCompression.BYTE_OFFSET;
|
||||
} else if (param.getCompressionMode() == ImageWriteParam.MODE_DISABLED) {
|
||||
compression = CbfCompression.NONE;
|
||||
} else if (param.getCompressionMode() == ImageWriteParam.MODE_EXPLICIT) {
|
||||
if (CbfImageWriteParam.COMPRESSION_BYTE_OFFSET.equals(param.getCompressionType())) {
|
||||
compression = CbfCompression.BYTE_OFFSET;
|
||||
} else {
|
||||
compression = CbfCompression.NONE;
|
||||
}
|
||||
}
|
||||
if (!compression.compatibleWith(elementType)) compression = CbfCompression.NONE;
|
||||
|
||||
if (CbfCompression.BYTE_OFFSET.equals(compression)) {
|
||||
return encodeByteOffset(rimage, dataBufferType, mdata, param);
|
||||
} else if (CbfCompression.NONE.equals(compression)) {
|
||||
return encodeNone(rimage, dataBufferType, mdata, param);
|
||||
} else {
|
||||
throw new RuntimeException("Bug; compression: " + compression);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Specified CbfMetadata indicates the type of data that should be
|
||||
* encoded. Only encodes to integer (non-floating point) data. Only
|
||||
* encodes integer (non-floating point) source data with the exception of
|
||||
* image data of type float which may be used as a signed or unsigned
|
||||
* 32-bit integer representation in which case the values must fit in a
|
||||
* signed or unsigned 32-bit integer, respectively, and the deltas must
|
||||
* fit within a 64-bit signed integer.
|
||||
*/
|
||||
private IIOByteBuffer encodeByteOffset(RenderedImage image, int dataBufferType,
|
||||
CbfMetadata mdata, ImageWriteParam param) {
|
||||
Rectangle srcBounds = new Rectangle(image.getWidth(), image.getHeight());
|
||||
Rectangle srcRegion = param.getSourceRegion();
|
||||
srcRegion = (srcRegion == null) ? srcBounds : srcRegion.intersection(srcBounds);
|
||||
int srcXSubsampOffset = param.getSubsamplingXOffset();
|
||||
int srcYSubsampOffset = param.getSubsamplingYOffset();
|
||||
srcRegion.translate(srcXSubsampOffset, srcYSubsampOffset);
|
||||
srcRegion.setSize(srcRegion.width - srcXSubsampOffset, srcRegion.height - srcYSubsampOffset);
|
||||
int srcRegionMaxY = srcRegion.y + srcRegion.height - 1;
|
||||
Raster srcRaster = image.getData(srcRegion);
|
||||
|
||||
int srcXSubsamp = param.getSourceXSubsampling();
|
||||
int srcYSubsamp = param.getSourceYSubsampling();
|
||||
int srcWidth = srcRaster.getWidth();
|
||||
int srcHeight = srcRaster.getHeight();
|
||||
int srcMaxX = srcRaster.getMinX() + srcWidth - 1;
|
||||
int srcMaxY = srcRaster.getMinY() + srcHeight - 1;
|
||||
int[] srcBands = param.getSourceBands();
|
||||
int srcBand = (srcBands == null) ? 0 : srcBands[0];
|
||||
|
||||
int dstWidth = srcWidth / srcXSubsamp;
|
||||
if (srcWidth % srcXSubsamp != 0) dstWidth++;
|
||||
int dstHeight = srcHeight / srcYSubsamp;
|
||||
if (srcHeight % srcYSubsamp != 0) dstHeight++;
|
||||
|
||||
int progressRowPeriod = Math.max(1, (srcRegionMaxY + 1) / 100);
|
||||
CbfElementType elementType = mdata.getDataElementType();
|
||||
|
||||
int estimatedSize = (int)((float)dstWidth * (float)dstHeight * 1.5f);
|
||||
ByteBuffer buffer = ByteBuffer.wrap(new byte[estimatedSize]);
|
||||
buffer.order(mdata.getDataElementByteOrder());
|
||||
|
||||
boolean clipped = false;
|
||||
long value = 0;
|
||||
long delta = 0;
|
||||
for (int srcY = srcRaster.getMinY(); srcY <= srcMaxY; srcY += srcYSubsamp) {
|
||||
if (abortRequested()) {
|
||||
processWriteAborted();
|
||||
return null;
|
||||
}
|
||||
if (srcY % progressRowPeriod == 0) {
|
||||
processImageProgress(((float)srcY / (float)(srcRegionMaxY + 1)) * 100.0f);
|
||||
}
|
||||
for (int srcX = srcRaster.getMinX(); srcX <= srcMaxX; srcX += srcXSubsamp) {
|
||||
long newValue;
|
||||
switch (elementType) {
|
||||
case UNSIGNED_8_BIT_INTEGER:
|
||||
case UNSIGNED_16_BIT_INTEGER:
|
||||
newValue = srcRaster.getSample(srcX, srcY, srcBand);
|
||||
if (newValue < 0L) {
|
||||
newValue = 0L;
|
||||
clipped = true;
|
||||
}
|
||||
break;
|
||||
case SIGNED_32_BIT_INTEGER:
|
||||
if (dataBufferType == DataBuffer.TYPE_FLOAT) {
|
||||
float newValueFloat = srcRaster.getSampleFloat(srcX, srcY, srcBand);
|
||||
if (newValueFloat < Integer.MIN_VALUE) {
|
||||
newValue = Integer.MIN_VALUE;
|
||||
clipped = true;
|
||||
} else if (newValueFloat > Integer.MAX_VALUE) {
|
||||
newValue = Integer.MAX_VALUE;
|
||||
clipped = true;
|
||||
} else {
|
||||
newValue = (long)newValueFloat;
|
||||
if (newValue < Integer.MIN_VALUE) newValue = Integer.MIN_VALUE;
|
||||
else if (newValue > Integer.MAX_VALUE) newValue = Integer.MAX_VALUE;
|
||||
}
|
||||
} else {
|
||||
newValue = srcRaster.getSample(srcX, srcY, srcBand);
|
||||
}
|
||||
break;
|
||||
case UNSIGNED_32_BIT_INTEGER:
|
||||
if (dataBufferType == DataBuffer.TYPE_FLOAT) {
|
||||
float newValueFloat = srcRaster.getSampleFloat(srcX, srcY, srcBand);
|
||||
if (newValueFloat < 0.0f) {
|
||||
newValue = 0L;
|
||||
clipped = true;
|
||||
} else if (newValueFloat > 4294967295.0f) {
|
||||
newValue = 4294967295L;
|
||||
clipped = true;
|
||||
} else {
|
||||
newValue = (long)newValueFloat;
|
||||
if (newValue < 0L) newValue = 0L;
|
||||
else if (newValue > 4294967295L) newValue = 4294967295L;
|
||||
}
|
||||
} else {
|
||||
newValue = srcRaster.getSample(srcX, srcY, srcBand);
|
||||
if (newValue < 0L) {
|
||||
newValue = 0L;
|
||||
clipped = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
newValue = srcRaster.getSample(srcX, srcY, srcBand);
|
||||
}
|
||||
delta = newValue - value;
|
||||
if (Byte.MIN_VALUE < delta && delta <= Byte.MAX_VALUE) {
|
||||
buffer = ensureRemaining(buffer, 1);
|
||||
buffer.put((byte)delta);
|
||||
value = newValue;
|
||||
continue;
|
||||
}
|
||||
buffer = ensureRemaining(buffer, 1);
|
||||
buffer.put(Byte.MIN_VALUE);
|
||||
if (Short.MIN_VALUE < delta && delta <= Short.MAX_VALUE) {
|
||||
buffer = ensureRemaining(buffer, 2);
|
||||
buffer.putShort((short)delta);
|
||||
value = newValue;
|
||||
continue;
|
||||
}
|
||||
buffer = ensureRemaining(buffer, 2);
|
||||
buffer.putShort(Short.MIN_VALUE);
|
||||
if (Integer.MIN_VALUE < delta && delta <= Integer.MAX_VALUE) {
|
||||
buffer = ensureRemaining(buffer, 4);
|
||||
buffer.putInt((int)delta);
|
||||
value = newValue;
|
||||
continue;
|
||||
}
|
||||
buffer = ensureRemaining(buffer, 4);
|
||||
buffer.putInt(Integer.MIN_VALUE);
|
||||
buffer = ensureRemaining(buffer, 8);
|
||||
buffer.putLong(delta);
|
||||
value = newValue;
|
||||
}
|
||||
}
|
||||
if (clipped) {
|
||||
processWarningOccurred(0, "Source value(s) clipped to fit in destination element type");
|
||||
}
|
||||
|
||||
IIOByteBuffer result = new IIOByteBuffer(buffer.array(), 0, buffer.limit());
|
||||
|
||||
mdata.setDataCompression(CbfCompression.BYTE_OFFSET);
|
||||
mdata.setDataWidth(dstWidth);
|
||||
mdata.setDataHeight(dstHeight);
|
||||
mdata.setDataNumElements(dstWidth * dstHeight);
|
||||
mdata.setDataSize(result.getLength());
|
||||
MessageDigest digest = null;
|
||||
try {
|
||||
digest = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
processWarningOccurred(0, "Failed to find MD5 algorithm for data MD5 digest calculation");
|
||||
}
|
||||
if (digest != null) {
|
||||
digest.update(result.getData(), result.getOffset(), result.getLength());
|
||||
mdata.setDataMd5(digest.digest());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private ByteBuffer ensureRemaining(ByteBuffer buffer, int remaining) {
|
||||
if (buffer.remaining() >= remaining) return buffer;
|
||||
int capacity = buffer.capacity();
|
||||
int extraCapacity = capacity / 3;
|
||||
int minExtraCapacity = remaining - buffer.remaining();
|
||||
if (extraCapacity < minExtraCapacity) extraCapacity = minExtraCapacity;
|
||||
int newCapacity = capacity + extraCapacity;
|
||||
byte[] newArray = Arrays.copyOf(buffer.array(), newCapacity);
|
||||
ByteBuffer newBuffer = ByteBuffer.wrap(newArray);
|
||||
newBuffer.position(buffer.position());
|
||||
newBuffer.order(buffer.order());
|
||||
return newBuffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Specified CbfMetadata indicates the type of data that should be
|
||||
* encoded.
|
||||
*/
|
||||
private IIOByteBuffer encodeNone(RenderedImage image, int dataBufferType, CbfMetadata mdata,
|
||||
ImageWriteParam param) {
|
||||
Rectangle srcBounds = new Rectangle(image.getWidth(), image.getHeight());
|
||||
Rectangle srcRegion = param.getSourceRegion();
|
||||
srcRegion = (srcRegion == null) ? srcBounds : srcRegion.intersection(srcBounds);
|
||||
int srcXSubsampOffset = param.getSubsamplingXOffset();
|
||||
int srcYSubsampOffset = param.getSubsamplingYOffset();
|
||||
srcRegion.translate(srcXSubsampOffset, srcYSubsampOffset);
|
||||
srcRegion.setSize(srcRegion.width - srcXSubsampOffset, srcRegion.height - srcYSubsampOffset);
|
||||
int srcRegionMaxY = srcRegion.y + srcRegion.height - 1;
|
||||
Raster srcRaster = image.getData(srcRegion);
|
||||
|
||||
int srcXSubsamp = param.getSourceXSubsampling();
|
||||
int srcYSubsamp = param.getSourceYSubsampling();
|
||||
int srcWidth = srcRaster.getWidth();
|
||||
int srcHeight = srcRaster.getHeight();
|
||||
int srcMaxX = srcRaster.getMinX() + srcWidth - 1;
|
||||
int srcMaxY = srcRaster.getMinY() + srcHeight - 1;
|
||||
int[] srcBands = param.getSourceBands();
|
||||
int srcBand = (srcBands == null) ? 0 : srcBands[0];
|
||||
|
||||
int dstWidth = srcWidth / srcXSubsamp;
|
||||
if (srcWidth % srcXSubsamp != 0) dstWidth++;
|
||||
int dstHeight = srcHeight / srcYSubsamp;
|
||||
if (srcHeight % srcYSubsamp != 0) dstHeight++;
|
||||
|
||||
int progressRowPeriod = Math.max(1, (srcRegionMaxY + 1) / 100);
|
||||
CbfElementType elementType = mdata.getDataElementType();
|
||||
int numBytesPerElement;
|
||||
switch (elementType) {
|
||||
case UNSIGNED_8_BIT_INTEGER:
|
||||
case SIGNED_8_BIT_INTEGER:
|
||||
numBytesPerElement = 1;
|
||||
break;
|
||||
case UNSIGNED_16_BIT_INTEGER:
|
||||
case SIGNED_16_BIT_INTEGER:
|
||||
numBytesPerElement = 2;
|
||||
break;
|
||||
case UNSIGNED_32_BIT_INTEGER:
|
||||
case SIGNED_32_BIT_INTEGER:
|
||||
case SIGNED_32_BIT_REAL_IEEE:
|
||||
numBytesPerElement = 4;
|
||||
break;
|
||||
case SIGNED_64_BIT_REAL_IEEE:
|
||||
numBytesPerElement = 8;
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Bug; element type: " + elementType);
|
||||
}
|
||||
|
||||
int dataSize = dstWidth * dstHeight * numBytesPerElement;
|
||||
ByteBuffer buffer = ByteBuffer.wrap(new byte[dataSize]);
|
||||
buffer.order(mdata.getDataElementByteOrder());
|
||||
|
||||
boolean clipped = false;
|
||||
for (int srcY = srcRaster.getMinY(); srcY <= srcMaxY; srcY += srcYSubsamp) {
|
||||
if (abortRequested()) {
|
||||
processWriteAborted();
|
||||
return null;
|
||||
}
|
||||
if (srcY % progressRowPeriod == 0) {
|
||||
processImageProgress(((float)srcY / (float)(srcRegionMaxY + 1)) * 100.0f);
|
||||
}
|
||||
for (int srcX = srcRaster.getMinX(); srcX <= srcMaxX; srcX += srcXSubsamp) {
|
||||
switch (elementType) {
|
||||
case UNSIGNED_8_BIT_INTEGER:
|
||||
int ubyteValue = srcRaster.getSample(srcX, srcY, srcBand);
|
||||
if (ubyteValue < 0) {
|
||||
ubyteValue = 0;
|
||||
clipped = true;
|
||||
}
|
||||
buffer.put((byte)ubyteValue);
|
||||
break;
|
||||
case SIGNED_8_BIT_INTEGER:
|
||||
buffer.put((byte)srcRaster.getSample(srcX, srcY, srcBand));
|
||||
break;
|
||||
case UNSIGNED_16_BIT_INTEGER:
|
||||
int ushortValue = srcRaster.getSample(srcX, srcY, srcBand);
|
||||
if (ushortValue < 0) {
|
||||
ushortValue = 0;
|
||||
clipped = true;
|
||||
}
|
||||
buffer.putShort((short)ushortValue);
|
||||
break;
|
||||
case SIGNED_16_BIT_INTEGER:
|
||||
buffer.putShort((short)srcRaster.getSample(srcX, srcY, srcBand));
|
||||
break;
|
||||
case UNSIGNED_32_BIT_INTEGER:
|
||||
if (dataBufferType == DataBuffer.TYPE_FLOAT) {
|
||||
float floatValue = srcRaster.getSampleFloat(srcX, srcY, srcBand);
|
||||
long longValue;
|
||||
if (floatValue < 0.0f) {
|
||||
longValue = 0L;
|
||||
clipped = true;
|
||||
} else if (floatValue > 4294967295.0f) {
|
||||
longValue = 4294967295L;
|
||||
clipped = true;
|
||||
} else {
|
||||
longValue = (long)floatValue;
|
||||
if (longValue < 0L) longValue = 0L;
|
||||
else if (longValue > 4294967295L) longValue = 4294967295L;
|
||||
}
|
||||
buffer.putInt((int)longValue);
|
||||
} else {
|
||||
int uintValue = srcRaster.getSample(srcX, srcY, srcBand);
|
||||
if (uintValue < 0) {
|
||||
uintValue = 0;
|
||||
clipped = true;
|
||||
}
|
||||
buffer.putInt(uintValue);
|
||||
}
|
||||
break;
|
||||
case SIGNED_32_BIT_INTEGER:
|
||||
if (dataBufferType == DataBuffer.TYPE_FLOAT) {
|
||||
float floatValue = srcRaster.getSampleFloat(srcX, srcY, srcBand);
|
||||
long longValue;
|
||||
if (floatValue < Integer.MIN_VALUE) {
|
||||
longValue = Integer.MIN_VALUE;
|
||||
clipped = true;
|
||||
} else if (floatValue > Integer.MAX_VALUE) {
|
||||
longValue = Integer.MAX_VALUE;
|
||||
clipped = true;
|
||||
} else {
|
||||
longValue = (long)floatValue;
|
||||
if (longValue < Integer.MIN_VALUE) longValue = Integer.MIN_VALUE;
|
||||
else if (longValue > Integer.MAX_VALUE) longValue = Integer.MAX_VALUE;
|
||||
}
|
||||
buffer.putInt((int)longValue);
|
||||
} else {
|
||||
buffer.putInt(srcRaster.getSample(srcX, srcY, srcBand));
|
||||
}
|
||||
break;
|
||||
case SIGNED_32_BIT_REAL_IEEE:
|
||||
buffer.putFloat(srcRaster.getSampleFloat(srcX, srcY, srcBand));
|
||||
break;
|
||||
case SIGNED_64_BIT_REAL_IEEE:
|
||||
buffer.putDouble(srcRaster.getSampleDouble(srcX, srcY, srcBand));
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Bug; element type: " + elementType);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (clipped) {
|
||||
processWarningOccurred(0, "Source value(s) clipped to fit in destination element type");
|
||||
}
|
||||
|
||||
IIOByteBuffer result = new IIOByteBuffer(buffer.array(), 0, buffer.limit());
|
||||
|
||||
mdata.setDataCompression(CbfCompression.NONE);
|
||||
mdata.setDataWidth(dstWidth);
|
||||
mdata.setDataHeight(dstHeight);
|
||||
mdata.setDataNumElements(dstWidth * dstHeight);
|
||||
mdata.setDataSize(result.getLength());
|
||||
MessageDigest digest = null;
|
||||
try {
|
||||
digest = MessageDigest.getInstance("MD5");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
processWarningOccurred(0, "Failed to find MD5 algorithm for data MD5 digest calculation");
|
||||
}
|
||||
if (digest != null) {
|
||||
digest.update(result.getData(), result.getOffset(), result.getLength());
|
||||
mdata.setDataMd5(digest.digest());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private ImageOutputStream getNonNullOutput() {
|
||||
Object output = getOutput();
|
||||
if (output == null) throw new IllegalStateException("No output stream");
|
||||
return (ImageOutputStream)output;
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.ImageWriter;
|
||||
import javax.imageio.spi.ImageWriterSpi;
|
||||
|
||||
/**
|
||||
* I am a writer SPI for CBF images.
|
||||
*/
|
||||
public class CbfImageWriterSpi extends ImageWriterSpi {
|
||||
private static final String VENDOR_NAME = "IMCA-CAT";
|
||||
private static final String VERSION = Version.ID;
|
||||
private static final String[] FORMAT_NAMES = { "cbf", "CBF" };
|
||||
private static final String[] FORMAT_SUFFIXES = { "cbf" };
|
||||
private static final String[] MIME_TYPES = { "image/x-cbf" };
|
||||
private static final String WRITER_CLASS_NAME = "imcacat.jcbf.CbfImageWriter";
|
||||
private static final String[] READER_SPI_CLASS_NAMES = { "imcacat.jcbf.CbfImageReaderSpi" };
|
||||
private static final String METADATA_FORMAT_NAME = "imcacat.jcbf.CbfMetadata_1.0";
|
||||
private static final String METADATA_FORMAT_CLASS_NAME = "imcacat.jcbf.CbfMetadataFormat";
|
||||
|
||||
public CbfImageWriterSpi() {
|
||||
super(VENDOR_NAME, VERSION, FORMAT_NAMES, FORMAT_SUFFIXES, MIME_TYPES, WRITER_CLASS_NAME,
|
||||
STANDARD_OUTPUT_TYPE, READER_SPI_CLASS_NAMES, false, null, null, null, null, false,
|
||||
METADATA_FORMAT_NAME, METADATA_FORMAT_CLASS_NAME, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canEncodeImage(ImageTypeSpecifier type) {
|
||||
return type.getBufferedImageType() == BufferedImage.TYPE_BYTE_BINARY
|
||||
|| (type.getNumBands() == 1 && type.getNumComponents() == 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageWriter createWriterInstance(Object extension) throws IOException {
|
||||
return new CbfImageWriter(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription(Locale locale) {
|
||||
return "CBF image writer";
|
||||
}
|
||||
|
||||
}
|
760
ch.psi.imagej.cbf/src/main/java/imcacat/jcbf/CbfMetadata.java
Normal file
760
ch.psi.imagej.cbf/src/main/java/imcacat/jcbf/CbfMetadata.java
Normal file
@ -0,0 +1,760 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.imageio.metadata.IIOInvalidTreeException;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.metadata.IIOMetadataNode;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* I am the metadata for a CBF image.
|
||||
*/
|
||||
public class CbfMetadata extends IIOMetadata {
|
||||
public static final String NATIVE_FORMAT_NAME = "imcacat.jcbf.CbfMetadataFormat_1.0";
|
||||
|
||||
private static final Pattern VALID_STRING = Pattern.compile("(?:\\p{Graph}|\\p{Blank})*");
|
||||
private static final Pattern HEADER_DETECTOR_COMMA_DELIM = Pattern.compile("\\s*,\\s*");
|
||||
private static final Pattern HEADER_DETECTOR_SN_DELIM = Pattern.compile("\\s+SN:\\s*");
|
||||
|
||||
private String identifier = "###CBF: VERSION 1.5, CBFlib v0.7.8 - SLS/DECTRIS PILATUS detectors";
|
||||
private String dataBlockName = "image";
|
||||
|
||||
private String headerConvention = "SLS_1.0";
|
||||
private String headerDetector;
|
||||
private String headerDetectorName;
|
||||
private String headerDetectorSerialNumber;
|
||||
private String headerDetectorDescription;
|
||||
private Date headerDate;
|
||||
private float[] headerPixelSize;
|
||||
private String headerSensorType;
|
||||
private Float headerSensorThickness;
|
||||
private Float headerExposureTime;
|
||||
private Float headerExposurePeriod;
|
||||
private Float headerTau;
|
||||
private Integer headerCountCutoff;
|
||||
private Float headerThreshold;
|
||||
private String headerGainType;
|
||||
private Float headerGainVrf;
|
||||
private Integer headerNumExcludedPixels;
|
||||
private String headerExcludedPixels;
|
||||
private String headerFlatField;
|
||||
private String headerTrim;
|
||||
private Float headerWavelength;
|
||||
private float[] headerEnergyRange;
|
||||
private Float headerDetectorDistance;
|
||||
private Float headerDetectorVOffset;
|
||||
private float[] headerBeamXY;
|
||||
private Float headerFlux;
|
||||
private Float headerFilterTransmission;
|
||||
private Float headerStartAngle;
|
||||
private Float headerAngleIncrement;
|
||||
private Float headerDetector2Theta;
|
||||
private Float headerPolarization;
|
||||
private Float headerAlpha;
|
||||
private Float headerKappa;
|
||||
private Float headerPhi;
|
||||
private Float headerChi;
|
||||
private String headerOscillationAxis;
|
||||
private Integer headerNumOscillations;
|
||||
private String headerComment;
|
||||
private List<String> headerUnrecognizedLines = new ArrayList<String>();
|
||||
|
||||
private CbfCompression dataCompression;
|
||||
private int dataSize;
|
||||
private int dataId;
|
||||
private CbfElementType dataElementType = CbfElementType.SIGNED_32_BIT_INTEGER;
|
||||
private ByteOrder dataElementByteOrder = ByteOrder.LITTLE_ENDIAN;
|
||||
private byte[] dataMd5;
|
||||
private int dataNumElements;
|
||||
private int dataWidth;
|
||||
private int dataHeight;
|
||||
private int dataPadding = 4095;
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node getAsTree(String formatName) {
|
||||
if (!NATIVE_FORMAT_NAME.equals(formatName)) {
|
||||
throw new IllegalArgumentException("Format name: " + formatName);
|
||||
}
|
||||
Node result = new IIOMetadataNode(NATIVE_FORMAT_NAME);
|
||||
if (identifier != null) {
|
||||
result.appendChild(createAssociation("identifier", identifier));
|
||||
}
|
||||
if (dataBlockName != null) {
|
||||
result.appendChild(createAssociation("dataBlockName", dataBlockName));
|
||||
}
|
||||
|
||||
if (headerConvention != null) {
|
||||
result.appendChild(createAssociation("headerConvention", headerConvention));
|
||||
}
|
||||
if (headerDetector != null) {
|
||||
result.appendChild(createAssociation("headerDetector", headerDetector));
|
||||
}
|
||||
if (headerDate != null) {
|
||||
DateFormat format = new SimpleDateFormat("yyyy-MMM-dd'T'HH:mm:ss.SSS", Locale.US);
|
||||
result.appendChild(createAssociation("headerDate", format.format(headerDate)));
|
||||
}
|
||||
if (headerPixelSize != null) {
|
||||
result.appendChild(createAssociation("headerPixelSize", String.format(Locale.US,
|
||||
"%.0fe-6 m x %.0fe-6 m", headerPixelSize[0] * 1e6f, headerPixelSize[1] * 1e6f)));
|
||||
}
|
||||
if (headerSensorType != null) {
|
||||
result.appendChild(createAssociation("headerSensorType", headerSensorType));
|
||||
}
|
||||
if (headerSensorThickness != null) {
|
||||
result.appendChild(createAssociation("headerSensorThickness",
|
||||
String.format(Locale.US, "%.6f m", headerSensorThickness)));
|
||||
}
|
||||
if (headerExposureTime != null) {
|
||||
result.appendChild(createAssociation("headerExposureTime",
|
||||
String.format(Locale.US, "%.6f s", headerExposureTime)));
|
||||
}
|
||||
if (headerExposurePeriod != null) {
|
||||
result.appendChild(createAssociation("headerExposurePeriod",
|
||||
String.format(Locale.US, "%.6f s", headerExposurePeriod)));
|
||||
}
|
||||
if (headerTau != null) {
|
||||
result.appendChild(createAssociation("headerTau",
|
||||
String.format(Locale.US, "%.1fe-09 s", 1e9f * headerTau)));
|
||||
}
|
||||
if (headerCountCutoff != null) {
|
||||
result.appendChild(createAssociation("headerCountCutoff",
|
||||
String.format(Locale.US, "%d counts", headerCountCutoff)));
|
||||
}
|
||||
if (headerThreshold != null) {
|
||||
result.appendChild(createAssociation("headerThreshold",
|
||||
String.format(Locale.US, "%.0f eV", headerThreshold)));
|
||||
}
|
||||
if (headerGainType != null) {
|
||||
result.appendChild(createAssociation("headerGainType", headerGainType));
|
||||
}
|
||||
if (headerGainVrf != null) {
|
||||
result.appendChild(createAssociation("headerGainVrf",
|
||||
String.format(Locale.US, "%.3f", headerGainVrf)));
|
||||
}
|
||||
if (headerNumExcludedPixels != null) {
|
||||
result.appendChild(createAssociation("headerNumExcludedPixels", headerExcludedPixels));
|
||||
}
|
||||
if (headerExcludedPixels != null) {
|
||||
result.appendChild(createAssociation("headerExcludedPixels", headerExcludedPixels));
|
||||
}
|
||||
if (headerFlatField != null) {
|
||||
result.appendChild(createAssociation("headerFlatField", headerFlatField));
|
||||
}
|
||||
if (headerTrim != null) {
|
||||
result.appendChild(createAssociation("headerTrim", headerTrim));
|
||||
}
|
||||
if (headerWavelength != null) {
|
||||
result.appendChild(createAssociation("headerWavelength",
|
||||
String.format(Locale.US, "%.4f A", headerWavelength)));
|
||||
}
|
||||
if (headerEnergyRange != null) {
|
||||
result.appendChild(createAssociation("headerEnergyRange",
|
||||
String.format(Locale.US, "(%.0f, %.0f) eV", headerEnergyRange[0], headerEnergyRange[1])));
|
||||
}
|
||||
if (headerDetectorDistance != null) {
|
||||
result.appendChild(createAssociation("headerDetectorDistance",
|
||||
String.format(Locale.US, "%.5f m", headerDetectorDistance)));
|
||||
}
|
||||
if (headerDetectorVOffset != null) {
|
||||
result.appendChild(createAssociation("headerDetectorVOffset",
|
||||
String.format(Locale.US, "%.5f m", headerDetectorVOffset)));
|
||||
}
|
||||
if (headerBeamXY != null) {
|
||||
result.appendChild(createAssociation("headerBeamXY",
|
||||
String.format(Locale.US, "(%.2f, %.2f) pixels", headerBeamXY[0], headerBeamXY[1])));
|
||||
}
|
||||
if (headerFlux != null) {
|
||||
result.appendChild(createAssociation("headerFlux",
|
||||
String.format(Locale.US, "%.4f ph/s", headerFlux)));
|
||||
}
|
||||
if (headerFilterTransmission != null) {
|
||||
result.appendChild(createAssociation("headerFilterTransmission",
|
||||
String.format(Locale.US, "%.4f", headerFilterTransmission)));
|
||||
}
|
||||
if (headerStartAngle != null) {
|
||||
result.appendChild(createAssociation("headerStartAngle",
|
||||
String.format(Locale.US, "%.4f deg.", headerStartAngle)));
|
||||
}
|
||||
if (headerAngleIncrement != null) {
|
||||
result.appendChild(createAssociation("headerAngleIncrement",
|
||||
String.format(Locale.US, "%.4f deg.", headerAngleIncrement)));
|
||||
}
|
||||
if (headerDetector2Theta != null) {
|
||||
result.appendChild(createAssociation("headerDetector2Theta",
|
||||
String.format(Locale.US, "%.4f deg.", headerDetector2Theta)));
|
||||
}
|
||||
if (headerPolarization != null) {
|
||||
result.appendChild(createAssociation("headerPolarization",
|
||||
String.format(Locale.US, "%.3f", headerPolarization)));
|
||||
}
|
||||
if (headerAlpha != null) {
|
||||
result.appendChild(createAssociation("headerAlpha",
|
||||
String.format(Locale.US, "%.4f deg.", headerAlpha)));
|
||||
}
|
||||
if (headerKappa != null) {
|
||||
result.appendChild(createAssociation("headerKappa",
|
||||
String.format(Locale.US, "%.4f deg.", headerKappa)));
|
||||
}
|
||||
if (headerPhi != null) {
|
||||
result.appendChild(createAssociation("headerPhi",
|
||||
String.format(Locale.US, "%.4f deg.", headerPhi)));
|
||||
}
|
||||
if (headerChi != null) {
|
||||
result.appendChild(createAssociation("headerChi",
|
||||
String.format(Locale.US, "%.4f deg.", headerChi)));
|
||||
}
|
||||
if (headerOscillationAxis != null) {
|
||||
result.appendChild(createAssociation("headerOscillationAxis", headerOscillationAxis));
|
||||
}
|
||||
if (headerNumOscillations != null) {
|
||||
result.appendChild(createAssociation("headerNumOscillations",
|
||||
String.format(Locale.US, "%d", headerNumOscillations)));
|
||||
}
|
||||
if (headerComment != null) {
|
||||
result.appendChild(createAssociation("headerComment", headerComment));
|
||||
}
|
||||
int i = 0;
|
||||
for (String each : getHeaderUnrecognizedLines()) {
|
||||
result.appendChild(createAssociation("headerUnrecognized" + i, each));
|
||||
i++;
|
||||
}
|
||||
|
||||
if (dataCompression != null) {
|
||||
result.appendChild(createAssociation("dataCompression",
|
||||
dataCompression.toContentTypeConversions()));
|
||||
}
|
||||
result.appendChild(createAssociation("dataSize", Integer.toString(dataSize)));
|
||||
result.appendChild(createAssociation("dataId", Integer.toString(dataId)));
|
||||
if (dataElementType != null) {
|
||||
result.appendChild(createAssociation("dataElementType",
|
||||
dataElementType.toXBinaryElementType()));
|
||||
}
|
||||
if (dataElementByteOrder != null) {
|
||||
result
|
||||
.appendChild(createAssociation("dataElementByteOrder", dataElementByteOrder.toString()));
|
||||
}
|
||||
if (dataMd5 != null) {
|
||||
result.appendChild(createAssociation("dataMd5", Base64.encode(dataMd5)));
|
||||
}
|
||||
result.appendChild(createAssociation("dataNumElements", Integer.toString(dataNumElements)));
|
||||
result.appendChild(createAssociation("dataWidth", Integer.toString(dataWidth)));
|
||||
result.appendChild(createAssociation("dataHeight", Integer.toString(dataHeight)));
|
||||
result.appendChild(createAssociation("dataPadding", Integer.toString(dataPadding)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private IIOMetadataNode createAssociation(String key, String value) {
|
||||
IIOMetadataNode result = new IIOMetadataNode("association");
|
||||
result.setAttribute("key", key);
|
||||
result.setAttribute("value", value);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mergeTree(String formatName, Node root) throws IIOInvalidTreeException {
|
||||
throw new IllegalStateException("Read-only");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
throw new IllegalStateException("Read-only");
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public void setIdentifier(String newIdentifier) {
|
||||
validate(newIdentifier);
|
||||
identifier = newIdentifier;
|
||||
}
|
||||
|
||||
public String getDataBlockName() {
|
||||
return dataBlockName;
|
||||
}
|
||||
|
||||
public void setDataBlockName(String newDataBlockName) {
|
||||
validate(newDataBlockName);
|
||||
dataBlockName = newDataBlockName;
|
||||
}
|
||||
|
||||
public String getHeaderConvention() {
|
||||
return headerConvention;
|
||||
}
|
||||
|
||||
public void setHeaderConvention(String newHeaderConvention) {
|
||||
validate(newHeaderConvention);
|
||||
headerConvention = newHeaderConvention;
|
||||
}
|
||||
|
||||
public String getHeaderDetector() {
|
||||
return headerDetector;
|
||||
}
|
||||
|
||||
public void setHeaderDetector(String headerDetector) {
|
||||
validate(headerDetector);
|
||||
this.headerDetector = headerDetector;
|
||||
updateHeaderDetectorParts(headerDetector);
|
||||
}
|
||||
|
||||
private void updateHeaderDetectorParts(String headerDetector) {
|
||||
headerDetectorName = null;
|
||||
headerDetectorSerialNumber = null;
|
||||
headerDetectorDescription = null;
|
||||
if (headerDetector == null) return;
|
||||
String[] parts = HEADER_DETECTOR_COMMA_DELIM.split(headerDetector);
|
||||
if (parts.length > 1) {
|
||||
headerDetectorName = parts[0];
|
||||
headerDetectorSerialNumber = parts[1];
|
||||
if (parts.length > 2) headerDetectorDescription = parts[2];
|
||||
return;
|
||||
}
|
||||
parts = HEADER_DETECTOR_SN_DELIM.split(headerDetector);
|
||||
if (parts.length > 1) {
|
||||
headerDetectorName = parts[0];
|
||||
headerDetectorSerialNumber = parts[1];
|
||||
}
|
||||
}
|
||||
|
||||
public String getHeaderDetectorName() {
|
||||
return headerDetectorName;
|
||||
}
|
||||
|
||||
public String getHeaderDetectorSerialNumber() {
|
||||
return headerDetectorSerialNumber;
|
||||
}
|
||||
|
||||
public String getHeaderDetectorDescription() {
|
||||
return headerDetectorDescription;
|
||||
}
|
||||
|
||||
public Date getHeaderDate() {
|
||||
return headerDate;
|
||||
}
|
||||
|
||||
public void setHeaderDate(Date headerDate) {
|
||||
this.headerDate = headerDate;
|
||||
}
|
||||
|
||||
public float[] getHeaderPixelSize() {
|
||||
return headerPixelSize;
|
||||
}
|
||||
|
||||
public void setHeaderPixelSize(float[] headerPixelSize) {
|
||||
this.headerPixelSize = headerPixelSize;
|
||||
}
|
||||
|
||||
public String getHeaderSensorType() {
|
||||
return headerSensorType;
|
||||
}
|
||||
|
||||
public void setHeaderSensorType(String headerSensorType) {
|
||||
validate(headerSensorType);
|
||||
this.headerSensorType = headerSensorType;
|
||||
}
|
||||
|
||||
public Float getHeaderSensorThickness() {
|
||||
return headerSensorThickness;
|
||||
}
|
||||
|
||||
public void setHeaderSensorThickness(Float headerSensorThickness) {
|
||||
this.headerSensorThickness = headerSensorThickness;
|
||||
}
|
||||
|
||||
public Float getHeaderExposureTime() {
|
||||
return headerExposureTime;
|
||||
}
|
||||
|
||||
public void setHeaderExposureTime(Float headerExposureTime) {
|
||||
this.headerExposureTime = headerExposureTime;
|
||||
}
|
||||
|
||||
public Float getHeaderExposurePeriod() {
|
||||
return headerExposurePeriod;
|
||||
}
|
||||
|
||||
public void setHeaderExposurePeriod(Float headerExposurePeriod) {
|
||||
this.headerExposurePeriod = headerExposurePeriod;
|
||||
}
|
||||
|
||||
public Float getHeaderTau() {
|
||||
return headerTau;
|
||||
}
|
||||
|
||||
public void setHeaderTau(Float headerTau) {
|
||||
this.headerTau = headerTau;
|
||||
}
|
||||
|
||||
public Integer getHeaderCountCutoff() {
|
||||
return headerCountCutoff;
|
||||
}
|
||||
|
||||
public void setHeaderCountCutoff(Integer headerCountCutoff) {
|
||||
this.headerCountCutoff = headerCountCutoff;
|
||||
}
|
||||
|
||||
public Float getHeaderThreshold() {
|
||||
return headerThreshold;
|
||||
}
|
||||
|
||||
public void setHeaderThreshold(Float headerThreshold) {
|
||||
this.headerThreshold = headerThreshold;
|
||||
}
|
||||
|
||||
public String getHeaderGainType() {
|
||||
return headerGainType;
|
||||
}
|
||||
|
||||
public void setHeaderGainType(String headerGainType) {
|
||||
validate(headerGainType);
|
||||
this.headerGainType = headerGainType;
|
||||
}
|
||||
|
||||
public Float getHeaderGainVrf() {
|
||||
return headerGainVrf;
|
||||
}
|
||||
|
||||
public void setHeaderGainVrf(Float headerGainVrf) {
|
||||
this.headerGainVrf = headerGainVrf;
|
||||
}
|
||||
|
||||
public Integer getHeaderNumExcludedPixels() {
|
||||
return headerNumExcludedPixels;
|
||||
}
|
||||
|
||||
public void setHeaderNumExcludedPixels(Integer headerNumExcludedPixels) {
|
||||
this.headerNumExcludedPixels = headerNumExcludedPixels;
|
||||
}
|
||||
|
||||
public String getHeaderExcludedPixels() {
|
||||
return headerExcludedPixels;
|
||||
}
|
||||
|
||||
public void setHeaderExcludedPixels(String headerExcludedPixels) {
|
||||
validate(headerExcludedPixels);
|
||||
this.headerExcludedPixels = headerExcludedPixels;
|
||||
}
|
||||
|
||||
public String getHeaderFlatField() {
|
||||
return headerFlatField;
|
||||
}
|
||||
|
||||
public void setHeaderFlatField(String headerFlatField) {
|
||||
validate(headerFlatField);
|
||||
this.headerFlatField = headerFlatField;
|
||||
}
|
||||
|
||||
public String getHeaderTrim() {
|
||||
return headerTrim;
|
||||
}
|
||||
|
||||
public void setHeaderTrim(String headerTrim) {
|
||||
validate(headerTrim);
|
||||
this.headerTrim = headerTrim;
|
||||
}
|
||||
|
||||
public Float getHeaderWavelength() {
|
||||
return headerWavelength;
|
||||
}
|
||||
|
||||
public void setHeaderWavelength(Float headerWavelength) {
|
||||
this.headerWavelength = headerWavelength;
|
||||
}
|
||||
|
||||
public float[] getHeaderEnergyRange() {
|
||||
return headerEnergyRange;
|
||||
}
|
||||
|
||||
public void setHeaderEnergyRange(float[] headerEnergyRange) {
|
||||
this.headerEnergyRange = headerEnergyRange;
|
||||
}
|
||||
|
||||
public Float getHeaderDetectorDistance() {
|
||||
return headerDetectorDistance;
|
||||
}
|
||||
|
||||
public void setHeaderDetectorDistance(Float headerDetectorDistance) {
|
||||
this.headerDetectorDistance = headerDetectorDistance;
|
||||
}
|
||||
|
||||
public Float getHeaderDetectorVOffset() {
|
||||
return headerDetectorVOffset;
|
||||
}
|
||||
|
||||
public void setHeaderDetectorVOffset(Float headerDetectorVOffset) {
|
||||
this.headerDetectorVOffset = headerDetectorVOffset;
|
||||
}
|
||||
|
||||
public float[] getHeaderBeamXY() {
|
||||
return headerBeamXY;
|
||||
}
|
||||
|
||||
public void setHeaderBeamXY(float[] headerBeamXY) {
|
||||
this.headerBeamXY = headerBeamXY;
|
||||
}
|
||||
|
||||
public Float getHeaderFlux() {
|
||||
return headerFlux;
|
||||
}
|
||||
|
||||
public void setHeaderFlux(Float headerFlux) {
|
||||
this.headerFlux = headerFlux;
|
||||
}
|
||||
|
||||
public Float getHeaderFilterTransmission() {
|
||||
return headerFilterTransmission;
|
||||
}
|
||||
|
||||
public void setHeaderFilterTransmission(Float headerFilterTransmission) {
|
||||
this.headerFilterTransmission = headerFilterTransmission;
|
||||
}
|
||||
|
||||
public Float getHeaderStartAngle() {
|
||||
return headerStartAngle;
|
||||
}
|
||||
|
||||
public void setHeaderStartAngle(Float headerStartAngle) {
|
||||
this.headerStartAngle = headerStartAngle;
|
||||
}
|
||||
|
||||
public Float getHeaderAngleIncrement() {
|
||||
return headerAngleIncrement;
|
||||
}
|
||||
|
||||
public void setHeaderAngleIncrement(Float headerAngleIncrement) {
|
||||
this.headerAngleIncrement = headerAngleIncrement;
|
||||
}
|
||||
|
||||
public Float getHeaderDetector2Theta() {
|
||||
return headerDetector2Theta;
|
||||
}
|
||||
|
||||
public void setHeaderDetector2Theta(Float headerDetector2Theta) {
|
||||
this.headerDetector2Theta = headerDetector2Theta;
|
||||
}
|
||||
|
||||
public Float getHeaderPolarization() {
|
||||
return headerPolarization;
|
||||
}
|
||||
|
||||
public void setHeaderPolarization(Float headerPolarization) {
|
||||
this.headerPolarization = headerPolarization;
|
||||
}
|
||||
|
||||
public Float getHeaderAlpha() {
|
||||
return headerAlpha;
|
||||
}
|
||||
|
||||
public void setHeaderAlpha(Float headerAlpha) {
|
||||
this.headerAlpha = headerAlpha;
|
||||
}
|
||||
|
||||
public Float getHeaderKappa() {
|
||||
return headerKappa;
|
||||
}
|
||||
|
||||
public void setHeaderKappa(Float headerKappa) {
|
||||
this.headerKappa = headerKappa;
|
||||
}
|
||||
|
||||
public Float getHeaderPhi() {
|
||||
return headerPhi;
|
||||
}
|
||||
|
||||
public void setHeaderPhi(Float headerPhi) {
|
||||
this.headerPhi = headerPhi;
|
||||
}
|
||||
|
||||
public Float getHeaderChi() {
|
||||
return headerChi;
|
||||
}
|
||||
|
||||
public void setHeaderChi(Float headerChi) {
|
||||
this.headerChi = headerChi;
|
||||
}
|
||||
|
||||
public String getHeaderOscillationAxis() {
|
||||
return headerOscillationAxis;
|
||||
}
|
||||
|
||||
public void setHeaderOscillationAxis(String headerOscillationAxis) {
|
||||
validate(headerOscillationAxis);
|
||||
this.headerOscillationAxis = headerOscillationAxis;
|
||||
}
|
||||
|
||||
public Integer getHeaderNumOscillations() {
|
||||
return headerNumOscillations;
|
||||
}
|
||||
|
||||
public void setHeaderNumOscillations(Integer headerNumOscillations) {
|
||||
this.headerNumOscillations = headerNumOscillations;
|
||||
}
|
||||
|
||||
public String getHeaderComment() {
|
||||
return headerComment;
|
||||
}
|
||||
|
||||
public void setHeaderComment(String headerComment) {
|
||||
validate(headerComment);
|
||||
this.headerComment = headerComment;
|
||||
}
|
||||
|
||||
public void setHeaderDefaults() {
|
||||
headerDetector = "PILATUS 6M";
|
||||
headerDate = new Date();
|
||||
headerPixelSize = new float[] { 172e-6f, 172e-6f };
|
||||
headerSensorType = "Silicon";
|
||||
headerSensorThickness = 0.000320f;
|
||||
headerExposureTime = 1.0f;
|
||||
headerExposurePeriod = 1.0f;
|
||||
headerTau = 124.0e-09f;
|
||||
headerCountCutoff = 1048575;
|
||||
headerThreshold = 7439.0f;
|
||||
headerGainType = "not implemented";
|
||||
headerGainVrf = 9.9f;
|
||||
headerWavelength = 1.0f;
|
||||
headerEnergyRange = new float[] { 0.0f, 0.0f };
|
||||
headerDetectorDistance = 0.2f;
|
||||
headerDetectorVOffset = 0.0f;
|
||||
headerBeamXY = new float[] { 1231.5f, 1263.5f };
|
||||
headerFlux = 0.0f;
|
||||
headerFilterTransmission = 0.0f;
|
||||
headerStartAngle = 0.0f;
|
||||
headerAngleIncrement = 0.0f;
|
||||
headerDetector2Theta = 0.0f;
|
||||
headerPolarization = 0.990f;
|
||||
headerAlpha = 0.0f;
|
||||
headerKappa = 0.0f;
|
||||
headerPhi = 0.0f;
|
||||
headerChi = 0.0f;
|
||||
headerOscillationAxis = "X, CW";
|
||||
headerNumOscillations = 1;
|
||||
}
|
||||
|
||||
public List<String> getHeaderUnrecognizedLines() {
|
||||
return Collections.unmodifiableList(headerUnrecognizedLines);
|
||||
}
|
||||
|
||||
public void addHeaderUnrecognizedLine(String line) {
|
||||
validate(line);
|
||||
headerUnrecognizedLines.add(line);
|
||||
}
|
||||
|
||||
public CbfCompression getDataCompression() {
|
||||
return dataCompression;
|
||||
}
|
||||
|
||||
public void setDataCompression(CbfCompression newDataCompression) {
|
||||
dataCompression = newDataCompression;
|
||||
}
|
||||
|
||||
public int getDataSize() {
|
||||
return dataSize;
|
||||
}
|
||||
|
||||
public void setDataSize(int newDataSize) {
|
||||
dataSize = newDataSize;
|
||||
}
|
||||
|
||||
public int getDataId() {
|
||||
return dataId;
|
||||
}
|
||||
|
||||
public void setDataId(int newDataId) {
|
||||
dataId = newDataId;
|
||||
}
|
||||
|
||||
public CbfElementType getDataElementType() {
|
||||
return dataElementType;
|
||||
}
|
||||
|
||||
public void setDataElementType(CbfElementType newDataElementType) {
|
||||
dataElementType = newDataElementType;
|
||||
}
|
||||
|
||||
public ByteOrder getDataElementByteOrder() {
|
||||
return dataElementByteOrder;
|
||||
}
|
||||
|
||||
public void setDataElementByteOrder(ByteOrder newDataElementByteOrder) {
|
||||
dataElementByteOrder = newDataElementByteOrder;
|
||||
}
|
||||
|
||||
public byte[] getDataMd5() {
|
||||
return dataMd5;
|
||||
}
|
||||
|
||||
public void setDataMd5(byte[] newDataMd5) {
|
||||
dataMd5 = newDataMd5;
|
||||
}
|
||||
|
||||
public int getDataNumElements() {
|
||||
return dataNumElements;
|
||||
}
|
||||
|
||||
public void setDataNumElements(int newDataNumElements) {
|
||||
dataNumElements = newDataNumElements;
|
||||
}
|
||||
|
||||
public int getDataWidth() {
|
||||
return dataWidth;
|
||||
}
|
||||
|
||||
public void setDataWidth(int newDataWidth) {
|
||||
dataWidth = newDataWidth;
|
||||
}
|
||||
|
||||
public int getDataHeight() {
|
||||
return dataHeight;
|
||||
}
|
||||
|
||||
public void setDataHeight(int newDataHeight) {
|
||||
dataHeight = newDataHeight;
|
||||
}
|
||||
|
||||
public int getDataPadding() {
|
||||
return dataPadding;
|
||||
}
|
||||
|
||||
public void setDataPadding(int newDataPadding) {
|
||||
dataPadding = newDataPadding;
|
||||
}
|
||||
|
||||
private void validate(String s) {
|
||||
if (s == null) return;
|
||||
if (VALID_STRING.matcher(s).matches()) return;
|
||||
throw new IllegalArgumentException("String contains an illegal character");
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.metadata.IIOMetadataFormatImpl;
|
||||
|
||||
/**
|
||||
* I am the metadata format for a CBF image.
|
||||
*/
|
||||
public class CbfMetadataFormat extends IIOMetadataFormatImpl {
|
||||
private static final String ASSOCIATION_ELEMENT_NAME = "association";
|
||||
|
||||
public CbfMetadataFormat() {
|
||||
super(CbfMetadata.NATIVE_FORMAT_NAME, CHILD_POLICY_REPEAT);
|
||||
addElement(ASSOCIATION_ELEMENT_NAME, CbfMetadata.NATIVE_FORMAT_NAME, CHILD_POLICY_EMPTY);
|
||||
addAttribute(ASSOCIATION_ELEMENT_NAME, "key", DATATYPE_STRING, true, null);
|
||||
addAttribute(ASSOCIATION_ELEMENT_NAME, "value", DATATYPE_STRING, true, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canNodeAppear(String elementName, ImageTypeSpecifier imageType) {
|
||||
return ASSOCIATION_ELEMENT_NAME.equals(elementName);
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
|
||||
/**
|
||||
* I am a <code>CbfData</code> backed by an <code>ImageInputStream</code>.
|
||||
*/
|
||||
public class ImageInputStreamCbfData implements CbfData {
|
||||
private ImageInputStream stream;
|
||||
|
||||
public ImageInputStreamCbfData(ImageInputStream stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void order(ByteOrder bo) {
|
||||
stream.setByteOrder(bo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getByte() throws IOException {
|
||||
return stream.readByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getUbyte() throws IOException {
|
||||
return (short)stream.readUnsignedByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort() throws IOException {
|
||||
return stream.readShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUshort() throws IOException {
|
||||
return stream.readUnsignedShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt() throws IOException {
|
||||
return stream.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getUint() throws IOException {
|
||||
return stream.readUnsignedInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong() throws IOException {
|
||||
return stream.readLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat() throws IOException {
|
||||
return stream.readFloat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble() throws IOException {
|
||||
return stream.readDouble();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skipBytes(int count) throws IOException {
|
||||
stream.skipBytes(count);
|
||||
}
|
||||
}
|
@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.DataBufferFloat;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReadParam;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.event.IIOReadWarningListener;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
|
||||
import ij.IJ;
|
||||
import ij.ImagePlus;
|
||||
import ij.io.OpenDialog;
|
||||
import ij.plugin.PlugIn;
|
||||
import ij.process.FloatProcessor;
|
||||
import ij.process.ImageProcessor;
|
||||
|
||||
/**
|
||||
* I am an ImageJ plug-in for reading a CBF image.
|
||||
*/
|
||||
public class ImageJCbfReader implements PlugIn {
|
||||
private static final Pattern WHITESPACE_PATTERN = Pattern.compile(" ");
|
||||
|
||||
@Override
|
||||
public void run(String arg) {
|
||||
OpenDialog dialog = new OpenDialog("Open image ...", arg);
|
||||
if (dialog.getFileName() == null) return;
|
||||
ImagePlus image = read(new File(dialog.getDirectory(), dialog.getFileName()));
|
||||
if (image == null) return;
|
||||
image.show();
|
||||
}
|
||||
|
||||
private ImagePlus read(File cbfFile) {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
ImageInputStream stream = null;
|
||||
try {
|
||||
stream = ImageIO.createImageInputStream(cbfFile);
|
||||
} catch (IOException e) {
|
||||
showError("Error creating input stream from specified file", e);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
if (!spi.canDecodeInput(stream)) {
|
||||
showMessage("The specified file is not a CBF image.");
|
||||
return null;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
showError("Error checking whether specified file is a CBF image", e);
|
||||
return null;
|
||||
}
|
||||
CbfImageReader reader = new CbfImageReader(spi);
|
||||
reader.setInput(stream);
|
||||
ImageReadParam param = reader.getDefaultReadParam();
|
||||
Iterator<ImageTypeSpecifier> types = null;
|
||||
try {
|
||||
types = reader.getImageTypes(0);
|
||||
} catch (IOException e) {
|
||||
showError("Error reading CBF image metadata", e);
|
||||
reader.dispose();
|
||||
return null;
|
||||
}
|
||||
while (types.hasNext()) {
|
||||
ImageTypeSpecifier each = types.next();
|
||||
if (each.getSampleModel().getDataType() == DataBuffer.TYPE_FLOAT) {
|
||||
param.setDestinationType(each);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final String cbfFilePath = cbfFile.getPath();
|
||||
reader.addIIOReadWarningListener(new IIOReadWarningListener() {
|
||||
@Override
|
||||
public void warningOccurred(ImageReader source, String warning) {
|
||||
IJ.log("Warning: " + warning + " (" + cbfFilePath + ")");
|
||||
}
|
||||
});
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
try {
|
||||
width = reader.getWidth(0);
|
||||
height = reader.getHeight(0);
|
||||
} catch (IOException e) {
|
||||
showError("Error determining width and height of CBF image", e);
|
||||
reader.dispose();
|
||||
return null;
|
||||
}
|
||||
BufferedImage image = null;
|
||||
try {
|
||||
image = reader.read(0, param);
|
||||
} catch (IOException e) {
|
||||
showError("Error reading CBF image data", e);
|
||||
reader.dispose();
|
||||
return null;
|
||||
}
|
||||
DataBuffer buffer = image.getData().getDataBuffer();
|
||||
int bufferType = buffer.getDataType();
|
||||
float[] pixels;
|
||||
ImageProcessor ip;
|
||||
if (buffer instanceof DataBufferFloat) {
|
||||
pixels = ((DataBufferFloat)buffer).getData();
|
||||
ip = new FloatProcessor(width, height, pixels, null);
|
||||
image.flush();
|
||||
reader.dispose();
|
||||
return new ImagePlus(cbfFile.getName(), ip);
|
||||
} else if (bufferType == DataBuffer.TYPE_INT || bufferType == DataBuffer.TYPE_FLOAT) {
|
||||
pixels = new float[width * height];
|
||||
for (int i = 0; i < pixels.length; i++)
|
||||
pixels[i] = buffer.getElemFloat(i);
|
||||
ip = new FloatProcessor(width, height, pixels, null);
|
||||
image.flush();
|
||||
reader.dispose();
|
||||
return new ImagePlus(cbfFile.getName(), ip);
|
||||
} else if (bufferType == DataBuffer.TYPE_DOUBLE) {
|
||||
pixels = new float[width * height];
|
||||
boolean clipped = false;
|
||||
for (int i = 0; i < pixels.length; i++) {
|
||||
double doubleValue = buffer.getElemDouble(i);
|
||||
float floatValue;
|
||||
if (doubleValue < Float.MIN_VALUE) {
|
||||
floatValue = Float.MIN_VALUE;
|
||||
clipped = true;
|
||||
} else if (doubleValue > Float.MAX_VALUE) {
|
||||
floatValue = Float.MAX_VALUE;
|
||||
clipped = true;
|
||||
} else {
|
||||
floatValue = (float)doubleValue;
|
||||
}
|
||||
pixels[i] = floatValue;
|
||||
}
|
||||
if (clipped) {
|
||||
IJ.log("Warning: pixel value(s) clipped to fit in type float (" + cbfFilePath + ")");
|
||||
}
|
||||
ip = new FloatProcessor(width, height, pixels, null);
|
||||
image.flush();
|
||||
reader.dispose();
|
||||
return new ImagePlus(cbfFile.getName(), ip);
|
||||
} else {
|
||||
reader.dispose();
|
||||
return new ImagePlus(cbfFile.getName(), image);
|
||||
}
|
||||
}
|
||||
|
||||
private static void showError(String msg, Throwable t) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append(msg);
|
||||
if (t != null) {
|
||||
buffer.append(": ");
|
||||
buffer.append(t.getMessage());
|
||||
}
|
||||
if (buffer.length() != 0) {
|
||||
char last = buffer.charAt(buffer.length() - 1);
|
||||
if (last != '.' && last != '!' && last != '?') buffer.append('.');
|
||||
}
|
||||
IJ.error("CBF Reader", wordWrap(buffer.toString(), 78));
|
||||
}
|
||||
|
||||
private static void showMessage(String msg) {
|
||||
IJ.showMessage("CBF Reader", wordWrap(msg, 78));
|
||||
}
|
||||
|
||||
private static String wordWrap(String text, int maxColumnWidth) {
|
||||
return wordWrap(text, maxColumnWidth, System.getProperty("line.separator"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a very basic type of word wrapping on the specified text.
|
||||
* Splits words on the space character and expects the text to not contain
|
||||
* any whitespace characters other than the space character.
|
||||
*/
|
||||
private static String wordWrap(String text, int maxColumnWidth, String lineSeparator) {
|
||||
if (maxColumnWidth <= 0) throw new IllegalArgumentException("maxColumnWidth must be > 0");
|
||||
|
||||
String buffer = "";
|
||||
String lineBuffer = "";
|
||||
String[] words = WHITESPACE_PATTERN.split(text);
|
||||
for (int i = 0; i < words.length; i++) {
|
||||
if (words[i].length() + 1 + lineBuffer.length() <= maxColumnWidth) {
|
||||
if (lineBuffer.length() != 0) lineBuffer += " ";
|
||||
lineBuffer += words[i];
|
||||
} else if (words[i].length() <= maxColumnWidth) {
|
||||
buffer += lineBuffer.trim() + lineSeparator;
|
||||
lineBuffer = "";
|
||||
i--;
|
||||
} else {
|
||||
buffer += lineBuffer.trim() + lineSeparator;
|
||||
lineBuffer = "";
|
||||
for (int j = 0; j < words[i].length(); j += maxColumnWidth) {
|
||||
lineBuffer = words[i].substring(j, Math.min(j + maxColumnWidth,
|
||||
words[i].length()));
|
||||
if (lineBuffer.length() == maxColumnWidth) {
|
||||
buffer += lineBuffer.trim() + lineSeparator;
|
||||
lineBuffer = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lineBuffer.length() != 0) buffer += lineBuffer.trim();
|
||||
return buffer.trim();
|
||||
}
|
||||
}
|
28
ch.psi.imagej.cbf/src/main/java/imcacat/jcbf/Version.java
Normal file
28
ch.psi.imagej.cbf/src/main/java/imcacat/jcbf/Version.java
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
/**
|
||||
* I provide the version identifier for this library.
|
||||
*/
|
||||
/*
|
||||
* WARNING: Changes made by hand to the value of my ID field will be lost;
|
||||
* it is automatically set at build time.
|
||||
*/
|
||||
public class Version {
|
||||
public static final String ID = "1.1.0";
|
||||
}
|
0
ch.psi.imagej.cbf/src/main/resources/.gitignore
vendored
Normal file
0
ch.psi.imagej.cbf/src/main/resources/.gitignore
vendored
Normal file
87
ch.psi.imagej.cbf/src/test/java/imcacat/jcbf/Base64Test.java
Normal file
87
ch.psi.imagej.cbf/src/test/java/imcacat/jcbf/Base64Test.java
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* I test <code>Base64</code>.
|
||||
*/
|
||||
public class Base64Test extends TestUtils {
|
||||
@Test
|
||||
public void testEncode01() {
|
||||
assertEquals("YWRtaW46YWRtaW4=", Base64.encode(asciiBytes("admin:admin")));
|
||||
assertEquals("YWRtaW46YWRtaQ==", Base64.encode(asciiBytes("admin:admi")));
|
||||
assertEquals("YWRtaW46YWRt", Base64.encode(asciiBytes("admin:adm")));
|
||||
assertEquals("", Base64.encode(asciiBytes("")));
|
||||
assertEquals("YQ==", Base64.encode(asciiBytes("a")));
|
||||
assertEquals("YWI=", Base64.encode(asciiBytes("ab")));
|
||||
assertEquals("YWJj", Base64.encode(asciiBytes("abc")));
|
||||
assertEquals("QWxhZGRpbjpvcGVuIHNlc2FtZQ==", Base64.encode(asciiBytes("Aladdin:open sesame")));
|
||||
}
|
||||
|
||||
/* Source data outside of US-ASCII range. */
|
||||
@Test
|
||||
public void testEncode02() {
|
||||
byte[] source = new byte[] { 0 };
|
||||
assertEquals("AA==", Base64.encode(source));
|
||||
source = new byte[] { -1 };
|
||||
assertEquals("/w==", Base64.encode(source));
|
||||
source = new byte[] { 1 };
|
||||
assertEquals("AQ==", Base64.encode(source));
|
||||
source = new byte[] { (byte)200, (byte)202, (byte)204, (byte)205, (byte)207 };
|
||||
assertArrayEquals(source, Base64.decode(Base64.encode(source)));
|
||||
source = new byte[] { 0, -2, -4, -5, -7 };
|
||||
assertArrayEquals(source, Base64.decode(Base64.encode(source)));
|
||||
source = new byte[] { Byte.MIN_VALUE, Byte.MAX_VALUE, -1 };
|
||||
assertArrayEquals(source, Base64.decode(Base64.encode(source)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecode01() {
|
||||
assertArrayEquals(asciiBytes("admin:admin"), Base64.decode("YWRtaW46YWRtaW4="));
|
||||
assertArrayEquals(asciiBytes("admin:admi"), Base64.decode("YWRtaW46YWRtaQ=="));
|
||||
assertArrayEquals(asciiBytes("admin:adm"), Base64.decode("YWRtaW46YWRt"));
|
||||
assertArrayEquals(asciiBytes(""), Base64.decode(""));
|
||||
assertArrayEquals(asciiBytes("a"), Base64.decode("YQ=="));
|
||||
assertArrayEquals(asciiBytes("ab"), Base64.decode("YWI="));
|
||||
assertArrayEquals(asciiBytes("abc"), Base64.decode("YWJj"));
|
||||
assertArrayEquals(asciiBytes("Aladdin:open sesame"),
|
||||
Base64.decode("QWxhZGRpbjpvcGVuIHNlc2FtZQ=="));
|
||||
}
|
||||
|
||||
/* Invalid character. */
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testDecode02() {
|
||||
Base64.decode("Y;RtaW46YWRtaW4=");
|
||||
}
|
||||
|
||||
/* Padding character is invalid when not at end. */
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testDecode03() {
|
||||
Base64.decode("YW=taW46YWRtaW4=");
|
||||
}
|
||||
|
||||
/* Invalid length. */
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testDecode04() {
|
||||
Base64.decode("YRtaW46YWRtaW4=");
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* I test <code>CbfCompression</code>.
|
||||
*/
|
||||
public class CbfCompressionTest extends TestUtils {
|
||||
@Test
|
||||
public void testParse01() throws ParseException {
|
||||
assertEquals(CbfCompression.NONE, CbfCompression.parse("x-CBF_NONE"));
|
||||
assertEquals(CbfCompression.BYTE_OFFSET, CbfCompression.parse("x-CBF_BYTE_OFFSET"));
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* I test <code>CbfElementType</code>.
|
||||
*/
|
||||
public class CbfElementTypeTest extends TestUtils {
|
||||
@Test
|
||||
public void testParse01() throws ParseException {
|
||||
assertEquals(CbfElementType.SIGNED_32_BIT_INTEGER,
|
||||
CbfElementType.parse("signed 32-bit integer"));
|
||||
}
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* I test <code>CbfImageReaderSpi</code>.
|
||||
*/
|
||||
public class CbfImageReaderSpiTest extends TestUtils {
|
||||
@Test
|
||||
public void testCanDecodeInput01() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
String input = "###CBF: VERSION";
|
||||
ImageInputStream stream = streamFromString(input);
|
||||
assertTrue(spi.canDecodeInput(stream));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanDecodeInput02() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
String input = "###CBF: VERSION 1.5, CBFlib v0.7.8 - SLS/DECTRIS PILATUS detectors";
|
||||
ImageInputStream stream = streamFromString(input);
|
||||
assertTrue(spi.canDecodeInput(stream));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanDecodeInput03() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
String input =
|
||||
"###CBF: VERSION 1.5, CBFlib v0.7.8 - SLS/DECTRIS PILATUS detectors\n" +
|
||||
"\n" +
|
||||
"data_thaumatin_0001\n";
|
||||
ImageInputStream stream = streamFromString(input);
|
||||
assertTrue(spi.canDecodeInput(stream));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanDecodeInput04() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
String input =
|
||||
"###CBF: VERSIO";
|
||||
ImageInputStream stream = streamFromString(input);
|
||||
assertFalse(spi.canDecodeInput(stream));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanDecodeInput05() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
String input = "###CBF: VERSION";
|
||||
assertFalse(spi.canDecodeInput(input));
|
||||
}
|
||||
}
|
@ -0,0 +1,953 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.Raster;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.ImageReadParam;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.ImageWriteParam;
|
||||
import javax.imageio.event.IIOReadProgressListener;
|
||||
import javax.imageio.event.IIOReadWarningListener;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* I test <code>CbfImageReader</code>.
|
||||
*/
|
||||
public class CbfImageReaderTest extends TestUtils {
|
||||
/* Ensure OK to invoke getImageMetadata twice. */
|
||||
@Test
|
||||
public void testGetImageMetadata01() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData());
|
||||
reader.setInput(stream);
|
||||
reader.getImageMetadata(0);
|
||||
reader.getImageMetadata(0);
|
||||
}
|
||||
|
||||
/* Ensure state is reset if new input source is set. */
|
||||
@Test
|
||||
public void testSetInput01() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData());
|
||||
reader.setInput(stream);
|
||||
CbfMetadata mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
assertEquals("thaumatin_0001", mdata.getDataBlockName());
|
||||
String text = createImageText().replaceFirst("data_thaumatin_0001", "data_thaumatin_0002");
|
||||
stream = streamFromBytes(createImageWithoutData(asciiBytes(text)));
|
||||
reader.setInput(stream);
|
||||
mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
assertEquals("thaumatin_0002", mdata.getDataBlockName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadMetadataIdentifier01() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData());
|
||||
reader.setInput(stream);
|
||||
CbfMetadata mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
String expected = "###CBF: VERSION 1.5, CBFlib v0.7.8 - SLS/DECTRIS PILATUS detectors";
|
||||
assertEquals(expected, mdata.getIdentifier());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadMetadataIdentifier02() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
String text = createImageText().replaceFirst(
|
||||
"###CBF: VERSION 1.5, CBFlib v0.7.8 - SLS/DECTRIS PILATUS detectors",
|
||||
"###CBF: VERSION 1.5\r\n# CBF file written by CBFlib v0.7.8");
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData(asciiBytes(text)));
|
||||
reader.setInput(stream);
|
||||
CbfMetadata mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
String expected = "###CBF: VERSION 1.5";
|
||||
assertEquals(expected, mdata.getIdentifier());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadMetadataDataBlockName01() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData());
|
||||
reader.setInput(stream);
|
||||
CbfMetadata mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
String expected = "thaumatin_0001";
|
||||
assertEquals(expected, mdata.getDataBlockName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadMetadataHeaderConvention01() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData());
|
||||
reader.setInput(stream);
|
||||
CbfMetadata mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
String expected = "SLS_1.0";
|
||||
assertEquals(expected, mdata.getHeaderConvention());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadMetadataHeaderConvention02() throws IOException, InterruptedException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
String text = createImageText().replaceFirst(
|
||||
"_array_data\\.header_convention \"SLS_1\\.0\"",
|
||||
"_array_data.header_convention \"SLS_1.1\"");
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData(asciiBytes(text)));
|
||||
reader.setInput(stream);
|
||||
final List<String> warnings = new ArrayList<String>();
|
||||
reader.addIIOReadWarningListener(new IIOReadWarningListener() {
|
||||
@Override
|
||||
public void warningOccurred(ImageReader source, String warning) {
|
||||
warnings.add(warning);
|
||||
}
|
||||
});
|
||||
CbfMetadata mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
assertEquals("SLS_1.1", mdata.getHeaderConvention());
|
||||
assertEquals(1, warnings.size());
|
||||
assertEquals("Unrecognized header convention: SLS_1.1", warnings.get(0));
|
||||
}
|
||||
|
||||
/* Header convention without quotes. */
|
||||
@Test
|
||||
public void testReadMetadataHeaderConvention03() throws IOException, InterruptedException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
String text = createImageText().replaceFirst(
|
||||
"_array_data\\.header_convention \"SLS_1\\.0\"",
|
||||
"_array_data.header_convention SLS_1.0");
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData(asciiBytes(text)));
|
||||
reader.setInput(stream);
|
||||
CbfMetadata mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
assertEquals("SLS_1.0", mdata.getHeaderConvention());
|
||||
}
|
||||
|
||||
/* Header convention not starting with "SLS_1.". */
|
||||
@Test(expected = IIOException.class)
|
||||
public void testReadMetadataHeaderConvention04() throws IOException, InterruptedException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
String text = createImageText().replaceFirst(
|
||||
"_array_data\\.header_convention \"SLS_1\\.0\"",
|
||||
"_array_data.header_convention \"SLS_2.0\"");
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData(asciiBytes(text)));
|
||||
reader.setInput(stream);
|
||||
reader.getImageMetadata(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadMetadataHeader01() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData());
|
||||
reader.setInput(stream);
|
||||
CbfMetadata mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
assertEquals("PILATUS 6M, 60-0103, IMCA-CAT", mdata.getHeaderDetector());
|
||||
Calendar c = Calendar.getInstance(Locale.US);
|
||||
c.set(Calendar.YEAR, 2010);
|
||||
c.set(Calendar.MONTH, 10);
|
||||
c.set(Calendar.DAY_OF_MONTH, 17);
|
||||
c.set(Calendar.HOUR_OF_DAY, 15);
|
||||
c.set(Calendar.MINUTE, 52);
|
||||
c.set(Calendar.SECOND, 30);
|
||||
c.set(Calendar.MILLISECOND, 834);
|
||||
assertEquals(c.getTime(), mdata.getHeaderDate());
|
||||
assertArrayEquals(new float[] { 172e-6f, 172e-6f }, mdata.getHeaderPixelSize(), 0.0f);
|
||||
assertEquals("Silicon", mdata.getHeaderSensorType());
|
||||
assertEquals((Float)0.000320f, mdata.getHeaderSensorThickness());
|
||||
assertEquals((Float)0.081033f, mdata.getHeaderExposureTime());
|
||||
assertEquals((Float)0.083333f, mdata.getHeaderExposurePeriod());
|
||||
assertEquals((Float)124.0e-09f, mdata.getHeaderTau());
|
||||
assertEquals((Integer)326741, mdata.getHeaderCountCutoff());
|
||||
assertEquals((Float)7439.0f, mdata.getHeaderThreshold());
|
||||
assertNull(mdata.getHeaderGainType());
|
||||
assertEquals((Float)9.900f, mdata.getHeaderGainVrf());
|
||||
assertEquals((Integer)2391, mdata.getHeaderNumExcludedPixels());
|
||||
assertEquals("badpix_mask.tif", mdata.getHeaderExcludedPixels());
|
||||
assertNull(mdata.getHeaderFlatField());
|
||||
assertNull(mdata.getHeaderTrim());
|
||||
assertEquals((Float)1.0000f, mdata.getHeaderWavelength());
|
||||
assertArrayEquals(new float[] { 0.0f, 0.0f }, mdata.getHeaderEnergyRange(), 0.0f);
|
||||
assertEquals((Float)0.94997f, mdata.getHeaderDetectorDistance());
|
||||
assertEquals((Float)0.0f, mdata.getHeaderDetectorVOffset());
|
||||
assertArrayEquals(new float[] { 1253.0f, 1288.0f }, mdata.getHeaderBeamXY(), 0.0f);
|
||||
assertEquals((Float)0.0f, mdata.getHeaderFlux());
|
||||
assertEquals((Float)0.0f, mdata.getHeaderFilterTransmission());
|
||||
assertEquals((Float)0.00f, mdata.getHeaderStartAngle());
|
||||
assertEquals((Float)1.0f, mdata.getHeaderAngleIncrement());
|
||||
assertEquals((Float)0.0007f, mdata.getHeaderDetector2Theta());
|
||||
assertEquals((Float)0.99f, mdata.getHeaderPolarization());
|
||||
assertEquals((Float)0.0f, mdata.getHeaderAlpha());
|
||||
assertEquals((Float)0.0f, mdata.getHeaderKappa());
|
||||
assertEquals((Float)0.0f, mdata.getHeaderPhi());
|
||||
assertEquals((Float)0.0f, mdata.getHeaderChi());
|
||||
assertEquals("X, CW", mdata.getHeaderOscillationAxis());
|
||||
assertEquals((Integer)1, mdata.getHeaderNumOscillations());
|
||||
}
|
||||
|
||||
/* Two date formats. */
|
||||
@Test
|
||||
public void testReadMetadataHeader02() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData());
|
||||
reader.setInput(stream);
|
||||
CbfMetadata mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
Calendar c = Calendar.getInstance(Locale.US);
|
||||
c.set(Calendar.YEAR, 2010);
|
||||
c.set(Calendar.MONTH, 10);
|
||||
c.set(Calendar.DAY_OF_MONTH, 17);
|
||||
c.set(Calendar.HOUR_OF_DAY, 15);
|
||||
c.set(Calendar.MINUTE, 52);
|
||||
c.set(Calendar.SECOND, 30);
|
||||
c.set(Calendar.MILLISECOND, 834);
|
||||
assertEquals(c.getTime(), mdata.getHeaderDate());
|
||||
String text = createImageText().replaceFirst(
|
||||
"# 2010-Nov-17T15:52:30.834\r\n",
|
||||
"# 2010/Nov/17 15:52:30.834\r\n");
|
||||
stream = streamFromBytes(createImageWithoutData(asciiBytes(text)));
|
||||
reader.setInput(stream);
|
||||
mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
assertEquals(c.getTime(), mdata.getHeaderDate());
|
||||
}
|
||||
|
||||
/* "(nil)" excluded pixels and trim directory; not "(nil)" flat field. */
|
||||
@Test
|
||||
public void testReadMetadataHeader03() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
String text = createImageText().replaceFirst(
|
||||
"# Excluded_pixels: badpix_mask.tif\r\n",
|
||||
"# Excluded_pixels: (nil)\r\n");
|
||||
text = text.replaceFirst(
|
||||
"# Flat_field: \\(nil\\)\r\n",
|
||||
"# Flat_field: flat_field.tif\r\n");
|
||||
text = text.replaceFirst(
|
||||
"Trim_directory: \r\n",
|
||||
"Trim_directory: (nil)\r\n");
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData(asciiBytes(text)));
|
||||
reader.setInput(stream);
|
||||
CbfMetadata mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
assertNull(mdata.getHeaderExcludedPixels());
|
||||
assertEquals("flat_field.tif", mdata.getHeaderFlatField());
|
||||
assertNull(mdata.getHeaderTrim());
|
||||
}
|
||||
|
||||
/* not "(nil)" trim directory. */
|
||||
@Test
|
||||
public void testReadMetadataHeader04() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
String text = createImageText().replaceFirst(
|
||||
"Trim_directory: \r\n",
|
||||
"Trim_directory: p6m0103_T8p0_vrf_m0p3_100323\r\n");
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData(asciiBytes(text)));
|
||||
reader.setInput(stream);
|
||||
CbfMetadata mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
assertEquals("p6m0103_T8p0_vrf_m0p3_100323", mdata.getHeaderTrim());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadMetadataMimeHeader01() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData());
|
||||
reader.setInput(stream);
|
||||
CbfMetadata mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
assertEquals(CbfCompression.BYTE_OFFSET, mdata.getDataCompression());
|
||||
assertEquals(6224001, mdata.getDataSize());
|
||||
assertEquals(1, mdata.getDataId());
|
||||
assertEquals(CbfElementType.SIGNED_32_BIT_INTEGER, mdata.getDataElementType());
|
||||
assertEquals(ByteOrder.LITTLE_ENDIAN, mdata.getDataElementByteOrder());
|
||||
assertArrayEquals(Base64.decode("Ti67wd6I6DPuGIsOnMalMw=="), mdata.getDataMd5());
|
||||
assertEquals(6224001, mdata.getDataNumElements());
|
||||
assertEquals(2463, mdata.getDataWidth());
|
||||
assertEquals(2527, mdata.getDataHeight());
|
||||
assertEquals(4095, mdata.getDataPadding());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadMetadataMimeHeader02() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
String text = createImageText().replaceFirst(
|
||||
" conversions=\"x-CBF_BYTE_OFFSET\"",
|
||||
" conversions=\"x-CBF_NONE\"");
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData(asciiBytes(text)));
|
||||
reader.setInput(stream);
|
||||
CbfMetadata mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
assertEquals(CbfCompression.NONE, mdata.getDataCompression());
|
||||
}
|
||||
|
||||
/* Missing content type conversions. */
|
||||
@Test(expected = IIOException.class)
|
||||
public void testReadMetadataMimeHeader03() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
String text = createImageText();
|
||||
text = text.replaceFirst(
|
||||
"Content-Type: application/octet-stream;",
|
||||
"Content-Type: application/octet-stream");
|
||||
text = text.replaceFirst(
|
||||
" +conversions=\"x-CBF_BYTE_OFFSET\"\r\n",
|
||||
"");
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData(asciiBytes(text)));
|
||||
reader.setInput(stream);
|
||||
reader.getImageMetadata(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadMetadataMimeHeader04() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
String text = createImageText().replaceFirst(
|
||||
"X-Binary-Element-Type: \"signed 32-bit integer\"",
|
||||
"X-Binary-Element-Type: \"unsigned 32-bit integer\"");
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData(asciiBytes(text)));
|
||||
reader.setInput(stream);
|
||||
CbfMetadata mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
assertEquals(CbfElementType.UNSIGNED_32_BIT_INTEGER, mdata.getDataElementType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadMetadataMimeHeader05() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
String text = createImageText().replaceFirst(
|
||||
"X-Binary-Element-Byte-Order: LITTLE_ENDIAN",
|
||||
"X-Binary-Element-Byte-Order: BIG_ENDIAN");
|
||||
ImageInputStream stream = streamFromBytes(createImageWithoutData(asciiBytes(text)));
|
||||
reader.setInput(stream);
|
||||
CbfMetadata mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
assertEquals(ByteOrder.BIG_ENDIAN, mdata.getDataElementByteOrder());
|
||||
}
|
||||
|
||||
/* Element type: unsigned 8-bit integer; compression: none. */
|
||||
@Test
|
||||
public void testRead01() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
String text = createImageText().replaceFirst(
|
||||
"conversions=\"x-CBF_BYTE_OFFSET\"",
|
||||
"conversions=\"x-CBF_NONE\"");
|
||||
text = text.replaceFirst(
|
||||
"X-Binary-Size: 6224001",
|
||||
"X-Binary-Size: 4");
|
||||
text = text.replaceFirst(
|
||||
"X-Binary-Element-Type: \"signed 32-bit integer\"",
|
||||
"X-Binary-Element-Type: \"unsigned 8-bit integer\"");
|
||||
text = text.replaceFirst(
|
||||
"Content-MD5: Ti67wd6I6DPuGIsOnMalMw==\r\n",
|
||||
"");
|
||||
text = text.replaceFirst(
|
||||
"X-Binary-Number-of-Elements: 6224001",
|
||||
"X-Binary-Number-of-Elements: 4");
|
||||
text = text.replaceFirst(
|
||||
"X-Binary-Size-Fastest-Dimension: 2463",
|
||||
"X-Binary-Size-Fastest-Dimension: 2");
|
||||
text = text.replaceFirst(
|
||||
"X-Binary-Size-Second-Dimension: 2527",
|
||||
"X-Binary-Size-Second-Dimension: 2");
|
||||
byte[] imageWithoutData = createImageWithoutData(asciiBytes(text));
|
||||
byte[] imageData = { 1, 2, 3, 4 };
|
||||
byte[] imageWithData = new byte[imageWithoutData.length + imageData.length];
|
||||
System.arraycopy(imageWithoutData, 0, imageWithData, 0, imageWithoutData.length);
|
||||
System.arraycopy(imageData, 0, imageWithData, imageWithoutData.length, imageData.length);
|
||||
ImageInputStream stream = streamFromBytes(imageWithData);
|
||||
reader.setInput(stream);
|
||||
BufferedImage image = reader.read(0);
|
||||
Raster raster = image.getData();
|
||||
assertEquals(1, raster.getNumBands());
|
||||
assertEquals(8, image.getColorModel().getComponentSize(0));
|
||||
assertEquals(2, raster.getWidth());
|
||||
assertEquals(2, raster.getHeight());
|
||||
assertEquals(BufferedImage.TYPE_BYTE_GRAY, image.getType());
|
||||
assertEquals(imageData[0], (byte)raster.getSample(0, 0, 0));
|
||||
assertEquals(imageData[1], (byte)raster.getSample(1, 0, 0));
|
||||
assertEquals(imageData[2], (byte)raster.getSample(0, 1, 0));
|
||||
assertEquals(imageData[3], (byte)raster.getSample(1, 1, 0));
|
||||
}
|
||||
|
||||
/* Element type: signed 32-bit integer; compression: byte_offset. */
|
||||
@Test
|
||||
public void testRead02() throws IOException {
|
||||
int[][] expected = {
|
||||
{ +1, +2 },
|
||||
{ -1, -2 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(expected);
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage));
|
||||
assertEquals(BufferedImage.TYPE_CUSTOM, inImage.getType());
|
||||
assertEquals(DataBuffer.TYPE_INT, inImage.getSampleModel().getDataType());
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/*
|
||||
* Element type: signed 32-bit integer; compression: byte_offset. Min and
|
||||
* max values.
|
||||
*/
|
||||
@Test
|
||||
public void testRead03() throws IOException {
|
||||
int[][] expected = {
|
||||
{ 0, Integer.MAX_VALUE },
|
||||
{ 5, Integer.MIN_VALUE }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(expected);
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage));
|
||||
assertEquals(BufferedImage.TYPE_CUSTOM, inImage.getType());
|
||||
assertEquals(DataBuffer.TYPE_INT, inImage.getSampleModel().getDataType());
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* Not square dimensions. */
|
||||
@Test
|
||||
public void testRead04() throws IOException {
|
||||
int[][] expected = {
|
||||
{ 0, 1, 2 },
|
||||
{ 3, 4, 5 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(expected);
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage));
|
||||
assertEquals(BufferedImage.TYPE_CUSTOM, inImage.getType());
|
||||
assertEquals(DataBuffer.TYPE_INT, inImage.getSampleModel().getDataType());
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/*
|
||||
* Element type: signed 32-bit integer; compression: byte_offset. Short
|
||||
* size values.
|
||||
*/
|
||||
@Test
|
||||
public void testRead05() throws IOException {
|
||||
int[][] expected = {
|
||||
{ Short.MIN_VALUE + 1, Short.MAX_VALUE },
|
||||
{ 5, 6 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(expected);
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage));
|
||||
assertEquals(BufferedImage.TYPE_CUSTOM, inImage.getType());
|
||||
assertEquals(DataBuffer.TYPE_INT, inImage.getSampleModel().getDataType());
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* Source region. */
|
||||
@Test
|
||||
public void testRead06() throws IOException {
|
||||
int[][] output = {
|
||||
{ 1, 2, 3 },
|
||||
{ 4, 5, 6 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 1, 2 },
|
||||
{ 4, 5 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceRegion(new Rectangle(0, 0, 2, 2));
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* Source region. */
|
||||
@Test
|
||||
public void testRead07() throws IOException {
|
||||
int[][] output = {
|
||||
{ 1, 2, 3 },
|
||||
{ 4, 5, 6 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 2, 3 },
|
||||
{ 5, 6 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceRegion(new Rectangle(1, 0, 2, 2));
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* Source region. */
|
||||
@Test
|
||||
public void testRead08() throws IOException {
|
||||
int[][] output = {
|
||||
{ 1, 2, 3 },
|
||||
{ 4, 5, 6 },
|
||||
{ 7, 8, 9 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 4, 5 },
|
||||
{ 7, 8 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceRegion(new Rectangle(0, 1, 2, 2));
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* Source region. */
|
||||
@Test
|
||||
public void testRead09() throws IOException {
|
||||
int[][] output = {
|
||||
{ 1, 2, 3 },
|
||||
{ 4, 5, 6 },
|
||||
{ 7, 8, 9 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 5, 6 },
|
||||
{ 8, 9 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceRegion(new Rectangle(1, 1, 2, 2));
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* Source region. */
|
||||
@Test
|
||||
public void testRead10() throws IOException {
|
||||
int[][] output = {
|
||||
{ 10, 11, 12, 13 },
|
||||
{ 14, 15, 16, 17 },
|
||||
{ 18, 19, 20, 21 },
|
||||
{ 22, 23, 24, 25 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 15, 16 },
|
||||
{ 19, 20 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceRegion(new Rectangle(1, 1, 2, 2));
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* Source region. */
|
||||
@Test
|
||||
public void testRead11() throws IOException {
|
||||
int[][] output = {
|
||||
{ 10, 11, 12, 13 },
|
||||
{ 14, 15, 16, 17 },
|
||||
{ 18, 19, 20, 21 },
|
||||
{ 22, 23, 24, 25 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 10, 11, 12, 13 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceRegion(new Rectangle(0, 0, 4, 1));
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* Source region. */
|
||||
@Test
|
||||
public void testRead12() throws IOException {
|
||||
int[][] output = {
|
||||
{ 10, 11, 12, 13 },
|
||||
{ 14, 15, 16, 17 },
|
||||
{ 18, 19, 20, 21 },
|
||||
{ 22, 23, 24, 25 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 15, 16, 17 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceRegion(new Rectangle(1, 1, 3, 1));
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* Source region. */
|
||||
@Test
|
||||
public void testRead13() throws IOException {
|
||||
int[][] output = {
|
||||
{ 10, 11, 12, 13 },
|
||||
{ 14, 15, 16, 17 },
|
||||
{ 18, 19, 20, 21 },
|
||||
{ 22, 23, 24, 25 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 10 },
|
||||
{ 14 },
|
||||
{ 18 },
|
||||
{ 22 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceRegion(new Rectangle(0, 0, 1, 4));
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* Source region. */
|
||||
@Test
|
||||
public void testRead14() throws IOException {
|
||||
int[][] output = {
|
||||
{ 10, 11, 12, 13 },
|
||||
{ 14, 15, 16, 17 },
|
||||
{ 18, 19, 20, 21 },
|
||||
{ 22, 23, 24, 25 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 15 },
|
||||
{ 19 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceRegion(new Rectangle(1, 1, 1, 2));
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* Source region of size 1x1. */
|
||||
@Test
|
||||
public void testRead15() throws IOException {
|
||||
int[][] output = {
|
||||
{ 10, 11, 12, 13 },
|
||||
{ 14, 15, 16, 17 },
|
||||
{ 18, 19, 20, 21 },
|
||||
{ 22, 23, 24, 25 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 25 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceRegion(new Rectangle(3, 3, 1, 1));
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* 2x2 subsampling without offset. */
|
||||
@Test
|
||||
public void testRead16() throws IOException {
|
||||
int[][] output = {
|
||||
{ 10, 11, 12, 13 },
|
||||
{ 14, 15, 16, 17 },
|
||||
{ 18, 19, 20, 21 },
|
||||
{ 22, 23, 24, 25 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 10, 12 },
|
||||
{ 18, 20 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceSubsampling(2, 2, 0, 0);
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* 2x1 subsampling without offset. */
|
||||
@Test
|
||||
public void testRead17() throws IOException {
|
||||
int[][] output = {
|
||||
{ 10, 11, 12, 13 },
|
||||
{ 14, 15, 16, 17 },
|
||||
{ 18, 19, 20, 21 },
|
||||
{ 22, 23, 24, 25 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 10, 12 },
|
||||
{ 14, 16 },
|
||||
{ 18, 20 },
|
||||
{ 22, 24 },
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceSubsampling(2, 1, 0, 0);
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* 1x2 subsampling without offset. */
|
||||
@Test
|
||||
public void testRead18() throws IOException {
|
||||
int[][] output = {
|
||||
{ 10, 11, 12, 13 },
|
||||
{ 14, 15, 16, 17 },
|
||||
{ 18, 19, 20, 21 },
|
||||
{ 22, 23, 24, 25 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 10, 11, 12, 13 },
|
||||
{ 18, 19, 20, 21 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceSubsampling(1, 2, 0, 0);
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* 3x3 subsampling without offset. */
|
||||
@Test
|
||||
public void testRead19() throws IOException {
|
||||
int[][] output = {
|
||||
{ 10, 11, 12, 13 },
|
||||
{ 14, 15, 16, 17 },
|
||||
{ 18, 19, 20, 21 },
|
||||
{ 22, 23, 24, 25 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 10, 13 },
|
||||
{ 22, 25 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceSubsampling(3, 3, 0, 0);
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* 2x2 subsampling with offset. */
|
||||
@Test
|
||||
public void testRead20() throws IOException {
|
||||
int[][] output = {
|
||||
{ 10, 11, 12, 13 },
|
||||
{ 14, 15, 16, 17 },
|
||||
{ 18, 19, 20, 21 },
|
||||
{ 22, 23, 24, 25 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 15, 17 },
|
||||
{ 23, 25 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceSubsampling(2, 2, 1, 1);
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* 2x1 subsampling with X offset. */
|
||||
@Test
|
||||
public void testRead21() throws IOException {
|
||||
int[][] output = {
|
||||
{ 10, 11, 12, 13 },
|
||||
{ 14, 15, 16, 17 },
|
||||
{ 18, 19, 20, 21 },
|
||||
{ 22, 23, 24, 25 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 11, 13 },
|
||||
{ 15, 17 },
|
||||
{ 19, 21 },
|
||||
{ 23, 25 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceSubsampling(2, 1, 1, 0);
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* 1x2 subsampling with Y offset. */
|
||||
@Test
|
||||
public void testRead22() throws IOException {
|
||||
int[][] output = {
|
||||
{ 10, 11, 12, 13 },
|
||||
{ 14, 15, 16, 17 },
|
||||
{ 18, 19, 20, 21 },
|
||||
{ 22, 23, 24, 25 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 14, 15, 16, 17 },
|
||||
{ 22, 23, 24, 25 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceSubsampling(1, 2, 0, 1);
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* 3x2 subsampling with offset. */
|
||||
@Test
|
||||
public void testRead23() throws IOException {
|
||||
int[][] output = {
|
||||
{ 10, 11, 12, 13, 14, 15 },
|
||||
{ 16, 17, 18, 19, 20, 21 },
|
||||
{ 22, 23, 24, 25, 26, 27 },
|
||||
{ 28, 29, 30, 31, 32, 33 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 18, 21 },
|
||||
{ 30, 33 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceSubsampling(3, 2, 2, 1);
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* Source region and 2x2 subsampling. */
|
||||
@Test
|
||||
public void testRead24() throws IOException {
|
||||
int[][] output = {
|
||||
{ 10, 11, 12, 13, 14, 15 },
|
||||
{ 16, 17, 18, 19, 20, 21 },
|
||||
{ 22, 23, 24, 25, 26, 27 },
|
||||
{ 28, 29, 30, 31, 32, 33 },
|
||||
{ 34, 35, 36, 37, 38, 39 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 17, 19 },
|
||||
{ 29, 31 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceRegion(new Rectangle(1, 1, 4, 4));
|
||||
param.setSourceSubsampling(2, 2, 0, 0);
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* Source region and 2x2 subsampling with offset. */
|
||||
@Test
|
||||
public void testRead25() throws IOException {
|
||||
int[][] output = {
|
||||
{ 10, 11, 12, 13, 14, 15 },
|
||||
{ 16, 17, 18, 19, 20, 21 },
|
||||
{ 22, 23, 24, 25, 26, 27 },
|
||||
{ 28, 29, 30, 31, 32, 33 },
|
||||
{ 34, 35, 36, 37, 38, 39 }
|
||||
};
|
||||
int[][] expected = {
|
||||
{ 24, 26 },
|
||||
{ 36, 38 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
ImageReadParam param = createImageReadParam();
|
||||
param.setSourceRegion(new Rectangle(1, 1, 4, 4));
|
||||
param.setSourceSubsampling(2, 2, 1, 1);
|
||||
BufferedImage inImage = readBufferedImage(writeBufferedImage(outImage), param);
|
||||
assertArrayEquals(expected, getIntPixels(inImage));
|
||||
}
|
||||
|
||||
/* Progress. */
|
||||
@Test
|
||||
public void testRead26() throws IOException {
|
||||
int[][] output = {
|
||||
{ 10, 11, 12, 13, 14, 15 },
|
||||
{ 16, 17, 18, 19, 20, 21 },
|
||||
{ 22, 23, 24, 25, 26, 27 },
|
||||
{ 28, 29, 30, 31, 32, 33 },
|
||||
{ 34, 35, 36, 37, 38, 39 }
|
||||
};
|
||||
BufferedImage outImage = createIntBufferedImage(output);
|
||||
final List<Boolean> started = Arrays.asList(new Boolean[] { Boolean.FALSE });
|
||||
final List<Float> percentDone = new ArrayList<Float>();
|
||||
final List<Boolean> completed = Arrays.asList(new Boolean[] { Boolean.FALSE });
|
||||
final List<Boolean> aborted = Arrays.asList(new Boolean[] { Boolean.FALSE });
|
||||
IIOReadProgressListener listener = new IIOReadProgressListener() {
|
||||
public void sequenceStarted(ImageReader source, int minIndex) {
|
||||
}
|
||||
|
||||
public void sequenceComplete(ImageReader source) {
|
||||
}
|
||||
|
||||
public void imageStarted(ImageReader source, int imageIndex) {
|
||||
started.set(0, Boolean.TRUE);
|
||||
}
|
||||
|
||||
public void imageProgress(ImageReader source, float percentageDone) {
|
||||
percentDone.add(percentageDone);
|
||||
}
|
||||
|
||||
public void imageComplete(ImageReader source) {
|
||||
completed.set(0, Boolean.TRUE);
|
||||
}
|
||||
|
||||
public void thumbnailStarted(ImageReader source, int imageIndex, int thumbnailIndex) {
|
||||
}
|
||||
|
||||
public void thumbnailProgress(ImageReader source, float percentageDone) {
|
||||
}
|
||||
|
||||
public void thumbnailComplete(ImageReader source) {
|
||||
}
|
||||
|
||||
public void readAborted(ImageReader source) {
|
||||
aborted.set(0, Boolean.TRUE);
|
||||
}
|
||||
};
|
||||
readBufferedImage(writeBufferedImage(outImage), listener);
|
||||
assertTrue(started.get(0));
|
||||
assertTrue(completed.get(0));
|
||||
assertFalse(aborted.get(0));
|
||||
assertEquals(5, percentDone.size());
|
||||
assertEquals(80.0f, percentDone.get(percentDone.size() - 1), 0.1f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read into second band (index 1) of RGB destination image.
|
||||
*/
|
||||
@Test
|
||||
public void testRead27() throws IOException {
|
||||
int[][][] output = {
|
||||
{ { 0, 0, 0 }, { 0, +1, 0 }, { 0, +2, 0 } },
|
||||
{ { 0, 3, 0 }, { 0, +4, 0 }, { 0, +5, 0 } },
|
||||
{ { 0, 6, 0 }, { 0, +7, 0 }, { 0, +8, 0 } },
|
||||
{ { 0, 9, 0 }, { 0, 10, 0 }, { 0, 11, 0 } }
|
||||
};
|
||||
int[][][] expected = output;
|
||||
|
||||
BufferedImage outImage = createIntRgbBufferedImage(output);
|
||||
ImageWriteParam outParam = createImageWriteParam();
|
||||
outParam.setSourceBands(new int[] { 1 });
|
||||
CbfMetadata outMdata = new CbfMetadata();
|
||||
outMdata.setDataElementType(CbfElementType.SIGNED_32_BIT_INTEGER);
|
||||
byte[] outBytes = writeBufferedImage(outImage, outMdata, outParam);
|
||||
BufferedImage inImage = createIntRgbBufferedImage(expected[0].length, expected.length);
|
||||
ImageReadParam inParam = createImageReadParam();
|
||||
inParam.setDestination(inImage);
|
||||
inParam.setDestinationBands(new int[] { 1 });
|
||||
BufferedImage inImage2 = readBufferedImage(outBytes, inParam);
|
||||
assertSame(inImage, inImage2);
|
||||
assertArrayEquals(expected, getIntRgbPixels(inImage));
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* I test <code>CbfImageWriterSpi</code>.
|
||||
*/
|
||||
public class CbfImageWriterSpiTest extends TestUtils {
|
||||
@Test
|
||||
public void testCanEncodeImage01() {
|
||||
CbfImageWriterSpi spi = new CbfImageWriterSpi();
|
||||
assertTrue(spi.canEncodeImage(createByteBinarySpecifier()));
|
||||
assertTrue(spi.canEncodeImage(createUbyteSpecifier()));
|
||||
assertTrue(spi.canEncodeImage(createByteSpecifier()));
|
||||
assertTrue(spi.canEncodeImage(createUshortSpecifier()));
|
||||
assertTrue(spi.canEncodeImage(createShortSpecifier()));
|
||||
assertTrue(spi.canEncodeImage(createIntSpecifier()));
|
||||
assertTrue(spi.canEncodeImage(createFloatSpecifier()));
|
||||
assertTrue(spi.canEncodeImage(createDoubleSpecifier()));
|
||||
}
|
||||
}
|
1731
ch.psi.imagej.cbf/src/test/java/imcacat/jcbf/CbfImageWriterTest.java
Normal file
1731
ch.psi.imagej.cbf/src/test/java/imcacat/jcbf/CbfImageWriterTest.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* I test <code>CbfMetadata</code>.
|
||||
*/
|
||||
public class CbfMetadataTest extends TestUtils {
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testSetHeaderDetector01() {
|
||||
CbfMetadata mdata = new CbfMetadata();
|
||||
mdata.setHeaderDetector("PILATUS 6M\r\nHosed");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetHeaderDetector02() {
|
||||
CbfMetadata mdata = new CbfMetadata();
|
||||
mdata.setHeaderDetector(null);
|
||||
assertNull(mdata.getHeaderDetectorName());
|
||||
assertNull(mdata.getHeaderDetectorSerialNumber());
|
||||
assertNull(mdata.getHeaderDetectorDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetHeaderDetector03() {
|
||||
CbfMetadata mdata = new CbfMetadata();
|
||||
mdata.setHeaderDetector("PILATUS 6M, 60-0002, IMCA-CAT");
|
||||
assertEquals("PILATUS 6M", mdata.getHeaderDetectorName());
|
||||
assertEquals("60-0002", mdata.getHeaderDetectorSerialNumber());
|
||||
assertEquals("IMCA-CAT", mdata.getHeaderDetectorDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetHeaderDetector04() {
|
||||
CbfMetadata mdata = new CbfMetadata();
|
||||
mdata.setHeaderDetector("PILATUS 6M, 60-0001, X06SA@SLS");
|
||||
assertEquals("PILATUS 6M", mdata.getHeaderDetectorName());
|
||||
assertEquals("60-0001", mdata.getHeaderDetectorSerialNumber());
|
||||
assertEquals("X06SA@SLS", mdata.getHeaderDetectorDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetHeaderDetector05() {
|
||||
CbfMetadata mdata = new CbfMetadata();
|
||||
mdata.setHeaderDetector("PILATUS 6M SN: 60-0003");
|
||||
assertEquals("PILATUS 6M", mdata.getHeaderDetectorName());
|
||||
assertEquals("60-0003", mdata.getHeaderDetectorSerialNumber());
|
||||
assertNull(mdata.getHeaderDetectorDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetHeaderDetector06() {
|
||||
CbfMetadata mdata = new CbfMetadata();
|
||||
mdata.setHeaderDetector("PILATUS 6M IMCA-CAT");
|
||||
assertNull(mdata.getHeaderDetectorName());
|
||||
assertNull(mdata.getHeaderDetectorSerialNumber());
|
||||
assertNull(mdata.getHeaderDetectorDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAsTree01() {
|
||||
(new CbfMetadata()).getAsTree(CbfMetadata.NATIVE_FORMAT_NAME);
|
||||
}
|
||||
}
|
474
ch.psi.imagej.cbf/src/test/java/imcacat/jcbf/TestUtils.java
Normal file
474
ch.psi.imagej.cbf/src/test/java/imcacat/jcbf/TestUtils.java
Normal file
@ -0,0 +1,474 @@
|
||||
/*
|
||||
* Copyright (c) 2011 J. Lewis Muir <jlmuir@imca.aps.anl.gov>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package imcacat.jcbf;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import javax.imageio.IIOImage;
|
||||
import javax.imageio.ImageReadParam;
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.ImageWriteParam;
|
||||
import javax.imageio.event.IIOReadProgressListener;
|
||||
import javax.imageio.event.IIOWriteProgressListener;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
import javax.imageio.stream.MemoryCacheImageInputStream;
|
||||
import javax.imageio.stream.MemoryCacheImageOutputStream;
|
||||
|
||||
/**
|
||||
* I provide utility methods for use in testing.
|
||||
*/
|
||||
public class TestUtils {
|
||||
public static ImageInputStream streamFromString(String s) {
|
||||
return streamFromBytes(asciiBytes(s));
|
||||
}
|
||||
|
||||
public static ImageInputStream streamFromBytes(byte[] b) {
|
||||
return new MemoryCacheImageInputStream(new ByteArrayInputStream(b));
|
||||
}
|
||||
|
||||
public static byte[] asciiBytes(String value) {
|
||||
try {
|
||||
return value.getBytes("US-ASCII");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
fail(e.toString());
|
||||
return new byte[] {};
|
||||
}
|
||||
}
|
||||
|
||||
protected static String createImageText() {
|
||||
return "###CBF: VERSION 1.5, CBFlib v0.7.8 - SLS/DECTRIS PILATUS detectors\r\n"
|
||||
+ "\r\n"
|
||||
+ "data_thaumatin_0001\r\n"
|
||||
+ "\r\n"
|
||||
+ "_array_data.header_convention \"SLS_1.0\"\r\n"
|
||||
+ "_array_data.header_contents\r\n"
|
||||
+ ";\r\n"
|
||||
+ "# Detector: PILATUS 6M, 60-0103, IMCA-CAT\r\n"
|
||||
+ "# 2010-Nov-17T15:52:30.834\r\n"
|
||||
+ "# Pixel_size 172e-6 m x 172e-6 m\r\n"
|
||||
+ "# Silicon sensor, thickness 0.000320 m\r\n"
|
||||
+ "# Exposure_time 0.081033 s\r\n"
|
||||
+ "# Exposure_period 0.083333 s\r\n"
|
||||
+ "# Tau = 124.0e-09 s\r\n"
|
||||
+ "# Count_cutoff 326741 counts\r\n"
|
||||
+ "# Threshold_setting 7439 eV\r\n"
|
||||
+ "# Gain_setting not implemented (vrf = 9.900)\r\n"
|
||||
+ "# N_excluded_pixels = 2391\r\n"
|
||||
+ "# Excluded_pixels: badpix_mask.tif\r\n"
|
||||
+ "# Flat_field: (nil)\r\n"
|
||||
+ "# Trim_directory: \r\n"
|
||||
+ "# Wavelength 1.0000 A\r\n"
|
||||
+ "# Energy_range (0, 0) eV\r\n"
|
||||
+ "# Detector_distance 0.94997 m\r\n"
|
||||
+ "# Detector_Voffset 0.00000 m\r\n"
|
||||
+ "# Beam_xy (1253.00, 1288.00) pixels\r\n"
|
||||
+ "# Flux 0.0000 ph/s\r\n"
|
||||
+ "# Filter_transmission 0.0000\r\n"
|
||||
+ "# Start_angle 0.0000 deg.\r\n"
|
||||
+ "# Angle_increment 1.0000 deg.\r\n"
|
||||
+ "# Detector_2theta 0.0007 deg.\r\n"
|
||||
+ "# Polarization 0.990\r\n"
|
||||
+ "# Alpha 0.0000 deg.\r\n"
|
||||
+ "# Kappa 0.0000 deg.\r\n"
|
||||
+ "# Phi 0.0000 deg.\r\n"
|
||||
+ "# Chi 0.0000 deg.\r\n"
|
||||
+ "# Oscillation_axis X, CW\r\n"
|
||||
+ "# N_oscillations 1\r\n"
|
||||
+ ";\r\n"
|
||||
+ "\r\n"
|
||||
+ "_array_data.data\r\n"
|
||||
+ ";\r\n"
|
||||
+ "--CIF-BINARY-FORMAT-SECTION--\r\n"
|
||||
+ "Content-Type: application/octet-stream;\r\n"
|
||||
+ " conversions=\"x-CBF_BYTE_OFFSET\"\r\n"
|
||||
+ "Content-Transfer-Encoding: BINARY\r\n"
|
||||
+ "X-Binary-Size: 6224001\r\n"
|
||||
+ "X-Binary-ID: 1\r\n"
|
||||
+ "X-Binary-Element-Type: \"signed 32-bit integer\"\r\n"
|
||||
+ "X-Binary-Element-Byte-Order: LITTLE_ENDIAN\r\n"
|
||||
+ "Content-MD5: Ti67wd6I6DPuGIsOnMalMw==\r\n"
|
||||
+ "X-Binary-Number-of-Elements: 6224001\r\n"
|
||||
+ "X-Binary-Size-Fastest-Dimension: 2463\r\n"
|
||||
+ "X-Binary-Size-Second-Dimension: 2527\r\n"
|
||||
+ "X-Binary-Size-Padding: 4095\r\n"
|
||||
+ "\r\n";
|
||||
}
|
||||
|
||||
protected static byte[] createImageWithoutData() {
|
||||
return createImageWithoutData(asciiBytes(createImageText()));
|
||||
}
|
||||
|
||||
protected static byte[] createImageWithoutData(byte[] text) {
|
||||
byte[] result = new byte[text.length + 4];
|
||||
System.arraycopy(text, 0, result, 0, text.length);
|
||||
result[result.length - 4] = 0x0C;
|
||||
result[result.length - 3] = 0x1A;
|
||||
result[result.length - 2] = 0x04;
|
||||
result[result.length - 1] = (byte)0xD5;
|
||||
return result;
|
||||
}
|
||||
|
||||
protected static ImageInputStream createInputStream(byte[] cbf) {
|
||||
return new MemoryCacheImageInputStream(new ByteArrayInputStream(cbf));
|
||||
}
|
||||
|
||||
protected static BufferedImage createByteBinaryBufferedImage(byte[][] pixels) {
|
||||
BufferedImage image = createByteBinaryBufferedImage(pixels[0].length, pixels.length);
|
||||
WritableRaster raster = image.getRaster();
|
||||
for (int y = 0; y < pixels.length; y++) {
|
||||
for (int x = 0; x < pixels[0].length; x++) {
|
||||
raster.setSample(x, y, 0, pixels[y][x]);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
protected static BufferedImage createByteBinaryBufferedImage(int width, int height) {
|
||||
return createByteBinarySpecifier().createBufferedImage(width, height);
|
||||
}
|
||||
|
||||
protected static ImageTypeSpecifier createByteBinarySpecifier() {
|
||||
return ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_BINARY);
|
||||
}
|
||||
|
||||
protected static BufferedImage createUbyteBufferedImage(short[][] pixels) {
|
||||
BufferedImage image = createUbyteBufferedImage(pixels[0].length, pixels.length);
|
||||
WritableRaster raster = image.getRaster();
|
||||
for (int y = 0; y < pixels.length; y++) {
|
||||
for (int x = 0; x < pixels[0].length; x++) {
|
||||
raster.setSample(x, y, 0, pixels[y][x]);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
protected static BufferedImage createUbyteBufferedImage(int width, int height) {
|
||||
return createUbyteSpecifier().createBufferedImage(width, height);
|
||||
}
|
||||
|
||||
protected static ImageTypeSpecifier createUbyteSpecifier() {
|
||||
return ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY);
|
||||
}
|
||||
|
||||
protected static BufferedImage createByteBufferedImage(byte[][] pixels) {
|
||||
BufferedImage image = createByteBufferedImage(pixels[0].length, pixels.length);
|
||||
WritableRaster raster = image.getRaster();
|
||||
for (int y = 0; y < pixels.length; y++) {
|
||||
for (int x = 0; x < pixels[0].length; x++) {
|
||||
raster.setSample(x, y, 0, pixels[y][x]);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
protected static BufferedImage createByteBufferedImage(int width, int height) {
|
||||
return createByteSpecifier().createBufferedImage(width, height);
|
||||
}
|
||||
|
||||
protected static ImageTypeSpecifier createByteSpecifier() {
|
||||
/*
|
||||
* The type DataBuffer.TYPE_BYTE is for unsigned byte data so must use
|
||||
* DataBuffer.TYPE_SHORT. ImageTypeSpecifier.createGrayscale does not
|
||||
* support 8 bits with DataBuffer.TYPE_SHORT, so must use 16.
|
||||
*/
|
||||
return ImageTypeSpecifier.createGrayscale(16, DataBuffer.TYPE_SHORT, true);
|
||||
}
|
||||
|
||||
protected static BufferedImage createUshortBufferedImage(int[][] pixels) {
|
||||
BufferedImage image = createUshortBufferedImage(pixels[0].length, pixels.length);
|
||||
WritableRaster raster = image.getRaster();
|
||||
for (int y = 0; y < pixels.length; y++) {
|
||||
for (int x = 0; x < pixels[0].length; x++) {
|
||||
raster.setSample(x, y, 0, pixels[y][x]);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
protected static BufferedImage createUshortBufferedImage(int width, int height) {
|
||||
return createUshortSpecifier().createBufferedImage(width, height);
|
||||
}
|
||||
|
||||
protected static ImageTypeSpecifier createUshortSpecifier() {
|
||||
return ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_USHORT_GRAY);
|
||||
}
|
||||
|
||||
protected static BufferedImage createShortBufferedImage(short[][] pixels) {
|
||||
BufferedImage image = createShortBufferedImage(pixels[0].length, pixels.length);
|
||||
WritableRaster raster = image.getRaster();
|
||||
for (int y = 0; y < pixels.length; y++) {
|
||||
for (int x = 0; x < pixels[0].length; x++) {
|
||||
raster.setSample(x, y, 0, pixels[y][x]);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
protected static BufferedImage createShortBufferedImage(int width, int height) {
|
||||
return createShortSpecifier().createBufferedImage(width, height);
|
||||
}
|
||||
|
||||
protected static ImageTypeSpecifier createShortSpecifier() {
|
||||
return ImageTypeSpecifier.createGrayscale(16, DataBuffer.TYPE_SHORT, true);
|
||||
}
|
||||
|
||||
protected static BufferedImage createIntBufferedImage(int[][] pixels) {
|
||||
BufferedImage image = createIntBufferedImage(pixels[0].length, pixels.length);
|
||||
WritableRaster raster = image.getRaster();
|
||||
for (int y = 0; y < pixels.length; y++) {
|
||||
for (int x = 0; x < pixels[0].length; x++) {
|
||||
raster.setSample(x, y, 0, pixels[y][x]);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
protected static BufferedImage createIntBufferedImage(int width, int height) {
|
||||
return createIntSpecifier().createBufferedImage(width, height);
|
||||
}
|
||||
|
||||
protected static ImageTypeSpecifier createIntSpecifier() {
|
||||
return ImageTypeSpecifier.createInterleaved(ColorSpace.getInstance(ColorSpace.CS_GRAY),
|
||||
new int[] { 0 }, DataBuffer.TYPE_INT, false, false);
|
||||
}
|
||||
|
||||
protected static BufferedImage createIntRgbBufferedImage(int[][][] rgbPixels) {
|
||||
BufferedImage image = createIntRgbBufferedImage(rgbPixels[0].length, rgbPixels.length);
|
||||
WritableRaster raster = image.getRaster();
|
||||
for (int y = 0; y < rgbPixels.length; y++) {
|
||||
for (int x = 0; x < rgbPixels[0].length; x++) {
|
||||
raster.setPixel(x, y, rgbPixels[y][x]);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
protected static BufferedImage createIntRgbBufferedImage(int width, int height) {
|
||||
return createIntRgbSpecifier().createBufferedImage(width, height);
|
||||
}
|
||||
|
||||
protected static ImageTypeSpecifier createIntRgbSpecifier() {
|
||||
return ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
|
||||
}
|
||||
|
||||
protected static BufferedImage createFloatBufferedImage(float[][] pixels) {
|
||||
BufferedImage image = createFloatBufferedImage(pixels[0].length, pixels.length);
|
||||
WritableRaster raster = image.getRaster();
|
||||
for (int y = 0; y < pixels.length; y++) {
|
||||
for (int x = 0; x < pixels[0].length; x++) {
|
||||
raster.setSample(x, y, 0, pixels[y][x]);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
protected static BufferedImage createFloatBufferedImage(int width, int height) {
|
||||
return createFloatSpecifier().createBufferedImage(width, height);
|
||||
}
|
||||
|
||||
protected static ImageTypeSpecifier createFloatSpecifier() {
|
||||
return ImageTypeSpecifier.createInterleaved(ColorSpace.getInstance(ColorSpace.CS_GRAY),
|
||||
new int[] { 0 }, DataBuffer.TYPE_FLOAT, false, false);
|
||||
}
|
||||
|
||||
protected static BufferedImage createDoubleBufferedImage(double[][] pixels) {
|
||||
BufferedImage image = createDoubleBufferedImage(pixels[0].length, pixels.length);
|
||||
WritableRaster raster = image.getRaster();
|
||||
for (int y = 0; y < pixels.length; y++) {
|
||||
for (int x = 0; x < pixels[0].length; x++) {
|
||||
raster.setSample(x, y, 0, pixels[y][x]);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
protected static BufferedImage createDoubleBufferedImage(int width, int height) {
|
||||
return createDoubleSpecifier().createBufferedImage(width, height);
|
||||
}
|
||||
|
||||
protected static ImageTypeSpecifier createDoubleSpecifier() {
|
||||
return ImageTypeSpecifier.createInterleaved(ColorSpace.getInstance(ColorSpace.CS_GRAY),
|
||||
new int[] { 0 }, DataBuffer.TYPE_DOUBLE, false, false);
|
||||
}
|
||||
|
||||
protected static byte[][] getBytePixels(BufferedImage image) {
|
||||
byte[][] pixels = new byte[image.getHeight()][image.getWidth()];
|
||||
Raster raster = image.getData();
|
||||
for (int y = 0; y < pixels.length; y++) {
|
||||
for (int x = 0; x < pixels[0].length; x++) {
|
||||
pixels[y][x] = (byte)raster.getSample(x, y, 0);
|
||||
}
|
||||
}
|
||||
return pixels;
|
||||
}
|
||||
|
||||
protected static short[][] getShortPixels(BufferedImage image) {
|
||||
short[][] pixels = new short[image.getHeight()][image.getWidth()];
|
||||
Raster raster = image.getData();
|
||||
for (int y = 0; y < pixels.length; y++) {
|
||||
for (int x = 0; x < pixels[0].length; x++) {
|
||||
pixels[y][x] = (short)raster.getSample(x, y, 0);
|
||||
}
|
||||
}
|
||||
return pixels;
|
||||
}
|
||||
|
||||
protected static int[][] getIntPixels(BufferedImage image) {
|
||||
int[][] pixels = new int[image.getHeight()][image.getWidth()];
|
||||
Raster raster = image.getData();
|
||||
for (int y = 0; y < pixels.length; y++) {
|
||||
for (int x = 0; x < pixels[0].length; x++) {
|
||||
pixels[y][x] = raster.getSample(x, y, 0);
|
||||
}
|
||||
}
|
||||
return pixels;
|
||||
}
|
||||
|
||||
protected static int[][][] getIntRgbPixels(BufferedImage image) {
|
||||
int[][][] pixels = new int[image.getHeight()][image.getWidth()][3];
|
||||
Raster raster = image.getData();
|
||||
for (int y = 0; y < pixels.length; y++) {
|
||||
for (int x = 0; x < pixels[0].length; x++) {
|
||||
raster.getPixel(x, y, pixels[y][x]);
|
||||
}
|
||||
}
|
||||
return pixels;
|
||||
}
|
||||
|
||||
protected static float[][] getFloatPixels(BufferedImage image) {
|
||||
float[][] pixels = new float[image.getHeight()][image.getWidth()];
|
||||
Raster raster = image.getData();
|
||||
for (int y = 0; y < pixels.length; y++) {
|
||||
for (int x = 0; x < pixels[0].length; x++) {
|
||||
pixels[y][x] = raster.getSampleFloat(x, y, 0);
|
||||
}
|
||||
}
|
||||
return pixels;
|
||||
}
|
||||
|
||||
protected static double[][] getDoublePixels(BufferedImage image) {
|
||||
double[][] pixels = new double[image.getHeight()][image.getWidth()];
|
||||
Raster raster = image.getData();
|
||||
for (int y = 0; y < pixels.length; y++) {
|
||||
for (int x = 0; x < pixels[0].length; x++) {
|
||||
pixels[y][x] = raster.getSampleDouble(x, y, 0);
|
||||
}
|
||||
}
|
||||
return pixels;
|
||||
}
|
||||
|
||||
protected static BufferedImage readBufferedImage(byte[] input) throws IOException {
|
||||
return readBufferedImage(input, null, null);
|
||||
}
|
||||
|
||||
protected static BufferedImage readBufferedImage(byte[] input, ImageReadParam param)
|
||||
throws IOException {
|
||||
return readBufferedImage(input, param, null);
|
||||
}
|
||||
|
||||
protected static BufferedImage readBufferedImage(byte[] input, IIOReadProgressListener listener)
|
||||
throws IOException {
|
||||
return readBufferedImage(input, null, listener);
|
||||
}
|
||||
|
||||
protected static BufferedImage readBufferedImage(byte[] input, ImageReadParam param,
|
||||
IIOReadProgressListener listener)
|
||||
throws IOException {
|
||||
return (BufferedImage)readBufferedImageAndMetadata(input, param, listener)[0];
|
||||
}
|
||||
|
||||
protected static Object[] readBufferedImageAndMetadata(byte[] input) throws IOException {
|
||||
return readBufferedImageAndMetadata(input, null, null);
|
||||
}
|
||||
|
||||
protected static Object[] readBufferedImageAndMetadata(byte[] input, ImageReadParam param,
|
||||
IIOReadProgressListener listener) throws IOException {
|
||||
ByteArrayInputStream inBytesStream = new ByteArrayInputStream(input);
|
||||
ImageInputStream inStream = new MemoryCacheImageInputStream(inBytesStream);
|
||||
CbfImageReader reader = createReader();
|
||||
if (listener != null) reader.addIIOReadProgressListener(listener);
|
||||
reader.setInput(inStream);
|
||||
BufferedImage result = reader.read(0, param);
|
||||
CbfMetadata mdata = (CbfMetadata)reader.getImageMetadata(0);
|
||||
if (listener != null) reader.removeIIOReadProgressListener(listener);
|
||||
return new Object[] { result, mdata };
|
||||
}
|
||||
|
||||
protected static CbfImageReader createReader() throws IOException {
|
||||
return (CbfImageReader)((new CbfImageReaderSpi()).createReaderInstance());
|
||||
}
|
||||
|
||||
protected static byte[] writeBufferedImage(BufferedImage image) throws IOException {
|
||||
return writeBufferedImage(image, null, null, null);
|
||||
}
|
||||
|
||||
protected static byte[] writeBufferedImage(BufferedImage image, CbfMetadata mdata)
|
||||
throws IOException {
|
||||
return writeBufferedImage(image, mdata, null);
|
||||
}
|
||||
|
||||
protected static byte[] writeBufferedImage(BufferedImage image, ImageWriteParam param)
|
||||
throws IOException {
|
||||
return writeBufferedImage(image, null, param);
|
||||
}
|
||||
|
||||
protected static byte[] writeBufferedImage(BufferedImage image, ImageWriteParam param,
|
||||
IIOWriteProgressListener listener) throws IOException {
|
||||
return writeBufferedImage(image, null, param, listener);
|
||||
}
|
||||
|
||||
protected static byte[] writeBufferedImage(BufferedImage image, CbfMetadata mdata,
|
||||
ImageWriteParam param) throws IOException {
|
||||
return writeBufferedImage(image, mdata, param, null);
|
||||
}
|
||||
|
||||
protected static byte[] writeBufferedImage(BufferedImage image, CbfMetadata mdata,
|
||||
ImageWriteParam param, IIOWriteProgressListener listener) throws IOException {
|
||||
ByteArrayOutputStream outBytesStream = new ByteArrayOutputStream();
|
||||
ImageOutputStream outStream = new MemoryCacheImageOutputStream(outBytesStream);
|
||||
CbfImageWriterSpi writerSpi = new CbfImageWriterSpi();
|
||||
CbfImageWriter writer = (CbfImageWriter)writerSpi.createWriterInstance();
|
||||
if (listener != null) writer.addIIOWriteProgressListener(listener);
|
||||
writer.setOutput(outStream);
|
||||
writer.write(null, new IIOImage(image, null, mdata), param);
|
||||
if (listener != null) writer.removeIIOWriteProgressListener(listener);
|
||||
return outBytesStream.toByteArray();
|
||||
}
|
||||
|
||||
protected static ImageReadParam createImageReadParam() throws IOException {
|
||||
CbfImageReaderSpi spi = new CbfImageReaderSpi();
|
||||
CbfImageReader reader = (CbfImageReader)spi.createReaderInstance();
|
||||
return reader.getDefaultReadParam();
|
||||
}
|
||||
|
||||
protected static ImageWriteParam createImageWriteParam() throws IOException {
|
||||
CbfImageWriterSpi spi = new CbfImageWriterSpi();
|
||||
CbfImageWriter writer = (CbfImageWriter)spi.createWriterInstance();
|
||||
return writer.getDefaultWriteParam();
|
||||
}
|
||||
}
|
0
ch.psi.imagej.cbf/src/test/resources/.gitignore
vendored
Normal file
0
ch.psi.imagej.cbf/src/test/resources/.gitignore
vendored
Normal file
Loading…
x
Reference in New Issue
Block a user