Search in sources :

Example 6 with MipMapImage

use of ini.trakem2.display.MipMapImage in project TrakEM2 by trakem2.

the class ExportARGB method makeFlatImageARGBFromMipMaps.

/**
 * Returns nonsense or throws an Exception if mipmaps are not available.
 * Limited to 2GB arrays for the final image.
 *
 * @param patches
 * @param roi
 * @param backgroundValue
 * @param scale
 * @return
 */
public static final Pair<ColorProcessor, ByteProcessor> makeFlatImageARGBFromMipMaps(final List<Patch> patches, final Rectangle roi, final double backgroundValue, final double scale) {
    final int width = (int) (roi.width * scale);
    final int height = (int) (roi.height * scale);
    // Process the three channels separately in order to use proper alpha composition
    final ColorProcessor target = new ColorProcessor(width, height);
    target.setInterpolationMethod(ImageProcessor.BILINEAR);
    final ByteProcessor targetMask = new ByteProcessor(width, height);
    targetMask.setInterpolationMethod(ImageProcessor.BILINEAR);
    final Loader loader = patches.get(0).getProject().getLoader();
    for (final Patch patch : patches) {
        // MipMap image, already including any coordinate transforms and the alpha mask (if any), by definition.
        final MipMapImage mipMap = loader.fetchImage(patch, scale);
        // / DEBUG: is there an alpha channel at all?
        // new ij.ImagePlus("alpha of " + patch.getTitle(), new ByteProcessor( mipMap.image.getWidth(null), mipMap.image.getHeight(null), new ColorProcessor( mipMap.image ).getChannel( 4 ))).show();
        // Yes, there is, even though the mipmap images have the alpha pre-multiplied
        // Work-around strange bug that makes mipmap-loaded images paint with 7-bit depth instead of 8-bit depth
        final BufferedImage bi = new BufferedImage(mipMap.image.getWidth(null), mipMap.image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
        final Graphics2D g2d = bi.createGraphics();
        g2d.drawImage(mipMap.image, 0, 0, null);
        g2d.dispose();
        final int[] pix = extractARGBIntArray(bi);
        bi.flush();
        // DEBUG: does the BufferedImage have the alpha channel?
        // {
        // final byte[] aa = new byte[pix.length];
        // for (int i=0; i<aa.length; ++i) aa[i] = (byte)((pix[i] & 0xff000000) >> 24);
        // new ij.ImagePlus("alpha of BI of " + patch.getTitle(), new ByteProcessor(bi.getWidth(), bi.getHeight(), aa)).show();
        // }
        // YES: the alpha, containing the outside too. All fine.
        final ByteProcessor alpha;
        final ColorProcessor rgb = new ColorProcessor(bi.getWidth(), bi.getHeight(), pix);
        if (patch.hasAlphaChannel()) {
            // The mipMap has the alpha channel in it, even if the alpha is pre-multiplied as well onto the images.
            final byte[] a = new byte[pix.length];
            for (int i = 0; i < a.length; ++i) {
                a[i] = (byte) ((pix[i] & 0xff000000) >> 24);
            }
            alpha = new ByteProcessor(bi.getWidth(), bi.getHeight(), a);
        } else {
            alpha = new ByteProcessor(bi.getWidth(), bi.getHeight());
            Arrays.fill((byte[]) alpha.getPixels(), (byte) 255);
        }
        // The affine to apply to the MipMap.image
        final AffineTransform atc = new AffineTransform();
        atc.scale(scale, scale);
        atc.translate(-roi.x, -roi.y);
        final AffineTransform at = new AffineTransform();
        at.preConcatenate(atc);
        at.concatenate(patch.getAffineTransform());
        at.scale(mipMap.scaleX, mipMap.scaleY);
        final AffineModel2D aff = new AffineModel2D();
        aff.set(at);
        final CoordinateTransformMesh mesh = new CoordinateTransformMesh(aff, patch.getMeshResolution(), bi.getWidth(), bi.getHeight());
        final TransformMeshMappingWithMasks<CoordinateTransformMesh> mapping = new TransformMeshMappingWithMasks<CoordinateTransformMesh>(mesh);
        // no interpolation
        alpha.setInterpolationMethod(ImageProcessor.NEAREST_NEIGHBOR);
        rgb.setInterpolationMethod(ImageProcessor.BILINEAR);
        mapping.map(rgb, alpha, target, targetMask);
    }
    return new Pair<ColorProcessor, ByteProcessor>(target, targetMask);
}
Also used : ByteProcessor(ij.process.ByteProcessor) Loader(ini.trakem2.persistence.Loader) BufferedImage(java.awt.image.BufferedImage) Graphics2D(java.awt.Graphics2D) ColorProcessor(ij.process.ColorProcessor) MipMapImage(ini.trakem2.display.MipMapImage) CoordinateTransformMesh(mpicbg.models.CoordinateTransformMesh) AffineTransform(java.awt.geom.AffineTransform) Patch(ini.trakem2.display.Patch) Pair(mpicbg.trakem2.util.Pair)

Aggregations

MipMapImage (ini.trakem2.display.MipMapImage)6 BufferedImage (java.awt.image.BufferedImage)3 Patch (ini.trakem2.display.Patch)2 Image (java.awt.Image)2 ByteProcessor (ij.process.ByteProcessor)1 ColorProcessor (ij.process.ColorProcessor)1 Loader (ini.trakem2.persistence.Loader)1 Graphics2D (java.awt.Graphics2D)1 AffineTransform (java.awt.geom.AffineTransform)1 IOException (java.io.IOException)1 Callable (java.util.concurrent.Callable)1 FutureTask (java.util.concurrent.FutureTask)1 FormatException (loci.formats.FormatException)1 CoordinateTransformMesh (mpicbg.models.CoordinateTransformMesh)1 Pair (mpicbg.trakem2.util.Pair)1