Commits

Michael Ludwig committed d5e7377

Make the texture loading more object-oriented and flexible.

Comments (0)

Files changed (5)

src/com/ferox/resource/texture/loader/DDSImageFileLoader.java

+package com.ferox.resource.texture.loader;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import com.ferox.resource.texture.TextureImage;
+
+/** An implementation of ImageFileLoader that
+ * relies on DDSTexture to load .dds files.
+ * 
+ * @author Michael Ludwig
+ *
+ */
+public class DDSImageFileLoader implements ImageFileLoader {
+	@Override
+	public TextureImage readImage(InputStream stream) throws IOException {
+		if (DDSTexture.isDDSTexture(stream))
+			return DDSTexture.readTexture(stream);
+		else
+			return null;
+	}
+}

src/com/ferox/resource/texture/loader/ImageFileLoader.java

+package com.ferox.resource.texture.loader;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import com.ferox.resource.texture.TextureImage;
+
+/** ImageFileLoader is a simple interface that provides
+ * loading capabilities for various types of image data,
+ * to then convert them into TextureImages.
+ * 
+ * To keep the interface simple, it only deals in streams,
+ * if a file format cannot be determined using just streams,
+ * then this interface is not suitable for that type.
+ * 
+ * @author Michael Ludwig
+ *
+ */
+public interface ImageFileLoader {	
+	/** Process the data from the given stream and
+	 * return a TextureImage representing its contents.
+	 * 
+	 * Return null if the stream doesn't represent an image
+	 * of any supported format.  If it is an image of the expected type,
+	 * but is otherwise invalid or unsupported, then throw an exception.
+	 * 
+	 * If null is returned, the stream should not have its position
+	 * modified.
+	 * 
+	 * Throw an IOException if there are any problems. */
+	public TextureImage readImage(InputStream stream) throws IOException;
+}

src/com/ferox/resource/texture/loader/ImageIOImageFileLoader.java

+package com.ferox.resource.texture.loader;
+
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.imageio.ImageIO;
+
+import com.ferox.resource.texture.TextureImage;
+
+/** An ImageFileLoader that uses ImageIO to load
+ * files in gif, png, or jpg files (this depends on
+ * the ImageIO loaders present on a given system).
+ * 
+ * @author Michael Ludwig
+ *
+ */
+public class ImageIOImageFileLoader implements ImageFileLoader {
+	@Override
+	public TextureImage readImage(InputStream stream) throws IOException {
+		// I'm assuming that read() will restore the stream's position
+		// if no reader is found
+		
+		BufferedImage b = ImageIO.read(stream);
+		if (b != null) {
+			if (b.getHeight() == 1)
+				return TextureLoader.createTexture1D(b);
+			else
+				return TextureLoader.createTexture2D(b);
+		} else
+			return null;
+	}
+
+}

src/com/ferox/resource/texture/loader/TGAImageFileLoader.java

+package com.ferox.resource.texture.loader;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import com.ferox.resource.texture.TextureImage;
+
+/** An implementation of ImageFileLoader that
+ * relies on TGATexture to load .tga files.
+ * 
+ * @author Michael Ludwig
+ *
+ */
+public class TGAImageFileLoader implements ImageFileLoader {
+	@Override
+	public TextureImage readImage(InputStream stream) throws IOException {
+		if (TGATexture.isTGATexture(stream))
+			return TGATexture.readTexture(stream);
+		else
+			return null;
+	}
+}

src/com/ferox/resource/texture/loader/TextureLoader.java

 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
-
-import javax.imageio.ImageIO;
+import java.util.ArrayList;
+import java.util.List;
 
 import com.ferox.resource.BufferData;
 import com.ferox.resource.BufferData.DataType;
 import com.ferox.resource.texture.TextureFormat;
 import com.ferox.resource.texture.TextureImage;
 import com.ferox.resource.texture.TextureRectangle;
+import com.ferox.resource.texture.converter.TextureConverter.Encoder;
 
 /** TextureIO provides functionality to load image files
  * as TextureImage objects.  It provides some utilities to generate
  * a TextureImage from a BufferedImage.
  * 
- * TextureIO supports the DDS texture format (via DDSTexture) and
- * any file format supported by javax.imageio.ImageIO.
+ * By default, the DDS, TGA and ImageIO image file loaders are
+ * registered.
  * 
  * @author Michael Ludwig
  *
  */
 public class TextureLoader {
+	private static List<ImageFileLoader> loaders = new ArrayList<ImageFileLoader>();
+	
+	// register some default loaders
+	static {
+		registerLoader(new ImageIOImageFileLoader());
+		registerLoader(new TGAImageFileLoader());
+		registerLoader(new DDSImageFileLoader());
+	}
+	
+	/** Register the given loader, so that it can be used in subsequent 
+	 * readTexture() calls.  The newer loaders are favored when resolving
+	 * conflicts between loaders that are capable of loading the same file.
+	 * 
+	 * Does nothing if e is null.  If e has already been registered,
+	 * then e becomes the "newest" with regards to resolving conflicts. */
+	public static void registerLoader(ImageFileLoader e) {
+		synchronized(loaders) {
+			if (e != null) {
+				int index = loaders.indexOf(e);
+				if (index >= 0)
+					loaders.remove(index);
+				loaders.add(e);
+			}
+		}
+	}
+	
+	/** Remove the given loader.  Does nothing if it's
+	 * null or was never registered.  After a call to this method,
+	 * that loader instance will not be used in calls to readTexture(). */
+	public static void unregisterLoader(Encoder e) {
+		synchronized(loaders) {
+			if (e != null)
+				loaders.remove(e);
+		}
+	}
+	
 	/** Read the texture from the given file, functions identically
 	 * to readTexture(stream). */
 	public static TextureImage readTexture(File file) throws IOException {
 			// load the file
 			TextureImage t;
 			
-			if (DDSTexture.isDDSTexture(stream)) // we're a DDS texture
-				t = DDSTexture.readTexture(stream);
-			else if (TGATexture.isTGATexture(stream)) // we should be a TGA texture
-				t = TGATexture.readTexture(stream);
-			else {
-				BufferedImage i = ImageIO.read(stream);
-				if (i == null)
-					throw new IOException("Unsupported file format");
-				if (i.getHeight() == 1)
-					t = createTexture1D(i);
-				else
-					t = createTexture2D(i);
+			synchronized(loaders) {
+				for (int i = loaders.size() - 1; i >= 0; i--) {
+					t = loaders.get(i).readImage(stream);
+					if (t != null)
+						return t; // we've loaded it
+				}
 			}
-			// return the result
-			return t;
+			
+			throw new IOException("Unable to load the given texture, no registered loader with support");
 		} catch (Exception io) {
 			throw new IOException(io);
 		}
 	 * 
 	 * Throws an exception if texture is null. */
 	public static TextureRectangle convertToRectangle(Texture2D texture) throws NullPointerException {
-		TextureRectangle tr = null;
-		if (texture != null) {
-			tr = new TextureRectangle(texture.getData(0), texture.getWidth(0), texture.getHeight(0), texture.getFormat(), texture.getType());
-			
-			tr.setDepthCompareEnabled(texture.isDepthCompareEnabled());
-			tr.setDepthCompareTest(texture.getDepthCompareTest());
-			tr.setDepthMode(texture.getDepthMode());
-			tr.setFilter(texture.getFilter());
-			tr.setWrapSTR(texture.getWrapS(), texture.getWrapT(), texture.getWrapT());
-		}
+		if (texture == null)
+			throw new NullPointerException("Cannot convert a null texture");
+		
+		TextureRectangle tr = new TextureRectangle(texture.getData(0), texture.getWidth(0), texture.getHeight(0), texture.getFormat(), texture.getType());
+
+		tr.setDepthCompareEnabled(texture.isDepthCompareEnabled());
+		tr.setDepthCompareTest(texture.getDepthCompareTest());
+		tr.setDepthMode(texture.getDepthMode());
+		tr.setFilter(texture.getFilter());
+		tr.setWrapSTR(texture.getWrapS(), texture.getWrapT(), texture.getWrapT());
+
 		return tr;
 	}