1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-19 13:40:49 +03:00

0031478: Visualization, TKOpenGl - allow uploading Cubemap in compressed DDS format when supported by GPU

Graphic3d_TextureRoot::GetCompressedImage() - added new interface for fetching compressed texture image.
Default implementation detects DDS image files using Image_DDSParser parser.

Graphic3d_TextureRoot::GetImage() has been extended with new parameter
- the list of image formats supported by OpenGL driver.
Graphic3d_TextureRoot::convertToCompatible() implicitly converts
BGRA image to RGBA on OpenGL ES, which normally does not support BGR formats.

OpenGl_Caps::isTopDownTextureUV - new property defines how application defines
UV texture coordinates in primitive arrays.
OpenGl_Context::SetTextureMatrix() compares this flag with OpenGl_Texture::IsTopDown()
and automatically flips V coordinate in case of mismatch.

OpenGl_Texture now holds exact number of mipmap levels
instead of Boolean flag indicating that they are defined.
This allows loading DDS files with incomplete mipmap level set
by setting GL_TEXTURE_MAX_LEVEL to appropriate value instead of default 1000
(causing black textures in case if mipmap levels are not defined till 1x1).

Fixed order of texture coordinates transformation within GLSL program to match FFP matrix:
Rotate -> Translate -> Scale (previously Rotation was applied afterwards).
This commit is contained in:
kgv
2020-05-16 02:47:20 +03:00
committed by bugmaster
parent 691711cd3e
commit faff37677c
45 changed files with 1625 additions and 301 deletions

View File

@@ -1,6 +1,10 @@
Image_AlienPixMap.cxx
Image_AlienPixMap.hxx
Image_Color.hxx
Image_CompressedFormat.hxx
Image_CompressedPixMap.hxx
Image_DDSParser.cxx
Image_DDSParser.hxx
Image_Diff.cxx
Image_Diff.hxx
Image_Format.hxx
@@ -8,6 +12,8 @@ Image_PixMap.cxx
Image_PixMap.hxx
Image_PixMapData.hxx
Image_PixMapTypedData.hxx
Image_SupportedFormats.cxx
Image_SupportedFormats.hxx
Image_Texture.cxx
Image_Texture.hxx
Image_VideoRecorder.cxx

View File

@@ -0,0 +1,31 @@
// Copyright (c) 2020 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _Image_CompressedFormat_HeaderFile
#define _Image_CompressedFormat_HeaderFile
#include <Image_Format.hxx>
//! List of compressed pixel formats natively supported by various graphics hardware (e.g. for efficient decoding on-the-fly).
//! It is defined as extension of Image_Format.
enum Image_CompressedFormat
{
Image_CompressedFormat_UNKNOWN = Image_Format_UNKNOWN,
Image_CompressedFormat_RGB_S3TC_DXT1 = Image_Format_NB,
Image_CompressedFormat_RGBA_S3TC_DXT1,
Image_CompressedFormat_RGBA_S3TC_DXT3,
Image_CompressedFormat_RGBA_S3TC_DXT5
};
enum { Image_CompressedFormat_NB = Image_CompressedFormat_RGBA_S3TC_DXT5 + 1 };
#endif // _Image_CompressedFormat_HeaderFile

View File

@@ -0,0 +1,108 @@
// Copyright (c) 2020 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _Image_CompressedPixMap_HeaderFile
#define _Image_CompressedPixMap_HeaderFile
#include <Image_Format.hxx>
#include <Image_CompressedFormat.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_Buffer.hxx>
#include <Standard_Type.hxx>
//! Compressed pixmap data definition.
//! It is defined independently from Image_PixMap, which defines only uncompressed formats.
class Image_CompressedPixMap : public Standard_Transient
{
DEFINE_STANDARD_RTTIEXT(Image_CompressedPixMap, Standard_Transient)
public:
//! Return base (uncompressed) pixel format.
Image_Format BaseFormat() const { return myBaseFormat; }
//! Set base (uncompressed) pixel format.
void SetBaseFormat (Image_Format theFormat) { myBaseFormat = theFormat; }
//! Return compressed format.
Image_CompressedFormat CompressedFormat() const { return myFormat; }
//! Set compressed format.
void SetCompressedFormat (Image_CompressedFormat theFormat) { myFormat = theFormat; }
//! Return raw (compressed) data.
const Handle(NCollection_Buffer)& FaceData() const { return myFaceData; }
//! Set raw (compressed) data.
void SetFaceData (const Handle(NCollection_Buffer)& theBuffer) { myFaceData = theBuffer; }
//! Return Array of mipmap sizes, including base level.
const NCollection_Array1<Standard_Integer>& MipMaps() const { return myMipMaps; }
//! Return Array of mipmap sizes, including base level.
NCollection_Array1<Standard_Integer>& ChangeMipMaps() { return myMipMaps; }
//! Return TRUE if complete mip map level set (up to 1x1 resolution).
Standard_Boolean IsCompleteMipMapSet() const { return myIsCompleteMips; }
//! Set if complete mip map level set (up to 1x1 resolution).
void SetCompleteMipMapSet (Standard_Boolean theIsComplete) { myIsCompleteMips = theIsComplete; }
//! Return surface length in bytes.
Standard_Size FaceBytes() const { return myFaceBytes; }
//! Set surface length in bytes.
void SetFaceBytes (Standard_Size theSize) { myFaceBytes = theSize; }
//! Return surface width.
Standard_Integer SizeX() const { return mySizeX; }
//! Return surface height.
Standard_Integer SizeY() const { return mySizeY; }
//! Set surface width x height.
void SetSize (Standard_Integer theSizeX, Standard_Integer theSizeY)
{
mySizeX = theSizeX;
mySizeY = theSizeY;
}
//! Return TRUE if image layout is top-down (always true).
bool IsTopDown() const { return true; }
//! Return number of faces in the file; should be 6 for cubemap.
Standard_Integer NbFaces() const { return myNbFaces; }
//! Set number of faces in the file.
void SetNbFaces (Standard_Integer theSize) { myNbFaces = theSize; }
public:
//! Empty constructor.
Image_CompressedPixMap()
: myFaceBytes (0), myNbFaces (0), mySizeX (0), mySizeY (0), myBaseFormat (Image_Format_UNKNOWN), myFormat (Image_CompressedFormat_UNKNOWN), myIsCompleteMips (false) {}
protected:
NCollection_Array1<Standard_Integer> myMipMaps; //!< Array of mipmap sizes, including base level
Handle(NCollection_Buffer) myFaceData; //!< raw compressed data
Standard_Size myFaceBytes; //!< surface length in bytes
Standard_Integer myNbFaces; //!< number of faces in the file
Standard_Integer mySizeX; //!< surface width
Standard_Integer mySizeY; //!< surface height
Image_Format myBaseFormat; //!< base (uncompressed) pixel format
Image_CompressedFormat myFormat; //!< compressed format
Standard_Boolean myIsCompleteMips; //!< flag indicating complete mip map level set (up to 1x1 resolution)
};
#endif // _Image_CompressedPixMap_HeaderFile

View File

@@ -0,0 +1,255 @@
// Copyright (c) 2020 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <Image_DDSParser.hxx>
#include <Image_PixMap.hxx>
#include <Image_SupportedFormats.hxx>
#include <Message.hxx>
#include <OSD_OpenFile.hxx>
IMPLEMENT_STANDARD_RTTIEXT(Image_CompressedPixMap, Standard_Transient)
//! DDS Pixel Format structure.
struct Image_DDSParser::DDSPixelFormat
{
uint32_t Size;
uint32_t Flags;
uint32_t FourCC;
uint32_t RGBBitCount;
uint32_t RBitMask;
uint32_t GBitMask;
uint32_t BBitMask;
uint32_t ABitMask;
};
//! DDS File header structure.
struct Image_DDSParser::DDSFileHeader
{
//! Caps2 flag indicating complete (6 faces) cubemap.
enum { DDSCompleteCubemap = 0xFE00 };
//! Return TRUE if cubmap flag is set.
bool IscompleteCubemap() const { return (Caps2 & DDSFileHeader::DDSCompleteCubemap) == DDSFileHeader::DDSCompleteCubemap; }
uint32_t Size;
uint32_t Flags;
uint32_t Height;
uint32_t Width;
uint32_t PitchOrLinearSize;
uint32_t Depth;
uint32_t MipMapCount;
uint32_t Reserved1[11];
DDSPixelFormat PixelFormatDef;
uint32_t Caps;
uint32_t Caps2;
uint32_t Caps3;
uint32_t Caps4;
uint32_t Reserved2;
};
// =======================================================================
// function : Load
// purpose :
// =======================================================================
Handle(Image_CompressedPixMap) Image_DDSParser::Load (const Handle(Image_SupportedFormats)& theSupported,
const TCollection_AsciiString& theFile,
const Standard_Integer theFaceIndex,
const int64_t theFileOffset)
{
std::ifstream aFile;
OSD_OpenStream (aFile, theFile.ToCString(), std::ios::in | std::ios::binary);
char aHeader[128] = {};
if (!aFile.is_open()
|| !aFile.good())
{
return Handle(Image_CompressedPixMap)();
}
if (theFileOffset != 0)
{
aFile.seekg ((std::streamoff )theFileOffset, std::ios::beg);
}
aFile.read (aHeader, 128);
Standard_Size aNbReadBytes = (Standard_Size )aFile.gcount();
if (aNbReadBytes < 128
|| ::memcmp (aHeader, "DDS ", 4) != 0)
{
return Handle(Image_CompressedPixMap)();
}
Handle(Image_CompressedPixMap) aDef = parseHeader (*(const DDSFileHeader* )(aHeader + 4));
if (aDef.IsNull())
{
return Handle(Image_CompressedPixMap)();
}
if (!theSupported.IsNull()
&& !theSupported->IsSupported (aDef->CompressedFormat()))
{
return Handle(Image_CompressedPixMap)();
}
if (theFaceIndex < 0)
{
return aDef;
}
if (theFaceIndex >= aDef->NbFaces()
|| aDef->FaceBytes() == 0)
{
Message::SendFail (TCollection_AsciiString ("DDS Reader error - invalid face index #") + theFaceIndex + " within file\n" + theFile);
return Handle(Image_CompressedPixMap)();
}
const Standard_Size anOffset = aDef->FaceBytes() * theFaceIndex;
if (anOffset != 0)
{
aFile.seekg ((std::streamoff )anOffset, std::ios::cur);
}
Handle(NCollection_Buffer) aBuffer = new NCollection_Buffer (Image_PixMap::DefaultAllocator(), aDef->FaceBytes());
aFile.read ((char* )aBuffer->ChangeData(), aDef->FaceBytes());
aNbReadBytes = (Standard_Size )aFile.gcount();
if (aNbReadBytes < aDef->FaceBytes())
{
Message::SendFail (TCollection_AsciiString ("DDS Reader error - unable to read face #") + theFaceIndex + " data from file\n" + theFile);
return Handle(Image_CompressedPixMap)();
}
aDef->SetFaceData (aBuffer);
return aDef;
}
// =======================================================================
// function : Load
// purpose :
// =======================================================================
Handle(Image_CompressedPixMap) Image_DDSParser::Load (const Handle(Image_SupportedFormats)& theSupported,
const Handle(NCollection_Buffer)& theBuffer,
const Standard_Integer theFaceIndex)
{
if (theBuffer.IsNull()
|| theBuffer->Size() < 128
|| ::memcmp (theBuffer->Data(), "DDS ", 4) != 0)
{
return Handle(Image_CompressedPixMap)();
}
Handle(Image_CompressedPixMap) aDef = parseHeader (*(const DDSFileHeader* )(theBuffer->Data() + 4));
if (aDef.IsNull())
{
return Handle(Image_CompressedPixMap)();
}
if (!theSupported.IsNull()
&& !theSupported->IsSupported (aDef->CompressedFormat()))
{
return Handle(Image_CompressedPixMap)();
}
if (theFaceIndex < 0)
{
return aDef;
}
if (theFaceIndex >= aDef->NbFaces()
|| aDef->FaceBytes() == 0)
{
Message::SendFail (TCollection_AsciiString ("DDS Reader error - invalid face index #") + theFaceIndex + " within buffer");
return Handle(Image_CompressedPixMap)();
}
const Standard_Size anOffset = aDef->FaceBytes() * theFaceIndex + 128;
if (theBuffer->Size() < anOffset + aDef->FaceBytes())
{
Message::SendFail (TCollection_AsciiString ("DDS Reader error - unable to read face #") + theFaceIndex + " data from buffer");
return Handle(Image_CompressedPixMap)();
}
Handle(NCollection_Buffer) aBuffer = new NCollection_Buffer (Image_PixMap::DefaultAllocator(), aDef->FaceBytes());
memcpy (aBuffer->ChangeData(), theBuffer->Data() + anOffset, aDef->FaceBytes());
aDef->SetFaceData (aBuffer);
return aDef;
}
// =======================================================================
// function : parseHeader
// purpose :
// =======================================================================
Handle(Image_CompressedPixMap) Image_DDSParser::parseHeader (const DDSFileHeader& theHeader)
{
if (theHeader.Size != 124
|| theHeader.Width == 0
|| theHeader.Height == 0
|| theHeader.PixelFormatDef.Size != 32)
{
return Handle(Image_CompressedPixMap)();
}
Image_Format aBaseFormat = Image_Format_UNKNOWN;
Image_CompressedFormat aFormat = Image_CompressedFormat_UNKNOWN;
Standard_Integer aBlockSize = 8;
const bool hasAlpha = (theHeader.PixelFormatDef.Flags & 0x1) != 0;
if (::memcmp (&theHeader.PixelFormatDef.FourCC, "DXT5", 4) == 0)
{
aBaseFormat = Image_Format_RGBA;
aFormat = Image_CompressedFormat_RGBA_S3TC_DXT5;
aBlockSize = 16;
}
else if (::memcmp (&theHeader.PixelFormatDef.FourCC, "DXT3", 4) == 0)
{
aBaseFormat = Image_Format_RGBA;
aFormat = Image_CompressedFormat_RGBA_S3TC_DXT3;
aBlockSize = 16;
}
else if (::memcmp (&theHeader.PixelFormatDef.FourCC, "DXT1", 4) == 0)
{
aBaseFormat = hasAlpha ? Image_Format_RGBA : Image_Format_RGB;
aFormat = hasAlpha ? Image_CompressedFormat_RGBA_S3TC_DXT1 : Image_CompressedFormat_RGB_S3TC_DXT1;
aBlockSize = 8;
}
if (aFormat == Image_CompressedFormat_UNKNOWN)
{
return Handle(Image_CompressedPixMap)();
}
Handle(Image_CompressedPixMap) aDef = new Image_CompressedPixMap();
aDef->SetSize ((Standard_Integer )theHeader.Width, (Standard_Integer )theHeader.Height);
aDef->SetNbFaces (theHeader.IscompleteCubemap() != 0 ? 6 : 1);
aDef->SetBaseFormat (aBaseFormat);
aDef->SetCompressedFormat (aFormat);
const Standard_Integer aNbMipMaps = Max ((Standard_Integer )theHeader.MipMapCount, 1);
aDef->ChangeMipMaps().Resize (0, aNbMipMaps - 1, false);
{
Standard_Size aFaceSize = 0;
NCollection_Vec2<Standard_Integer> aMipSizeXY (aDef->SizeX(), aDef->SizeY());
for (Standard_Integer aMipIter = 0;; ++aMipIter)
{
const Standard_Integer aMipLength = ((aMipSizeXY.x() + 3) / 4) * ((aMipSizeXY.y() + 3) / 4) * aBlockSize;
aFaceSize += aMipLength;
aDef->ChangeMipMaps().SetValue (aMipIter, aMipLength);
if (aMipIter + 1 >= aNbMipMaps)
{
break;
}
aMipSizeXY /= 2;
if (aMipSizeXY.x() == 0) { aMipSizeXY.x() = 1; }
if (aMipSizeXY.y() == 0) { aMipSizeXY.y() = 1; }
}
aDef->SetCompleteMipMapSet (aMipSizeXY.x() == 1 && aMipSizeXY.y() == 1);
aDef->SetFaceBytes (aFaceSize);
}
return aDef;
}

View File

@@ -0,0 +1,62 @@
// Copyright (c) 2020 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _Image_DDSParser_HeaderFile
#define _Image_DDSParser_HeaderFile
#include <Image_CompressedPixMap.hxx>
#include <NCollection_Buffer.hxx>
class Image_SupportedFormats;
//! Auxiliary tool for parsing DDS file structure (without decoding).
class Image_DDSParser
{
public:
//! Load the face from DDS file.
//! @param theSupported [in] list of supported image formats
//! @param theFile [in] file path
//! @param theFaceIndex [in] face index, within [0, Image_CompressedPixMap::NbFaces()) range;
//! use -1 to skip reading the face data
//! @param theFileOffset [in] offset to the DDS data
//! @return loaded face or NULL if file cannot be read or not valid DDS file
Standard_EXPORT static Handle(Image_CompressedPixMap) Load (const Handle(Image_SupportedFormats)& theSupported,
const TCollection_AsciiString& theFile,
const Standard_Integer theFaceIndex,
const int64_t theFileOffset = 0);
//! Load the face from DDS file.
//! @param theSupported [in] list of supported image formats
//! @param theBuffer [in] pre-loaded file data, should be at least of 128 bytes long defining DDS header.
//! @param theFaceIndex [in] face index, within [0, Image_CompressedPixMap::NbFaces()) range;
//! use -1 to skip reading the face data
//! @return loaded face or NULL if file cannot be read or not valid DDS file
Standard_EXPORT static Handle(Image_CompressedPixMap) Load (const Handle(Image_SupportedFormats)& theSupported,
const Handle(NCollection_Buffer)& theBuffer,
const Standard_Integer theFaceIndex);
private:
struct DDSPixelFormat;
struct DDSFileHeader;
private:
//! Parse DDS header.
static Handle(Image_CompressedPixMap) parseHeader (const DDSFileHeader& theHeader);
};
#endif // _Image_DDSParser_HeaderFile

View File

@@ -34,5 +34,6 @@ enum Image_Format
Image_Format_RGBAF, //!< 4 floats (16-bytes) RGBA image plane
Image_Format_BGRAF, //!< same as RGBAF but with different components order
};
enum { Image_Format_NB = Image_Format_BGRAF + 1 };
#endif // _Image_Format_HeaderFile

View File

@@ -14,6 +14,7 @@
// commercial license or contractual agreement.
#include <Image_PixMap.hxx>
#include <NCollection_AlignedAllocator.hxx>
#include <Standard_ProgramError.hxx>
@@ -21,6 +22,16 @@
IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap,Standard_Transient)
// =======================================================================
// function : DefaultAllocator
// purpose :
// =======================================================================
const Handle(NCollection_BaseAllocator)& Image_PixMap::DefaultAllocator()
{
static const Handle(NCollection_BaseAllocator) THE_ALLOC = new NCollection_AlignedAllocator (16);
return THE_ALLOC;
}
// =======================================================================
// function : Image_PixMap
// purpose :
@@ -40,6 +51,10 @@ Image_PixMap::~Image_PixMap()
Clear();
}
// =======================================================================
// function : SizePixelBytes
// purpose :
// =======================================================================
Standard_Size Image_PixMap::SizePixelBytes (const Image_Format thePixelFormat)
{
switch (thePixelFormat)
@@ -135,8 +150,7 @@ bool Image_PixMap::InitTrash (Image_Format thePixelFormat,
// use argument only if it greater
const Standard_Size aSizeRowBytes = std::max (theSizeRowBytes, theSizeX * SizePixelBytes (thePixelFormat));
Handle(NCollection_BaseAllocator) anAlloc = new NCollection_AlignedAllocator (16);
myData.Init (anAlloc, Image_PixMap::SizePixelBytes (thePixelFormat),
myData.Init (DefaultAllocator(), Image_PixMap::SizePixelBytes (thePixelFormat),
theSizeX, theSizeY, aSizeRowBytes, NULL);
return !myData.IsEmpty();
}

View File

@@ -48,6 +48,9 @@ public:
//! Convert image to Black/White.
Standard_EXPORT static void ToBlackWhite (Image_PixMap& theImage);
//! Return default image data allocator.
Standard_EXPORT static const Handle(NCollection_BaseAllocator)& DefaultAllocator();
public: // high-level API
Image_Format Format() const { return myImgFormat; }

View File

@@ -0,0 +1,27 @@
// Copyright (c) 2020 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <Image_SupportedFormats.hxx>
IMPLEMENT_STANDARD_RTTIEXT(Image_SupportedFormats, Standard_Transient)
// =======================================================================
// function : Image_SupportedFormats
// purpose :
// =======================================================================
Image_SupportedFormats::Image_SupportedFormats()
: myFormats (Image_Format_UNKNOWN, Image_CompressedFormat_NB - 1),
myHasCompressed (false)
{
myFormats.Init (false);
}

View File

@@ -0,0 +1,63 @@
// Copyright (c) 2020 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _Image_SupportedFormats_HeaderFile
#define _Image_SupportedFormats_HeaderFile
#include <Image_CompressedFormat.hxx>
#include <NCollection_Array1.hxx>
#include <Standard_Type.hxx>
//! Structure holding information about supported texture formats.
class Image_SupportedFormats : public Standard_Transient
{
DEFINE_STANDARD_RTTIEXT(Image_SupportedFormats, Standard_Transient)
public:
//! Empty constructor.
Standard_EXPORT Image_SupportedFormats();
//! Return TRUE if image format is supported.
bool IsSupported (Image_Format theFormat) const { return myFormats.Value (theFormat); }
//! Set if image format is supported or not.
void Add (Image_Format theFormat) { myFormats.SetValue (theFormat, true); }
//! Return TRUE if there are compressed image formats supported.
bool HasCompressed() const { return myHasCompressed; }
//! Return TRUE if compressed image format is supported.
bool IsSupported (Image_CompressedFormat theFormat) const { return myFormats.Value (theFormat); }
//! Set if compressed image format is supported or not.
void Add (Image_CompressedFormat theFormat)
{
myFormats.SetValue (theFormat, true);
myHasCompressed = true;
}
//! Reset flags.
void Clear()
{
myFormats.Init (false);
myHasCompressed = false;
}
protected:
NCollection_Array1<bool> myFormats; //!< list of supported formats
Standard_Boolean myHasCompressed; //!< flag indicating that some compressed image formats are supported
};
#endif // _Image_SupportedFormats_HeaderFile

View File

@@ -15,6 +15,8 @@
#include <Image_Texture.hxx>
#include <Image_AlienPixMap.hxx>
#include <Image_DDSParser.hxx>
#include <Image_SupportedFormats.hxx>
#include <Message.hxx>
#include <Message_Messenger.hxx>
#include <OSD_OpenFile.hxx>
@@ -73,11 +75,41 @@ Image_Texture::Image_Texture (const Handle(NCollection_Buffer)& theBuffer,
}
}
// ================================================================
// Function : ReadCompressedImage
// Purpose :
// ================================================================
Handle(Image_CompressedPixMap) Image_Texture::ReadCompressedImage (const Handle(Image_SupportedFormats)& theSupported) const
{
if (!theSupported->HasCompressed())
{
return Handle(Image_CompressedPixMap)();
}
if (!myBuffer.IsNull())
{
return Image_DDSParser::Load (theSupported, myBuffer, 0);
}
else if (myOffset >= 0)
{
return Image_DDSParser::Load (theSupported, myImagePath, 0, myOffset);
}
TCollection_AsciiString aFilePathLower = myImagePath;
aFilePathLower.LowerCase();
if (!aFilePathLower.EndsWith (".dds"))
{
// do not waste time on file system access in case of wrong file extension
return Handle(Image_CompressedPixMap)();
}
return Image_DDSParser::Load (theSupported, myImagePath, 0);
}
// ================================================================
// Function : ReadImage
// Purpose :
// ================================================================
Handle(Image_PixMap) Image_Texture::ReadImage() const
Handle(Image_PixMap) Image_Texture::ReadImage (const Handle(Image_SupportedFormats)& ) const
{
Handle(Image_PixMap) anImage;
if (!myBuffer.IsNull())
@@ -240,6 +272,10 @@ TCollection_AsciiString Image_Texture::ProbeImageFileFormat() const
{
return "webp";
}
else if (memcmp (aBuffer, "DDS ", 4) == 0)
{
return "dds";
}
return "";
}

View File

@@ -18,6 +18,8 @@
#include <NCollection_Buffer.hxx>
#include <TCollection_AsciiString.hxx>
class Image_CompressedPixMap;
class Image_SupportedFormats;
class Image_PixMap;
//! Texture image definition.
@@ -57,8 +59,11 @@ public:
//! Return image file format.
Standard_EXPORT TCollection_AsciiString ProbeImageFileFormat() const;
//! Image reader without decoding data for formats supported natively by GPUs.
Standard_EXPORT virtual Handle(Image_CompressedPixMap) ReadCompressedImage (const Handle(Image_SupportedFormats)& theSupported) const;
//! Image reader.
Standard_EXPORT virtual Handle(Image_PixMap) ReadImage() const;
Standard_EXPORT virtual Handle(Image_PixMap) ReadImage (const Handle(Image_SupportedFormats)& theSupported) const;
//! Write image to specified file without decoding data.
Standard_EXPORT virtual Standard_Boolean WriteImage (const TCollection_AsciiString& theFile);