Initial commit

This commit is contained in:
ebner 2014-03-28 15:08:05 +01:00
commit 378d929a00
36 changed files with 7569 additions and 0 deletions

View 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
View File

@ -0,0 +1 @@
/target

View 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>

View File

@ -0,0 +1,3 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/test/java=UTF-8

View 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

View File

@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

View 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).

View 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
View 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>

View 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 + "'");
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View 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;
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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";
}
}

View File

@ -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 };
}
}

View 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;
}
}

View File

@ -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";
}
}

View 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");
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View 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";
}

View File

View 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=");
}
}

View File

@ -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"));
}
}

View File

@ -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"));
}
}

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -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()));
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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);
}
}

View 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();
}
}

View File