diff options
Diffstat (limited to 'engine/src/core-plugins/com/jme3/texture/plugins/PFMLoader.java')
-rw-r--r-- | engine/src/core-plugins/com/jme3/texture/plugins/PFMLoader.java | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/engine/src/core-plugins/com/jme3/texture/plugins/PFMLoader.java b/engine/src/core-plugins/com/jme3/texture/plugins/PFMLoader.java new file mode 100644 index 0000000..082dc83 --- /dev/null +++ b/engine/src/core-plugins/com/jme3/texture/plugins/PFMLoader.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2009-2010 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jme3.texture.plugins; + +import com.jme3.asset.AssetInfo; +import com.jme3.asset.AssetLoader; +import com.jme3.asset.TextureKey; +import com.jme3.texture.Image; +import com.jme3.texture.Image.Format; +import com.jme3.util.BufferUtils; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.logging.Logger; + +public class PFMLoader implements AssetLoader { + + private static final Logger logger = Logger.getLogger(PFMLoader.class.getName()); + + private String readString(InputStream is) throws IOException{ + StringBuilder sb = new StringBuilder(); + while (true){ + int i = is.read(); + if (i == 0x0a || i == -1) // new line or EOF + return sb.toString(); + + sb.append((char)i); + } + } + + private void flipScanline(byte[] scanline){ + for (int i = 0; i < scanline.length; i+=4){ + // flip first and fourth bytes + byte tmp = scanline[i+3]; + scanline[i+3] = scanline[i+0]; + scanline[i+0] = tmp; + + // flip second and third bytes + tmp = scanline[i+2]; + scanline[i+2] = scanline[i+1]; + scanline[i+1] = tmp; + } + } + + private Image load(InputStream in, boolean needYFlip) throws IOException{ + Format format = null; + + String fmtStr = readString(in); + if (fmtStr.equals("PF")){ + format = Format.RGB32F; + }else if (fmtStr.equals("Pf")){ + format = Format.Luminance32F; + }else{ + throw new IOException("File is not PFM format"); + } + + String sizeStr = readString(in); + int spaceIdx = sizeStr.indexOf(" "); + if (spaceIdx <= 0 || spaceIdx >= sizeStr.length() - 1) + throw new IOException("Invalid size syntax in PFM file"); + + int width = Integer.parseInt(sizeStr.substring(0,spaceIdx)); + int height = Integer.parseInt(sizeStr.substring(spaceIdx+1)); + + if (width <= 0 || height <= 0) + throw new IOException("Invalid size specified in PFM file"); + + String scaleStr = readString(in); + float scale = Float.parseFloat(scaleStr); + ByteOrder order = scale < 0 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN; + boolean needEndienFlip = order != ByteOrder.nativeOrder(); + + // make sure all unneccessary stuff gets deleted from heap + // before allocating large amount of memory + System.gc(); + + int bytesPerPixel = format.getBitsPerPixel() / 8; + int scanLineBytes = bytesPerPixel * width; + + ByteBuffer imageData = BufferUtils.createByteBuffer(width * height * bytesPerPixel); + byte[] scanline = new byte[width * bytesPerPixel]; + + for (int y = height - 1; y >= 0; y--) { + if (!needYFlip) + imageData.position(scanLineBytes * y); + + int read = 0; + int off = 0; + do { + read = in.read(scanline, off, scanline.length - off); + off += read; + } while (read > 0); + + if (needEndienFlip){ + flipScanline(scanline); + } + + imageData.put(scanline); + } + imageData.rewind(); + + return new Image(format, width, height, imageData); + } + + public Object load(AssetInfo info) throws IOException { + if (!(info.getKey() instanceof TextureKey)) + throw new IllegalArgumentException("Texture assets must be loaded using a TextureKey"); + + InputStream in = null; + try { + in = info.openStream(); + return load(in, ((TextureKey)info.getKey()).isFlipY()); + } finally { + if (in != null){ + in.close(); + } + } + + } + +} |