使用 JAI 读取时对图像进行二次采样

发布于 2024-08-09 03:41:50 字数 852 浏览 13 评论 0原文

我已经读取了相当大的图像(jpeg)的应用程序,但只需要处理较小的图像,因此我使用类似的内容对它们进行子采样

ImageReadParam param = reader.getDefaultReadParam();
param.setSourceSubsampling(4, 4, 0, 0);
img = reader.read(0);

但是,由于jpeg阅读器中的一个错误,它无法处理我已经回退的一些元数据其他方法,一种是使用 JAI 读取图像,然后调整大小(代码如下,不是我必须使用反射,因为某些部署环境没有可用的 JAI,我知道我可以更好地围绕此进行设计,但事实就是如此) 。

try {
Class<?> c = ImageUtil.class.getClassLoader().loadClass("javax.media.jai.JAI");

if (c != null) { 
    URL url = new URL("file://" + file.getAbsolutePath());
    Method m = c.getMethod("create", String.class, Object.class);
    Object pi = m.invoke(null, "url", url);
    img = (BufferedImage) pi.getClass().getMethod("getAsBufferedImage").invoke(pi);
}
} catch (Throwable tt) {
// ...
}

然而,有些图像非常大,我时不时地会出现内存不足的异常,无论如何,当我以使用 ImageReader 读取图像的方式读取图像时,我是否可以让 JAI 对图像进行二次采样?

An application I have reads in quite large images (jpegs) but only needs to work with smaller images so I subsample them with something like

ImageReadParam param = reader.getDefaultReadParam();
param.setSourceSubsampling(4, 4, 0, 0);
img = reader.read(0);

However, due to a bug in the jpeg reader that does not handle some meta data that I have fall back to other methods, one is using JAI to read the image and then resize (code is below, not I have to use reflection as some deployment environments don't have JAI available, I know I could design around this better but that's how it is).

try {
Class<?> c = ImageUtil.class.getClassLoader().loadClass("javax.media.jai.JAI");

if (c != null) { 
    URL url = new URL("file://" + file.getAbsolutePath());
    Method m = c.getMethod("create", String.class, Object.class);
    Object pi = m.invoke(null, "url", url);
    img = (BufferedImage) pi.getClass().getMethod("getAsBufferedImage").invoke(pi);
}
} catch (Throwable tt) {
// ...
}

However some of the images are really large an now and again I get out of memory exceptions, is there anyway I can get JAI to subsample the image when it is read in the manner i read the images using an ImageReader?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

靑春怀旧 2024-08-16 03:41:50
RenderedOp rop = JAI.create("fileload", file.getAbsolutePath());

ParameterBlock pb = new ParameterBlock();
pb.addSource(rop);
pb.add(0.5f);
pb.add(0.5f);
rop = JAI.create("scale", pb);

// For better looking results, but slower:
// rop = JAI.create("SubsampleAverage", pb);

BufferedImage bufImg = rop.getAsBufferedImage();   
RenderedOp rop = JAI.create("fileload", file.getAbsolutePath());

ParameterBlock pb = new ParameterBlock();
pb.addSource(rop);
pb.add(0.5f);
pb.add(0.5f);
rop = JAI.create("scale", pb);

// For better looking results, but slower:
// rop = JAI.create("SubsampleAverage", pb);

BufferedImage bufImg = rop.getAsBufferedImage();   
心碎的声音 2024-08-16 03:41:50

我假设当您尝试转换为 BufferedImage 时会抛出内存不足异常?

如果是这种情况,那么也许考虑坚持使用 JAI 的创建方法返回的 RenderedOp,而不是使用 ParameterBlock 和进一步的 JAI 创建来生成缩放图像?

ParameterBlock paramBlock = new ParameterBlock();
paramBlock.addSource(((RenderedOp) pi).createInstance()); // Updated this
paramBlock.add(0.5f); // x Scale (Change these two Scale values!)
paramBlock.add(0.5f); // y Scale
paramBlock.add(0.0f); // x Translate
paramBlock.add(0.0f); // y Translate
paramBlock.add(new InterpolationBilinear()); // I think this Interpolation should work...)
RenderedOp resized = JAI.create("scale", paramBlock, null);

恐怕上面的代码完全未经测试作为标准,但应该可以帮助您入门!

一旦你调整了 RenderedOp 的大小,如果需要的话,你应该能够安全地将其转换为 BufferedImage。

I'm assuming the out of memory exception is thrown when you attempt to do the conversion to a BufferedImage?

If that's the case then perhaps considering sticking to the RenderedOp that's returned by JAI's create method and instead use a ParameterBlock and a further JAI create to produce the scaled image?

ParameterBlock paramBlock = new ParameterBlock();
paramBlock.addSource(((RenderedOp) pi).createInstance()); // Updated this
paramBlock.add(0.5f); // x Scale (Change these two Scale values!)
paramBlock.add(0.5f); // y Scale
paramBlock.add(0.0f); // x Translate
paramBlock.add(0.0f); // y Translate
paramBlock.add(new InterpolationBilinear()); // I think this Interpolation should work...)
RenderedOp resized = JAI.create("scale", paramBlock, null);

The above code comes fully untested as standard I'm afraid, but should get you started!

Once you've got that resized RenderedOp you should be able to safely convert it to a BufferedImage if you have to.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文