1

我正在尝试将多个图像串联成一个,但一直遇到问题。为了隔离这一点,我创建了以下 POC,我正在尝试解决它,以便我了解如何使用 JAI API。

在 POC 中,我有两个图像“image1.gif”和“image2.gif”,它们都是 256x256。目标是将它们水平连接成一个 512x256 的图像“image3.png”。这是我使用 JAI 为此编写的代码。

try {
    InputStream stream1 = new FileInputStream("D:\\poc\\image1.gif");
    InputStream stream2 = new FileInputStream("D:\\poc\\image2.gif");
    RenderedImage image1 = ImageIO.read(stream1);
    RenderedImage image2 = ImageIO.read(stream2);
    ImageLayout imageLayout = new ImageLayout(0,0,512,256);
    RenderingHints renderingHints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, imageLayout);
    RenderedImage finalImage = MosaicDescriptor.create(new RenderedImage[]{image1, image2}, MosaicDescriptor.MOSAIC_TYPE_OVERLAY, null, null, null, null, renderingHints);
    FileStoreDescriptor.create(finalImage, "D:\\poc\\image3.png", "PNG", null, null, null);
} catch (FileNotFoundException e) {
    e.printStackTrace();
    return;
} catch (IOException e) {
    e.printStackTrace();
    return;
}

我得到的是正确尺寸 512x256 的图像,第一张图像 (image1) 完全位于图像的左侧,而图像的右侧完全是黑色的。换句话说,就像我将 image1.gif 与 256x256 黑色方块连接起来一样。

我尝试将 MosaicType 更改为 MosaicDescriptor.MOSAIC_TYPE_BLEND,但这只是创建了一个类似的图像,只有左半部分由覆盖在 image2 顶部的 image1 组成(反之亦然),而右半部分仍然完全是黑色的。

我还尝试更改 ImageLayout 构造函数的前两个参数。这也不起作用——例如,我可以将 ImageLayout 的第一个参数设置为 -256,但随后 image1 显示在图像的右半部分,而图像的左半部分为黑色。

请帮忙!

4

2 回答 2

0

这是我想出的最终解决方案 - 这些通用方法创建了两个图像的马赛克来说明。您只需将它们映射到一个公共坐标空间 - 首先创建一个图像的马赛克(以增加整体大小,因为 ScaleDescriptor 由于某种原因不起作用),然后翻译第二个图像,以便它可以覆盖第一的。

private static RenderedImage horizontalMosaic(RenderedImage image1, RenderedImage image2) {
    ImageLayout imageLayout = new ImageLayout(0, 0, image1.getWidth() + image2.getWidth(), image1.getHeight());
    RenderingHints renderingHints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, imageLayout);
    RenderedImage image3 = MosaicDescriptor.create(new RenderedImage[]{image1}, MosaicDescriptor.MOSAIC_TYPE_OVERLAY, null, null, null, null, renderingHints);
    RenderedImage image4 = MosaicDescriptor.create(new RenderedImage[]{image2}, MosaicDescriptor.MOSAIC_TYPE_OVERLAY, null, null, null, null, renderingHints);
    RenderedImage image5 = TranslateDescriptor.create(image4, (float)image1.getWidth(), 0.0f, null, renderingHints);
    return MosaicDescriptor.create(new RenderedImage[]{image3, image5}, MosaicDescriptor.MOSAIC_TYPE_OVERLAY, null, null, null, null, renderingHints);
}

private static RenderedImage verticalMosaic(RenderedImage image1, RenderedImage image2) {
    ImageLayout imageLayout = new ImageLayout(0, 0, image1.getWidth(), image1.getHeight() + image2.getHeight());
    RenderingHints renderingHints = new RenderingHints(JAI.KEY_IMAGE_LAYOUT, imageLayout);
    RenderedImage image3 = MosaicDescriptor.create(new RenderedImage[]{image1}, MosaicDescriptor.MOSAIC_TYPE_OVERLAY, null, null, null, null, renderingHints);
    RenderedImage image4 = MosaicDescriptor.create(new RenderedImage[]{image2}, MosaicDescriptor.MOSAIC_TYPE_OVERLAY, null, null, null, null, renderingHints);
    RenderedImage image5 = TranslateDescriptor.create(image4, 0.0f, (float)image1.getHeight(), null, renderingHints);
    return MosaicDescriptor.create(new RenderedImage[]{image3, image5}, MosaicDescriptor.MOSAIC_TYPE_OVERLAY, null, null, null, null, renderingHints);
}
于 2011-09-19T10:05:32.360 回答
0

这是使用 JAI 拼接两个图像的更简洁的方法。基本过程是将源图像转换(或变形)到马赛克的公共图像空间中。然后,您可以将所有翻译后的图像提供给马赛克操作。无需执行两次马赛克操作。由于所有输入图像的图像空间的并集对应于马赛克的所需输出图像空间,因此您无需提供 ImageLayout 作为 RenderingHint。在此示例中,输入图像是在内存中创建的,但可以像在原始帖子中那样从文件中读取它们。

   public void makeMosaic(String fileName) throws IOException{
        // Make a black image in memory
        RenderedImage blackImage = ConstantDescriptor.create(256f,256f,new Byte[]{0x00,0x00,0x00},null);
        // Make a white image in memory
        RenderedImage whiteImage = ConstantDescriptor.create(256f, 256f, new Byte[]{(byte) 0xff, (byte) 0xff, (byte) 0xff},null);
        // Translate the white image to shift it 256 pixels to the right
        RenderedImage translatedWhiteImage = TranslateDescriptor.create(whiteImage, 256f, 0f, new InterpolationNearest(), null);
        // Now you can mosaic the two images.  No need to supply an ImageLayout hint or pre-mosaic the black image.
        RenderedImage mosaic = MosaicDescriptor.create(new RenderedImage[]{blackImage,translatedWhiteImage}, MosaicDescriptor.MOSAIC_TYPE_OVERLAY, null, null, null, null, null);
        // Write out the output image.  Should be 256 pixels tall and 512 pixels wide with black tile on left and white tile on right.
        ImageIO.write(mosaic, "PNG", new File(fileName));
    }
于 2014-12-11T16:40:48.590 回答