|
38 | 38 | import static ome.xml.model.Pixels.getPhysicalSizeYUnitXsdDefault; |
39 | 39 | import static ome.xml.model.Pixels.getPhysicalSizeZUnitXsdDefault; |
40 | 40 |
|
| 41 | +import java.awt.Font; |
| 42 | +import java.awt.Graphics2D; |
| 43 | +import java.awt.geom.Rectangle2D; |
| 44 | +import java.awt.image.BufferedImage; |
| 45 | + |
41 | 46 | import java.io.File; |
42 | 47 | import java.io.IOException; |
43 | 48 | import java.util.ArrayList; |
|
64 | 69 | import loci.formats.FormatTools; |
65 | 70 | import loci.formats.MetadataTools; |
66 | 71 | import loci.formats.ResourceNamer; |
| 72 | +import loci.formats.gui.AWTImageTools; |
67 | 73 | import loci.formats.meta.MetadataStore; |
68 | 74 | import loci.formats.ome.OMEXMLMetadata; |
69 | 75 | import loci.formats.services.OMEXMLService; |
@@ -223,6 +229,7 @@ public class FakeReader extends FormatReader { |
223 | 229 | // Misc. debugging |
224 | 230 | private int sleepOpenBytes = 0; |
225 | 231 | private int sleepInitFile = 0; |
| 232 | + private boolean labelPlanes = false; |
226 | 233 |
|
227 | 234 | static void sleep(String msg, int ms) { |
228 | 235 | if (ms <= 0) return; // EARLY EXIT |
@@ -418,6 +425,70 @@ public byte[] openBytes(int no, byte[] buf, int x, int y, int w, int h) |
418 | 425 | } |
419 | 426 | } |
420 | 427 |
|
| 428 | + // if requested, add human-readable dimension and index data to the image |
| 429 | + if (labelPlanes) { |
| 430 | + final BufferedImage plane = AWTImageTools.openImage(buf, this, w, h); |
| 431 | + final Graphics2D g = plane.createGraphics(); |
| 432 | + |
| 433 | + // build list of text lines from planar information |
| 434 | + final ArrayList<TextLine> lines = new ArrayList<TextLine>(); |
| 435 | + final Font font = g.getFont(); |
| 436 | + lines.add(new TextLine(new Location(getCurrentFile()).getName(), |
| 437 | + font.deriveFont(16f), 5, -5)); |
| 438 | + lines.add(new TextLine("Core index " + getCoreIndex(), |
| 439 | + font.deriveFont(16f), 5, 5)); |
| 440 | + lines.add(new TextLine(getSizeX() + " x " + getSizeY(), |
| 441 | + font.deriveFont(Font.ITALIC, 16f), 20, 10)); |
| 442 | + lines.add(new TextLine(getDimensionOrder(), |
| 443 | + font.deriveFont(Font.ITALIC, 14f), 30, 5)); |
| 444 | + int space = 5; |
| 445 | + if (getSizeZ() > 1) { |
| 446 | + lines.add(new TextLine( |
| 447 | + "Focal plane = " + (zIndex + 1) + "/" + getSizeZ(), font, 20, space)); |
| 448 | + space = 2; |
| 449 | + } |
| 450 | + if (getSizeC() > 1) { |
| 451 | + lines.add(new TextLine("Channel = " + (cIndex + 1) + "/" + getSizeC(), |
| 452 | + font, 20, space)); |
| 453 | + space = 2; |
| 454 | + } |
| 455 | + if (getSizeT() > 1) { |
| 456 | + lines.add(new TextLine("Time point = " + (tIndex + 1) + "/" + getSizeT(), |
| 457 | + font, 20, space)); |
| 458 | + space = 2; |
| 459 | + } |
| 460 | + |
| 461 | + // draw text lines to image |
| 462 | + g.setColor(java.awt.Color.white); |
| 463 | + int yoff = BOX_SIZE; // start drawing below special pixels |
| 464 | + for (TextLine text : lines) { |
| 465 | + g.setFont(text.font); |
| 466 | + final Rectangle2D r = |
| 467 | + g.getFont().getStringBounds(text.line, g.getFontRenderContext()); |
| 468 | + yoff += (int) r.getHeight() + text.ypad; |
| 469 | + g.drawString(text.line, text.xoff, yoff); |
| 470 | + } |
| 471 | + g.dispose(); |
| 472 | + |
| 473 | + // unpack pixel bytes from BufferedImage |
| 474 | + byte[][] pixelBytes = AWTImageTools.getPixelBytes(plane, little); |
| 475 | + if (interleaved) { |
| 476 | + for (int i=0; i<pixelBytes[0].length; i+=bpp) { |
| 477 | + for (int j=0; j<pixelBytes.length; j++) { |
| 478 | + System.arraycopy(pixelBytes[j], i, buf, |
| 479 | + i * pixelBytes.length + j * bpp, bpp); |
| 480 | + } |
| 481 | + } |
| 482 | + } |
| 483 | + else { |
| 484 | + for (int i=0; i<pixelBytes.length; i++) { |
| 485 | + System.arraycopy(pixelBytes[i], 0, buf, |
| 486 | + i * pixelBytes[0].length, pixelBytes[i].length); |
| 487 | + } |
| 488 | + } |
| 489 | + pixelBytes = null; |
| 490 | + } |
| 491 | + |
421 | 492 | return buf; |
422 | 493 | } |
423 | 494 |
|
@@ -515,6 +586,7 @@ public void close(boolean fileOnly) throws IOException { |
515 | 586 | plateCols = 0; |
516 | 587 | fields = 0; |
517 | 588 | plateAcqs = 0; |
| 589 | + labelPlanes = false; |
518 | 590 | excitationWavelengths.clear(); |
519 | 591 | emissionWavelengths.clear(); |
520 | 592 | super.close(fileOnly); |
@@ -783,6 +855,8 @@ else if (key.startsWith("color_")) { |
783 | 855 | sleepOpenBytes = intValue; |
784 | 856 | } else if (key.equals("sleepInitFile")) { |
785 | 857 | sleepInitFile = intValue; |
| 858 | + } else if (key.equals("labelPlanes")) { |
| 859 | + labelPlanes = boolValue; |
786 | 860 | } |
787 | 861 | } |
788 | 862 |
|
@@ -1589,4 +1663,24 @@ private Length parseWavelength(String s, String defaultUnit) { |
1589 | 1663 | return wavelength; |
1590 | 1664 | } |
1591 | 1665 |
|
| 1666 | + |
| 1667 | + // -- Helper classes -- |
| 1668 | + |
| 1669 | + private static class TextLine { |
| 1670 | + |
| 1671 | + final String line; |
| 1672 | + final Font font; |
| 1673 | + final int xoff; |
| 1674 | + final int ypad; |
| 1675 | + |
| 1676 | + TextLine(final String line, final Font font, final int xoff, final int ypad) |
| 1677 | + { |
| 1678 | + this.line = line; |
| 1679 | + this.font = font; |
| 1680 | + this.xoff = xoff; |
| 1681 | + this.ypad = ypad; |
| 1682 | + } |
| 1683 | + |
| 1684 | + } |
| 1685 | + |
1592 | 1686 | } |
0 commit comments