From 88d64954a408f7369d4d3298fee531314e4e5090 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Sun, 7 Apr 2013 17:18:34 -0300 Subject: [PATCH] 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. --HG-- branch : image-CompressedData --- .../love-framework.xcodeproj/project.pbxproj | 58 ++++--- src/libraries/ddsparse/ddsparse.cpp | 150 +++++++++--------- src/libraries/ddsparse/ddsparse.h | 61 +++---- .../filesystem/physfs/wrap_Filesystem.cpp | 34 +++- src/modules/graphics/opengl/Image.cpp | 6 +- src/modules/graphics/opengl/wrap_Graphics.cpp | 8 +- src/modules/image/CompressedData.cpp | 27 ++-- src/modules/image/CompressedData.h | 22 +-- src/modules/image/Image.h | 44 ++--- src/modules/image/ImageData.cpp | 3 +- src/modules/image/magpie/CompressedData.cpp | 66 ++++++++ .../image/{devil => magpie}/CompressedData.h | 22 +-- .../ImageData.cpp => magpie/DevilHandler.cpp} | 139 ++++++++-------- src/modules/image/magpie/DevilHandler.h | 56 +++++++ src/modules/image/magpie/FormatHandler.h | 94 +++++++++++ src/modules/image/{devil => magpie}/Image.cpp | 64 ++------ src/modules/image/{devil => magpie}/Image.h | 29 ++-- src/modules/image/magpie/ImageData.cpp | 133 ++++++++++++++++ .../image/{devil => magpie}/ImageData.h | 39 ++--- .../ddsHandler.cpp} | 119 +++++++------- src/modules/image/magpie/ddsHandler.h | 75 +++++++++ src/modules/image/wrap_Image.cpp | 128 +++++---------- 22 files changed, 846 insertions(+), 531 deletions(-) create mode 100644 src/modules/image/magpie/CompressedData.cpp rename src/modules/image/{devil => magpie}/CompressedData.h (75%) rename src/modules/image/{devil/ImageData.cpp => magpie/DevilHandler.cpp} (65%) create mode 100644 src/modules/image/magpie/DevilHandler.h create mode 100644 src/modules/image/magpie/FormatHandler.h rename src/modules/image/{devil => magpie}/Image.cpp (60%) rename src/modules/image/{devil => magpie}/Image.h (74%) create mode 100644 src/modules/image/magpie/ImageData.cpp rename src/modules/image/{devil => magpie}/ImageData.h (77%) rename src/modules/image/{devil/CompressedData.cpp => magpie/ddsHandler.cpp} (60%) create mode 100644 src/modules/image/magpie/ddsHandler.h diff --git a/platform/macosx/love-framework.xcodeproj/project.pbxproj b/platform/macosx/love-framework.xcodeproj/project.pbxproj index 252418c19..88abbfb3c 100644 --- a/platform/macosx/love-framework.xcodeproj/project.pbxproj +++ b/platform/macosx/love-framework.xcodeproj/project.pbxproj @@ -134,7 +134,7 @@ 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 */; }; @@ -209,6 +209,7 @@ 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 */; }; @@ -231,10 +232,14 @@ 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 */; }; @@ -353,7 +358,7 @@ 1A95437F513E662113AC154A /* b2Rope.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = b2Rope.h; sourceTree = ""; }; 1A9810F758AC1D1E4B6431FD /* wrap_Graphics.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Graphics.cpp; sourceTree = ""; }; 1AA213FC158815FA77C40330 /* ChainShape.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ChainShape.h; sourceTree = ""; }; - 1AA7781A230065F346E2313A /* ImageData.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ImageData.cpp; sourceTree = ""; }; + 1AA7781A230065F346E2313A /* DevilHandler.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DevilHandler.cpp; sourceTree = ""; }; 1B036C7C5A8832AE53BB1C06 /* b2CollideEdge.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = b2CollideEdge.cpp; sourceTree = ""; }; 1B1C4E4D288A1D2F29E57B1B /* Rasterizer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Rasterizer.cpp; sourceTree = ""; }; 1B4E22F1388E2B2E76E3377B /* wrap_GlyphData.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_GlyphData.cpp; sourceTree = ""; }; @@ -398,7 +403,7 @@ 27F777AB188D674F30BC1829 /* wrap_World.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = wrap_World.h; sourceTree = ""; }; 28016C9B51FE1A893DC35B66 /* Variant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Variant.h; sourceTree = ""; }; 28024635525B077E08A73D9B /* Source.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Source.cpp; sourceTree = ""; }; - 283342E174613897621A43F1 /* ImageData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ImageData.h; sourceTree = ""; }; + 283342E174613897621A43F1 /* DevilHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DevilHandler.h; sourceTree = ""; }; 286660042F9654F61AB90D7A /* Body.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Body.h; sourceTree = ""; }; 2912092853050AF9785F39BE /* wrap_RevoluteJoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = wrap_RevoluteJoint.h; sourceTree = ""; }; 295C665B1E0B6B2D03CC4937 /* wrap_Event.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = wrap_Event.h; sourceTree = ""; }; @@ -686,6 +691,7 @@ 7F796B7A3362196075C62E61 /* wrap_Fixture.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_Fixture.cpp; sourceTree = ""; }; 7F911CF2107B22F44C5B2542 /* b2Collision.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = b2Collision.h; sourceTree = ""; }; FA08F5AE16C7525600F007B5 /* Info-Framework.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Framework.plist"; sourceTree = ""; }; + FA0CDE3B1710F9A50056E8D7 /* FormatHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormatHandler.h; sourceTree = ""; }; FA5454C016F1310000D30303 /* MathModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MathModule.cpp; sourceTree = ""; }; FA5454C116F1310000D30303 /* MathModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MathModule.h; sourceTree = ""; }; FA577A6716C719D900860150 /* FreeType.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = FreeType.framework; path = /Library/Frameworks/FreeType.framework; sourceTree = ""; }; @@ -717,10 +723,14 @@ FAE010D8170DDE99006F29D0 /* ddsinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ddsinfo.h; sourceTree = ""; }; FAE010D9170DDE99006F29D0 /* ddsparse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ddsparse.cpp; sourceTree = ""; }; FAE010DA170DDE99006F29D0 /* ddsparse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ddsparse.h; sourceTree = ""; }; - FAE010DE170DE25E006F29D0 /* CompressedData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompressedData.cpp; sourceTree = ""; }; - FAE010DF170DE25E006F29D0 /* CompressedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompressedData.h; sourceTree = ""; }; + FAE010DE170DE25E006F29D0 /* ddsHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ddsHandler.cpp; sourceTree = ""; }; + FAE010DF170DE25E006F29D0 /* ddsHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ddsHandler.h; sourceTree = ""; }; FAE010E2170DF75B006F29D0 /* wrap_CompressedData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wrap_CompressedData.cpp; sourceTree = ""; }; FAE010E3170DF75C006F29D0 /* wrap_CompressedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrap_CompressedData.h; sourceTree = ""; }; + FAEC80881710FEA60057279A /* ImageData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageData.cpp; sourceTree = ""; }; + FAEC80891710FEA60057279A /* ImageData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageData.h; sourceTree = ""; }; + FAEC808C1711E76C0057279A /* CompressedData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompressedData.cpp; sourceTree = ""; }; + FAEC808D1711E76C0057279A /* CompressedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompressedData.h; sourceTree = ""; }; FAF2729816E3D44400CC193A /* Channel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Channel.cpp; sourceTree = ""; }; FAF2729916E3D44400CC193A /* Channel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Channel.h; sourceTree = ""; }; FAF2729A16E3D44400CC193A /* LuaThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LuaThread.cpp; sourceTree = ""; }; @@ -768,16 +778,16 @@ 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 = ""; @@ -927,17 +937,22 @@ path = libluasocket; sourceTree = ""; }; - 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 = ""; }; 153D76205F7A4ACD12FB4C0E /* window */ = { @@ -1685,8 +1700,11 @@ 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; }; @@ -1877,7 +1895,7 @@ 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 */, @@ -1964,8 +1982,10 @@ 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; }; diff --git a/src/libraries/ddsparse/ddsparse.cpp b/src/libraries/ddsparse/ddsparse.cpp index cf248b359..853f621f2 100644 --- a/src/libraries/ddsparse/ddsparse.cpp +++ b/src/libraries/ddsparse/ddsparse.cpp @@ -36,9 +36,9 @@ using namespace dds::dxinfo; 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; } @@ -86,46 +86,54 @@ bool Parser::isDDS(const void *data, size_t dataSize) 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::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 @@ -146,12 +154,7 @@ size_t Parser::getNumMipmaps() 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) { @@ -161,8 +164,16 @@ Format Parser::parseDDSFormat(const DDSPixelFormat &fmt) const 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; } @@ -170,7 +181,7 @@ Format Parser::parseDDSFormat(const DDSPixelFormat &fmt) const return FORMAT_UNKNOWN; } -Format Parser::parseDX10Format(DXGIFormat fmt) const +Format Parser::parseDX10Format(DXGIFormat fmt) { Format f = FORMAT_UNKNOWN; @@ -191,19 +202,34 @@ Format Parser::parseDX10Format(DXGIFormat fmt) const 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; } @@ -248,6 +274,7 @@ size_t Parser::parseImageSize(Format fmt, int width, int height) const bool Parser::parseTexData(const uint8_t *data, size_t dataSize, Format fmt, int w, int h, int mips) { size_t offset = 0; + std::vector newTexData; for (int i = 0; i < mips; i++) { @@ -259,33 +286,12 @@ bool Parser::parseTexData(const uint8_t *data, size_t dataSize, Format fmt, int // 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; @@ -294,6 +300,8 @@ bool Parser::parseTexData(const uint8_t *data, size_t dataSize, Format fmt, int h = std::max(h / 2, 1); } + texData = newTexData; + return true; } @@ -347,20 +355,4 @@ bool Parser::parseData(const void *data, size_t dataSize) 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::iterator it; - for (it = texData.begin(); it != texData.end(); ++it) - { - delete[] it->data; - it->data = 0; - } - } - - texData.clear(); -} - } // dds diff --git a/src/libraries/ddsparse/ddsparse.h b/src/libraries/ddsparse/ddsparse.h index 0e84b001b..1cd61a720 100644 --- a/src/libraries/ddsparse/ddsparse.h +++ b/src/libraries/ddsparse/ddsparse.h @@ -37,13 +37,18 @@ namespace dds { // 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 @@ -53,12 +58,6 @@ class Parser { 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 { @@ -71,20 +70,35 @@ public: }; /** - * 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(); @@ -96,8 +110,9 @@ public: /** * 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; @@ -108,29 +123,19 @@ public: **/ 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 texData; Format format; - Options options; }; // Parser diff --git a/src/modules/filesystem/physfs/wrap_Filesystem.cpp b/src/modules/filesystem/physfs/wrap_Filesystem.cpp index d830e701e..0c194eb7d 100644 --- a/src/modules/filesystem/physfs/wrap_Filesystem.cpp +++ b/src/modules/filesystem/physfs/wrap_Filesystem.cpp @@ -105,14 +105,36 @@ int w_newFile(lua_State *L) 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(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; diff --git a/src/modules/graphics/opengl/Image.cpp b/src/modules/graphics/opengl/Image.cpp index beee76181..7f0080daf 100644 --- a/src/modules/graphics/opengl/Image.cpp +++ b/src/modules/graphics/opengl/Image.cpp @@ -537,10 +537,10 @@ GLenum Image::getCompressedFormat(image::CompressedData::TextureType type) const return GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; case image::CompressedData::TYPE_DXT5: return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - 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_BC5s: + return GL_COMPRESSED_SIGNED_RG_RGTC2; case image::CompressedData::TYPE_BC7: return GL_COMPRESSED_RGBA_BPTC_UNORM_ARB; case image::CompressedData::TYPE_BC7srgb: @@ -587,8 +587,8 @@ bool Image::hasCompressedTextureSupport(image::CompressedData::TextureType type) case image::CompressedData::TYPE_DXT5: return GLEE_EXT_texture_compression_s3tc; - case image::CompressedData::TYPE_BC5s: case image::CompressedData::TYPE_BC5: + case image::CompressedData::TYPE_BC5s: return (GLEE_VERSION_3_0 || GLEE_ARB_texture_compression_rgtc || GLEE_EXT_texture_compression_rgtc); case image::CompressedData::TYPE_BC7: diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp index 6ab99669b..b6c7c9bf1 100644 --- a/src/modules/graphics/opengl/wrap_Graphics.cpp +++ b/src/modules/graphics/opengl/wrap_Graphics.cpp @@ -279,12 +279,12 @@ int w_newImage(lua_State *L) 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"); diff --git a/src/modules/image/CompressedData.cpp b/src/modules/image/CompressedData.cpp index 8a34c1529..b3aaa6eb7 100644 --- a/src/modules/image/CompressedData.cpp +++ b/src/modules/image/CompressedData.cpp @@ -26,22 +26,20 @@ namespace image { 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; } @@ -49,40 +47,40 @@ int CompressedData::getSize() const 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 @@ -92,7 +90,7 @@ 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); } @@ -108,11 +106,12 @@ bool CompressedData::getConstant(CompressedData::TextureType in, const char *&ou StringMap::Entry CompressedData::typeEntries[] = { + {"unknown", CompressedData::TYPE_UNKNOWN}, {"dxt1", CompressedData::TYPE_DXT1}, {"dxt3", CompressedData::TYPE_DXT3}, {"dxt5", CompressedData::TYPE_DXT5}, - {"bc5s", CompressedData::TYPE_BC5s}, {"bc5", CompressedData::TYPE_BC5}, + {"bc5s", CompressedData::TYPE_BC5s}, {"bc7", CompressedData::TYPE_BC7}, {"bc7srgb", CompressedData::TYPE_BC7srgb}, }; diff --git a/src/modules/image/CompressedData.h b/src/modules/image/CompressedData.h index e4710f96b..416202454 100644 --- a/src/modules/image/CompressedData.h +++ b/src/modules/image/CompressedData.h @@ -47,18 +47,27 @@ public: // Types of compressed image data. enum TextureType { + TYPE_UNKNOWN, TYPE_DXT1, TYPE_DXT3, TYPE_DXT5, - TYPE_BC5s, TYPE_BC5, + TYPE_BC5s, TYPE_BC7, TYPE_BC7srgb, TYPE_MAX_ENUM }; - CompressedData(); + // Compressed image data can have multiple mipmap levels, each represented + // by a sub-image. + struct SubImage + { + size_t size; + int width, height; + std::vector data; + }; + CompressedData(); virtual ~CompressedData(); // Implements Data. @@ -101,17 +110,10 @@ public: protected: - struct MipmapInfo - { - size_t size; - int width, height; - std::vector data; - }; - TextureType type; // Texture info for each mipmap level. - std::vector dataMipmapInfo; + std::vector dataImages; void checkMipmapLevelExists(int miplevel) const; diff --git a/src/modules/image/Image.h b/src/modules/image/Image.h index 469c44c51..5d866feb0 100644 --- a/src/modules/image/Image.h +++ b/src/modules/image/Image.h @@ -35,8 +35,10 @@ namespace image /** * 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 { @@ -48,18 +50,11 @@ public: 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. @@ -79,30 +74,17 @@ public: 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 diff --git a/src/modules/image/ImageData.cpp b/src/modules/image/ImageData.cpp index c7a372a39..1a052a753 100644 --- a/src/modules/image/ImageData.cpp +++ b/src/modules/image/ImageData.cpp @@ -20,8 +20,6 @@ #include "ImageData.h" -#include - using love::thread::Lock; namespace love @@ -30,6 +28,7 @@ namespace image { ImageData::ImageData() + : data(0) { mutex = thread::newMutex(); } diff --git a/src/modules/image/magpie/CompressedData.cpp b/src/modules/image/magpie/CompressedData.cpp new file mode 100644 index 000000000..f9ac1de98 --- /dev/null +++ b/src/modules/image/magpie/CompressedData.cpp @@ -0,0 +1,66 @@ +/** + * 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 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 diff --git a/src/modules/image/devil/CompressedData.h b/src/modules/image/magpie/CompressedData.h similarity index 75% rename from src/modules/image/devil/CompressedData.h rename to src/modules/image/magpie/CompressedData.h index 2a8eb7799..2da786509 100644 --- a/src/modules/image/devil/CompressedData.h +++ b/src/modules/image/magpie/CompressedData.h @@ -18,43 +18,37 @@ * 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 +#ifndef LOVE_IMAGE_MAGPIE_COMPRESSED_DATA_H +#define LOVE_IMAGE_MAGPIE_COMPRESSED_DATA_H // LOVE #include "filesystem/File.h" #include "image/CompressedData.h" -// dds parser -#include "ddsparse/ddsparse.h" - namespace love { namespace image { -namespace devil +namespace magpie { class CompressedData : public love::image::CompressedData { public: - CompressedData(love::filesystem::File *file); - CompressedData(Data *data); - + CompressedData(love::filesystem::FileData *data); virtual ~CompressedData(); - static bool isCompressed(const Data *data); + static bool isCompressed(love::filesystem::FileData *data); private: - bool convertFormat(dds::Format ddsformat); - void load(Data *data); + void load(love::filesystem::FileData *data); }; // CompressedData -} // devil +} // magpie } // image } // love -#endif // LOVE_DEVIL_COMPRESSED_DATA_H +#endif // LOVE_IMAGE_MAGPIE_COMPRESSED_DATA_H diff --git a/src/modules/image/devil/ImageData.cpp b/src/modules/image/magpie/DevilHandler.cpp similarity index 65% rename from src/modules/image/devil/ImageData.cpp rename to src/modules/image/magpie/DevilHandler.cpp index 76b11a5ad..ac85b98e2 100644 --- a/src/modules/image/devil/ImageData.cpp +++ b/src/modules/image/magpie/DevilHandler.cpp @@ -18,16 +18,16 @@ * 3. This notice may not be removed or altered from any source distribution. **/ -#include "ImageData.h" - -// STD -#include -#include +#include "DevilHandler.h" // LOVE #include "common/Exception.h" #include "common/math.h" #include "filesystem/File.h" +#include "thread/threads.h" + +// DevIL +#include using love::thread::Lock; @@ -37,7 +37,7 @@ namespace love { namespace image { -namespace devil +namespace magpie { static inline void ilxClearErrors() @@ -45,81 +45,61 @@ static inline void ilxClearErrors() while (ilGetError() != IL_NO_ERROR); } -ImageData::ImageData(Data *data) +void DevilHandler::init() { - load(data); + ilInit(); + ilEnable(IL_ORIGIN_SET); + ilOriginFunc(IL_ORIGIN_UPPER_LEFT); } -ImageData::ImageData(filesystem::File *file) +void DevilHandler::quit() { - Data *data = file->read(); - try + 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) { - 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"); + case ImageData::FORMAT_BMP: + case ImageData::FORMAT_TGA: + case ImageData::FORMAT_JPG: + case ImageData::FORMAT_PNG: + return true; + default: + return false; } - if (data) - memcpy(this->data, data, width*height*sizeof(pixel)); + return false; } -void ImageData::load(Data *data) +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 = IL_TRUE == ilLoadL(IL_TYPE_UNKNOWN, (void *)data->getData(), data->getSize()); + bool success = ilLoadL(IL_TYPE_UNKNOWN, (void *)data->getData(), data->getSize()) == IL_TRUE; if (!success) throw love::Exception("Could not decode image!"); - width = ilGetInteger(IL_IMAGE_WIDTH); - height = ilGetInteger(IL_IMAGE_HEIGHT); + 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); @@ -129,7 +109,18 @@ void ImageData::load(Data *data) if (bpp != sizeof(pixel)) throw love::Exception("Could not convert image!"); - create(width, height, ilGetData()); + 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) { @@ -139,25 +130,26 @@ void ImageData::load(Data *data) } ilDeleteImage(image); + + return img; } -void ImageData::encode(love::filesystem::File *f, ImageData::Format format) +DevilHandler::EncodedImage DevilHandler::encode(const DecodedImage &img, ImageData::Format format) { if (!devilMutex) devilMutex = thread::newMutex(); - Lock lock1(devilMutex); - Lock lock2(mutex); + Lock lock(devilMutex); ILuint tempimage = ilGenImage(); ilBindImage(tempimage); ilxClearErrors(); - ILubyte *encoded_data = NULL; + EncodedImage encodedimg; try { - bool success = IL_TRUE == ilTexImage(width, height, 1, sizeof(pixel), IL_RGBA, IL_UNSIGNED_BYTE, this->data); + bool success = ilTexImage(img.width, img.height, 1, sizeof(pixel), IL_RGBA, IL_UNSIGNED_BYTE, img.data) == IL_TRUE; ILenum err = ilGetError(); ilxClearErrors(); @@ -202,37 +194,34 @@ void ImageData::encode(love::filesystem::File *f, ImageData::Format format) break; } - ILuint size = ilSaveL(ilFormat, NULL, 0); - if (!size) + encodedimg.size = ilSaveL(ilFormat, NULL, 0); + if (!encodedimg.size) throw love::Exception("Could not encode image!"); try { - encoded_data = new ILubyte[size]; + encodedimg.data = new ILubyte[encodedimg.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(); + ilSaveL(ilFormat, encodedimg.data, encodedimg.size); } catch (std::exception &e) { // catches love and std exceptions ilDeleteImage(tempimage); - delete[] encoded_data; + delete[] encodedimg.data; throw love::Exception("%s", e.what()); } ilDeleteImage(tempimage); - delete[] encoded_data; + + return encodedimg; } -} // devil +} // magpie } // image } // love diff --git a/src/modules/image/magpie/DevilHandler.h b/src/modules/image/magpie/DevilHandler.h new file mode 100644 index 000000000..d5cd80a4a --- /dev/null +++ b/src/modules/image/magpie/DevilHandler.h @@ -0,0 +1,56 @@ +/** + * 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 diff --git a/src/modules/image/magpie/FormatHandler.h b/src/modules/image/magpie/FormatHandler.h new file mode 100644 index 000000000..e5412bd0e --- /dev/null +++ b/src/modules/image/magpie/FormatHandler.h @@ -0,0 +1,94 @@ +/** + * 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_FORMAT_HANDLER_H +#define LOVE_IMAGE_MAGPIE_FORMAT_HANDLER_H + +// LOVE +#include "image/ImageData.h" +#include "filesystem/File.h" + +namespace love +{ +namespace image +{ +namespace magpie +{ + +/** + * Base class for all ImageData encoder/decoder library interfaces. + **/ +class FormatHandler +{ +public: + + // Raw RGBA pixel data. + struct DecodedImage + { + int width, height; + size_t size; + unsigned char *data; + DecodedImage() : width(0), height(0), size(0), data(0) {}; + }; + + // Pixel data encoded in a particular format. + struct EncodedImage + { + size_t size; + unsigned char *data; + EncodedImage() : size(0), data(0) {}; + }; + + // Lets pretend we have virtual static methods... + + /** + * Determines whether a particular FileData can be decoded by this handler. + * @param data The data to decode. + **/ + // virtual static bool canDecode(love::filesystem::FileData *data) = 0; + + /** + * Determines whether this handler can encode to a particular format. + * @param format The format to encode to. + **/ + // virtual static bool canEncode(ImageData::Format format) = 0; + + /** + * Decodes an image from its encoded form into raw pixel data. + * @param data The encoded data to decode. + * @return The decoded pixel data. + **/ + // virtual static DecodedImage decode(love::filesystem::FileData *data) = 0; + + /** + * Encodes an image from raw pixel data into a particular format. + * @param img The raw image data to encode. + * @param format The format to encode to. + * @return The encoded image data. + **/ + // virtual static EncodedImage encode(const DecodedImage &img, ImageData::Format format) = 0; + +}; // FormatHandler + +} // magpie +} // image +} // love + +#endif // LOVE_IMAGE_MAGPIE_FORMAT_HANDLER_H diff --git a/src/modules/image/devil/Image.cpp b/src/modules/image/magpie/Image.cpp similarity index 60% rename from src/modules/image/devil/Image.cpp rename to src/modules/image/magpie/Image.cpp index 06240d22d..6f7e5261c 100644 --- a/src/modules/image/devil/Image.cpp +++ b/src/modules/image/magpie/Image.cpp @@ -20,47 +20,34 @@ #include "Image.h" -#include "ImageData.h" +#include "imageData.h" #include "CompressedData.h" -// DevIL -#include +#include "DevilHandler.h" namespace love { namespace image { -namespace devil +namespace magpie { -const std::string Image::compressedExts[] = -{ - ".dds", "" -}; - Image::Image() { - ilInit(); - ilOriginFunc(IL_ORIGIN_UPPER_LEFT); - ilEnable(IL_ORIGIN_SET); + DevilHandler::init(); } Image::~Image() { - ilShutDown(); + DevilHandler::quit(); } const char *Image::getName() const { - return "love.image.devil"; + return "love.image.magpie"; } -love::image::ImageData *Image::newImageData(love::filesystem::File *file) -{ - return new ImageData(file); -} - -love::image::ImageData *Image::newImageData(Data *data) +love::image::ImageData *Image::newImageData(love::filesystem::FileData *data) { return new ImageData(data); } @@ -75,47 +62,16 @@ 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) +love::image::CompressedData *Image::newCompressedData(love::filesystem::FileData *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) +bool Image::isCompressed(love::filesystem::FileData *data) { return CompressedData::isCompressed(data); } -} // devil +} // magpie } // image } // love diff --git a/src/modules/image/devil/Image.h b/src/modules/image/magpie/Image.h similarity index 74% rename from src/modules/image/devil/Image.h rename to src/modules/image/magpie/Image.h index fce3f722b..d0ea76713 100644 --- a/src/modules/image/devil/Image.h +++ b/src/modules/image/magpie/Image.h @@ -18,22 +18,24 @@ * 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 +#ifndef LOVE_IMAGE_MAGPIE_IMAGE_H +#define LOVE_IMAGE_MAGPIE_IMAGE_H // LOVE #include "image/Image.h" -// STL -#include - namespace love { namespace image { -namespace devil +namespace magpie { +/** + * Similar to love.sound's Lullaby module, love.image.magpie interfaces with + * multiple image libraries and determines the correct one to use on a + * per-image basis at runtime. + **/ class Image : public love::image::Image { public: @@ -44,23 +46,18 @@ public: // Implements Module. const char *getName() const; - love::image::ImageData *newImageData(love::filesystem::File *file); - love::image::ImageData *newImageData(Data *data); + love::image::ImageData *newImageData(love::filesystem::FileData *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); + love::image::CompressedData *newCompressedData(love::filesystem::FileData *data); - bool isCompressed(love::filesystem::File *file); - bool isCompressed(Data *data); - - static const std::string compressedExts[]; + bool isCompressed(love::filesystem::FileData *data); }; // Image -} // devil +} // magpie } // image } // love -#endif // LOVE_IMAGE_DEVIL_IMAGE_H \ No newline at end of file +#endif // LOVE_IMAGE_MAGPIE_IMAGE_H diff --git a/src/modules/image/magpie/ImageData.cpp b/src/modules/image/magpie/ImageData.cpp new file mode 100644 index 000000000..c5127fa3e --- /dev/null +++ b/src/modules/image/magpie/ImageData.cpp @@ -0,0 +1,133 @@ +/** + * 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" + +#include "FormatHandler.h" +#include "DevilHandler.h" + +namespace love +{ +namespace image +{ +namespace magpie +{ + +ImageData::ImageData(love::filesystem::FileData *data) +{ + decode(data); +} + +ImageData::ImageData(int width, int height) +{ + this->width = width; + this->height = height; + create(width, height); + + // Set to black/transparency. + memset(data, 0, width*height*sizeof(pixel)); +} + +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::decode(love::filesystem::FileData *data) +{ + FormatHandler::DecodedImage decodedimg; + + if (DevilHandler::canDecode(data)) + decodedimg = DevilHandler::decode(data); + else + throw love::Exception("Image format has no suitable decoder."); + + // The decoder *must* output a 32 bits-per-pixel image. + if (decodedimg.size != decodedimg.width*decodedimg.height*sizeof(pixel)) + { + delete[] decodedimg.data; + throw love::Exception("Coult not convert image!"); + } + + if (this->data) + delete[] this->data; + + this->width = decodedimg.width; + this->height = decodedimg.height; + this->data = decodedimg.data; +} + +void ImageData::encode(love::filesystem::File *f, ImageData::Format format) +{ + thread::Lock lock(mutex); + + FormatHandler::DecodedImage rawimage; + rawimage.width = width; + rawimage.height = height; + rawimage.size = width*height*sizeof(pixel); + rawimage.data = data; + + FormatHandler::EncodedImage encodedimage; + + try + { + if (DevilHandler::canEncode(format)) + encodedimage = DevilHandler::encode(rawimage, format); + else + throw love::Exception("Image format has no suitable encoder."); + + f->open(love::filesystem::File::WRITE); + f->write(encodedimage.data, encodedimage.size); + f->close(); + } + catch (love::Exception &) + { + delete[] encodedimage.data; + throw; + } + + delete[] encodedimage.data; +} + +} // magpie +} // image +} // love diff --git a/src/modules/image/devil/ImageData.h b/src/modules/image/magpie/ImageData.h similarity index 77% rename from src/modules/image/devil/ImageData.h rename to src/modules/image/magpie/ImageData.h index 37e9f4edf..64eafa86a 100644 --- a/src/modules/image/devil/ImageData.h +++ b/src/modules/image/magpie/ImageData.h @@ -18,49 +18,44 @@ * 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 +#ifndef LOVE_IMAGE_MAGPIE_IMAGE_DATA_H +#define LOVE_IMAGE_MAGPIE_IMAGE_DATA_H // LOVE #include "filesystem/File.h" #include "image/ImageData.h" -// DevIL -#include - - namespace love { namespace image { -namespace devil +namespace magpie { class ImageData : public love::image::ImageData { +public: + + ImageData(love::filesystem::FileData *data); + ImageData(int width, int height); + ImageData(int width, int height, void *data); + virtual ~ImageData(); + + // Implements image::ImageData. + virtual void encode(love::filesystem::File *f, ImageData::Format format); + 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); + // Decode and load an encoded format. + void decode(love::filesystem::FileData *data); }; // ImageData -} // devil +} // magpie } // image } // love -#endif // LOVE_DEVIL_IMAGE_DATA_H +#endif // LOVE_IMAGE_MAGPIE_IMAGE_DATA_H diff --git a/src/modules/image/devil/CompressedData.cpp b/src/modules/image/magpie/ddsHandler.cpp similarity index 60% rename from src/modules/image/devil/CompressedData.cpp rename to src/modules/image/magpie/ddsHandler.cpp index 8bcff4434..5a149f20a 100644 --- a/src/modules/image/devil/CompressedData.cpp +++ b/src/modules/image/magpie/ddsHandler.cpp @@ -18,83 +18,53 @@ * 3. This notice may not be removed or altered from any source distribution. **/ -#include "CompressedData.h" +#include "ddsHandler.h" namespace love { namespace image { -namespace devil +namespace magpie { -CompressedData::CompressedData(Data *data) +bool ddsHandler::canParse(const filesystem::FileData *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: + if (!accepts(data->getExtension())) return false; - } - return true; + return dds::Parser::isCompressedDDS(data->getData(), data->getSize()); } -void CompressedData::load(Data *data) +bool ddsHandler::accepts(const std::string &ext) +{ + static const std::string supported[] = + { + "dds", "" + }; + + for (int i = 0; !(supported[i].empty()); i++) + { + if (supported[i].compare(ext) == 0) + return true; + } + + return false; +} + +CompressedData::TextureType ddsHandler::parse(filesystem::FileData *data, std::vector &images) { if (!dds::Parser::isDDS(data->getData(), data->getSize())) throw love::Exception("Could not decode compressed data (not a DDS file?)"); + CompressedData::TextureType textype = CompressedData::TYPE_UNKNOWN; + try { dds::Parser parser(data->getData(), data->getSize()); - dds::Format format = parser.getFormat(); + textype = convertFormat(parser.getFormat()); - if (format == dds::FORMAT_UNKNOWN || !convertFormat(format)) + if (textype == CompressedData::TYPE_UNKNOWN) throw love::Exception("Could not parse compressed data: Unsupported format."); if (parser.getNumMipmaps() == 0) @@ -104,30 +74,49 @@ void CompressedData::load(Data *data) { const dds::Parser::Image *img = parser.getImageData(i); - MipmapInfo mip; + CompressedData::SubImage mip; mip.width = img->width; mip.height = img->height; mip.size = img->dataSize; + mip.data.insert(mip.data.begin(), &img->data[0], &img->data[mip.size]); - mip.data.resize(mip.size); - memcpy(&mip.data[0], img->data, mip.size); - - dataMipmapInfo.push_back(mip); + images.push_back(mip); } - } catch (std::exception &e) { throw love::Exception(e.what()); } + + return textype; } -bool CompressedData::isCompressed(const Data *data) +CompressedData::TextureType ddsHandler::convertFormat(dds::Format ddsformat) { - return dds::Parser::isDDS(data->getData(), data->getSize()); + switch (ddsformat) + { + case dds::FORMAT_DXT1: + return CompressedData::TYPE_DXT1; + case dds::FORMAT_DXT3: + return CompressedData::TYPE_DXT3; + case dds::FORMAT_DXT5: + return CompressedData::TYPE_DXT5; + case dds::FORMAT_BC5: + return CompressedData::TYPE_BC5; + case dds::FORMAT_BC5s: + return CompressedData::TYPE_BC5s; + case dds::FORMAT_BC7: + return CompressedData::TYPE_BC7; + case dds::FORMAT_BC7srgb: + return CompressedData::TYPE_BC7srgb; + default: + return CompressedData::TYPE_UNKNOWN; + } + + return CompressedData::TYPE_UNKNOWN; } -} // devil +} // magpie } // image } // love diff --git a/src/modules/image/magpie/ddsHandler.h b/src/modules/image/magpie/ddsHandler.h new file mode 100644 index 000000000..d5ca057e2 --- /dev/null +++ b/src/modules/image/magpie/ddsHandler.h @@ -0,0 +1,75 @@ +/** + * 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_DDS_HANDLER_H +#define LOVE_IMAGE_MAGPIE_DDS_HANDLER_H + +// LOVE +#include "filesystem/File.h" +#include "image/CompressedData.h" + +// dds parser +#include "ddsparse/ddsparse.h" + +// STL +#include + +namespace love +{ +namespace image +{ +namespace magpie +{ + +/** + * Interface between CompressedData and the ddsparse library. + **/ +class ddsHandler +{ +public: + + /** + * Determines whether a particular FileData can be parsed as CompressedData + * by this handler. + * @param data The data to parse. + **/ + static bool canParse(const filesystem::FileData *data); + + /** + * Parses Compressed image data into a list of sub-images. + * @param[in] data The data to parse. + * @param[out] images The list of sub-images (including byte data for each) + * outputted by the parser. + * @return The type of CompressedData. + **/ + static CompressedData::TextureType parse(filesystem::FileData *data, std::vector &images); + +private: + + static bool accepts(const std::string &ext); + static CompressedData::TextureType convertFormat(dds::Format ddsformat); + +}; // ddsHandler + +} // magpie +} // image +} // love + +#endif // LOVE_IMAGE_MAGPIE_DDS_HANDLER_H diff --git a/src/modules/image/wrap_Image.cpp b/src/modules/image/wrap_Image.cpp index d77079caf..c87afbf5a 100644 --- a/src/modules/image/wrap_Image.cpp +++ b/src/modules/image/wrap_Image.cpp @@ -23,7 +23,7 @@ #include "common/Data.h" #include "common/StringMap.h" -#include "devil/Image.h" +#include "magpie/Image.h" namespace love { @@ -55,82 +55,47 @@ int w_newImageData(lua_State *L) return 1; } - // Case 2: Data - if (luax_istype(L, 1, DATA_T)) - { - Data *d = luax_checktype(L, 1, "Data", DATA_T); - ImageData *t = 0; - try - { - t = instance->newImageData(d); - } - catch(love::Exception &e) - { - return luaL_error(L, "%s", e.what()); - } - luax_newtype(L, "ImageData", IMAGE_IMAGE_DATA_T, (void *)t); - return 1; - } + // Case 2: File(Data). - // Case 3: String/File. + // 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 File, if necessary. - if (lua_isstring(L, 1)) - luax_convobj(L, 1, "filesystem", "newFile"); - - love::filesystem::File *file = luax_checktype(L, 1, "File", FILESYSTEM_FILE_T); + love::filesystem::FileData *data = luax_checktype(L, 1, "FileData", FILESYSTEM_FILE_DATA_T); ImageData *t = 0; try { - t = instance->newImageData(file); - } - catch(love::Exception &e) - { - return luaL_error(L, "%s", e.what()); - } - luax_newtype(L, "ImageData", IMAGE_IMAGE_DATA_T, (void *)t); - return 1; -} - -int w_newCompressedData(lua_State *L) -{ - // Case 1: Data - if (luax_istype(L, 1, DATA_T)) - { - Data *d = luax_checktype(L, 1, "Data", DATA_T); - - CompressedData *t = 0; - try - { - t = instance->newCompressedData(d); - } - catch (love::Exception &e) - { - return luaL_error(L, "%s", e.what()); - } - luax_newtype(L, "CompressedData", IMAGE_COMPRESSED_DATA_T, (void *) t); - - return 1; - } - - // Case 2: String/File. - - // Convert to File, if necessary. - if (lua_isstring(L, 1)) - luax_convobj(L, 1, "filesystem", "newFile"); - - love::filesystem::File *file = luax_checktype(L, 1, "File", FILESYSTEM_FILE_T); - - CompressedData *t = 0; - try - { - t = instance->newCompressedData(file); + t = instance->newImageData(data); } catch (love::Exception &e) { return luaL_error(L, "%s", e.what()); } + + luax_newtype(L, "ImageData", IMAGE_IMAGE_DATA_T, (void *) t); + + return 1; +} + +int w_newCompressedData(lua_State *L) +{ + // Convert to FileData, if necessary. + if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T)) + luax_convobj(L, 1, "filesystem", "newFileData"); + + love::filesystem::FileData *data = luax_checktype(L, 1, "FileData", FILESYSTEM_FILE_DATA_T); + + CompressedData *t = 0; + try + { + t = instance->newCompressedData(data); + } + catch(love::Exception &e) + { + return luaL_error(L, "%s", e.what()); + } + luax_newtype(L, "CompressedData", IMAGE_COMPRESSED_DATA_T, (void *) t); return 1; @@ -138,37 +103,22 @@ int w_newCompressedData(lua_State *L) int w_isCompressed(lua_State *L) { - if (luax_istype(L, 1, DATA_T)) - { - Data *d = luax_checktype(L, 1, "Data", DATA_T); - try - { - bool compressed = instance->isCompressed(d); - luax_pushboolean(L, compressed); - } - catch (love::Exception &e) - { - return luaL_error(L, "%s", e.what()); - } - return 1; - } + // 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 File, if necessary. - if (lua_isstring(L, 1)) - luax_convobj(L, 1, "filesystem", "newFile"); - - filesystem::File *file = luax_checktype(L, 1, "File", FILESYSTEM_FILE_T); + love::filesystem::FileData *data = luax_checktype(L, 1, "FileData", FILESYSTEM_FILE_DATA_T); + bool compressed = false; try { - bool compressed = instance->isCompressed(file); - luax_pushboolean(L, compressed); + compressed = instance->isCompressed(data); } catch (love::Exception &e) { return luaL_error(L, "%s", e.what()); } - + luax_pushboolean(L, compressed); return 1; } @@ -194,7 +144,7 @@ extern "C" int luaopen_love_image(lua_State *L) { try { - instance = new love::image::devil::Image(); + instance = new love::image::magpie::Image(); } catch(Exception &e) {