我的维度为18000 * 18000维度, 1.20 GB 。 tiff有72 DPI。
我想使用400 DPI将此TIFF转换为PNG / JPEG。
我正在使用以下代码来执行此操作
public static void ConvertTiffToJpg(String str_TiffUrl,
String str_JpgFileDestinationUrl) throws Exception {
try {
FileSeekableStream obj_FileSeekableStream = new FileSeekableStream(
new File(str_TiffUrl));
ImageDecoder obj_ImageDecoder = ImageCodec.createImageDecoder(
"tiff", obj_FileSeekableStream, null);
RenderedImage obj_RenderedImage = obj_ImageDecoder
.decodeAsRenderedImage();
JAI.create("filestore", obj_RenderedImage,
str_JpgFileDestinationUrl, "jpeg");
obj_RenderedImage = null;
obj_ImageDecoder = null;
obj_FileSeekableStream.close();
} catch (Exception ex) {
throw ex;
}
以上代码完美适用于较小的图像然后指定的图像,例如尺寸小于5000 * 5000的tiff图像可以很容易地转换为JPEG / PNG [虽然我需要更改PNG编码器],
但是当我尝试为上面提到的文件运行相同的代码时,它会抛出以下异常
Error: One factory fails for the operation "encode"
Occurs in: javax.media.jai.ThreadSafeOperationRegistry
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
at com.sun.media.jai.opimage.FileStoreRIF.create(FileStoreRIF.java:138)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
at javax.media.jai.RenderedOp.createInstance(RenderedOp.java:819)
at javax.media.jai.RenderedOp.createRendering(RenderedOp.java:867)
at javax.media.jai.RenderedOp.getRendering(RenderedOp.java:888)
at javax.media.jai.JAI.createNS(JAI.java:1099)
at javax.media.jai.JAI.create(JAI.java:973)
at javax.media.jai.JAI.create(JAI.java:1621)
at com.vs.graphics.concepts.TiffToJpeg.ConvertTiffToJpg(TiffToJpeg.java:30)
at com.vs.graphics.svg.SvgRefresh$1.actionPerformed(SvgRefresh.java:106)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:387)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:242)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:236)
at java.awt.Component.processMouseEvent(Component.java:6216)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3265)
at java.awt.Component.processEvent(Component.java:5981)
at java.awt.Container.processEvent(Container.java:2041)
at java.awt.Component.dispatchEventImpl(Component.java:4583)
at java.awt.Container.dispatchEventImpl(Container.java:2099)
at java.awt.Component.dispatchEvent(Component.java:4413)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4556)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4220)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4150)
at java.awt.Container.dispatchEventImpl(Container.java:2085)
at java.awt.Window.dispatchEventImpl(Window.java:2475)
at java.awt.Component.dispatchEvent(Component.java:4413)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Caused by: java.lang.OutOfMemoryError: Java heap space
at java.awt.image.DataBufferByte.<init>(DataBufferByte.java:42)
at java.awt.image.Raster.createInterleavedRaster(Raster.java:253)
at java.awt.image.Raster.createInterleavedRaster(Raster.java:194)
at com.sun.media.jai.codecimpl.JPEGImageEncoder.encode(JPEGImageEncoder.java:182)
at com.sun.media.jai.opimage.EncodeRIF.create(EncodeRIF.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
at com.sun.media.jai.opimage.FileStoreRIF.create(FileStoreRIF.java:138)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
at javax.media.jai.RenderedOp.createInstance(RenderedOp.java:819)
at javax.media.jai.RenderedOp.createRendering(RenderedOp.java:867)
at javax.media.jai.RenderedOp.getRendering(RenderedOp.java:888)
at javax.media.jai.JAI.createNS(JAI.java:1099)
at javax.media.jai.JAI.create(JAI.java:973)
at javax.media.jai.JAI.create(JAI.java:1621)
at com.vs.graphics.concepts.TiffToJpeg.ConvertTiffToJpg(TiffToJpeg.java:30)
at com.vs.graphics.svg.SvgRefresh$1.actionPerformed(SvgRefresh.java:106)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1995)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2318)
Error: One factory fails for the operation "filestore"
Occurs in: javax.media.jai.ThreadSafeOperationRegistry
这是因为内存不足错误。
有没有使用它的Tiled Image Writer或Fragement Image Writer我们只会一次转换一部分图像,因此我们可以使用普通的内存 我认为它可能被称为转换使用图像分割。
编辑
使用pngJ直接编写png文件。
我的目的是使用400 DPI将SVG画布转码为PNG
如果我使用PNGTranscoder,它会为所提到的图像大小抛出内存不足的异常。
所以我使用TiledImageTranscoder使用以下代码将SVG转码为Image。
protected void transcode(Document document, String uri,
TranscoderOutput output) throws TranscoderException {
// Sets up root, curTxf & curAoi
super.transcode(document, uri, output);
Filter f = this.root.getGraphicsNodeRable(true);
RenderContext rc = new RenderContext(curTxf, null, null);
RenderedImage img = f.createRendering(rc);
// prepare the image to be painted
int w = img.getWidth();
int h = img.getHeight();
try {
int bands = img.getSampleModel().getNumBands();
int[] off = new int[bands];
for (int i = 0; i < bands; i++)
off[i] = i;
SampleModel sm = new PixelInterleavedSampleModel(
DataBuffer.TYPE_BYTE, w, (100000 + w - 1) / w, bands, w
* bands, off);
RenderedImage rimg = new FormatRed(GraphicsUtil.wrap(img), sm);
TIFFImageEncoder enc = new TIFFImageEncoder(output
.getOutputStream(), null);
enc.encode(rimg);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
所以你可以在这里看到上面的代码最后使用TIFFImageEncoder逐步写入磁盘并在我的情况下生成1.30 GB的TIFF文件。
这就是为什么我需要将这个生成的文件转换为PNG文件。
我的问题特别针对@leonbloy
我们可以使用pngJ库中的PNGWriter直接使用400 DPI编写png文件而不会出现内存错误,这样我们就可以节省时间并避免不必要的转换。
或
我们可以用pngJ库覆盖PngImageWriter的writeImage方法,以便实现我们的目标吗?
谢谢 Mihir Parekh
答案 0 :(得分:2)
您可能会尝试找到一些支持渐进式(例如,每次一行)处理的TIFF解码器和JPEG / PNG编码器。这TIFF decoder似乎支持它; PNGJ支持它。
更新:尝试在PNGTrasncoder中插入PNGJ似乎是要走的路,但这并不容易:你(或我或某人)必须编写RenderedImage格式与PNGJ期望格式之间的桥梁。 (PNGJ故意与java.awt.*
分离)。当我有一段时间时它可能会看一看,它似乎是包含在Batik中的一个有趣的替代方案,我预见的唯一限制是我不支持隔行扫描,但我不认为这是相关的。