• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009-2010 jMonkeyEngine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17  *   may be used to endorse or promote products derived from this software
18  *   without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 package com.jme3.texture.plugins;
34 
35 import com.jme3.asset.AssetInfo;
36 import com.jme3.asset.AssetLoader;
37 import com.jme3.asset.TextureKey;
38 import com.jme3.texture.Image;
39 import com.jme3.texture.Image.Format;
40 import com.jme3.util.BufferUtils;
41 import java.io.IOException;
42 import java.io.InputStream;
43 import java.nio.ByteBuffer;
44 import java.nio.ByteOrder;
45 import java.util.logging.Logger;
46 
47 public class PFMLoader implements AssetLoader {
48 
49     private static final Logger logger = Logger.getLogger(PFMLoader.class.getName());
50 
readString(InputStream is)51     private String readString(InputStream is) throws IOException{
52         StringBuilder sb = new StringBuilder();
53         while (true){
54             int i = is.read();
55             if (i == 0x0a || i == -1) // new line or EOF
56                 return sb.toString();
57 
58             sb.append((char)i);
59         }
60     }
61 
flipScanline(byte[] scanline)62     private void flipScanline(byte[] scanline){
63         for (int i = 0; i < scanline.length; i+=4){
64             // flip first and fourth bytes
65             byte tmp = scanline[i+3];
66             scanline[i+3] = scanline[i+0];
67             scanline[i+0] = tmp;
68 
69             // flip second and third bytes
70             tmp = scanline[i+2];
71             scanline[i+2] = scanline[i+1];
72             scanline[i+1] = tmp;
73         }
74     }
75 
load(InputStream in, boolean needYFlip)76     private Image load(InputStream in, boolean needYFlip) throws IOException{
77         Format format = null;
78 
79         String fmtStr = readString(in);
80         if (fmtStr.equals("PF")){
81             format = Format.RGB32F;
82         }else if (fmtStr.equals("Pf")){
83             format = Format.Luminance32F;
84         }else{
85             throw new IOException("File is not PFM format");
86         }
87 
88         String sizeStr = readString(in);
89         int spaceIdx = sizeStr.indexOf(" ");
90         if (spaceIdx <= 0 || spaceIdx >= sizeStr.length() - 1)
91             throw new IOException("Invalid size syntax in PFM file");
92 
93         int width = Integer.parseInt(sizeStr.substring(0,spaceIdx));
94         int height = Integer.parseInt(sizeStr.substring(spaceIdx+1));
95 
96         if (width <= 0 || height <= 0)
97             throw new IOException("Invalid size specified in PFM file");
98 
99         String scaleStr = readString(in);
100         float scale = Float.parseFloat(scaleStr);
101         ByteOrder order = scale < 0 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN;
102         boolean needEndienFlip = order != ByteOrder.nativeOrder();
103 
104         // make sure all unneccessary stuff gets deleted from heap
105         // before allocating large amount of memory
106         System.gc();
107 
108         int bytesPerPixel = format.getBitsPerPixel() / 8;
109         int scanLineBytes = bytesPerPixel * width;
110 
111         ByteBuffer imageData = BufferUtils.createByteBuffer(width * height * bytesPerPixel);
112         byte[] scanline = new byte[width * bytesPerPixel];
113 
114         for (int y = height - 1; y >= 0; y--) {
115             if (!needYFlip)
116                 imageData.position(scanLineBytes * y);
117 
118             int read = 0;
119             int off = 0;
120             do {
121                 read = in.read(scanline, off, scanline.length - off);
122                 off += read;
123             } while (read > 0);
124 
125             if (needEndienFlip){
126                 flipScanline(scanline);
127             }
128 
129             imageData.put(scanline);
130         }
131         imageData.rewind();
132 
133         return new Image(format, width, height, imageData);
134     }
135 
load(AssetInfo info)136     public Object load(AssetInfo info) throws IOException {
137         if (!(info.getKey() instanceof TextureKey))
138             throw new IllegalArgumentException("Texture assets must be loaded using a TextureKey");
139 
140         InputStream in = null;
141         try {
142             in = info.openStream();
143             return load(in, ((TextureKey)info.getKey()).isFlipY());
144         } finally {
145             if (in != null){
146                 in.close();
147             }
148         }
149 
150     }
151 
152 }
153