Skip to content

Commit

Permalink
Merge branch 'ebremer:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
ebremer authored Aug 11, 2023
2 parents 125d357 + 195e2fc commit 58d5958
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 69 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Hatch 3.0.2
# Hatch 3.1.1


This tool converts the largest image in a VSI, SVS, or TIF image into a new TIFF image with a freshly created image pyramid with each scaling 1/2 dimensions each scale.

Expand Down
24 changes: 1 addition & 23 deletions dependency-reduced-pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>edu.stonybrook.bmi</groupId>
<artifactId>hatch</artifactId>
<version>3.0.2</version>
<version>3.1.1</version>
<build>
<resources>
<resource>
Expand Down Expand Up @@ -52,28 +52,6 @@
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>false</shadedArtifactAttached>
<transformers>
<transformer>
<mainClass>edu.stonybrook.bmi.hatch.Hatch</mainClass>
<manifestEntries>
<Multi-Release>true</Multi-Release>
</manifestEntries>
</transformer>
<transformer />
</transformers>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
<configuration>
Expand Down
12 changes: 6 additions & 6 deletions nbactions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
<properties>
<exec.vmArgs></exec.vmArgs>
<exec.args>${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}</exec.args>
<exec.appArgs>-v /svs/TCGA-5T-A9QA-01Z-00-DX1.B4212117-E0A7-4EF2-B324-8396042ACEC1.svs /svs/TCGA-5T-A9QA-01Z-00-DX1.B4212117-E0A7-4EF2-B324-8396042ACEC1.tif</exec.appArgs>
<exec.mainClass>edu.stonybrook.bmi.hatch.X2TIF</exec.mainClass>
<exec.appArgs>-s 0 -v -src /svs/test.svs -dest /svs/hold/text.tif -quality 0.1</exec.appArgs>
<exec.mainClass>edu.stonybrook.bmi.hatch.Hatch</exec.mainClass>
<exec.executable>java</exec.executable>
</properties>
</action>
Expand All @@ -29,8 +29,8 @@
<properties>
<exec.vmArgs>-agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address}</exec.vmArgs>
<exec.args>${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}</exec.args>
<exec.appArgs>-v /svs/TCGA-5T-A9QA-01Z-00-DX1.B4212117-E0A7-4EF2-B324-8396042ACEC1.svs /svs/TCGA-5T-A9QA-01Z-00-DX1.B4212117-E0A7-4EF2-B324-8396042ACEC1.tif</exec.appArgs>
<exec.mainClass>edu.stonybrook.bmi.hatch.X2TIF</exec.mainClass>
<exec.appArgs>-s 0 -v -src /svs/test.svs -dest /svs/hold/text.tif -quality 0.1</exec.appArgs>
<exec.mainClass>edu.stonybrook.bmi.hatch.Hatch</exec.mainClass>
<exec.executable>java</exec.executable>
<jpda.listen>true</jpda.listen>
</properties>
Expand All @@ -47,9 +47,9 @@
<properties>
<exec.vmArgs></exec.vmArgs>
<exec.args>${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}</exec.args>
<exec.mainClass>edu.stonybrook.bmi.hatch.X2TIF</exec.mainClass>
<exec.mainClass>edu.stonybrook.bmi.hatch.Hatch</exec.mainClass>
<exec.executable>java</exec.executable>
<exec.appArgs>-v /svs/TCGA-5T-A9QA-01Z-00-DX1.B4212117-E0A7-4EF2-B324-8396042ACEC1.svs /svs/TCGA-5T-A9QA-01Z-00-DX1.B4212117-E0A7-4EF2-B324-8396042ACEC1.tif</exec.appArgs>
<exec.appArgs>-s 0 -v -src /svs/test.svs -dest /svs/hold/text.tif -quality 0.1</exec.appArgs>
</properties>
</action>
</actions>
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>edu.stonybrook.bmi</groupId>
<artifactId>hatch</artifactId>
<version>3.0.2</version>
<version>3.1.1</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down
58 changes: 48 additions & 10 deletions src/main/java/edu/stonybrook/bmi/hatch/Hatch.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* @author erich
*/
public class Hatch {
public static String software = "hatch 3.0.2 by Wing-n-Beak";
public static String software = "hatch 3.1.1 by Wing-n-Beak";
private static final String[] ext = new String[] {".vsi", ".svs", ".tif"};
public static final String HELP = Hatch.software+"\n"+
"""
Expand Down Expand Up @@ -73,13 +73,19 @@ private static void Traverse(HatchParameters params) {
engine.shutdown();
}

private static String getFileNameBase(File file) {
String tail = file.getName();
return tail.substring(0,tail.length()-4);
}

public static void main(String[] args) {
loci.common.DebugTools.setRootLevel("WARN");
HatchParameters params = new HatchParameters();
JCommander jc = JCommander.newBuilder().addObject(params).build();
jc.setProgramName(Hatch.software+"\nhatch");
jc.setProgramName(Hatch.software+"\nhatch");
try {
jc.parse(args);
System.out.println(params);
if (params.isHelp()) {
jc.usage();
System.exit(0);
Expand All @@ -91,26 +97,58 @@ public static void main(String[] args) {
if (!params.dest.isDirectory()) {
jc.usage();
} else {
params.series.clear(); // ignore series parameter
Traverse(params);
}
} else {
// Source is a single file
if (!params.dest.exists()&&(!params.dest.toString().toLowerCase().endsWith(".tif"))) {
params.dest.mkdirs();
}
if (params.dest.exists()) {
if (!params.dest.isDirectory()) {
params.dest.delete();
try (X2TIF v2t = new X2TIF(params, params.src.toString(), params.dest.toString())){
v2t.Execute();
} catch (Exception ex) {
Logger.getLogger(Hatch.class.getName()).log(Level.SEVERE, null, ex);
if (params.series.size()>1) {
jc.usage();
} else {
Integer series = null;
if (params.series.size()==1) {
series = Integer.valueOf(params.series.get(0));
}
try (X2TIF v2t = new X2TIF(params, params.src.toString(), params.dest.toString(), series)){
v2t.Execute();
} catch (Exception ex) {
Logger.getLogger(Hatch.class.getName()).log(Level.SEVERE, null, ex);
}
}
} else {
jc.usage();
// destination is a directory
if (params.series.isEmpty()) {
File dest = Path.of(params.dest.toString(),getFileNameBase(params.src)+".tif").toFile();
try (X2TIF v2t = new X2TIF(params, params.src.toString(), dest.toString(), null);) {
v2t.Execute();
} catch (Exception ex) {
Logger.getLogger(Hatch.class.getName()).log(Level.SEVERE, null, ex);
}
} else {
params.series.forEach(s->{
File dest = Path.of(params.dest.toString(),getFileNameBase(params.src)+"-series-"+s+".tif").toFile();
try (X2TIF v2t = new X2TIF(params, params.src.toString(), dest.toString(), Integer.valueOf(s));) {
v2t.Execute();
} catch (Exception ex) {
Logger.getLogger(Hatch.class.getName()).log(Level.SEVERE, null, ex);
}
});
}
}
} else {
try (X2TIF v2t = new X2TIF(params, params.src.toString(), params.dest.toString());) {
// Source and destination are a file
params.series.clear(); // ignore series parameter
try (X2TIF v2t = new X2TIF(params, params.src.toString(), params.dest.toString(), null);) {
v2t.Execute();
} catch (Exception ex) {
Logger.getLogger(Hatch.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
} else {
Expand Down Expand Up @@ -140,7 +178,7 @@ public String call() {
} else {
dest.getParentFile().mkdirs();
}
try (X2TIF v2t = new X2TIF(params, src.toString(), dest.toString())) {
try (X2TIF v2t = new X2TIF(params, src.toString(), dest.toString(), null)) {
v2t.Execute();
} catch (Exception ex) {
System.out.println("FILE PROCESSOR ERROR --> "+src+" "+dest+" "+ex.toString());
Expand Down
16 changes: 10 additions & 6 deletions src/main/java/edu/stonybrook/bmi/hatch/HatchParameters.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,20 @@ public boolean isHelp() {

@Parameter(names = "-cores", description = "# of cores for processing")
public int cores = Runtime.getRuntime().availableProcessors();

@Parameter
public List<String> parameters = Lists.newArrayList();


@Parameter(names = {"-v","-verbose"})
public boolean verbose = false;

@Parameter(names = "-meta")
public boolean meta = false;
//@Parameter(names = "-meta")
//public boolean meta = false;

@Parameter(names = "-jp2", hidden = true)
public boolean jp2 = false;

@Parameter(names = {"-quality","-q"}, description = "pyramid JPEG compression quality 0.0 < q <1.0")
public float quality = 1.0f;

@Parameter(names = {"-s","-series"}, description = "specify source series separated by commas")
public List<String> series = Lists.newArrayList();

}
18 changes: 12 additions & 6 deletions src/main/java/edu/stonybrook/bmi/hatch/Pyramid.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package edu.stonybrook.bmi.hatch;

import static edu.stonybrook.bmi.hatch.Pyramid.CompressionSize;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.geom.AffineTransform;
Expand Down Expand Up @@ -37,7 +36,6 @@ public class Pyramid {
private final int tileSizeX;
private final int tileSizeY;
private int xscale = 0;
public static float CompressionSize = 0.70f;
public static float DownScale = 0.5f;
private int width;
private int height;
Expand All @@ -54,6 +52,10 @@ public Pyramid(HatchParameters params, int tilesX, int tilesY, int tileSizeX, in
tiles = new JPEGBuffer[tilesX][tilesY];
}

public HatchParameters getParameters() {
return params;
}

public int gettilesX() {
return tilesX;
}
Expand Down Expand Up @@ -99,7 +101,7 @@ public byte[] GetImageBytes(int a, int b) {
ImageWriteParam param = jpgWriter.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setProgressiveMode(ImageWriteParam.MODE_DISABLED);
param.setCompressionQuality(CompressionSize);
param.setCompressionQuality(params.quality);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
MemoryCacheImageOutputStream outputStream = new MemoryCacheImageOutputStream(baos);
outputStream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
Expand Down Expand Up @@ -146,7 +148,7 @@ public void Dump() throws FileNotFoundException, IOException {
ImageWriteParam param = jpgWriter.getDefaultWriteParam();
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
param.setProgressiveMode(ImageWriteParam.MODE_DISABLED);
param.setCompressionQuality(CompressionSize);
param.setCompressionQuality(params.quality);
FileOutputStream fos = new FileOutputStream("/vsi/whoa/"+xscale+"----"+a+"-"+b+".jpg");
ImageOutputStream stream = ImageIO.createImageOutputStream(fos);
jpgWriter.setOutput(stream);
Expand All @@ -166,7 +168,11 @@ public void Dump() throws FileNotFoundException, IOException {
}

public void put(BufferedImage bi, int x, int y) {
tiles[x][y] = new JPEGBuffer(bi,CompressionSize);
tiles[x][y] = new JPEGBuffer(bi,params.quality);
}

public void put(byte[] buffer, int x, int y) {
tiles[x][y] = new JPEGBuffer(buffer);
}

public void put(BufferedImage bi, int x, int y, float scale) {
Expand Down Expand Up @@ -310,7 +316,7 @@ public JPEGBuffer call() throws Exception {
}
int nx = a/2;
int ny = b/2;
neotiles[nx][ny] = new JPEGBuffer(Merge(nw,ne,sw,se),CompressionSize);
neotiles[nx][ny] = new JPEGBuffer(Merge(nw,ne,sw,se),pyramid.getParameters().quality);
} else {
throw new Error("NW TILE NULL!!!");
}
Expand Down
38 changes: 22 additions & 16 deletions src/main/java/edu/stonybrook/bmi/hatch/X2TIF.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,16 @@ public class X2TIF implements AutoCloseable {
private IMetadata meta;
private byte compression;

public X2TIF(HatchParameters params, String src, String dest) {
public X2TIF(HatchParameters params, String src, String dest, Integer series) {
time = new StopWatch();
inputFile = src;
outputFile = dest;
this.params = params;
try {
writer = new HatchWriter(dest);
} catch (IOException ex) {
Logger.getLogger(X2TIF.class.getName()).log(Level.SEVERE, null, ex);
}
if (params.meta) {
// if (params.meta) {
// m = ModelFactory.createDefaultModel();
} else {
// } else {
// m = null;
}
//}
if (params.verbose) {
System.out.println("initializing...");
}
Expand All @@ -100,7 +95,20 @@ public X2TIF(HatchParameters params, String src, String dest) {
}
reader.setMetadataStore(omexml);
reader.setId(inputFile);
maximage = MaxImage(reader);
if (series==null) {
maximage = MaxImage(reader);
} else {
maximage = series;
}
if ((series!=null)&&((series<0)||(series>reader.getSeriesCount()))) {
System.out.println("Series doesn't exist : "+src+" --> "+series);
System.exit(0);
}
try {
writer = new HatchWriter(dest);
} catch (IOException ex) {
Logger.getLogger(X2TIF.class.getName()).log(Level.SEVERE, null, ex);
}
reader.setSeries(maximage);
tileSizeX = reader.getOptimalTileWidth();
tileSizeY = reader.getOptimalTileHeight();
Expand Down Expand Up @@ -330,9 +338,10 @@ public void readWriteTiles() throws FormatException, IOException {
//Dump2File3(raw, x, y);
switch (compression) {
case 0:
BufferedImage bi = ImageIO.read(new ByteArrayInputStream(raw));
bi = bi.getSubimage(0, 0, effTileSizeX, effTileSizeY);
pyramid.put(bi, x, y);
//BufferedImage bi = ImageIO.read(new ByteArrayInputStream(raw));
//bi = bi.getSubimage(0, 0, effTileSizeX, effTileSizeY);
//pyramid.put(bi, x, y);
pyramid.put(raw, x, y);
break;
case 2:
try {
Expand Down Expand Up @@ -387,9 +396,6 @@ public void readWriteTiles() throws FormatException, IOException {
for (int y=0; y<pyramid.gettilesY(); y++) {
for (int x=0; x<pyramid.gettilesX(); x++) {
byte[] b = pyramid.GetImageBytes(x, y);
BufferedImage bi = pyramid.getBufferedImage(x, y);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(bi, "jpg", baos);
writer.writeIFDStrips(ifd, b, ((x==(pyramid.gettilesX()-1))&&(y==(pyramid.gettilesY()-1))&&(s==depth-1)), x*tileSizeX, y*tileSizeY);
}
}
Expand Down

0 comments on commit 58d5958

Please sign in to comment.