Commits

Alex Szpakowski committed 377f9da

Replaced the devil love.image module with love.image.magpie, which can decide which image library to use in a similar manner to love.sound.lullaby. Some rough edges still exist.
love.filesystem.newFileData now accepts filepaths and File objects.

Comments (0)

Files changed (28)

platform/macosx/love-framework.xcodeproj/project.pbxproj

 		FA08F62D16C7541400F007B5 /* wrap_SpriteBatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 02C16FDB537A702F4D42534E /* wrap_SpriteBatch.cpp */; };
 		FA08F62E16C7542600F007B5 /* ImageData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 78115E763B723C0C40AD47CF /* ImageData.cpp */; };
 		FA08F62F16C7542600F007B5 /* Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 505F23A73BFE250833D650E4 /* Image.cpp */; };
-		FA08F63016C7542600F007B5 /* ImageData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA7781A230065F346E2313A /* ImageData.cpp */; };
+		FA08F63016C7542600F007B5 /* DevilHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA7781A230065F346E2313A /* DevilHandler.cpp */; };
 		FA08F63116C7542600F007B5 /* wrap_Image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0B0728FA73B107B37A956A09 /* wrap_Image.cpp */; };
 		FA08F63216C7542600F007B5 /* wrap_ImageData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 076840774B0B6E721D0C18D0 /* wrap_ImageData.cpp */; };
 		FA08F63316C7542D00F007B5 /* Joystick.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 677F545C76EA3B247329358D /* Joystick.cpp */; };
 		FA08F67A16C754B100F007B5 /* wrap_Timer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 695E4ED13AA0689E64280573 /* wrap_Timer.cpp */; };
 		FA08F67B16C754BA00F007B5 /* Window.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 351B09E51FDC338622F44624 /* Window.cpp */; };
 		FA08F67C16C754BA00F007B5 /* Window.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6CDD4F3320303D222C180CD0 /* Window.cpp */; };
+		FA0CDE3D1710F9A50056E8D7 /* FormatHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = FA0CDE3B1710F9A50056E8D7 /* FormatHandler.h */; };
 		FA5454C216F1310000D30303 /* MathModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FA5454C016F1310000D30303 /* MathModule.cpp */; };
 		FA5454C316F1310000D30303 /* MathModule.h in Headers */ = {isa = PBXBuildFile; fileRef = FA5454C116F1310000D30303 /* MathModule.h */; };
 		FA577AB016C7507900860150 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA577A7916C71A1700860150 /* Cocoa.framework */; };
 		FAE010DB170DDE99006F29D0 /* ddsinfo.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE010D8170DDE99006F29D0 /* ddsinfo.h */; };
 		FAE010DC170DDE99006F29D0 /* ddsparse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAE010D9170DDE99006F29D0 /* ddsparse.cpp */; };
 		FAE010DD170DDE99006F29D0 /* ddsparse.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE010DA170DDE99006F29D0 /* ddsparse.h */; };
-		FAE010E0170DE25E006F29D0 /* CompressedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAE010DE170DE25E006F29D0 /* CompressedData.cpp */; };
-		FAE010E1170DE25E006F29D0 /* CompressedData.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE010DF170DE25E006F29D0 /* CompressedData.h */; };
+		FAE010E0170DE25E006F29D0 /* ddsHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAE010DE170DE25E006F29D0 /* ddsHandler.cpp */; };
+		FAE010E1170DE25E006F29D0 /* ddsHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE010DF170DE25E006F29D0 /* ddsHandler.h */; };
 		FAE010E4170DF75C006F29D0 /* wrap_CompressedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAE010E2170DF75B006F29D0 /* wrap_CompressedData.cpp */; };
 		FAE010E5170DF75C006F29D0 /* wrap_CompressedData.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE010E3170DF75C006F29D0 /* wrap_CompressedData.h */; };
+		FAEC808A1710FEA60057279A /* ImageData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAEC80881710FEA60057279A /* ImageData.cpp */; };
+		FAEC808B1710FEA60057279A /* ImageData.h in Headers */ = {isa = PBXBuildFile; fileRef = FAEC80891710FEA60057279A /* ImageData.h */; };
+		FAEC808E1711E76C0057279A /* CompressedData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAEC808C1711E76C0057279A /* CompressedData.cpp */; };
+		FAEC808F1711E76C0057279A /* CompressedData.h in Headers */ = {isa = PBXBuildFile; fileRef = FAEC808D1711E76C0057279A /* CompressedData.h */; };
 		FAF272A416E3D44400CC193A /* Channel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF2729816E3D44400CC193A /* Channel.cpp */; };
 		FAF272A516E3D44400CC193A /* Channel.h in Headers */ = {isa = PBXBuildFile; fileRef = FAF2729916E3D44400CC193A /* Channel.h */; };
 		FAF272A616E3D44400CC193A /* LuaThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FAF2729A16E3D44400CC193A /* LuaThread.cpp */; };
 		1A95437F513E662113AC154A /* b2Rope.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = b2Rope.h; sourceTree = "<group>"; };
 		1A9810F758AC1D1E4B6431FD /* wrap_Graphics.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Graphics.cpp; sourceTree = "<group>"; };
 		1AA213FC158815FA77C40330 /* ChainShape.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ChainShape.h; sourceTree = "<group>"; };
-		1AA7781A230065F346E2313A /* ImageData.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ImageData.cpp; sourceTree = "<group>"; };
+		1AA7781A230065F346E2313A /* DevilHandler.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DevilHandler.cpp; sourceTree = "<group>"; };
 		1B036C7C5A8832AE53BB1C06 /* b2CollideEdge.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = b2CollideEdge.cpp; sourceTree = "<group>"; };
 		1B1C4E4D288A1D2F29E57B1B /* Rasterizer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Rasterizer.cpp; sourceTree = "<group>"; };
 		1B4E22F1388E2B2E76E3377B /* wrap_GlyphData.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_GlyphData.cpp; sourceTree = "<group>"; };
 		27F777AB188D674F30BC1829 /* wrap_World.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = wrap_World.h; sourceTree = "<group>"; };
 		28016C9B51FE1A893DC35B66 /* Variant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Variant.h; sourceTree = "<group>"; };
 		28024635525B077E08A73D9B /* Source.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Source.cpp; sourceTree = "<group>"; };
-		283342E174613897621A43F1 /* ImageData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ImageData.h; sourceTree = "<group>"; };
+		283342E174613897621A43F1 /* DevilHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DevilHandler.h; sourceTree = "<group>"; };
 		286660042F9654F61AB90D7A /* Body.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Body.h; sourceTree = "<group>"; };
 		2912092853050AF9785F39BE /* wrap_RevoluteJoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = wrap_RevoluteJoint.h; sourceTree = "<group>"; };
 		295C665B1E0B6B2D03CC4937 /* wrap_Event.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = wrap_Event.h; sourceTree = "<group>"; };
 		7F796B7A3362196075C62E61 /* wrap_Fixture.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Fixture.cpp; sourceTree = "<group>"; };
 		7F911CF2107B22F44C5B2542 /* b2Collision.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = b2Collision.h; sourceTree = "<group>"; };
 		FA08F5AE16C7525600F007B5 /* Info-Framework.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Framework.plist"; sourceTree = "<group>"; };
+		FA0CDE3B1710F9A50056E8D7 /* FormatHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormatHandler.h; sourceTree = "<group>"; };
 		FA5454C016F1310000D30303 /* MathModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MathModule.cpp; sourceTree = "<group>"; };
 		FA5454C116F1310000D30303 /* MathModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MathModule.h; sourceTree = "<group>"; };
 		FA577A6716C719D900860150 /* FreeType.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FreeType.framework; path = /Library/Frameworks/FreeType.framework; sourceTree = "<absolute>"; };
 		FAE010D8170DDE99006F29D0 /* ddsinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ddsinfo.h; sourceTree = "<group>"; };
 		FAE010D9170DDE99006F29D0 /* ddsparse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ddsparse.cpp; sourceTree = "<group>"; };
 		FAE010DA170DDE99006F29D0 /* ddsparse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ddsparse.h; sourceTree = "<group>"; };
-		FAE010DE170DE25E006F29D0 /* CompressedData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompressedData.cpp; sourceTree = "<group>"; };
-		FAE010DF170DE25E006F29D0 /* CompressedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompressedData.h; sourceTree = "<group>"; };
+		FAE010DE170DE25E006F29D0 /* ddsHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ddsHandler.cpp; sourceTree = "<group>"; };
+		FAE010DF170DE25E006F29D0 /* ddsHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ddsHandler.h; sourceTree = "<group>"; };
 		FAE010E2170DF75B006F29D0 /* wrap_CompressedData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_CompressedData.cpp; sourceTree = "<group>"; };
 		FAE010E3170DF75C006F29D0 /* wrap_CompressedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_CompressedData.h; sourceTree = "<group>"; };
+		FAEC80881710FEA60057279A /* ImageData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageData.cpp; sourceTree = "<group>"; };
+		FAEC80891710FEA60057279A /* ImageData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageData.h; sourceTree = "<group>"; };
+		FAEC808C1711E76C0057279A /* CompressedData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompressedData.cpp; sourceTree = "<group>"; };
+		FAEC808D1711E76C0057279A /* CompressedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompressedData.h; sourceTree = "<group>"; };
 		FAF2729816E3D44400CC193A /* Channel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Channel.cpp; sourceTree = "<group>"; };
 		FAF2729916E3D44400CC193A /* Channel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Channel.h; sourceTree = "<group>"; };
 		FAF2729A16E3D44400CC193A /* LuaThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LuaThread.cpp; sourceTree = "<group>"; };
 			children = (
 				FAAC6B00170A373A008A61C5 /* CompressedData.cpp */,
 				FAAC6B01170A373A008A61C5 /* CompressedData.h */,
-				13730AB030E309FF6E2961F1 /* devil */,
 				25C325DC2128769F6C6A54C3 /* Image.h */,
 				78115E763B723C0C40AD47CF /* ImageData.cpp */,
 				07B301984BE42246402F7D27 /* ImageData.h */,
+				13730AB030E309FF6E2961F1 /* magpie */,
+				FAE010E2170DF75B006F29D0 /* wrap_CompressedData.cpp */,
+				FAE010E3170DF75C006F29D0 /* wrap_CompressedData.h */,
 				0B0728FA73B107B37A956A09 /* wrap_Image.cpp */,
 				006B015320155B4D42B43B61 /* wrap_Image.h */,
 				076840774B0B6E721D0C18D0 /* wrap_ImageData.cpp */,
 				31B85B507F466FE158A3718E /* wrap_ImageData.h */,
-				FAE010E2170DF75B006F29D0 /* wrap_CompressedData.cpp */,
-				FAE010E3170DF75C006F29D0 /* wrap_CompressedData.h */,
 			);
 			path = image;
 			sourceTree = "<group>";
 			path = libluasocket;
 			sourceTree = "<group>";
 		};
-		13730AB030E309FF6E2961F1 /* devil */ = {
+		13730AB030E309FF6E2961F1 /* magpie */ = {
 			isa = PBXGroup;
 			children = (
+				FAEC808C1711E76C0057279A /* CompressedData.cpp */,
+				FAEC808D1711E76C0057279A /* CompressedData.h */,
+				FAE010DE170DE25E006F29D0 /* ddsHandler.cpp */,
+				FAE010DF170DE25E006F29D0 /* ddsHandler.h */,
+				1AA7781A230065F346E2313A /* DevilHandler.cpp */,
+				283342E174613897621A43F1 /* DevilHandler.h */,
+				FA0CDE3B1710F9A50056E8D7 /* FormatHandler.h */,
 				505F23A73BFE250833D650E4 /* Image.cpp */,
 				68616BD516DB124312B47EB3 /* Image.h */,
-				1AA7781A230065F346E2313A /* ImageData.cpp */,
-				283342E174613897621A43F1 /* ImageData.h */,
-				FAE010DE170DE25E006F29D0 /* CompressedData.cpp */,
-				FAE010DF170DE25E006F29D0 /* CompressedData.h */,
+				FAEC80881710FEA60057279A /* ImageData.cpp */,
+				FAEC80891710FEA60057279A /* ImageData.h */,
 			);
-			path = devil;
+			path = magpie;
 			sourceTree = "<group>";
 		};
 		153D76205F7A4ACD12FB4C0E /* window */ = {
 				FAAC6B03170A373B008A61C5 /* CompressedData.h in Headers */,
 				FAE010DB170DDE99006F29D0 /* ddsinfo.h in Headers */,
 				FAE010DD170DDE99006F29D0 /* ddsparse.h in Headers */,
-				FAE010E1170DE25E006F29D0 /* CompressedData.h in Headers */,
+				FAE010E1170DE25E006F29D0 /* ddsHandler.h in Headers */,
 				FAE010E5170DF75C006F29D0 /* wrap_CompressedData.h in Headers */,
+				FA0CDE3D1710F9A50056E8D7 /* FormatHandler.h in Headers */,
+				FAEC808B1710FEA60057279A /* ImageData.h in Headers */,
+				FAEC808F1711E76C0057279A /* CompressedData.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 				FA08F62D16C7541400F007B5 /* wrap_SpriteBatch.cpp in Sources */,
 				FA08F62E16C7542600F007B5 /* ImageData.cpp in Sources */,
 				FA08F62F16C7542600F007B5 /* Image.cpp in Sources */,
-				FA08F63016C7542600F007B5 /* ImageData.cpp in Sources */,
+				FA08F63016C7542600F007B5 /* DevilHandler.cpp in Sources */,
 				FA08F63116C7542600F007B5 /* wrap_Image.cpp in Sources */,
 				FA08F63216C7542600F007B5 /* wrap_ImageData.cpp in Sources */,
 				FA08F63316C7542D00F007B5 /* Joystick.cpp in Sources */,
 				FA5454C216F1310000D30303 /* MathModule.cpp in Sources */,
 				FAAC6B02170A373B008A61C5 /* CompressedData.cpp in Sources */,
 				FAE010DC170DDE99006F29D0 /* ddsparse.cpp in Sources */,
-				FAE010E0170DE25E006F29D0 /* CompressedData.cpp in Sources */,
+				FAE010E0170DE25E006F29D0 /* ddsHandler.cpp in Sources */,
 				FAE010E4170DF75C006F29D0 /* wrap_CompressedData.cpp in Sources */,
+				FAEC808A1710FEA60057279A /* ImageData.cpp in Sources */,
+				FAEC808E1711E76C0057279A /* CompressedData.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

src/libraries/ddsparse/ddsparse.cpp

 static inline uint32_t FourCC(char a, char b, char c, char d)
 {
 	uint32_t fcc = ((uint32_t) a)
-	| (((uint32_t) b) << 8)
-	| (((uint32_t) c) << 16)
-	| (((uint32_t) d) << 24);
+	            | (((uint32_t) b) << 8)
+	            | (((uint32_t) c) << 16)
+	            | (((uint32_t) d) << 24);
 
 	return fcc;
 }
 	return true;
 }
 
-Parser::Parser(const void *data, size_t dataSize, Options opts)
+bool Parser::isCompressedDDS(const void *data, size_t dataSize)
+{
+	if (!isDDS(data, dataSize))
+		return false;
+
+	const uint8_t *readData = (const uint8_t *) data;
+	ptrdiff_t offset = sizeof(uint32_t);
+
+	DDSHeader *header = (DDSHeader *) &readData[offset];
+	offset += sizeof(DDSHeader);
+
+	// Check for DX10 extension.
+	if ((header->format.flags & DDPF_FOURCC) && (header->format.fourCC == FourCC('D','X','1','0')))
+	{
+		DDSHeader10 *header10 = (DDSHeader10 *) &readData[offset];
+		return parseDX10Format(header10->dxgiFormat) != FORMAT_UNKNOWN;
+	}
+
+	return parseDDSFormat(header->format) != FORMAT_UNKNOWN;
+}
+
+Parser::Parser(const void *data, size_t dataSize)
 	: format(FORMAT_UNKNOWN)
-	, options(opts)
 {
 	parseData(data, dataSize);
 }
 
 Parser::Parser(const Parser &other)
-	: format(other.format)
-	, options(other.options)
+	: texData(other.texData)
+	, format(other.format)
 {
-	std::vector<Image>::const_iterator it;
-	for (it = other.texData.begin(); it != other.texData.end(); ++it)
-	{
-		Image img = *it;
+}
 
-		if ((options & OPTIONS_COPY_DATA) && img.dataSize > 0)
-		{
-			uint8_t *data = 0;
-			try
-			{
-				data = new uint8_t[img.dataSize];
-			}
-			catch (std::exception &)
-			{
-				clearData();
-				throw;
-			}
-			memcpy(data, it->data, img.dataSize);
-			img.data = data;
-		}
+Parser::Parser()
+	: format(FORMAT_UNKNOWN)
+{
+}
 
-		texData.push_back(img);
-	}
+Parser &Parser::operator = (const Parser &other)
+{
+	texData = other.texData;
+	format = other.format;
+
+	return *this;
 }
 
 Parser::~Parser()
 {
-	// Delete any data we created.
-	clearData();
 }
 
 Format Parser::getFormat() const
 	return texData.size();
 }
 
-bool Parser::ownsData() const
-{
-	return (options & OPTIONS_COPY_DATA) != 0;
-}
-
-Format Parser::parseDDSFormat(const DDSPixelFormat &fmt) const
+Format Parser::parseDDSFormat(const DDSPixelFormat &fmt)
 {
 	if (fmt.flags & DDPF_FOURCC)
 	{
 			return FORMAT_DXT3;
 		else if (fmt.fourCC == FourCC('D','X','T','5'))
 			return FORMAT_DXT5;
+		else if (fmt.fourCC == FourCC('A','T','I','1'))
+			return FORMAT_BC4;
 		else if (fmt.fourCC == FourCC('A','T','I','2'))
 			return FORMAT_BC5;
+		else if (fmt.fourCC == FourCC('B','C','4','U'))
+			return FORMAT_BC4;
+		else if (fmt.fourCC == FourCC('B','C','4','S'))
+			return FORMAT_BC4s;
+		else if (fmt.fourCC == FourCC('B','C','5','U'))
+			return FORMAT_BC5;
 		else if (fmt.fourCC == FourCC('B','C','5','S'))
 			return FORMAT_BC5s;
 	}
 	return FORMAT_UNKNOWN;
 }
 
-Format Parser::parseDX10Format(DXGIFormat fmt) const
+Format Parser::parseDX10Format(DXGIFormat fmt)
 {
 	Format f = FORMAT_UNKNOWN;
 
 	case DXGI_FORMAT_BC3_UNORM_SRGB:
 		f = FORMAT_DXT5;
 		break;
-	case DXGI_FORMAT_BC5_SNORM:
-		f = FORMAT_BC5s;
+	case DXGI_FORMAT_BC4_TYPELESS:
+	case DXGI_FORMAT_BC4_UNORM:
+		f = FORMAT_BC4;
+		break;
+	case DXGI_FORMAT_BC4_SNORM:
+		f = FORMAT_BC4s;
 		break;
 	case DXGI_FORMAT_BC5_TYPELESS:
 	case DXGI_FORMAT_BC5_UNORM:
 		f = FORMAT_BC5;
 		break;
+	case DXGI_FORMAT_BC5_SNORM:
+		f = FORMAT_BC5s;
+		break;
+	case DXGI_FORMAT_BC6H_TYPELESS:
+	case DXGI_FORMAT_BC6H_UF16:
+		f = FORMAT_BC6H;
+		break;
+	case DXGI_FORMAT_BC6H_SF16:
+		f = FORAMT_BC6Hs;
+		break;
 	case DXGI_FORMAT_BC7_TYPELESS:
 	case DXGI_FORMAT_BC7_UNORM:
 		f = FORMAT_BC7;
 		break;
 	case DXGI_FORMAT_BC7_UNORM_SRGB:
 		f = FORMAT_BC7srgb;
+		break;
 	default:
 		break;
 	}
 bool Parser::parseTexData(const uint8_t *data, size_t dataSize, Format fmt, int w, int h, int mips)
 {
 	size_t offset = 0;
+	std::vector<Image> newTexData;
 
 	for (int i = 0; i < mips; i++)
 	{
 
 		// Make sure the data size is valid.
 		if (img.dataSize == 0 || (offset + img.dataSize) > dataSize)
-		{
-			// Clean up any data we allocated previously.
-			clearData();
 			return false;
-		}
 
-		// Create our own copy of the data, if requested.
-		if (options & OPTIONS_COPY_DATA)
-		{
-			uint8_t *newData = 0;
-			try
-			{
-				newData = new uint8_t[img.dataSize];
-			}
-			catch (std::exception &)
-			{
-				// Clean up before throwing.
-				clearData();
-				throw;
-			}
-			memcpy(newData, &data[offset], img.dataSize);
-			img.data = newData;
-		}
-		else
-			img.data = &data[offset];
+		// Store the memory address of the data representing this mip level.
+		img.data = &data[offset];
 
-		texData.push_back(img);
+		newTexData.push_back(img);
 
 		// Move to the next mip level.
 		offset += img.dataSize;
 		h = std::max(h / 2, 1);
 	}
 
+	texData = newTexData;
+
 	return true;
 }
 
 	return parseTexData(&readData[offset], dataSize - offset, format, w, h, mips);
 }
 
-void Parser::clearData()
-{
-	if (options & OPTIONS_COPY_DATA)
-	{
-		// Delete any data we created.
-		std::vector<Image>::iterator it;
-		for (it = texData.begin(); it != texData.end(); ++it)
-		{
-			delete[] it->data;
-			it->data = 0;
-		}
-	}
-
-	texData.clear();
-}
-
 } // dds

src/libraries/ddsparse/ddsparse.h

 {
 
 // Supported DDS formats.
+// Formats with an 's' suffix have signed data.
 enum Format
 {
 	FORMAT_DXT1,
 	FORMAT_DXT3,
 	FORMAT_DXT5,
-	FORMAT_BC5s,    // Signed.
-	FORMAT_BC5,     // Unsigned.
+	FORMAT_BC4,
+	FORMAT_BC4s,
+	FORMAT_BC5,
+	FORMAT_BC5s,
+	FORMAT_BC6H,
+	FORAMT_BC6Hs,
 	FORMAT_BC7,
 	FORMAT_BC7srgb, // sRGB color space.
 	FORMAT_UNKNOWN
 {
 public:
 
-	enum Options
-	{
-		OPTIONS_NONE      = 0x00,
-		OPTIONS_COPY_DATA = 0x01 // Copy texture data internally when parsing.
-	};
-
 	// Represents a single mipmap level of a texture.
 	struct Image
 	{
 	};
 
 	/**
-	 * Determines whether the input byte data is a valid DDS representation.
+	 * Determines whether the input byte data represents a valid DDS file.
+	 * Does not take into account whether the texture format is supported.
+	 *
+	 * @param data     The byte data to parse.
+	 * @param dataSize The size in bytes of the data.
 	 **/
 	static bool isDDS(const void *data, size_t dataSize);
 
 	/**
-	 * Constructor.
-	 * Attempts to parse byte data as DDS. May throw std::bad_alloc if out of
-	 * memory.
+	 * Determines whether the input byte data represents a valid compressed DDS
+	 * file. Takes into account texture format, but not type (3D textures, etc.)
+	 *
 	 * @param data     The byte data to parse.
 	 * @param dataSize The size in bytes of the data.
-	 * @param options  Any optional settings (see above.)
 	 **/
-	Parser(const void *data, size_t dataSize, Options opts = OPTIONS_NONE);
+	static bool isCompressedDDS(const void *data, size_t dataSize);
+
+	/**
+	 * Constructor.
+	 * Attempts to parse byte data as a compressed DDS file.
+	 *
+	 * @param data     The byte data to parse.
+	 * @param dataSize The size in bytes of the data.
+	 **/
+	Parser(const void *data, size_t dataSize);
 	Parser(const Parser &other);
+	Parser();
+
+	Parser &operator = (const Parser &other);
 
 	~Parser();
 
 	/**
 	 * Gets the data of this texture at a mipmap level. Mipmap level 0
 	 * represents the base image.
+	 *
 	 * @param miplevel The mipmap level to get the data of.
-	 * @return Pointer to the image data, or 0 if miplevel is not within the
+	 * @return Pointer to the image data, or NULL if miplevel is not within the
 	 *         range of [0, numMipmaps).
 	 **/
 	const Image *getImageData(size_t miplevel = 0) const;
 	 **/
 	size_t getNumMipmaps() const;
 
-	/**
-	 * Gets whether this Parser is using an internal copy of the texture data.
-	 * Accessing texture data from a Parser which hasn't internally copied the
-	 * DDS data will result in undefined behaviour if the original data is deleted.
-	 **/
-	bool ownsData() const;
-
 private:
 
-	Format parseDDSFormat(const dxinfo::DDSPixelFormat &fmt) const;
-	Format parseDX10Format(dxinfo::DXGIFormat fmt) const;
+	static Format parseDDSFormat(const dxinfo::DDSPixelFormat &fmt);
+	static Format parseDX10Format(dxinfo::DXGIFormat fmt);
+
 	size_t parseImageSize(Format fmt, int width, int height) const;
 
 	bool parseTexData(const uint8_t *data, size_t dataSize, Format fmt, int w, int h, int mips);
 
 	bool parseData(const void *data, size_t dataSize);
 
-	// Delete any heap data created by this object.
-	void clearData();
-
 	std::vector<Image> texData;
 	Format format;
-	Options options;
 
 }; // Parser
 

src/modules/filesystem/physfs/wrap_Filesystem.cpp

 
 int w_newFileData(lua_State *L)
 {
-	if (!lua_isstring(L, 1))
-		return luaL_error(L, "String expected.");
-	if (!lua_isstring(L, 2))
-		return luaL_error(L, "String expected.");
+	// Single argument: treat as filepath or File.
+	if (lua_gettop(L) == 1)
+	{
+		if (lua_isstring(L, 1))
+			luax_convobj(L, 1, "filesystem", "newFile");
+
+		// Get FileData from the File.
+		if (luax_istype(L, 1, FILESYSTEM_FILE_T))
+		{
+			File *file = luax_checktype<File>(L, 1, "File", FILESYSTEM_FILE_T);
+
+			FileData *data = 0;
+			try
+			{
+				data = file->read();
+			}
+			catch (love::Exception &e)
+			{
+				return luaL_error(L, "%s", e.what());
+			}
+			luax_newtype(L, "FileData", FILESYSTEM_FILE_DATA_T, (void *) data);
+			return 1;
+		}
+		else
+			return luaL_argerror(L, 1, "string or File expected");
+	}
 
 	size_t length = 0;
-	const char *str = lua_tolstring(L, 1, &length);
-	const char *filename = lua_tostring(L, 2);
+	const char *str = luaL_checklstring(L, 1, &length);
+	const char *filename = luaL_checkstring(L, 2);
 	const char *decstr = lua_isstring(L, 3) ? lua_tostring(L, 3) : 0;
 
 	FileData::Decoder decoder = FileData::FILE;

src/modules/graphics/opengl/Image.cpp

 		return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
 	case image::CompressedData::TYPE_DXT5:
 		return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+	case image::CompressedData::TYPE_BC5:
+		return GL_COMPRESSED_RG_RGTC2;
 	case image::CompressedData::TYPE_BC5s:
 		return GL_COMPRESSED_SIGNED_RG_RGTC2;
-	case image::CompressedData::TYPE_BC5:
-		return GL_COMPRESSED_RG_RGTC2;
 	case image::CompressedData::TYPE_BC7:
 		return GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;
 	case image::CompressedData::TYPE_BC7srgb:
 	case image::CompressedData::TYPE_DXT5:
 		return GLEE_EXT_texture_compression_s3tc;
 
+	case image::CompressedData::TYPE_BC5:
 	case image::CompressedData::TYPE_BC5s:
-	case image::CompressedData::TYPE_BC5:
 		return (GLEE_VERSION_3_0 || GLEE_ARB_texture_compression_rgtc || GLEE_EXT_texture_compression_rgtc);
 
 	case image::CompressedData::TYPE_BC7:

src/modules/graphics/opengl/wrap_Graphics.cpp

 	love::image::ImageData *data = 0;
 	love::image::CompressedData *cdata = 0;
 
-	// Convert to File, if necessary.
-	if (lua_isstring(L, 1))
-		luax_convobj(L, 1, "filesystem", "newFile");
+	// Convert to FileData, if necessary.
+	if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T))
+		luax_convobj(L, 1, "filesystem", "newFileData");
 
 	// Convert to ImageData/CompressedData, if necessary.
-	if (luax_istype(L, 1, FILESYSTEM_FILE_T))
+	if (luax_istype(L, 1, FILESYSTEM_FILE_DATA_T))
 	{
 		// Determine whether to convert to ImageData or CompressedData.
 		luax_getfunction(L, "image", "isCompressed");

src/modules/image/CompressedData.cpp

 {
 
 CompressedData::CompressedData()
-	: type(TYPE_MAX_ENUM)
+	: type(TYPE_UNKNOWN)
 {
-	
 }
 
 CompressedData::~CompressedData()
 {
-	
 }
 
 int CompressedData::getSize() const
 {
-	size_t totalsize = sizeof(MipmapInfo) * dataMipmapInfo.size();
+	size_t totalsize = sizeof(SubImage) * dataImages.size();
 
-	for (size_t i = 0; i < dataMipmapInfo.size(); i++)
-		totalsize += dataMipmapInfo[i].size;
+	for (size_t i = 0; i < dataImages.size(); i++)
+		totalsize += dataImages[i].size;
 
 	return totalsize;
 }
 void *CompressedData::getData() const
 {
 	// ?
-	return (void *) &dataMipmapInfo[0].data[0];
+	return (void *) &dataImages[0].data[0];
 }
 
 int CompressedData::getNumMipmaps() const
 {
-	return dataMipmapInfo.size();
+	return dataImages.size();
 }
 
 int CompressedData::getSize(int miplevel) const
 {
 	checkMipmapLevelExists(miplevel);
 
-	return dataMipmapInfo[miplevel].size;
+	return dataImages[miplevel].size;
 }
 
 void *CompressedData::getData(int miplevel) const
 {
 	checkMipmapLevelExists(miplevel);
 
-	return (void *) &dataMipmapInfo[miplevel].data[0];
+	return (void *) &dataImages[miplevel].data[0];
 }
 
 int CompressedData::getWidth(int miplevel) const
 {
 	checkMipmapLevelExists(miplevel);
 
-	return dataMipmapInfo[miplevel].width;
+	return dataImages[miplevel].width;
 }
 
 int CompressedData::getHeight(int miplevel) const
 {
 	checkMipmapLevelExists(miplevel);
 
-	return dataMipmapInfo[miplevel].height;
+	return dataImages[miplevel].height;
 }
 
 CompressedData::TextureType CompressedData::getType() const
 
 void CompressedData::checkMipmapLevelExists(int miplevel) const
 {
-	if (miplevel < 0 || miplevel >= dataMipmapInfo.size())
+	if (miplevel < 0 || miplevel >= dataImages.size())
 		throw love::Exception("Mipmap level %d does not exist", miplevel);
 }
 
 
 StringMap<CompressedData::TextureType, CompressedData::TYPE_MAX_ENUM>::Entry CompressedData::typeEntries[] =
 {
+	{"unknown", CompressedData::TYPE_UNKNOWN},
 	{"dxt1", CompressedData::TYPE_DXT1},
 	{"dxt3", CompressedData::TYPE_DXT3},
 	{"dxt5", CompressedData::TYPE_DXT5},
+	{"bc5", CompressedData::TYPE_BC5},
 	{"bc5s", CompressedData::TYPE_BC5s},
-	{"bc5", CompressedData::TYPE_BC5},
 	{"bc7", CompressedData::TYPE_BC7},
 	{"bc7srgb", CompressedData::TYPE_BC7srgb},
 };

src/modules/image/CompressedData.h

 	// Types of compressed image data.
 	enum TextureType
 	{
+		TYPE_UNKNOWN,
 		TYPE_DXT1,
 		TYPE_DXT3,
 		TYPE_DXT5,
+		TYPE_BC5,
 		TYPE_BC5s,
-		TYPE_BC5,
 		TYPE_BC7,
 		TYPE_BC7srgb,
 		TYPE_MAX_ENUM
 	};
 
+	// Compressed image data can have multiple mipmap levels, each represented
+	// by a sub-image.
+	struct SubImage
+	{
+		size_t size;
+		int width, height;
+		std::vector<unsigned char> data;
+	};
+
 	CompressedData();
-
 	virtual ~CompressedData();
 
 	// Implements Data.
 
 protected:
 
-	struct MipmapInfo
-	{
-		size_t size;
-		int width, height;
-		std::vector<unsigned char> data;
-	};
-
 	TextureType type;
 
 	// Texture info for each mipmap level.
-	std::vector<MipmapInfo> dataMipmapInfo;
+	std::vector<SubImage> dataImages;
 
 	void checkMipmapLevelExists(int miplevel) const;
 

src/modules/image/Image.h

 
 /**
  * This module is responsible for decoding files such as PNG, GIF, JPEG
- * into raw pixel data. This module does not know how to draw images on
- * screen; only love.graphics knows that.
+ * into raw pixel data, as well as parsing compressed formats which are designed
+ * to be uploaded to the GPU and rendered without being un-compressed.
+ * This module does not know how to draw images on screen; only love.graphics
+ * knows that.
  **/
 class Image : public Module
 {
 	virtual ~Image() {};
 
 	/**
-	 * Creates new ImageData from a file.
-	 * @param file The file containing the encoded image data.
+	 * Creates new ImageData from FileData.
+	 * @param data The FileData containing the encoded image data.
 	 * @return The new ImageData.
 	 **/
-	virtual ImageData *newImageData(love::filesystem::File *file) = 0;
-
-	/**
-	 * Creates new ImageData from a raw Data.
-	 * @param data The object containing encoded pixel data.
-	 * @return The new ImageData.
-	 **/
-	virtual ImageData *newImageData(Data *data) = 0;
+	virtual ImageData *newImageData(love::filesystem::FileData *data) = 0;
 
 	/**
 	 * Creates empty ImageData with the given size.
 	virtual ImageData *newImageData(int width, int height, void *data) = 0;
 
 	/**
-	 * Creates new CompressedData from a file.
-	 * @param file The file containing the compressed image data.
+	 * Creates new CompressedData from FileData.
+	 * @param data The FileData containing the compressed image data.
 	 * @return The new CompressedData.
 	 **/
-	virtual CompressedData *newCompressedData(love::filesystem::File *file) = 0;
+	virtual CompressedData *newCompressedData(love::filesystem::FileData *data) = 0;
 
 	/**
-	 * Creates new CompressedData from a raw Data.
-	 * @param data The object containing the compressed image data.
-	 * @return The new CompressedData.
+	 * Determines whether a FileData is Compressed image data or not.
+	 * @param data The FileData to test.
 	 **/
-	virtual CompressedData *newCompressedData(Data *data) = 0;
-
-	/**
-	 * Determines whether a File is Compressed image data or not.
-	 * @param file The file to test.
-	 **/
-	virtual bool isCompressed(love::filesystem::File *file) = 0;
-
-	/**
-	 * Determines whether a raw Data is Compressed image data or not.
-	 * @param data The data to test.
-	 **/
-	virtual bool isCompressed(Data *data) = 0;
+	virtual bool isCompressed(love::filesystem::FileData *data) = 0;
 
 }; // Image
 

src/modules/image/ImageData.cpp

 
 #include "ImageData.h"
 
-#include <stdio.h>
-
 using love::thread::Lock;
 
 namespace love
 {
 
 ImageData::ImageData()
+	: data(0)
 {
 	mutex = thread::newMutex();
 }

src/modules/image/devil/CompressedData.cpp

-/**
- * Copyright (c) 2006-2013 LOVE Development Team
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.  In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- *    claim that you wrote the original software. If you use this software
- *    in a product, an acknowledgment in the product documentation would be
- *    appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- *    misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- **/
-
-#include "CompressedData.h"
-
-namespace love
-{
-namespace image
-{
-namespace devil
-{
-
-CompressedData::CompressedData(Data *data)
-{
-	load(data);
-}
-
-CompressedData::CompressedData(love::filesystem::File *file)
-{
-	Data *data = file->read();
-	try
-	{
-		load(data);
-	}
-	catch (love::Exception &)
-	{
-		data->release();
-		throw;
-	}
-}
-
-CompressedData::~CompressedData()
-{
-	
-}
-
-bool CompressedData::convertFormat(dds::Format ddsformat)
-{
-	switch (ddsformat)
-	{
-	case dds::FORMAT_DXT1:
-		type = TYPE_DXT1;
-		break;
-	case dds::FORMAT_DXT3:
-		type = TYPE_DXT3;
-		break;
-	case dds::FORMAT_DXT5:
-		type = TYPE_DXT5;
-		break;
-	case dds::FORMAT_BC5s:
-		type = TYPE_BC5s;
-		break;
-	case dds::FORMAT_BC5:
-		type = TYPE_BC5;
-		break;
-	case dds::FORMAT_BC7:
-		type = TYPE_BC7;
-		break;
-	case dds::FORMAT_BC7srgb:
-		type = TYPE_BC7srgb;
-		break;
-	default:
-		return false;
-	}
-
-	return true;
-}
-
-void CompressedData::load(Data *data)
-{
-	if (!dds::Parser::isDDS(data->getData(), data->getSize()))
-		throw love::Exception("Could not decode compressed data (not a DDS file?)");
-
-	try
-	{
-		dds::Parser parser(data->getData(), data->getSize());
-
-		dds::Format format = parser.getFormat();
-
-		if (format == dds::FORMAT_UNKNOWN || !convertFormat(format))
-			throw love::Exception("Could not parse compressed data: Unsupported format.");
-
-		if (parser.getNumMipmaps() == 0)
-			throw love::Exception("Could not parse compressed data: No readable texture data.");
-
-		for (size_t i = 0; i < parser.getNumMipmaps(); i++)
-		{
-			const dds::Parser::Image *img = parser.getImageData(i);
-
-			MipmapInfo mip;
-
-			mip.width = img->width;
-			mip.height = img->height;
-			mip.size = img->dataSize;
-
-			mip.data.resize(mip.size);
-			memcpy(&mip.data[0], img->data, mip.size);
-
-			dataMipmapInfo.push_back(mip);
-		}
-		
-	}
-	catch (std::exception &e)
-	{
-		throw love::Exception(e.what());
-	}
-}
-
-bool CompressedData::isCompressed(const Data *data)
-{
-	return dds::Parser::isDDS(data->getData(), data->getSize());
-}
-
-} // devil
-} // image
-} // love

src/modules/image/devil/CompressedData.h

-/**
- * Copyright (c) 2006-2013 LOVE Development Team
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.  In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- *    claim that you wrote the original software. If you use this software
- *    in a product, an acknowledgment in the product documentation would be
- *    appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- *    misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- **/
-
-#ifndef LOVE_DEVIL_COMPRESSED_DATA_H
-#define LOVE_DEVIL_COMPRESSED_DATA_H
-
-// LOVE
-#include "filesystem/File.h"
-#include "image/CompressedData.h"
-
-// dds parser
-#include "ddsparse/ddsparse.h"
-
-namespace love
-{
-namespace image
-{
-namespace devil
-{
-
-class CompressedData : public love::image::CompressedData
-{
-public:
-
-	CompressedData(love::filesystem::File *file);
-	CompressedData(Data *data);
-
-	virtual ~CompressedData();
-
-	static bool isCompressed(const Data *data);
-
-private:
-
-	bool convertFormat(dds::Format ddsformat);
-	void load(Data *data);
-
-}; // CompressedData
-
-} // devil
-} // image
-} // love
-
-#endif // LOVE_DEVIL_COMPRESSED_DATA_H

src/modules/image/devil/Image.cpp

-/**
- * Copyright (c) 2006-2013 LOVE Development Team
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.  In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- *    claim that you wrote the original software. If you use this software
- *    in a product, an acknowledgment in the product documentation would be
- *    appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- *    misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- **/
-
-#include "Image.h"
-
-#include "ImageData.h"
-#include "CompressedData.h"
-
-// DevIL
-#include <IL/il.h>
-
-namespace love
-{
-namespace image
-{
-namespace devil
-{
-
-const std::string Image::compressedExts[] =
-{
-	".dds", ""
-};
-
-Image::Image()
-{
-	ilInit();
-	ilOriginFunc(IL_ORIGIN_UPPER_LEFT);
-	ilEnable(IL_ORIGIN_SET);
-}
-
-Image::~Image()
-{
-	ilShutDown();
-}
-
-const char *Image::getName() const
-{
-	return "love.image.devil";
-}
-
-love::image::ImageData *Image::newImageData(love::filesystem::File *file)
-{
-	return new ImageData(file);
-}
-
-love::image::ImageData *Image::newImageData(Data *data)
-{
-	return new ImageData(data);
-}
-
-love::image::ImageData *Image::newImageData(int width, int height)
-{
-	return new ImageData(width, height);
-}
-
-love::image::ImageData *Image::newImageData(int width, int height, void *data)
-{
-	return new ImageData(width, height, data);
-}
-
-love::image::CompressedData *Image::newCompressedData(love::filesystem::File *file)
-{
-	return new CompressedData(file);
-}
-
-love::image::CompressedData *Image::newCompressedData(love::Data *data)
-{
-	return new CompressedData(data);
-}
-
-bool Image::isCompressed(love::filesystem::File *file)
-{
-	bool hasExt = false;
-
-	// Check whether the file has an extension known to contain compressed data.
-	const std::string &ext = file->getExtension();
-	for (int i = 0; !(compressedExts[i].empty()); i++)
-	{
-		if (compressedExts[i].compare(ext))
-		{
-			hasExt = true;
-			break;
-		}
-	}
-
-	if (!hasExt)
-		return false;
-
-	// Check whether the actual data is compressed.
-	Data *data = file->read();
-	bool compressed = isCompressed(data);
-	data->release();
-
-	return compressed;
-}
-
-bool Image::isCompressed(love::Data *data)
-{
-	return CompressedData::isCompressed(data);
-}
-
-} // devil
-} // image
-} // love

src/modules/image/devil/Image.h

-/**
- * Copyright (c) 2006-2013 LOVE Development Team
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.  In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- *    claim that you wrote the original software. If you use this software
- *    in a product, an acknowledgment in the product documentation would be
- *    appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- *    misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- **/
-
-#ifndef LOVE_IMAGE_DEVIL_IMAGE_H
-#define LOVE_IMAGE_DEVIL_IMAGE_H
-
-// LOVE
-#include "image/Image.h"
-
-// STL
-#include <string>
-
-namespace love
-{
-namespace image
-{
-namespace devil
-{
-
-class Image : public love::image::Image
-{
-public:
-
-	Image();
-	~Image();
-
-	// Implements Module.
-	const char *getName() const;
-
-	love::image::ImageData *newImageData(love::filesystem::File *file);
-	love::image::ImageData *newImageData(Data *data);
-	love::image::ImageData *newImageData(int width, int height);
-	love::image::ImageData *newImageData(int width, int height, void *data);
-
-	love::image::CompressedData *newCompressedData(love::filesystem::File *file);
-	love::image::CompressedData *newCompressedData(Data *data);
-
-	bool isCompressed(love::filesystem::File *file);
-	bool isCompressed(Data *data);
-
-	static const std::string compressedExts[];
-
-}; // Image
-
-} // devil
-} // image
-} // love
-
-#endif // LOVE_IMAGE_DEVIL_IMAGE_H

src/modules/image/devil/ImageData.cpp

-/**
- * Copyright (c) 2006-2013 LOVE Development Team
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.  In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- *    claim that you wrote the original software. If you use this software
- *    in a product, an acknowledgment in the product documentation would be
- *    appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- *    misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- **/
-
-#include "ImageData.h"
-
-// STD
-#include <cstring>
-#include <iostream>
-
-// LOVE
-#include "common/Exception.h"
-#include "common/math.h"
-#include "filesystem/File.h"
-
-using love::thread::Lock;
-
-static Mutex *devilMutex = 0;
-
-namespace love
-{
-namespace image
-{
-namespace devil
-{
-
-static inline void ilxClearErrors()
-{
-	while (ilGetError() != IL_NO_ERROR);
-}
-
-ImageData::ImageData(Data *data)
-{
-	load(data);
-}
-
-ImageData::ImageData(filesystem::File *file)
-{
-	Data *data = file->read();
-	try
-	{
-		load(data);
-	}
-	catch (love::Exception &)
-	{
-		data->release();
-		throw;
-	}
-	data->release();
-}
-
-ImageData::ImageData(int width, int height)
-{
-	this->width = width;
-	this->height = height;
-	create(width, height);
-
-	// Set to black.
-	memset(data, 0, width*height*4);
-}
-
-ImageData::ImageData(int width, int height, void *data)
-{
-	this->width = width;
-	this->height = height;
-	create(width, height, data);
-}
-
-ImageData::~ImageData()
-{
-	delete[] data;
-}
-
-void ImageData::create(int width, int height, void *data)
-{
-	try
-	{
-		this->data = new unsigned char[width*height*sizeof(pixel)];
-	}
-	catch(std::bad_alloc &)
-	{
-		throw love::Exception("Out of memory");
-	}
-
-	if (data)
-		memcpy(this->data, data, width*height*sizeof(pixel));
-}
-
-void ImageData::load(Data *data)
-{
-	if (!devilMutex)
-		devilMutex = thread::newMutex();
-
-	Lock lock(devilMutex);
-	ILuint image = ilGenImage();
-	ilBindImage(image);
-
-	try
-	{
-		bool success = IL_TRUE == ilLoadL(IL_TYPE_UNKNOWN, (void *)data->getData(), data->getSize());
-
-		if (!success)
-			throw love::Exception("Could not decode image!");
-
-		width = ilGetInteger(IL_IMAGE_WIDTH);
-		height = ilGetInteger(IL_IMAGE_HEIGHT);
-
-		// Make sure the image is in RGBA format.
-		ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
-
-		// This should always be four.
-		int bpp = ilGetInteger(IL_IMAGE_BPP);
-		if (bpp != sizeof(pixel))
-			throw love::Exception("Could not convert image!");
-
-		create(width, height, ilGetData());
-	}
-	catch (std::exception &e)
-	{
-		// catches love and std exceptions
-		ilDeleteImage(image);
-		throw love::Exception("%s", e.what());
-	}
-
-	ilDeleteImage(image);
-}
-
-void ImageData::encode(love::filesystem::File *f, ImageData::Format format)
-{
-	if (!devilMutex)
-		devilMutex = thread::newMutex();
-
-	Lock lock1(devilMutex);
-	Lock lock2(mutex);
-
-	ILuint tempimage = ilGenImage();
-	ilBindImage(tempimage);
-	ilxClearErrors();
-
-	ILubyte *encoded_data = NULL;
-
-	try
-	{
-		bool success = IL_TRUE == ilTexImage(width, height, 1, sizeof(pixel), IL_RGBA, IL_UNSIGNED_BYTE, this->data);
-
-		ILenum err = ilGetError();
-		ilxClearErrors();
-
-		if (!success)
-		{
-			if (err != IL_NO_ERROR)
-			{
-				switch (err)
-				{
-				case IL_ILLEGAL_OPERATION:
-					throw love::Exception("Illegal operation");
-				case IL_INVALID_PARAM:
-					throw love::Exception("Invalid parameters");
-				case IL_OUT_OF_MEMORY:
-					throw love::Exception("Out of memory");
-				default:
-					throw love::Exception("Unknown error (%d)", (int) err);
-				}
-			}
-
-			throw love::Exception("Could not create image for the encoding!");
-		}
-
-		ilRegisterOrigin(IL_ORIGIN_UPPER_LEFT);
-
-		ILuint ilFormat;
-		switch (format)
-		{
-		case ImageData::FORMAT_BMP:
-			ilFormat = IL_BMP;
-			break;
-		case ImageData::FORMAT_TGA:
-			ilFormat = IL_TGA;
-			break;
-		case ImageData::FORMAT_JPG:
-			ilFormat = IL_JPG;
-			break;
-		case ImageData::FORMAT_PNG:
-		default: // PNG is the default format
-			ilFormat = IL_PNG;
-			break;
-		}
-
-		ILuint size = ilSaveL(ilFormat, NULL, 0);
-		if (!size)
-			throw love::Exception("Could not encode image!");
-
-		try
-		{
-			encoded_data = new ILubyte[size];
-		}
-		catch(std::bad_alloc &)
-		{
-			throw love::Exception("Out of memory");
-		}
-
-		ilSaveL(ilFormat, encoded_data, size);
-
-		f->open(love::filesystem::File::WRITE);
-		f->write(encoded_data, size);
-		f->close();
-	}
-	catch (std::exception &e)
-	{
-		// catches love and std exceptions
-		ilDeleteImage(tempimage);
-		delete[] encoded_data;
-		throw love::Exception("%s", e.what());
-	}
-
-	ilDeleteImage(tempimage);
-	delete[] encoded_data;
-}
-
-} // devil
-} // image
-} // love

src/modules/image/devil/ImageData.h

-/**
- * Copyright (c) 2006-2013 LOVE Development Team
- *
- * This software is provided 'as-is', without any express or implied
- * warranty.  In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must not
- *    claim that you wrote the original software. If you use this software
- *    in a product, an acknowledgment in the product documentation would be
- *    appreciated but is not required.
- * 2. Altered source versions must be plainly marked as such, and must not be
- *    misrepresented as being the original software.
- * 3. This notice may not be removed or altered from any source distribution.
- **/
-
-#ifndef LOVE_DEVIL_IMAGE_DATA_H
-#define LOVE_DEVIL_IMAGE_DATA_H
-
-// LOVE
-#include "filesystem/File.h"
-#include "image/ImageData.h"
-
-// DevIL
-#include <IL/il.h>
-
-
-namespace love
-{
-namespace image
-{
-namespace devil
-{
-
-class ImageData : public love::image::ImageData
-{
-private:
-
-	// Create imagedata. Initialize with data if not null.
-	void create(int width, int height, void *data = 0);
-
-	// Load an encoded format.
-	void load(Data *data);
-
-public:
-
-	ImageData(Data *data);
-	ImageData(love::filesystem::File *file);
-	ImageData(int width, int height);
-	ImageData(int width, int height, void *data);
-	virtual ~ImageData();
-
-	// Implements ImageData.
-	void encode(love::filesystem::File *f, Format format);
-
-}; // ImageData
-
-} // devil
-} // image
-} // love
-
-#endif // LOVE_DEVIL_IMAGE_DATA_H

src/modules/image/magpie/CompressedData.cpp

+/**
+ * Copyright (c) 2006-2013 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#include "CompressedData.h"
+
+#include "ddsHandler.h"
+
+namespace love
+{
+namespace image
+{
+namespace magpie
+{
+
+CompressedData::CompressedData(love::filesystem::FileData *data)
+{
+	load(data);
+}
+
+CompressedData::~CompressedData()
+{
+}
+
+void CompressedData::load(love::filesystem::FileData *data)
+{
+	std::vector<SubImage> imageMipmaps;
+	TextureType textype = TYPE_UNKNOWN;
+
+	if (ddsHandler::canParse(data))
+		textype = ddsHandler::parse(data, imageMipmaps);
+
+	if (textype == TYPE_UNKNOWN)
+		throw (love::Exception("Could not parse compressed data: Unknown format."));
+
+	dataImages = imageMipmaps;
+	type = textype;
+}
+
+bool CompressedData::isCompressed(love::filesystem::FileData *data)
+{
+	if (ddsHandler::canParse(data))
+		return true;
+
+	return false;
+}
+
+} // magpie
+} // image
+} // love

src/modules/image/magpie/CompressedData.h

+/**
+ * Copyright (c) 2006-2013 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#ifndef LOVE_IMAGE_MAGPIE_COMPRESSED_DATA_H
+#define LOVE_IMAGE_MAGPIE_COMPRESSED_DATA_H
+
+// LOVE
+#include "filesystem/File.h"
+#include "image/CompressedData.h"
+
+namespace love
+{
+namespace image
+{
+namespace magpie
+{
+
+class CompressedData : public love::image::CompressedData
+{
+public:
+
+	CompressedData(love::filesystem::FileData *data);
+	virtual ~CompressedData();
+
+	static bool isCompressed(love::filesystem::FileData *data);
+
+private:
+
+	void load(love::filesystem::FileData *data);
+
+}; // CompressedData
+
+} // magpie
+} // image
+} // love
+
+#endif // LOVE_IMAGE_MAGPIE_COMPRESSED_DATA_H

src/modules/image/magpie/DevilHandler.cpp

+/**
+ * Copyright (c) 2006-2013 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#include "DevilHandler.h"
+
+// LOVE
+#include "common/Exception.h"
+#include "common/math.h"
+#include "filesystem/File.h"
+#include "thread/threads.h"
+
+// DevIL
+#include <IL/il.h>
+
+using love::thread::Lock;
+
+static Mutex *devilMutex = 0;
+
+namespace love
+{
+namespace image
+{
+namespace magpie
+{
+
+static inline void ilxClearErrors()
+{
+	while (ilGetError() != IL_NO_ERROR);
+}
+
+void DevilHandler::init()
+{
+	ilInit();
+	ilEnable(IL_ORIGIN_SET);
+	ilOriginFunc(IL_ORIGIN_UPPER_LEFT);
+}
+
+void DevilHandler::quit()
+{
+	ilShutDown();
+}
+
+bool DevilHandler::canDecode(love::filesystem::FileData *data)
+{
+	// DevIL can decode a lot of formats...
+	return true;
+}
+
+bool DevilHandler::canEncode(ImageData::Format format)
+{
+	switch (format)
+	{
+	case ImageData::FORMAT_BMP:
+	case ImageData::FORMAT_TGA:
+	case ImageData::FORMAT_JPG:
+	case ImageData::FORMAT_PNG:
+		return true;
+	default:
+		return false;
+	}
+
+	return false;
+}
+
+DevilHandler::DecodedImage DevilHandler::decode(love::filesystem::FileData *data)
+{
+	if (!devilMutex)
+		devilMutex = thread::newMutex();
+
+	Lock lock(devilMutex);
+
+	ILuint image = ilGenImage();
+	ilBindImage(image);
+
+	DecodedImage img;
+
+	try
+	{
+		bool success = ilLoadL(IL_TYPE_UNKNOWN, (void *)data->getData(), data->getSize()) == IL_TRUE;
+
+		if (!success)
+			throw love::Exception("Could not decode image!");
+
+		img.width = ilGetInteger(IL_IMAGE_WIDTH);
+		img.height = ilGetInteger(IL_IMAGE_HEIGHT);
+
+		// Make sure the image is in RGBA format.
+		ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
+
+		// This should always be four.
+		int bpp = ilGetInteger(IL_IMAGE_BPP);
+		if (bpp != sizeof(pixel))
+			throw love::Exception("Could not convert image!");
+
+		img.size = ilGetInteger(IL_IMAGE_SIZE_OF_DATA);
+
+		try
+		{
+			img.data = new ILubyte[img.size];
+		}
+		catch (std::bad_alloc &)
+		{
+			throw love::Exception("Out of memory.");
+		}
+
+		memcpy(img.data, ilGetData(), img.size);
+	}
+	catch (std::exception &e)
+	{
+		// catches love and std exceptions
+		ilDeleteImage(image);
+		throw love::Exception("%s", e.what());
+	}
+
+	ilDeleteImage(image);
+
+	return img;
+}
+
+DevilHandler::EncodedImage DevilHandler::encode(const DecodedImage &img, ImageData::Format format)
+{
+	if (!devilMutex)
+		devilMutex = thread::newMutex();
+
+	Lock lock(devilMutex);
+
+	ILuint tempimage = ilGenImage();
+	ilBindImage(tempimage);
+	ilxClearErrors();
+
+	EncodedImage encodedimg;
+
+	try
+	{
+		bool success = ilTexImage(img.width, img.height, 1, sizeof(pixel), IL_RGBA, IL_UNSIGNED_BYTE, img.data) ==  IL_TRUE;
+
+		ILenum err = ilGetError();
+		ilxClearErrors();
+
+		if (!success)
+		{
+			if (err != IL_NO_ERROR)
+			{
+				switch (err)
+				{
+				case IL_ILLEGAL_OPERATION:
+					throw love::Exception("Illegal operation");
+				case IL_INVALID_PARAM:
+					throw love::Exception("Invalid parameters");
+				case IL_OUT_OF_MEMORY:
+					throw love::Exception("Out of memory");
+				default:
+					throw love::Exception("Unknown error (%d)", (int) err);
+				}
+			}
+
+			throw love::Exception("Could not create image for the encoding!");
+		}
+
+		ilRegisterOrigin(IL_ORIGIN_UPPER_LEFT);
+
+		ILuint ilFormat;
+		switch (format)
+		{
+		case ImageData::FORMAT_BMP:
+			ilFormat = IL_BMP;
+			break;
+		case ImageData::FORMAT_TGA:
+			ilFormat = IL_TGA;
+			break;
+		case ImageData::FORMAT_JPG:
+			ilFormat = IL_JPG;
+			break;
+		case ImageData::FORMAT_PNG:
+		default: // PNG is the default format
+			ilFormat = IL_PNG;
+			break;
+		}
+
+		encodedimg.size = ilSaveL(ilFormat, NULL, 0);
+		if (!encodedimg.size)
+			throw love::Exception("Could not encode image!");
+
+		try
+		{
+			encodedimg.data = new ILubyte[encodedimg.size];
+		}
+		catch(std::bad_alloc &)
+		{
+			throw love::Exception("Out of memory");
+		}
+
+		ilSaveL(ilFormat, encodedimg.data, encodedimg.size);
+	}
+	catch (std::exception &e)
+	{
+		// catches love and std exceptions
+		ilDeleteImage(tempimage);
+		delete[] encodedimg.data;
+		throw love::Exception("%s", e.what());
+	}
+
+	ilDeleteImage(tempimage);
+
+	return encodedimg;
+}
+
+} // magpie
+} // image
+} // love

src/modules/image/magpie/DevilHandler.h

+/**
+ * Copyright (c) 2006-2013 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ **/
+
+#ifndef LOVE_IMAGE_MAGPIE_DEVIL_HANDLER_H
+#define LOVE_IMAGE_MAGPIE_DEVIL_HANDLER_H
+
+// LOVE
+#include "filesystem/File.h"
+#include "FormatHandler.h"
+
+namespace love
+{
+namespace image
+{
+namespace magpie
+{
+
+class DevilHandler : public FormatHandler
+{
+public:
+
+	static void init();
+	static void quit();
+
+	// Implements FormatHandler.
+
+	static bool canDecode(love::filesystem::FileData *data);
+	static bool canEncode(ImageData::Format format);
+
+	static DecodedImage decode(love::filesystem::FileData *data);
+	static EncodedImage encode(const DecodedImage &img, ImageData::Format format);
+
+}; // DevilHandler
+
+} // magpie
+} // image
+} // love
+
+#endif // LOVE_IMAGE_MAGPIE_DEVIL_HANDLER_H

src/modules/image/magpie/FormatHandler.h

+/**
+ * Copyright (c) 2006-2013 LOVE Development Team
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.