Skip to content

Commit 82a61de

Browse files
authored
Merge pull request #4380 from melissalinkert/gh-3644
Calculate resolution counts when generating pyramids with `bfconvert`
2 parents 3fa05af + 01b2e7a commit 82a61de

File tree

2 files changed

+121
-1
lines changed

2 files changed

+121
-1
lines changed

components/bio-formats-tools/src/loci/formats/tools/ImageConverter.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ public boolean testConvert(IFormatWriter writer, String[] args)
485485
// TODO: there may be other options not compatible with -precompressed
486486
if (precompressed &&
487487
(width_crop > 0 || height_crop > 0 ||
488-
pyramidResolutions > 1 ||
488+
pyramidScale > 1 || pyramidResolutions > 1 ||
489489
fillColor != null ||
490490
autoscale
491491
))
@@ -591,6 +591,23 @@ public boolean testConvert(IFormatWriter writer, String[] args)
591591
height = Math.min(reader.getSizeY(), height_crop);
592592
}
593593

594+
// want to generate a pyramid but no resolution count specified
595+
// calculate based upon the scale and image size
596+
// the tile size has not been yet been set on the writer,
597+
// and the writer needs a MetadataRetrieve with resolutions populated first
598+
if (pyramidScale > 1 && pyramidResolutions == 1) {
599+
pyramidResolutions = 0;
600+
int checkWidth = width;
601+
int checkHeight = height;
602+
while (checkWidth >= (int) Math.max(saveTileWidth, pyramidScale) &&
603+
checkHeight >= (int) Math.max(saveTileHeight, pyramidScale))
604+
{
605+
pyramidResolutions++;
606+
checkWidth /= pyramidScale;
607+
checkHeight /= pyramidScale;
608+
}
609+
}
610+
594611
if (channel >= reader.getEffectiveSizeC()) {
595612
throw new FormatException("Invalid channel '" + channel + "' (" +
596613
reader.getEffectiveSizeC() + " channels in source file)");
@@ -1230,6 +1247,12 @@ private void setupResolutions(IMetadata meta) {
12301247
int height = meta.getPixelsSizeY(series).getValue();
12311248
for (int i=1; i<pyramidResolutions; i++) {
12321249
int scale = (int) Math.pow(pyramidScale, i);
1250+
if (width < scale || height < scale) {
1251+
LOGGER.warn("Specified pyramid resolutions {} too large; adjusted to {}",
1252+
pyramidResolutions, i);
1253+
pyramidResolutions = i;
1254+
break;
1255+
}
12331256
((OMEPyramidStore) meta).setResolutionSizeX(
12341257
new PositiveInteger(width / scale), series, i);
12351258
((OMEPyramidStore) meta).setResolutionSizeY(

components/bio-formats-tools/test/loci/formats/tools/ImageConverterTest.java

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,103 @@ public void testConvertResolutionsSingleZ() throws FormatException, IOException
421421
assertEquals(meta.getPixelsSizeT(0).getValue().intValue(), 1);
422422
}
423423

424+
/**
425+
* Generate a pyramid with the defined number of resolutions.
426+
*/
427+
@Test
428+
public void testGenerateDefinedResolutions() throws FormatException, IOException {
429+
outFile = getOutFile("defined-pyramid.ome.tiff");
430+
String[] args = {
431+
"defined-pyramid&sizeX=8100&sizeY=7500.fake",
432+
"-pyramid-resolutions", "4",
433+
"-pyramid-scale", "2",
434+
outFile.getAbsolutePath()
435+
};
436+
resolutionCount = 4;
437+
assertConversion(args, outFile.getAbsolutePath(), 8100);
438+
439+
IMetadata meta = getOMEXMLMetadata(outFile);
440+
assertEquals(meta.getImageCount(), 1);
441+
}
442+
443+
/**
444+
* Generate a pyramid with downsample factor of 3.
445+
*/
446+
@Test
447+
public void testPyramidFactor3() throws FormatException, IOException {
448+
outFile = getOutFile("factor-3.ome.tiff");
449+
String[] args = {
450+
"factor-3&sizeX=8100&sizeY=7500.fake",
451+
"-pyramid-resolutions", "4",
452+
"-pyramid-scale", "3",
453+
outFile.getAbsolutePath()
454+
};
455+
resolutionCount = 4;
456+
assertConversion(args, outFile.getAbsolutePath(), 8100);
457+
458+
IMetadata meta = getOMEXMLMetadata(outFile);
459+
assertEquals(meta.getImageCount(), 1);
460+
}
461+
462+
/**
463+
* Generate a pyramid, where the defined number of resolutions is unreasonably large.
464+
*/
465+
@Test
466+
public void testGenerateTooManyResolutions() throws FormatException, IOException {
467+
outFile = getOutFile("big-pyramid.ome.tiff");
468+
String[] args = {
469+
"big-pyramid&sizeX=6073&sizeY=9247.fake",
470+
"-pyramid-resolutions", "20",
471+
"-pyramid-scale", "2",
472+
outFile.getAbsolutePath()
473+
};
474+
// 20 is too many, so the count should be reset
475+
resolutionCount = 13;
476+
assertConversion(args, outFile.getAbsolutePath(), 6073);
477+
478+
IMetadata meta = getOMEXMLMetadata(outFile);
479+
assertEquals(meta.getImageCount(), 1);
480+
}
481+
482+
/**
483+
* Generate a pyramid, but calculate internally how many resolutions are needed.
484+
*/
485+
@Test
486+
public void testGenerateCalculatedResolutions() throws FormatException, IOException {
487+
outFile = getOutFile("calculated-pyramid.ome.tiff");
488+
String[] args = {
489+
"calculated-pyramid&sizeX=7673&sizeY=1541.fake",
490+
"-pyramid-scale", "2",
491+
outFile.getAbsolutePath()
492+
};
493+
resolutionCount = 10;
494+
assertConversion(args, outFile.getAbsolutePath(), 7673);
495+
496+
IMetadata meta = getOMEXMLMetadata(outFile);
497+
assertEquals(meta.getImageCount(), 1);
498+
}
499+
500+
/**
501+
* Generate a pyramid, but calculate internally how many resolutions are needed
502+
* based on specified tile size.
503+
*/
504+
@Test
505+
public void testGenerateCalculatedResolutionsByTileSize() throws FormatException, IOException {
506+
outFile = getOutFile("tile-size-calculated-pyramid.ome.tiff");
507+
String[] args = {
508+
"calculated-pyramid&sizeX=7673&sizeY=1541.fake",
509+
"-pyramid-scale", "2",
510+
"-tilex", "512",
511+
"-tiley", "512",
512+
outFile.getAbsolutePath()
513+
};
514+
resolutionCount = 2;
515+
assertConversion(args, outFile.getAbsolutePath(), 7673);
516+
517+
IMetadata meta = getOMEXMLMetadata(outFile);
518+
assertEquals(meta.getImageCount(), 1);
519+
}
520+
424521
private Path getTempSubdir() throws IOException {
425522
Path subdir = Files.createTempDirectory(tempDir, "ImageConverterTest");
426523
subdir.toFile().deleteOnExit();

0 commit comments

Comments
 (0)