{
return Standard_False;
}
- anImage.SetTopDown (false);
// Setup image data
BITMAPINFOHEADER aBitmapInfo;
memset (&aBitmapInfo, 0, sizeof(BITMAPINFOHEADER));
aBitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
aBitmapInfo.biWidth = aBitmap.bmWidth;
- aBitmapInfo.biHeight = aBitmap.bmHeight; // positive means bottom-up!
+ aBitmapInfo.biHeight = anImage.IsTopDown() ? -aBitmap.bmHeight : aBitmap.bmHeight;
aBitmapInfo.biPlanes = 1;
aBitmapInfo.biBitCount = 24;
aBitmapInfo.biCompression = BI_RGB;
// Copy the pixels
HDC aDC = GetDC (NULL);
- Standard_Boolean isSuccess = GetDIBits (aDC, theHBitmap,
- 0, // first scan line to set
- aBitmap.bmHeight, // number of scan lines to copy
- anImage.ChangeData(), // array for bitmap bits
- (LPBITMAPINFO )&aBitmapInfo, // bitmap data info
- DIB_RGB_COLORS) != 0;
+ Standard_Boolean isSuccess = Standard_True;
+ if (anImage.SizeRowBytes() != aSizeRowBytes)
+ {
+ for (Standard_Size aRowIter = 0; aRowIter < anImage.SizeY(); ++aRowIter)
+ {
+ const Standard_Size aRow = anImage.SizeY() - aRowIter - 1;
+ isSuccess = isSuccess && GetDIBits (aDC, theHBitmap,
+ (UINT )aRow, 1,
+ anImage.ChangeRow (aRowIter),
+ (LPBITMAPINFO )&aBitmapInfo, DIB_RGB_COLORS) != 0;
+ }
+ }
+ else
+ {
+ isSuccess = GetDIBits (aDC, theHBitmap,
+ 0, // first scan line to set
+ aBitmap.bmHeight, // number of scan lines to copy
+ anImage.ChangeData(), // array for bitmap bits
+ (LPBITMAPINFO )&aBitmapInfo, // bitmap data info
+ DIB_RGB_COLORS) != 0;
+ }
ReleaseDC (NULL, aDC);
return isSuccess && anImage.Save (theFileName);
}
Image_AlienPixMap.cxx
Image_AlienPixMap.hxx
+Image_AlienPixMapI.cxx
+Image_AlienPixMapI.hxx
Image_Color.hxx
Image_Diff.cxx
Image_Diff.hxx
Image_Format.hxx
+Image_FreeImage.cxx
+Image_FreeImage.hxx
Image_PixMap.cxx
Image_PixMap.hxx
Image_PixMapData.hxx
Image_PixMapTypedData.hxx
Image_VideoRecorder.cxx
Image_VideoRecorder.hxx
+Image_WinCodec.cxx
+Image_WinCodec.hxx
\ No newline at end of file
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
-#if !defined(HAVE_FREEIMAGE) && defined(_WIN32)
- #define HAVE_WINCODEC
-#endif
-
-#ifdef HAVE_FREEIMAGE
- #include <FreeImage.h>
+#include <Image_AlienPixMap.hxx>
- #ifdef _MSC_VER
- #pragma comment( lib, "FreeImage.lib" )
- #endif
-#elif defined(HAVE_WINCODEC)
- //#include <initguid.h>
- #include <wincodec.h>
- #undef min
- #undef max
-#endif
+#include <Image_FreeImage.hxx>
+#include <Image_WinCodec.hxx>
-#include <Image_AlienPixMap.hxx>
-#include <gp.hxx>
#include <Message.hxx>
#include <Message_Messenger.hxx>
-#include <NCollection_Array1.hxx>
-#include <Standard_ArrayStreamBuffer.hxx>
#include <TCollection_AsciiString.hxx>
#include <TCollection_ExtendedString.hxx>
-#include <OSD_OpenFile.hxx>
-#include <fstream>
-#include <algorithm>
IMPLEMENT_STANDARD_RTTIEXT(Image_AlienPixMap,Image_PixMap)
namespace
{
-#ifdef HAVE_FREEIMAGE
- static Image_Format convertFromFreeFormat (FREE_IMAGE_TYPE theFormatFI,
- FREE_IMAGE_COLOR_TYPE theColorTypeFI,
- unsigned theBitsPerPixel)
+ //! Global instance of image factory.
+ static Handle(Image_AlienPixMapI)& getFactory()
{
- switch (theFormatFI)
- {
- case FIT_RGBF: return Image_Format_RGBF;
- case FIT_RGBAF: return Image_Format_RGBAF;
- case FIT_FLOAT: return Image_Format_GrayF;
- case FIT_BITMAP:
- {
- switch (theColorTypeFI)
- {
- case FIC_MINISBLACK:
- {
- return Image_Format_Gray;
- }
- case FIC_RGB:
- {
- if (Image_PixMap::IsBigEndianHost())
- {
- return (theBitsPerPixel == 32) ? Image_Format_RGB32 : Image_Format_RGB;
- }
- else
- {
- return (theBitsPerPixel == 32) ? Image_Format_BGR32 : Image_Format_BGR;
- }
- }
- case FIC_RGBALPHA:
- {
- return Image_PixMap::IsBigEndianHost() ? Image_Format_RGBA : Image_Format_BGRA;
- }
- default:
- return Image_Format_UNKNOWN;
- }
- }
- default:
- return Image_Format_UNKNOWN;
- }
- }
-
- static FREE_IMAGE_TYPE convertToFreeFormat (Image_Format theFormat)
- {
- switch (theFormat)
- {
- case Image_Format_GrayF:
- case Image_Format_AlphaF:
- return FIT_FLOAT;
- case Image_Format_RGBAF:
- return FIT_RGBAF;
- case Image_Format_RGBF:
- return FIT_RGBF;
- case Image_Format_RGBA:
- case Image_Format_BGRA:
- case Image_Format_RGB32:
- case Image_Format_BGR32:
- case Image_Format_RGB:
- case Image_Format_BGR:
- case Image_Format_Gray:
- case Image_Format_Alpha:
- return FIT_BITMAP;
- default:
- return FIT_UNKNOWN;
- }
- }
-
- //! Wrapper for accessing C++ stream from FreeImage.
- class Image_FreeImageStream
- {
- public:
- //! Construct wrapper over input stream.
- Image_FreeImageStream (std::istream& theStream)
- : myIStream (&theStream), myOStream (NULL), myInitPos (theStream.tellg()) {}
-
- //! Get io object.
- FreeImageIO GetFiIO() const
- {
- FreeImageIO anIo;
- memset (&anIo, 0, sizeof(anIo));
- if (myIStream != NULL)
- {
- anIo.read_proc = readProc;
- anIo.seek_proc = seekProc;
- anIo.tell_proc = tellProc;
- }
- if (myOStream != NULL)
- {
- anIo.write_proc = writeProc;
- }
- return anIo;
- }
- public:
- //! Simulate fread().
- static unsigned int DLL_CALLCONV readProc (void* theBuffer, unsigned int theSize, unsigned int theCount, fi_handle theHandle)
- {
- Image_FreeImageStream* aThis = (Image_FreeImageStream* )theHandle;
- if (aThis->myIStream == NULL)
- {
- return 0;
- }
-
- if (!aThis->myIStream->read ((char* )theBuffer, std::streamsize(theSize) * std::streamsize(theCount)))
- {
- //aThis->myIStream->clear();
- }
- const std::streamsize aNbRead = aThis->myIStream->gcount();
- return (unsigned int )(aNbRead / theSize);
- }
-
- //! Simulate fwrite().
- static unsigned int DLL_CALLCONV writeProc (void* theBuffer, unsigned int theSize, unsigned int theCount, fi_handle theHandle)
- {
- Image_FreeImageStream* aThis = (Image_FreeImageStream* )theHandle;
- if (aThis->myOStream != NULL
- && aThis->myOStream->write ((const char* )theBuffer, std::streamsize(theSize) * std::streamsize(theCount)))
- {
- return theCount;
- }
- return 0;
- }
-
- //! Simulate fseek().
- static int DLL_CALLCONV seekProc (fi_handle theHandle, long theOffset, int theOrigin)
- {
- Image_FreeImageStream* aThis = (Image_FreeImageStream* )theHandle;
- if (aThis->myIStream == NULL)
- {
- return -1;
- }
-
- bool isSeekDone = false;
- switch (theOrigin)
- {
- case SEEK_SET:
- if (aThis->myIStream->seekg ((std::streamoff )aThis->myInitPos + theOffset, std::ios::beg))
- {
- isSeekDone = true;
- }
- break;
- case SEEK_CUR:
- if (aThis->myIStream->seekg (theOffset, std::ios::cur))
- {
- isSeekDone = true;
- }
- break;
- case SEEK_END:
- if (aThis->myIStream->seekg (theOffset, std::ios::end))
- {
- isSeekDone = true;
- }
- break;
- }
- return isSeekDone ? 0 : -1;
- }
-
- //! Simulate ftell().
- static long DLL_CALLCONV tellProc (fi_handle theHandle)
- {
- Image_FreeImageStream* aThis = (Image_FreeImageStream* )theHandle;
- const long aPos = aThis->myIStream != NULL ? (long )(aThis->myIStream->tellg() - aThis->myInitPos) : 0;
- return aPos;
- }
- private:
- std::istream* myIStream;
- std::ostream* myOStream;
- std::streampos myInitPos;
- };
-
-#elif defined(HAVE_WINCODEC)
-
- //! Return a zero GUID
- static GUID getNullGuid()
- {
- GUID aGuid = { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
- return aGuid;
- }
-
- //! Sentry over IUnknown pointer.
- template<class T> class Image_ComPtr
- {
- public:
- //! Empty constructor.
- Image_ComPtr()
- : myPtr (NULL) {}
-
- //! Destructor.
- ~Image_ComPtr()
- {
- Nullify();
- }
-
- //! Return TRUE if pointer is NULL.
- bool IsNull() const { return myPtr == NULL; }
-
- //! Release the pointer.
- void Nullify()
- {
- if (myPtr != NULL)
- {
- myPtr->Release();
- myPtr = NULL;
- }
- }
-
- //! Return pointer for initialization.
- T*& ChangePtr()
- {
- Standard_ASSERT_RAISE (myPtr == NULL, "Pointer cannot be initialized twice!");
- return myPtr;
- }
-
- //! Return pointer.
- T* get() { return myPtr; }
-
- //! Return pointer.
- T* operator->() { return get(); }
-
- //! Cast handle to contained type
- T& operator*() { return *get(); }
-
- private:
- T* myPtr;
- };
-
- //! Convert WIC GUID to Image_Format.
- static Image_Format convertFromWicFormat (const WICPixelFormatGUID& theFormat)
- {
- if (theFormat == GUID_WICPixelFormat32bppBGRA)
- {
- return Image_Format_BGRA;
- }
- else if (theFormat == GUID_WICPixelFormat32bppBGR)
- {
- return Image_Format_BGR32;
- }
- else if (theFormat == GUID_WICPixelFormat24bppRGB)
- {
- return Image_Format_RGB;
- }
- else if (theFormat == GUID_WICPixelFormat24bppBGR)
- {
- return Image_Format_BGR;
- }
- else if (theFormat == GUID_WICPixelFormat8bppGray)
- {
- return Image_Format_Gray;
- }
- return Image_Format_UNKNOWN;
+ static Handle(Image_AlienPixMapI) THE_IMAGE_FACTORY =
+ #if defined(HAVE_FREEIMAGE)
+ new Image_FreeImage();
+ #elif defined(HAVE_WINCODEC)
+ new Image_WinCodec();
+ #else
+ Handle(Image_AlienPixMapI)();
+ #endif
+ return THE_IMAGE_FACTORY;
}
+}
- //! Convert Image_Format to WIC GUID.
- static WICPixelFormatGUID convertToWicFormat (Image_Format theFormat)
+// =======================================================================
+// function : CreateDefault
+// purpose :
+// =======================================================================
+Handle(Image_AlienPixMapI) Image_AlienPixMap::CreateDefault()
+{
+ if (!getFactory().IsNull())
{
- switch (theFormat)
- {
- case Image_Format_BGRA: return GUID_WICPixelFormat32bppBGRA;
- case Image_Format_BGR32: return GUID_WICPixelFormat32bppBGR;
- case Image_Format_RGB: return GUID_WICPixelFormat24bppRGB;
- case Image_Format_BGR: return GUID_WICPixelFormat24bppBGR;
- case Image_Format_Gray: return GUID_WICPixelFormat8bppGray;
- case Image_Format_Alpha: return GUID_WICPixelFormat8bppGray; // GUID_WICPixelFormat8bppAlpha
- case Image_Format_GrayF: // GUID_WICPixelFormat32bppGrayFloat
- case Image_Format_AlphaF:
- case Image_Format_RGBAF: // GUID_WICPixelFormat128bppRGBAFloat
- case Image_Format_RGBF: // GUID_WICPixelFormat96bppRGBFloat
- case Image_Format_RGBA: // GUID_WICPixelFormat32bppRGBA
- case Image_Format_RGB32: // GUID_WICPixelFormat32bppRGB
- default:
- return getNullGuid();
- }
+ return getFactory()->createDefault();
}
-
-#endif
+ return Handle(Image_AlienPixMapI)();
}
// =======================================================================
-// function : Image_AlienPixMap
+// function : SetDefaultFactory
// purpose :
// =======================================================================
-Image_AlienPixMap::Image_AlienPixMap()
-: myLibImage (NULL)
+void Image_AlienPixMap::SetDefaultFactory (const Handle(Image_AlienPixMapI)& theLibrary)
{
- SetTopDown (false);
+ getFactory() = theLibrary;
}
// =======================================================================
-// function : ~Image_AlienPixMap
+// function : Image_AlienPixMap
// purpose :
// =======================================================================
-Image_AlienPixMap::~Image_AlienPixMap()
+Image_AlienPixMap::Image_AlienPixMap()
{
- Clear();
+ myLibImage = CreateDefault();
}
// =======================================================================
-// function : InitWrapper
+// function : ~Image_AlienPixMap
// purpose :
// =======================================================================
-bool Image_AlienPixMap::InitWrapper (Image_Format,
- Standard_Byte*,
- const Standard_Size,
- const Standard_Size,
- const Standard_Size)
+Image_AlienPixMap::~Image_AlienPixMap()
{
Clear();
- return false;
}
// =======================================================================
// function : InitTrash
// purpose :
// =======================================================================
-#ifdef HAVE_FREEIMAGE
-bool Image_AlienPixMap::InitTrash (Image_Format thePixelFormat,
- const Standard_Size theSizeX,
- const Standard_Size theSizeY,
- const Standard_Size /*theSizeRowBytes*/)
-{
- Clear();
- FREE_IMAGE_TYPE aFormatFI = convertToFreeFormat (thePixelFormat);
- int aBitsPerPixel = (int )Image_PixMap::SizePixelBytes (thePixelFormat) * 8;
- if (aFormatFI == FIT_UNKNOWN)
- {
- aFormatFI = FIT_BITMAP;
- aBitsPerPixel = 24;
- }
-
- FIBITMAP* anImage = FreeImage_AllocateT (aFormatFI, (int )theSizeX, (int )theSizeY, aBitsPerPixel);
- Image_Format aFormat = convertFromFreeFormat (FreeImage_GetImageType(anImage),
- FreeImage_GetColorType(anImage),
- FreeImage_GetBPP (anImage));
- if (thePixelFormat == Image_Format_BGR32
- || thePixelFormat == Image_Format_RGB32)
- {
- //FreeImage_SetTransparent (anImage, FALSE);
- aFormat = (aFormat == Image_Format_BGRA) ? Image_Format_BGR32 : Image_Format_RGB32;
- }
-
- Image_PixMap::InitWrapper (aFormat, FreeImage_GetBits (anImage),
- FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
- SetTopDown (false);
-
- // assign image after wrapper initialization (virtual Clear() called inside)
- myLibImage = anImage;
- return true;
-}
-#elif defined(HAVE_WINCODEC)
bool Image_AlienPixMap::InitTrash (Image_Format thePixelFormat,
const Standard_Size theSizeX,
const Standard_Size theSizeY,
const Standard_Size theSizeRowBytes)
{
Clear();
- Image_Format aFormat = thePixelFormat;
- switch (aFormat)
+ if (myLibImage.IsNull())
{
- case Image_Format_RGB:
- aFormat = Image_Format_BGR;
- break;
- case Image_Format_RGB32:
- aFormat = Image_Format_BGR32;
- break;
- case Image_Format_RGBA:
- aFormat = Image_Format_BGRA;
- break;
- default:
- break;
+ return base_type::InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes);
}
-
- if (!Image_PixMap::InitTrash (aFormat, theSizeX, theSizeY, theSizeRowBytes))
+ if (myLibImage->InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes))
{
- return false;
- }
- SetTopDown (true);
- return true;
-}
-#else
-bool Image_AlienPixMap::InitTrash (Image_Format thePixelFormat,
- const Standard_Size theSizeX,
- const Standard_Size theSizeY,
- const Standard_Size theSizeRowBytes)
-{
- return Image_PixMap::InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes);
-}
-#endif
-
-// =======================================================================
-// function : InitCopy
-// purpose :
-// =======================================================================
-bool Image_AlienPixMap::InitCopy (const Image_PixMap& theCopy)
-{
- if (&theCopy == this)
- {
- // self-copying disallowed
- return false;
- }
- if (!InitTrash (theCopy.Format(), theCopy.SizeX(), theCopy.SizeY(), theCopy.SizeRowBytes()))
- {
- return false;
- }
-
- if (myImgFormat == theCopy.Format())
- {
- if (SizeRowBytes() == theCopy.SizeRowBytes()
- && TopDownInc() == theCopy.TopDownInc())
- {
- // copy with one call
- memcpy (ChangeData(), theCopy.Data(), std::min (SizeBytes(), theCopy.SizeBytes()));
- return true;
- }
-
- // copy row-by-row
- const Standard_Size aRowSizeBytes = std::min (SizeRowBytes(), theCopy.SizeRowBytes());
- for (Standard_Size aRow = 0; aRow < myData.SizeY; ++aRow)
- {
- memcpy (ChangeRow (aRow), theCopy.Row (aRow), aRowSizeBytes);
- }
+ Handle(Image_AlienPixMapI) aLibImage = myLibImage;
+ myLibImage.Nullify(); // prevent clearing
+ initWrapper (aLibImage->Format(), aLibImage->ChangeData(),
+ aLibImage->SizeX(), aLibImage->SizeY(), aLibImage->SizeRowBytes());
+ myLibImage = aLibImage;
+ base_type::SetTopDown (myLibImage->IsTopDown());
return true;
}
-
- // pixel format conversion required
- Clear();
return false;
}
void Image_AlienPixMap::Clear()
{
Image_PixMap::Clear();
-#ifdef HAVE_FREEIMAGE
- if (myLibImage != NULL)
+ if (!myLibImage.IsNull())
{
- FreeImage_Unload (myLibImage);
- myLibImage = NULL;
+ myLibImage->Clear();
}
-#endif
}
// =======================================================================
// =======================================================================
bool Image_AlienPixMap::IsTopDownDefault()
{
-#ifdef HAVE_FREEIMAGE
- return false;
-#elif defined(HAVE_WINCODEC)
- return true;
-#else
- return false;
-#endif
+ return getFactory().IsNull()
+ || getFactory()->IsTopDown();
}
// =======================================================================
// function : Load
// purpose :
// =======================================================================
-#ifdef HAVE_FREEIMAGE
bool Image_AlienPixMap::Load (const Standard_Byte* theData,
Standard_Size theLength,
const TCollection_AsciiString& theImagePath)
{
Clear();
-
-#ifdef _WIN32
- const TCollection_ExtendedString aFileNameW (theImagePath);
-#endif
- FREE_IMAGE_FORMAT aFIF = FIF_UNKNOWN;
- FIMEMORY* aFiMem = NULL;
- if (theData != NULL)
- {
- aFiMem = FreeImage_OpenMemory ((BYTE* )theData, (DWORD )theLength);
- aFIF = FreeImage_GetFileTypeFromMemory (aFiMem, 0);
- }
- else
- {
- #ifdef _WIN32
- aFIF = FreeImage_GetFileTypeU (aFileNameW.ToWideString(), 0);
- #else
- aFIF = FreeImage_GetFileType (theImagePath.ToCString(), 0);
- #endif
- }
- if (aFIF == FIF_UNKNOWN)
- {
- // no signature? try to guess the file format from the file extension
- aFIF = FreeImage_GetFIFFromFilename (theImagePath.ToCString());
- }
- if ((aFIF == FIF_UNKNOWN) || !FreeImage_FIFSupportsReading (aFIF))
- {
- ::Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error: image '") + theImagePath + "' has unsupported file format.",
- Message_Fail);
- if (aFiMem != NULL)
- {
- FreeImage_CloseMemory (aFiMem);
- }
- return false;
- }
-
- int aLoadFlags = 0;
- if (aFIF == FIF_GIF)
- {
- // 'Play' the GIF to generate each frame (as 32bpp) instead of returning raw frame data when loading
- aLoadFlags = GIF_PLAYBACK;
- }
- else if (aFIF == FIF_ICO)
- {
- // convert to 32bpp and create an alpha channel from the AND-mask when loading
- aLoadFlags = ICO_MAKEALPHA;
- }
-
- FIBITMAP* anImage = NULL;
- if (theData != NULL)
- {
- anImage = FreeImage_LoadFromMemory (aFIF, aFiMem, aLoadFlags);
- FreeImage_CloseMemory (aFiMem);
- aFiMem = NULL;
- }
- else
- {
- #ifdef _WIN32
- anImage = FreeImage_LoadU (aFIF, aFileNameW.ToWideString(), aLoadFlags);
- #else
- anImage = FreeImage_Load (aFIF, theImagePath.ToCString(), aLoadFlags);
- #endif
- }
- if (anImage == NULL)
- {
- TCollection_AsciiString aMessage = "Error: image file '";
- aMessage.AssignCat (theImagePath);
- aMessage.AssignCat ("' is missing or invalid.");
- ::Message::DefaultMessenger()->Send (aMessage, Message_Fail);
- return false;
- }
-
- Image_Format aFormat = convertFromFreeFormat (FreeImage_GetImageType(anImage),
- FreeImage_GetColorType(anImage),
- FreeImage_GetBPP (anImage));
- if (aFormat == Image_Format_UNKNOWN)
- {
- //anImage = FreeImage_ConvertTo24Bits (anImage);
- ::Message::DefaultMessenger()->Send ( TCollection_AsciiString ("Error: image '") + theImagePath + "' has unsupported pixel format.",
- Message_Fail);
- return false;
- }
-
- Image_PixMap::InitWrapper (aFormat, FreeImage_GetBits (anImage),
- FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
- SetTopDown (false);
-
- // assign image after wrapper initialization (virtual Clear() called inside)
- myLibImage = anImage;
- return true;
-}
-
-bool Image_AlienPixMap::Load (std::istream& theStream,
- const TCollection_AsciiString& theFileName)
-{
- Clear();
-
- Image_FreeImageStream aStream (theStream);
- FreeImageIO aFiIO = aStream.GetFiIO();
-
- FREE_IMAGE_FORMAT aFIF = FreeImage_GetFileTypeFromHandle (&aFiIO, &aStream, 0);
- if (aFIF == FIF_UNKNOWN)
- {
- // no signature? try to guess the file format from the file extension
- aFIF = FreeImage_GetFIFFromFilename (theFileName.ToCString());
- }
- if ((aFIF == FIF_UNKNOWN) || !FreeImage_FIFSupportsReading (aFIF))
- {
- ::Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error: image stream '") + theFileName + "' has unsupported file format.",
- Message_Fail);
- return false;
- }
-
- int aLoadFlags = 0;
- if (aFIF == FIF_GIF)
- {
- // 'Play' the GIF to generate each frame (as 32bpp) instead of returning raw frame data when loading
- aLoadFlags = GIF_PLAYBACK;
- }
- else if (aFIF == FIF_ICO)
- {
- // convert to 32bpp and create an alpha channel from the AND-mask when loading
- aLoadFlags = ICO_MAKEALPHA;
- }
-
- FIBITMAP* anImage = FreeImage_LoadFromHandle (aFIF, &aFiIO, &aStream, aLoadFlags);
- if (anImage == NULL)
- {
- ::Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error: image stream '") + theFileName + "' is missing or invalid.",
- Message_Fail);
- return false;
- }
-
- Image_Format aFormat = convertFromFreeFormat (FreeImage_GetImageType(anImage),
- FreeImage_GetColorType(anImage),
- FreeImage_GetBPP (anImage));
- if (aFormat == Image_Format_UNKNOWN)
- {
- ::Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error: image stream '") + theFileName + "' has unsupported pixel format.",
- Message_Fail);
- return false;
- }
-
- Image_PixMap::InitWrapper (aFormat, FreeImage_GetBits (anImage),
- FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
- SetTopDown (false);
-
- // assign image after wrapper initialization (virtual Clear() called inside)
- myLibImage = anImage;
- return true;
-}
-
-#elif defined(HAVE_WINCODEC)
-bool Image_AlienPixMap::Load (const Standard_Byte* theData,
- Standard_Size theLength,
- const TCollection_AsciiString& theFileName)
-{
- Clear();
-
- Image_ComPtr<IWICImagingFactory> aWicImgFactory;
- CoInitializeEx (NULL, COINIT_MULTITHREADED);
- if (CoCreateInstance (CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&aWicImgFactory.ChangePtr())) != S_OK)
- {
- Message::DefaultMessenger()->Send ("Error: cannot initialize WIC Imaging Factory", Message_Fail);
- return false;
- }
-
- Image_ComPtr<IWICBitmapDecoder> aWicDecoder;
- Image_ComPtr<IWICStream> aWicStream;
- if (theData != NULL)
- {
- if (aWicImgFactory->CreateStream (&aWicStream.ChangePtr()) != S_OK
- || aWicStream->InitializeFromMemory ((BYTE* )theData, (DWORD )theLength) != S_OK)
- {
- Message::DefaultMessenger()->Send ("Error: cannot initialize WIC Stream", Message_Fail);
- return false;
- }
- if (aWicImgFactory->CreateDecoderFromStream (aWicStream.get(), NULL, WICDecodeMetadataCacheOnDemand, &aWicDecoder.ChangePtr()) != S_OK)
- {
- Message::DefaultMessenger()->Send ("Error: cannot create WIC Image Decoder", Message_Fail);
- return false;
- }
- }
- else
- {
- const TCollection_ExtendedString aFileNameW (theFileName);
- if (aWicImgFactory->CreateDecoderFromFilename (aFileNameW.ToWideString(), NULL, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &aWicDecoder.ChangePtr()) != S_OK)
- {
- Message::DefaultMessenger()->Send ("Error: cannot create WIC Image Decoder", Message_Fail);
- return false;
- }
- }
-
- UINT aFrameCount = 0, aFrameSizeX = 0, aFrameSizeY = 0;
- WICPixelFormatGUID aWicPixelFormat = getNullGuid();
- Image_ComPtr<IWICBitmapFrameDecode> aWicFrameDecode;
- if (aWicDecoder->GetFrameCount (&aFrameCount) != S_OK
- || aFrameCount < 1
- || aWicDecoder->GetFrame (0, &aWicFrameDecode.ChangePtr()) != S_OK
- || aWicFrameDecode->GetSize (&aFrameSizeX, &aFrameSizeY) != S_OK
- || aWicFrameDecode->GetPixelFormat (&aWicPixelFormat))
- {
- Message::DefaultMessenger()->Send ("Error: cannot get WIC Image Frame", Message_Fail);
- return false;
- }
-
- Image_ComPtr<IWICFormatConverter> aWicConvertedFrame;
- Image_Format aPixelFormat = convertFromWicFormat (aWicPixelFormat);
- if (aPixelFormat == Image_Format_UNKNOWN)
- {
- aPixelFormat = Image_Format_RGB;
- if (aWicImgFactory->CreateFormatConverter (&aWicConvertedFrame.ChangePtr()) != S_OK
- || aWicConvertedFrame->Initialize (aWicFrameDecode.get(), convertToWicFormat (aPixelFormat), WICBitmapDitherTypeNone, NULL, 0.0f, WICBitmapPaletteTypeCustom) != S_OK)
- {
- Message::DefaultMessenger()->Send ("Error: cannot convert WIC Image Frame to RGB format", Message_Fail);
- return false;
- }
- aWicFrameDecode.Nullify();
- }
-
- if (!Image_PixMap::InitTrash (aPixelFormat, aFrameSizeX, aFrameSizeY))
- {
- Message::DefaultMessenger()->Send ("Error: cannot initialize memory for image", Message_Fail);
- return false;
- }
-
- IWICBitmapSource* aWicSrc = aWicFrameDecode.get();
- if(!aWicConvertedFrame.IsNull())
- {
- aWicSrc = aWicConvertedFrame.get();
- }
- if (aWicSrc->CopyPixels (NULL, (UINT )SizeRowBytes(), (UINT )SizeBytes(), ChangeData()) != S_OK)
- {
- Message::DefaultMessenger()->Send ("Error: cannot copy pixels from WIC Image", Message_Fail);
- return false;
- }
- SetTopDown (true);
- return true;
-}
-bool Image_AlienPixMap::Load (std::istream& theStream,
- const TCollection_AsciiString& theFilePath)
-{
- Clear();
-
- // fallback copying stream data into transient buffer
- const std::streamoff aStart = theStream.tellg();
- theStream.seekg (0, std::ios::end);
- const Standard_Integer aLen = Standard_Integer(theStream.tellg() - aStart);
- theStream.seekg (aStart);
- if (aLen <= 0)
- {
- Message::DefaultMessenger()->Send ("Error: empty stream", Message_Fail);
- return false;
- }
-
- NCollection_Array1<Standard_Byte> aBuff (1, aLen);
- if (!theStream.read ((char* )&aBuff.ChangeFirst(), aBuff.Size()))
- {
- Message::DefaultMessenger()->Send ("Error: unable to read stream", Message_Fail);
- return false;
+ if (!myLibImage.IsNull()
+ && myLibImage->Load (theData, theLength, theImagePath))
+ {
+ Handle(Image_AlienPixMapI) aLibImage = myLibImage;
+ myLibImage.Nullify(); // prevent clearing
+ initWrapper (aLibImage->Format(), aLibImage->ChangeData(),
+ aLibImage->SizeX(), aLibImage->SizeY(), aLibImage->SizeRowBytes());
+ myLibImage = aLibImage;
+ base_type::SetTopDown (myLibImage->IsTopDown());
+ return true;
}
-
- return Load (&aBuff.ChangeFirst(), aBuff.Size(), theFilePath);
-}
-#else
-bool Image_AlienPixMap::Load (std::istream& ,
- const TCollection_AsciiString& )
-{
- Clear();
- Message::DefaultMessenger()->Send ("Error: no image library available", Message_Fail);
- return false;
-}
-bool Image_AlienPixMap::Load (const Standard_Byte* ,
- Standard_Size ,
- const TCollection_AsciiString& )
-{
- Clear();
- Message::DefaultMessenger()->Send ("Error: no image library available", Message_Fail);
return false;
}
-#endif
// =======================================================================
-// function : savePPM
+// function : Load
// purpose :
// =======================================================================
-bool Image_AlienPixMap::savePPM (const TCollection_AsciiString& theFileName) const
+bool Image_AlienPixMap::Load (std::istream& theStream,
+ const TCollection_AsciiString& theFileName)
{
- if (IsEmpty())
- {
- return false;
- }
-
- // Open file
- FILE* aFile = OSD_OpenFile (theFileName.ToCString(), "wb");
- if (aFile == NULL)
- {
- return false;
- }
-
- // Write header
- fprintf (aFile, "P6\n%d %d\n255\n", (int )SizeX(), (int )SizeY());
- fprintf (aFile, "# Image stored by OpenCASCADE framework in linear RGB colorspace\n");
-
- // Write pixel data
- Standard_Byte aByte;
- for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
- {
- for (Standard_Size aCol = 0; aCol < SizeX(); ++aCol)
- {
- // extremely SLOW but universal (implemented for all supported pixel formats)
- const Quantity_ColorRGBA aColor = PixelColor ((Standard_Integer )aCol, (Standard_Integer )aRow);
- aByte = Standard_Byte(aColor.GetRGB().Red() * 255.0); fwrite (&aByte, 1, 1, aFile);
- aByte = Standard_Byte(aColor.GetRGB().Green() * 255.0); fwrite (&aByte, 1, 1, aFile);
- aByte = Standard_Byte(aColor.GetRGB().Blue() * 255.0); fwrite (&aByte, 1, 1, aFile);
- }
+ Clear();
+ if (!myLibImage.IsNull()
+ && myLibImage->Load (theStream, theFileName))
+ {
+ Handle(Image_AlienPixMapI) aLibImage = myLibImage;
+ myLibImage.Nullify(); // prevent clearing
+ initWrapper (aLibImage->Format(), aLibImage->ChangeData(),
+ aLibImage->SizeX(), aLibImage->SizeY(), aLibImage->SizeRowBytes());
+ myLibImage = aLibImage;
+ base_type::SetTopDown (myLibImage->IsTopDown());
+ return true;
}
-
- // Close file
- fclose (aFile);
- return true;
+ return false;
}
// =======================================================================
// =======================================================================
bool Image_AlienPixMap::Save (const TCollection_AsciiString& theFileName)
{
-#ifdef HAVE_FREEIMAGE
- if (myLibImage == NULL)
- {
- return false;
- }
-
-#ifdef _WIN32
- const TCollection_ExtendedString aFileNameW (theFileName.ToCString(), Standard_True);
- FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilenameU (aFileNameW.ToWideString());
-#else
- FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilename (theFileName.ToCString());
-#endif
- if (anImageFormat == FIF_UNKNOWN)
- {
-#ifdef OCCT_DEBUG
- std::cerr << "Image_PixMap, image format doesn't supported!\n";
-#endif
- return false;
- }
-
- if (IsTopDown())
- {
- FreeImage_FlipVertical (myLibImage);
- SetTopDown (false);
- }
-
- // FreeImage doesn't provide flexible format conversion API
- // so we should perform multiple conversions in some cases!
- FIBITMAP* anImageToDump = myLibImage;
- switch (anImageFormat)
- {
- case FIF_PNG:
- case FIF_BMP:
- {
- if (Format() == Image_Format_BGR32
- || Format() == Image_Format_RGB32)
- {
- // stupid FreeImage treats reserved byte as alpha if some bytes not set to 0xFF
- for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
- {
- for (Standard_Size aCol = 0; aCol < SizeX(); ++aCol)
- {
- myData.ChangeValue (aRow, aCol)[3] = 0xFF;
- }
- }
- }
- else if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
- {
- anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
- }
- break;
- }
- case FIF_GIF:
- {
- FIBITMAP* aTmpBitmap = myLibImage;
- if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
- {
- aTmpBitmap = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
- if (aTmpBitmap == NULL)
- {
- return false;
- }
- }
-
- if (FreeImage_GetBPP (aTmpBitmap) != 24)
- {
- FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (aTmpBitmap);
- if (aTmpBitmap != myLibImage)
- {
- FreeImage_Unload (aTmpBitmap);
- }
- if (aTmpBitmap24 == NULL)
- {
- return false;
- }
- aTmpBitmap = aTmpBitmap24;
- }
-
- // need conversion to image with palette (requires 24bit bitmap)
- anImageToDump = FreeImage_ColorQuantize (aTmpBitmap, FIQ_NNQUANT);
- if (aTmpBitmap != myLibImage)
- {
- FreeImage_Unload (aTmpBitmap);
- }
- break;
- }
- case FIF_HDR:
- case FIF_EXR:
- {
- if (Format() == Image_Format_Gray
- || Format() == Image_Format_Alpha)
- {
- anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_FLOAT);
- }
- else if (Format() == Image_Format_RGBA
- || Format() == Image_Format_BGRA)
- {
- anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBAF);
- }
- else
- {
- FREE_IMAGE_TYPE aImgTypeFI = FreeImage_GetImageType (myLibImage);
- if (aImgTypeFI != FIT_RGBF
- && aImgTypeFI != FIT_RGBAF
- && aImgTypeFI != FIT_FLOAT)
- {
- anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBF);
- }
- }
- break;
- }
- default:
- {
- if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
- {
- anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
- if (anImageToDump == NULL)
- {
- return false;
- }
- }
-
- if (FreeImage_GetBPP (anImageToDump) != 24)
- {
- FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (anImageToDump);
- if (anImageToDump != myLibImage)
- {
- FreeImage_Unload (anImageToDump);
- }
- if (aTmpBitmap24 == NULL)
- {
- return false;
- }
- anImageToDump = aTmpBitmap24;
- }
- break;
- }
- }
-
- if (anImageToDump == NULL)
- {
- return false;
- }
-
-#ifdef _WIN32
- bool isSaved = (FreeImage_SaveU (anImageFormat, anImageToDump, aFileNameW.ToWideString()) != FALSE);
-#else
- bool isSaved = (FreeImage_Save (anImageFormat, anImageToDump, theFileName.ToCString()) != FALSE);
-#endif
- if (anImageToDump != myLibImage)
- {
- FreeImage_Unload (anImageToDump);
- }
- return isSaved;
-
-#elif defined(HAVE_WINCODEC)
-
TCollection_AsciiString aFileNameLower = theFileName;
aFileNameLower.LowerCase();
- GUID aFileFormat = getNullGuid();
- if (aFileNameLower.EndsWith (".ppm"))
- {
- return savePPM (theFileName);
- }
- else if (aFileNameLower.EndsWith (".bmp"))
- {
- aFileFormat = GUID_ContainerFormatBmp;
- }
- else if (aFileNameLower.EndsWith (".png"))
- {
- aFileFormat = GUID_ContainerFormatPng;
- }
- else if (aFileNameLower.EndsWith (".jpg")
- || aFileNameLower.EndsWith (".jpeg"))
+ if (aFileNameLower.EndsWith (".ppm")
+ || myLibImage.IsNull())
{
- aFileFormat = GUID_ContainerFormatJpeg;
- }
- else if (aFileNameLower.EndsWith (".tiff"))
- {
- aFileFormat = GUID_ContainerFormatTiff;
- }
- else if (aFileNameLower.EndsWith (".gif"))
- {
- aFileFormat = GUID_ContainerFormatGif;
- }
-
- if (aFileFormat == getNullGuid())
- {
- Message::DefaultMessenger()->Send ("Error: unsupported image format", Message_Fail);
- return false;
- }
-
- Image_ComPtr<IWICImagingFactory> aWicImgFactory;
- CoInitializeEx (NULL, COINIT_MULTITHREADED);
- if (CoCreateInstance (CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&aWicImgFactory.ChangePtr())) != S_OK)
- {
- Message::DefaultMessenger()->Send ("Error: cannot initialize WIC Imaging Factory", Message_Fail);
- return false;
- }
-
- Image_ComPtr<IWICStream> aWicFileStream;
- Image_ComPtr<IWICBitmapEncoder> aWicEncoder;
- const TCollection_ExtendedString aFileNameW (theFileName);
- if (aWicImgFactory->CreateStream (&aWicFileStream.ChangePtr()) != S_OK
- || aWicFileStream->InitializeFromFilename (aFileNameW.ToWideString(), GENERIC_WRITE) != S_OK)
- {
- Message::DefaultMessenger()->Send ("Error: cannot create WIC File Stream", Message_Fail);
- return false;
- }
- if (aWicImgFactory->CreateEncoder (aFileFormat, NULL, &aWicEncoder.ChangePtr()) != S_OK
- || aWicEncoder->Initialize (aWicFileStream.get(), WICBitmapEncoderNoCache) != S_OK)
- {
- Message::DefaultMessenger()->Send ("Error: cannot create WIC Encoder", Message_Fail);
- return false;
- }
-
- const WICPixelFormatGUID aWicPixelFormat = convertToWicFormat (myImgFormat);
- if (aWicPixelFormat == getNullGuid())
- {
- Message::DefaultMessenger()->Send ("Error: unsupported pixel format", Message_Fail);
- return false;
- }
-
- WICPixelFormatGUID aWicPixelFormatRes = aWicPixelFormat;
- Image_ComPtr<IWICBitmapFrameEncode> aWicFrameEncode;
- if (aWicEncoder->CreateNewFrame (&aWicFrameEncode.ChangePtr(), NULL) != S_OK
- || aWicFrameEncode->Initialize (NULL) != S_OK
- || aWicFrameEncode->SetSize ((UINT )SizeX(), (UINT )SizeY()) != S_OK
- || aWicFrameEncode->SetPixelFormat (&aWicPixelFormatRes) != S_OK)
- {
- Message::DefaultMessenger()->Send ("Error: cannot create WIC Frame", Message_Fail);
- return false;
- }
-
- if (aWicPixelFormatRes != aWicPixelFormat)
- {
- Message::DefaultMessenger()->Send ("Error: pixel format is unsupported by image format", Message_Fail);
- return false;
- }
-
- if (IsTopDown())
- {
- if (aWicFrameEncode->WritePixels ((UINT )SizeY(), (UINT )SizeRowBytes(), (UINT )SizeBytes(), (BYTE* )Data()) != S_OK)
- {
- Message::DefaultMessenger()->Send ("Error: cannot write pixels to WIC Frame", Message_Fail);
- return false;
- }
- }
- else
- {
- for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
+ if (!aFileNameLower.EndsWith (".ppm"))
{
- if (aWicFrameEncode->WritePixels (1, (UINT )SizeRowBytes(), (UINT )SizeRowBytes(), (BYTE* )Row (aRow)) != S_OK)
- {
- Message::DefaultMessenger()->Send ("Error: cannot write pixels to WIC Frame", Message_Fail);
- return false;
- }
+ Message::DefaultMessenger()->Send ("Image_AlienPixMap, no image library available! Image saved in PPM format.", Message_Warning);
}
- }
-
- if (aWicFrameEncode->Commit() != S_OK
- || aWicEncoder->Commit() != S_OK)
- {
- Message::DefaultMessenger()->Send ("Error: cannot commit data to WIC Frame", Message_Fail);
- return false;
- }
- if (aWicFileStream->Commit (STGC_DEFAULT) != S_OK)
- {
- //Message::DefaultMessenger()->Send ("Error: cannot commit data to WIC File Stream", Message_Fail);
- //return false;
- }
- return true;
-#else
- const Standard_Integer aLen = theFileName.Length();
- if ((aLen >= 4) && (theFileName.Value (aLen - 3) == '.')
- && strcasecmp( theFileName.ToCString() + aLen - 3, "ppm") == 0 )
- {
return savePPM (theFileName);
}
-#ifdef OCCT_DEBUG
- std::cerr << "Image_PixMap, no image library available! Image saved in PPM format.\n";
-#endif
- return savePPM (theFileName);
-#endif
+
+ return myLibImage->Save (theFileName);
}
// =======================================================================
// function : AdjustGamma
// purpose :
// =======================================================================
-bool Image_AlienPixMap::AdjustGamma (const Standard_Real theGammaCorr)
+bool Image_AlienPixMap::AdjustGamma (Standard_Real theGammaCorr)
{
-#ifdef HAVE_FREEIMAGE
- return FreeImage_AdjustGamma (myLibImage, theGammaCorr) != FALSE;
-#else
- (void )theGammaCorr;
- return false;
-#endif
+ return !myLibImage.IsNull()
+ && myLibImage->AdjustGamma (theGammaCorr);
}
#ifndef _Image_AlienPixMap_H__
#define _Image_AlienPixMap_H__
-#include <Image_PixMap.hxx>
-
-class TCollection_AsciiString;
-struct FIBITMAP;
+#include <Image_AlienPixMapI.hxx>
//! Image class that support file reading/writing operations using auxiliary image library.
-//! Supported image formats:
-//! - *.bmp - bitmap image, lossless format without compression.
-//! - *.ppm - PPM (Portable Pixmap Format), lossless format without compression.
-//! - *.png - PNG (Portable Network Graphics) lossless format with compression.
-//! - *.jpg, *.jpe, *.jpeg - JPEG/JIFF (Joint Photographic Experts Group) lossy format (compressed with quality losses). YUV color space used (automatically converted from/to RGB).
-//! - *.tif, *.tiff - TIFF (Tagged Image File Format).
-//! - *.tga - TGA (Truevision Targa Graphic), lossless format.
-//! - *.gif - GIF (Graphical Interchange Format), lossy format. Color stored using palette (up to 256 distinct colors).
-//! - *.exr - OpenEXR high dynamic-range format (supports float pixel formats).
-class Image_AlienPixMap : public Image_PixMap
+//! This is a wrapper over Image_FreeImage or Image_WinCodec basing on availability.
+class Image_AlienPixMap : public Image_AlienPixMapI
{
- DEFINE_STANDARD_RTTIEXT(Image_AlienPixMap, Image_PixMap)
+ DEFINE_STANDARD_RTTIEXT(Image_AlienPixMap, Image_AlienPixMapI)
public:
//! Return default rows order used by underlying image library.
Standard_EXPORT static bool IsTopDownDefault();
+
+ //! Create default instance of available image library or NULL if no library available.
+ Standard_EXPORT static Handle(Image_AlienPixMapI) CreateDefault();
+
+ //! Setup default image library to be used as factory.
+ //! Note that access to the factory is not protected by mutex,
+ //! make sure to call this method at the early application startup stage before using.
+ //! In this way, application might provide image library replacement implementing
+ //! image reading/writing operations which will be used by standard image tools within OCCT
+ //! (like image dump or texture loads).
+ Standard_EXPORT static void SetDefaultFactory (const Handle(Image_AlienPixMapI)& theLibrary);
+
public:
//! Empty constructor.
//! Destructor
Standard_EXPORT virtual ~Image_AlienPixMap();
- //! Read image data from file.
- bool Load (const TCollection_AsciiString& theFileName)
- {
- return Load (NULL, 0, theFileName);
- }
+ using Image_AlienPixMapI::Load;
//! Read image data from stream.
- Standard_EXPORT bool Load (std::istream& theStream,
- const TCollection_AsciiString& theFileName);
+ Standard_EXPORT virtual bool Load (std::istream& theStream,
+ const TCollection_AsciiString& theFileName) Standard_OVERRIDE;
//! Read image data from memory buffer.
//! @param theData memory pointer to read from;
//! when NULL, function will attempt to open theFileName file
//! @param theLength memory buffer length
//! @param theFileName optional file name
- Standard_EXPORT bool Load (const Standard_Byte* theData,
- Standard_Size theLength,
- const TCollection_AsciiString& theFileName);
+ Standard_EXPORT virtual bool Load (const Standard_Byte* theData,
+ Standard_Size theLength,
+ const TCollection_AsciiString& theFileName) Standard_OVERRIDE;
//! Write image data to file using file extension to determine compression format.
- Standard_EXPORT bool Save (const TCollection_AsciiString& theFileName);
+ Standard_EXPORT virtual bool Save (const TCollection_AsciiString& theFileName) Standard_OVERRIDE;
//! Initialize image plane with required dimensions.
- //! thePixelFormat - if specified pixel format doesn't supported by image library
- //! than nearest supported will be used instead!
- //! theSizeRowBytes - may be ignored by this class and required alignemnt will be used instead!
+ //! @param thePixelFormat if specified pixel format doesn't supported by image library
+ //! than nearest supported will be used instead!
+ //! @param theSizeX image width
+ //! @param theSizeY image height
+ //! @param theSizeRowBytes may be ignored by this class and required alignment will be used instead!
Standard_EXPORT virtual bool InitTrash (Image_Format thePixelFormat,
const Standard_Size theSizeX,
const Standard_Size theSizeY,
const Standard_Size theSizeRowBytes = 0) Standard_OVERRIDE;
- //! Initialize by copying data.
- Standard_EXPORT virtual bool InitCopy (const Image_PixMap& theCopy) Standard_OVERRIDE;
-
//! Method correctly deallocate internal buffer.
Standard_EXPORT virtual void Clear() Standard_OVERRIDE;
//! Performs gamma correction on image.
//! theGamma - gamma value to use; a value of 1.0 leaves the image alone
- Standard_EXPORT bool AdjustGamma (const Standard_Real theGammaCorr);
+ Standard_EXPORT virtual bool AdjustGamma (Standard_Real theGammaCorr) Standard_OVERRIDE;
-private:
-
- FIBITMAP* myLibImage;
+ //! Setup scanlines order in memory - top-down or bottom-up.
+ virtual void SetTopDown (bool theIsTopDown) Standard_OVERRIDE
+ {
+ if (!myLibImage.IsNull())
+ {
+ myLibImage->SetTopDown (theIsTopDown);
+ }
+ base_type::SetTopDown (theIsTopDown);
+ }
private:
+ //! Return NULL.
+ Handle(Image_AlienPixMapI) createDefault() const Standard_OVERRIDE { return Handle(Image_AlienPixMapI)(); }
+
//! Copying allowed only within Handles
Image_AlienPixMap (const Image_AlienPixMap& );
Image_AlienPixMap& operator= (const Image_AlienPixMap& );
- //! Wrapper initialization is disallowed for this class (will return false in any case)!
- //! Use only copying and allocation initializers.
- Standard_EXPORT virtual bool InitWrapper (Image_Format thePixelFormat,
- Standard_Byte* theDataPtr,
- const Standard_Size theSizeX,
- const Standard_Size theSizeY,
- const Standard_Size theSizeRowBytes) Standard_OVERRIDE;
+private:
- //! Built-in PPM export
- Standard_EXPORT bool savePPM (const TCollection_AsciiString& theFileName) const;
+ Handle(Image_AlienPixMapI) myLibImage;
};
--- /dev/null
+// Created on: 2010-09-16
+// Created by: KGV
+// Copyright (c) 2010-2014 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_AlienPixMapI.hxx>
+#include <gp.hxx>
+#include <Message.hxx>
+#include <Message_Messenger.hxx>
+#include <NCollection_Array1.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <TCollection_ExtendedString.hxx>
+#include <OSD_OpenFile.hxx>
+#include <fstream>
+#include <algorithm>
+
+IMPLEMENT_STANDARD_RTTIEXT(Image_AlienPixMapI, Image_PixMap)
+
+// =======================================================================
+// function : InitWrapper
+// purpose :
+// =======================================================================
+bool Image_AlienPixMapI::InitWrapper (Image_Format,
+ Standard_Byte*,
+ const Standard_Size,
+ const Standard_Size,
+ const Standard_Size)
+{
+ Clear();
+ return false;
+}
+
+// =======================================================================
+// function : InitCopy
+// purpose :
+// =======================================================================
+bool Image_AlienPixMapI::InitCopy (const Image_PixMap& theCopy)
+{
+ if (&theCopy == this)
+ {
+ // self-copying disallowed
+ return false;
+ }
+ if (!InitTrash (theCopy.Format(), theCopy.SizeX(), theCopy.SizeY(), theCopy.SizeRowBytes()))
+ {
+ return false;
+ }
+
+ if (myImgFormat == theCopy.Format())
+ {
+ if (SizeRowBytes() == theCopy.SizeRowBytes()
+ && TopDownInc() == theCopy.TopDownInc())
+ {
+ // copy with one call
+ memcpy (ChangeData(), theCopy.Data(), std::min (SizeBytes(), theCopy.SizeBytes()));
+ return true;
+ }
+
+ // copy row-by-row
+ const Standard_Size aRowSizeBytes = std::min (SizeRowBytes(), theCopy.SizeRowBytes());
+ for (Standard_Size aRow = 0; aRow < myData.SizeY; ++aRow)
+ {
+ memcpy (ChangeRow (aRow), theCopy.Row (aRow), aRowSizeBytes);
+ }
+ return true;
+ }
+
+ // pixel format conversion required
+ Clear();
+ return false;
+}
+
+// =======================================================================
+// function : loadStreamToBuffer
+// purpose :
+// =======================================================================
+bool Image_AlienPixMapI::loadStreamToBuffer (std::istream& theStream,
+ const TCollection_AsciiString& theFileName)
+{
+ Clear();
+
+ const std::streamoff aStart = theStream.tellg();
+ theStream.seekg (0, std::ios::end);
+ const Standard_Integer aLen = Standard_Integer(theStream.tellg() - aStart);
+ theStream.seekg (aStart);
+ if (aLen <= 0)
+ {
+ Message::DefaultMessenger()->Send ("Error: empty stream", Message_Fail);
+ return false;
+ }
+
+ NCollection_Array1<Standard_Byte> aBuff (1, aLen);
+ if (!theStream.read ((char* )&aBuff.ChangeFirst(), aBuff.Size()))
+ {
+ Message::DefaultMessenger()->Send ("Error: unable to read stream", Message_Fail);
+ return false;
+ }
+
+ return Load (&aBuff.ChangeFirst(), aBuff.Size(), theFileName);
+}
+
+// =======================================================================
+// function : savePPM
+// purpose :
+// =======================================================================
+bool Image_AlienPixMapI::savePPM (const TCollection_AsciiString& theFileName) const
+{
+ if (IsEmpty())
+ {
+ return false;
+ }
+
+ // Open file
+ FILE* aFile = OSD_OpenFile (theFileName.ToCString(), "wb");
+ if (aFile == NULL)
+ {
+ return false;
+ }
+
+ // Write header
+ fprintf (aFile, "P6\n%d %d\n255\n", (int )SizeX(), (int )SizeY());
+ fprintf (aFile, "# Image stored by OpenCASCADE framework in linear RGB colorspace\n");
+
+ // Write pixel data
+ Standard_Byte aByte;
+ for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
+ {
+ for (Standard_Size aCol = 0; aCol < SizeX(); ++aCol)
+ {
+ // extremely SLOW but universal (implemented for all supported pixel formats)
+ const Quantity_ColorRGBA aColor = PixelColor ((Standard_Integer )aCol, (Standard_Integer )aRow);
+ aByte = Standard_Byte(aColor.GetRGB().Red() * 255.0); fwrite (&aByte, 1, 1, aFile);
+ aByte = Standard_Byte(aColor.GetRGB().Green() * 255.0); fwrite (&aByte, 1, 1, aFile);
+ aByte = Standard_Byte(aColor.GetRGB().Blue() * 255.0); fwrite (&aByte, 1, 1, aFile);
+ }
+ }
+
+ // Close file
+ fclose (aFile);
+ return true;
+}
--- /dev/null
+// Created on: 2012-07-18
+// Created by: Kirill GAVRILOV
+// Copyright (c) 2012-2014 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_AlienPixMapI_HeaderFile
+#define _Image_AlienPixMapI_HeaderFile
+
+#include <Image_PixMap.hxx>
+#include <TCollection_AsciiString.hxx>
+
+//! Interface for reading/writing image files.
+class Image_AlienPixMapI : public Image_PixMap
+{
+ DEFINE_STANDARD_RTTIEXT(Image_AlienPixMapI, Image_PixMap)
+public:
+
+ //! Empty constructor.
+ Image_AlienPixMapI() {}
+
+ //! Read image data from file.
+ bool Load (const TCollection_AsciiString& theFileName)
+ {
+ return Load (NULL, 0, theFileName);
+ }
+
+ //! Read image data from stream.
+ virtual bool Load (std::istream& theStream,
+ const TCollection_AsciiString& theFileName) = 0;
+
+ //! Read image data from memory buffer.
+ //! @param theData memory pointer to read from;
+ //! when NULL, function will attempt to open theFileName file
+ //! @param theLength memory buffer length
+ //! @param theFileName optional file name
+ virtual bool Load (const Standard_Byte* theData,
+ Standard_Size theLength,
+ const TCollection_AsciiString& theFileName) = 0;
+
+ //! Write image data to file using file extension to determine compression format.
+ virtual bool Save (const TCollection_AsciiString& theFileName) = 0;
+
+ //! Performs gamma correction on image.
+ //! theGamma - gamma value to use; a value of 1.0 leaves the image alone
+ virtual bool AdjustGamma (Standard_Real theGammaCorr) { (void )theGammaCorr; return false; }
+
+ //! Initializes image data as copy of another image.
+ Standard_EXPORT virtual bool InitCopy (const Image_PixMap& theCopy) Standard_OVERRIDE;
+
+public:
+
+ //! Create default instance of this class.
+ virtual Handle(Image_AlienPixMapI) createDefault() const = 0;
+
+protected:
+
+ //! Fallback copying stream data into transient buffer
+ Standard_EXPORT bool loadStreamToBuffer (std::istream& theStream,
+ const TCollection_AsciiString& theFileName);
+
+ //! Built-in PPM export
+ Standard_EXPORT bool savePPM (const TCollection_AsciiString& theFileName) const;
+
+ //! Wrapper initialization for sub-classes.
+ bool initWrapper (Image_Format thePixelFormat,
+ Standard_Byte* theDataPtr,
+ Standard_Size theSizeX,
+ Standard_Size theSizeY,
+ Standard_Size theSizeRowBytes)
+ {
+ return Image_PixMap::InitWrapper (thePixelFormat, theDataPtr, theSizeX, theSizeY, theSizeRowBytes);
+ }
+
+private:
+
+ //! Wrapper initialization by user is disallowed for this class (will return false in any case)!
+ //! Use only copying and allocation initializers.
+ Standard_EXPORT virtual bool InitWrapper (Image_Format thePixelFormat,
+ Standard_Byte* theDataPtr,
+ const Standard_Size theSizeX,
+ const Standard_Size theSizeY,
+ const Standard_Size theSizeRowBytes) Standard_OVERRIDE;
+
+};
+
+DEFINE_STANDARD_HANDLE(Image_AlienPixMapI, Image_PixMap)
+
+#endif // _Image_AlienPixMapI_HeaderFile
--- /dev/null
+// Copyright (c) 2019 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.
+
+#ifdef HAVE_FREEIMAGE
+ #include <FreeImage.h>
+
+ #ifdef _MSC_VER
+ #pragma comment( lib, "FreeImage.lib" )
+ #endif
+#endif
+
+#include <Image_FreeImage.hxx>
+
+#include <gp.hxx>
+#include <Message.hxx>
+#include <Message_Messenger.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <TCollection_ExtendedString.hxx>
+#include <OSD_OpenFile.hxx>
+#include <fstream>
+#include <algorithm>
+
+IMPLEMENT_STANDARD_RTTIEXT(Image_FreeImage, Image_AlienPixMapI)
+
+namespace
+{
+#ifdef HAVE_FREEIMAGE
+ static Image_Format convertFromFreeFormat (FREE_IMAGE_TYPE theFormatFI,
+ FREE_IMAGE_COLOR_TYPE theColorTypeFI,
+ unsigned theBitsPerPixel)
+ {
+ switch (theFormatFI)
+ {
+ case FIT_RGBF: return Image_Format_RGBF;
+ case FIT_RGBAF: return Image_Format_RGBAF;
+ case FIT_FLOAT: return Image_Format_GrayF;
+ case FIT_BITMAP:
+ {
+ switch (theColorTypeFI)
+ {
+ case FIC_MINISBLACK:
+ {
+ return Image_Format_Gray;
+ }
+ case FIC_RGB:
+ {
+ if (Image_PixMap::IsBigEndianHost())
+ {
+ return (theBitsPerPixel == 32) ? Image_Format_RGB32 : Image_Format_RGB;
+ }
+ else
+ {
+ return (theBitsPerPixel == 32) ? Image_Format_BGR32 : Image_Format_BGR;
+ }
+ }
+ case FIC_RGBALPHA:
+ {
+ return Image_PixMap::IsBigEndianHost() ? Image_Format_RGBA : Image_Format_BGRA;
+ }
+ default:
+ return Image_Format_UNKNOWN;
+ }
+ }
+ default:
+ return Image_Format_UNKNOWN;
+ }
+ }
+
+ static FREE_IMAGE_TYPE convertToFreeFormat (Image_Format theFormat)
+ {
+ switch (theFormat)
+ {
+ case Image_Format_GrayF:
+ case Image_Format_AlphaF:
+ return FIT_FLOAT;
+ case Image_Format_RGBAF:
+ return FIT_RGBAF;
+ case Image_Format_RGBF:
+ return FIT_RGBF;
+ case Image_Format_RGBA:
+ case Image_Format_BGRA:
+ case Image_Format_RGB32:
+ case Image_Format_BGR32:
+ case Image_Format_RGB:
+ case Image_Format_BGR:
+ case Image_Format_Gray:
+ case Image_Format_Alpha:
+ return FIT_BITMAP;
+ default:
+ return FIT_UNKNOWN;
+ }
+ }
+
+ //! Wrapper for accessing C++ stream from FreeImage.
+ class Image_FreeImageStream
+ {
+ public:
+ //! Construct wrapper over input stream.
+ Image_FreeImageStream (std::istream& theStream)
+ : myIStream (&theStream), myOStream (NULL), myInitPos (theStream.tellg()) {}
+
+ //! Get io object.
+ FreeImageIO GetFiIO() const
+ {
+ FreeImageIO anIo;
+ memset (&anIo, 0, sizeof(anIo));
+ if (myIStream != NULL)
+ {
+ anIo.read_proc = readProc;
+ anIo.seek_proc = seekProc;
+ anIo.tell_proc = tellProc;
+ }
+ if (myOStream != NULL)
+ {
+ anIo.write_proc = writeProc;
+ }
+ return anIo;
+ }
+ public:
+ //! Simulate fread().
+ static unsigned int DLL_CALLCONV readProc (void* theBuffer, unsigned int theSize, unsigned int theCount, fi_handle theHandle)
+ {
+ Image_FreeImageStream* aThis = (Image_FreeImageStream* )theHandle;
+ if (aThis->myIStream == NULL)
+ {
+ return 0;
+ }
+
+ if (!aThis->myIStream->read ((char* )theBuffer, std::streamsize(theSize) * std::streamsize(theCount)))
+ {
+ //aThis->myIStream->clear();
+ }
+ const std::streamsize aNbRead = aThis->myIStream->gcount();
+ return (unsigned int )(aNbRead / theSize);
+ }
+
+ //! Simulate fwrite().
+ static unsigned int DLL_CALLCONV writeProc (void* theBuffer, unsigned int theSize, unsigned int theCount, fi_handle theHandle)
+ {
+ Image_FreeImageStream* aThis = (Image_FreeImageStream* )theHandle;
+ if (aThis->myOStream != NULL
+ && aThis->myOStream->write ((const char* )theBuffer, std::streamsize(theSize) * std::streamsize(theCount)))
+ {
+ return theCount;
+ }
+ return 0;
+ }
+
+ //! Simulate fseek().
+ static int DLL_CALLCONV seekProc (fi_handle theHandle, long theOffset, int theOrigin)
+ {
+ Image_FreeImageStream* aThis = (Image_FreeImageStream* )theHandle;
+ if (aThis->myIStream == NULL)
+ {
+ return -1;
+ }
+
+ bool isSeekDone = false;
+ switch (theOrigin)
+ {
+ case SEEK_SET:
+ if (aThis->myIStream->seekg ((std::streamoff )aThis->myInitPos + theOffset, std::ios::beg))
+ {
+ isSeekDone = true;
+ }
+ break;
+ case SEEK_CUR:
+ if (aThis->myIStream->seekg (theOffset, std::ios::cur))
+ {
+ isSeekDone = true;
+ }
+ break;
+ case SEEK_END:
+ if (aThis->myIStream->seekg (theOffset, std::ios::end))
+ {
+ isSeekDone = true;
+ }
+ break;
+ }
+ return isSeekDone ? 0 : -1;
+ }
+
+ //! Simulate ftell().
+ static long DLL_CALLCONV tellProc (fi_handle theHandle)
+ {
+ Image_FreeImageStream* aThis = (Image_FreeImageStream* )theHandle;
+ const long aPos = aThis->myIStream != NULL ? (long )(aThis->myIStream->tellg() - aThis->myInitPos) : 0;
+ return aPos;
+ }
+ private:
+ std::istream* myIStream;
+ std::ostream* myOStream;
+ std::streampos myInitPos;
+ };
+#endif
+}
+
+// =======================================================================
+// function : IsAvailable
+// purpose :
+// =======================================================================
+bool Image_FreeImage::IsAvailable()
+{
+#if defined(HAVE_FREEIMAGE)
+ return true;
+#else
+ return false;
+#endif
+}
+
+// =======================================================================
+// function : Image_FreeImage
+// purpose :
+// =======================================================================
+Image_FreeImage::Image_FreeImage()
+: myLibImage (NULL)
+{
+ SetTopDown (false);
+}
+
+// =======================================================================
+// function : ~Image_FreeImage
+// purpose :
+// =======================================================================
+Image_FreeImage::~Image_FreeImage()
+{
+ Clear();
+}
+
+// =======================================================================
+// function : InitTrash
+// purpose :
+// =======================================================================
+bool Image_FreeImage::InitTrash (Image_Format thePixelFormat,
+ const Standard_Size theSizeX,
+ const Standard_Size theSizeY,
+ const Standard_Size theSizeRowBytes)
+{
+ Clear();
+#ifdef HAVE_FREEIMAGE
+ (void )theSizeRowBytes;
+ FREE_IMAGE_TYPE aFormatFI = convertToFreeFormat (thePixelFormat);
+ int aBitsPerPixel = (int )Image_PixMap::SizePixelBytes (thePixelFormat) * 8;
+ if (aFormatFI == FIT_UNKNOWN)
+ {
+ aFormatFI = FIT_BITMAP;
+ aBitsPerPixel = 24;
+ }
+
+ FIBITMAP* anImage = FreeImage_AllocateT (aFormatFI, (int )theSizeX, (int )theSizeY, aBitsPerPixel);
+ Image_Format aFormat = convertFromFreeFormat (FreeImage_GetImageType(anImage),
+ FreeImage_GetColorType(anImage),
+ FreeImage_GetBPP (anImage));
+ if (thePixelFormat == Image_Format_BGR32
+ || thePixelFormat == Image_Format_RGB32)
+ {
+ //FreeImage_SetTransparent (anImage, FALSE);
+ aFormat = (aFormat == Image_Format_BGRA) ? Image_Format_BGR32 : Image_Format_RGB32;
+ }
+
+ initWrapper (aFormat, FreeImage_GetBits (anImage),
+ FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
+ SetTopDown (false);
+
+ // assign image after wrapper initialization (virtual Clear() called inside)
+ myLibImage = anImage;
+ return true;
+#else
+ return base_type::InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes);
+#endif
+}
+
+// =======================================================================
+// function : Clear
+// purpose :
+// =======================================================================
+void Image_FreeImage::Clear()
+{
+ base_type::Clear();
+#ifdef HAVE_FREEIMAGE
+ if (myLibImage != NULL)
+ {
+ FreeImage_Unload (myLibImage);
+ myLibImage = NULL;
+ }
+#endif
+}
+
+// =======================================================================
+// function : Load
+// purpose :
+// =======================================================================
+bool Image_FreeImage::Load (const Standard_Byte* theData,
+ Standard_Size theLength,
+ const TCollection_AsciiString& theImagePath)
+{
+ Clear();
+#ifdef HAVE_FREEIMAGE
+#ifdef _WIN32
+ const TCollection_ExtendedString aFileNameW (theImagePath);
+#endif
+ FREE_IMAGE_FORMAT aFIF = FIF_UNKNOWN;
+ FIMEMORY* aFiMem = NULL;
+ if (theData != NULL)
+ {
+ aFiMem = FreeImage_OpenMemory ((BYTE* )theData, (DWORD )theLength);
+ aFIF = FreeImage_GetFileTypeFromMemory (aFiMem, 0);
+ }
+ else
+ {
+ #ifdef _WIN32
+ aFIF = FreeImage_GetFileTypeU (aFileNameW.ToWideString(), 0);
+ #else
+ aFIF = FreeImage_GetFileType (theImagePath.ToCString(), 0);
+ #endif
+ }
+ if (aFIF == FIF_UNKNOWN)
+ {
+ // no signature? try to guess the file format from the file extension
+ aFIF = FreeImage_GetFIFFromFilename (theImagePath.ToCString());
+ }
+ if ((aFIF == FIF_UNKNOWN) || !FreeImage_FIFSupportsReading (aFIF))
+ {
+ ::Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error: image '") + theImagePath + "' has unsupported file format.",
+ Message_Fail);
+ if (aFiMem != NULL)
+ {
+ FreeImage_CloseMemory (aFiMem);
+ }
+ return false;
+ }
+
+ int aLoadFlags = 0;
+ if (aFIF == FIF_GIF)
+ {
+ // 'Play' the GIF to generate each frame (as 32bpp) instead of returning raw frame data when loading
+ aLoadFlags = GIF_PLAYBACK;
+ }
+ else if (aFIF == FIF_ICO)
+ {
+ // convert to 32bpp and create an alpha channel from the AND-mask when loading
+ aLoadFlags = ICO_MAKEALPHA;
+ }
+
+ FIBITMAP* anImage = NULL;
+ if (theData != NULL)
+ {
+ anImage = FreeImage_LoadFromMemory (aFIF, aFiMem, aLoadFlags);
+ FreeImage_CloseMemory (aFiMem);
+ aFiMem = NULL;
+ }
+ else
+ {
+ #ifdef _WIN32
+ anImage = FreeImage_LoadU (aFIF, aFileNameW.ToWideString(), aLoadFlags);
+ #else
+ anImage = FreeImage_Load (aFIF, theImagePath.ToCString(), aLoadFlags);
+ #endif
+ }
+ if (anImage == NULL)
+ {
+ TCollection_AsciiString aMessage = "Error: image file '";
+ aMessage.AssignCat (theImagePath);
+ aMessage.AssignCat ("' is missing or invalid.");
+ ::Message::DefaultMessenger()->Send (aMessage, Message_Fail);
+ return false;
+ }
+
+ Image_Format aFormat = convertFromFreeFormat (FreeImage_GetImageType(anImage),
+ FreeImage_GetColorType(anImage),
+ FreeImage_GetBPP (anImage));
+ if (aFormat == Image_Format_UNKNOWN)
+ {
+ //anImage = FreeImage_ConvertTo24Bits (anImage);
+ ::Message::DefaultMessenger()->Send ( TCollection_AsciiString ("Error: image '") + theImagePath + "' has unsupported pixel format.",
+ Message_Fail);
+ return false;
+ }
+
+ initWrapper (aFormat, FreeImage_GetBits (anImage),
+ FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
+ SetTopDown (false);
+
+ // assign image after wrapper initialization (virtual Clear() called inside)
+ myLibImage = anImage;
+ return true;
+#else
+ (void )theData;
+ (void )theLength;
+ (void )theImagePath;
+ Message::DefaultMessenger()->Send ("Error: FreeImage library is unavailable", Message_Fail);
+ return false;
+#endif
+}
+
+// =======================================================================
+// function : Load
+// purpose :
+// =======================================================================
+bool Image_FreeImage::Load (std::istream& theStream,
+ const TCollection_AsciiString& theFileName)
+{
+ Clear();
+#ifdef HAVE_FREEIMAGE
+ Image_FreeImageStream aStream (theStream);
+ FreeImageIO aFiIO = aStream.GetFiIO();
+
+ FREE_IMAGE_FORMAT aFIF = FreeImage_GetFileTypeFromHandle (&aFiIO, &aStream, 0);
+ if (aFIF == FIF_UNKNOWN)
+ {
+ // no signature? try to guess the file format from the file extension
+ aFIF = FreeImage_GetFIFFromFilename (theFileName.ToCString());
+ }
+ if ((aFIF == FIF_UNKNOWN) || !FreeImage_FIFSupportsReading (aFIF))
+ {
+ ::Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error: image stream '") + theFileName + "' has unsupported file format.",
+ Message_Fail);
+ return false;
+ }
+
+ int aLoadFlags = 0;
+ if (aFIF == FIF_GIF)
+ {
+ // 'Play' the GIF to generate each frame (as 32bpp) instead of returning raw frame data when loading
+ aLoadFlags = GIF_PLAYBACK;
+ }
+ else if (aFIF == FIF_ICO)
+ {
+ // convert to 32bpp and create an alpha channel from the AND-mask when loading
+ aLoadFlags = ICO_MAKEALPHA;
+ }
+
+ FIBITMAP* anImage = FreeImage_LoadFromHandle (aFIF, &aFiIO, &aStream, aLoadFlags);
+ if (anImage == NULL)
+ {
+ ::Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error: image stream '") + theFileName + "' is missing or invalid.",
+ Message_Fail);
+ return false;
+ }
+
+ Image_Format aFormat = convertFromFreeFormat (FreeImage_GetImageType(anImage),
+ FreeImage_GetColorType(anImage),
+ FreeImage_GetBPP (anImage));
+ if (aFormat == Image_Format_UNKNOWN)
+ {
+ ::Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error: image stream '") + theFileName + "' has unsupported pixel format.",
+ Message_Fail);
+ return false;
+ }
+
+ initWrapper (aFormat, FreeImage_GetBits (anImage),
+ FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
+ SetTopDown (false);
+
+ // assign image after wrapper initialization (virtual Clear() called inside)
+ myLibImage = anImage;
+ return true;
+#else
+ (void )theStream;
+ (void )theFileName;
+ Message::DefaultMessenger()->Send ("Error: FreeImage library is unavailable", Message_Fail);
+ return false;
+#endif
+}
+
+// =======================================================================
+// function : Save
+// purpose :
+// =======================================================================
+bool Image_FreeImage::Save (const TCollection_AsciiString& theFileName)
+{
+#ifdef HAVE_FREEIMAGE
+ if (myLibImage == NULL)
+ {
+ return false;
+ }
+
+#ifdef _WIN32
+ const TCollection_ExtendedString aFileNameW (theFileName.ToCString(), Standard_True);
+ FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilenameU (aFileNameW.ToWideString());
+#else
+ FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilename (theFileName.ToCString());
+#endif
+ if (anImageFormat == FIF_UNKNOWN)
+ {
+#ifdef OCCT_DEBUG
+ std::cerr << "Image_FreeImage, image format doesn't supported!\n";
+#endif
+ return false;
+ }
+
+ if (IsTopDown())
+ {
+ FreeImage_FlipVertical (myLibImage);
+ SetTopDown (false);
+ }
+
+ // FreeImage doesn't provide flexible format conversion API
+ // so we should perform multiple conversions in some cases!
+ FIBITMAP* anImageToDump = myLibImage;
+ switch (anImageFormat)
+ {
+ case FIF_PNG:
+ case FIF_BMP:
+ {
+ if (Format() == Image_Format_BGR32
+ || Format() == Image_Format_RGB32)
+ {
+ // stupid FreeImage treats reserved byte as alpha if some bytes not set to 0xFF
+ for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
+ {
+ for (Standard_Size aCol = 0; aCol < SizeX(); ++aCol)
+ {
+ myData.ChangeValue (aRow, aCol)[3] = 0xFF;
+ }
+ }
+ }
+ else if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
+ {
+ anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
+ }
+ break;
+ }
+ case FIF_GIF:
+ {
+ FIBITMAP* aTmpBitmap = myLibImage;
+ if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
+ {
+ aTmpBitmap = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
+ if (aTmpBitmap == NULL)
+ {
+ return false;
+ }
+ }
+
+ if (FreeImage_GetBPP (aTmpBitmap) != 24)
+ {
+ FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (aTmpBitmap);
+ if (aTmpBitmap != myLibImage)
+ {
+ FreeImage_Unload (aTmpBitmap);
+ }
+ if (aTmpBitmap24 == NULL)
+ {
+ return false;
+ }
+ aTmpBitmap = aTmpBitmap24;
+ }
+
+ // need conversion to image with palette (requires 24bit bitmap)
+ anImageToDump = FreeImage_ColorQuantize (aTmpBitmap, FIQ_NNQUANT);
+ if (aTmpBitmap != myLibImage)
+ {
+ FreeImage_Unload (aTmpBitmap);
+ }
+ break;
+ }
+ case FIF_HDR:
+ case FIF_EXR:
+ {
+ if (Format() == Image_Format_Gray
+ || Format() == Image_Format_Alpha)
+ {
+ anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_FLOAT);
+ }
+ else if (Format() == Image_Format_RGBA
+ || Format() == Image_Format_BGRA)
+ {
+ anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBAF);
+ }
+ else
+ {
+ FREE_IMAGE_TYPE aImgTypeFI = FreeImage_GetImageType (myLibImage);
+ if (aImgTypeFI != FIT_RGBF
+ && aImgTypeFI != FIT_RGBAF
+ && aImgTypeFI != FIT_FLOAT)
+ {
+ anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBF);
+ }
+ }
+ break;
+ }
+ default:
+ {
+ if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
+ {
+ anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
+ if (anImageToDump == NULL)
+ {
+ return false;
+ }
+ }
+
+ if (FreeImage_GetBPP (anImageToDump) != 24)
+ {
+ FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (anImageToDump);
+ if (anImageToDump != myLibImage)
+ {
+ FreeImage_Unload (anImageToDump);
+ }
+ if (aTmpBitmap24 == NULL)
+ {
+ return false;
+ }
+ anImageToDump = aTmpBitmap24;
+ }
+ break;
+ }
+ }
+
+ if (anImageToDump == NULL)
+ {
+ return false;
+ }
+
+#ifdef _WIN32
+ bool isSaved = (FreeImage_SaveU (anImageFormat, anImageToDump, aFileNameW.ToWideString()) != FALSE);
+#else
+ bool isSaved = (FreeImage_Save (anImageFormat, anImageToDump, theFileName.ToCString()) != FALSE);
+#endif
+ if (anImageToDump != myLibImage)
+ {
+ FreeImage_Unload (anImageToDump);
+ }
+ return isSaved;
+#else
+ (void )theFileName;
+ Message::DefaultMessenger()->Send ("Error: FreeImage library is unavailable", Message_Fail);
+ return false;
+#endif
+}
+
+// =======================================================================
+// function : AdjustGamma
+// purpose :
+// =======================================================================
+bool Image_FreeImage::AdjustGamma (const Standard_Real theGammaCorr)
+{
+#ifdef HAVE_FREEIMAGE
+ return FreeImage_AdjustGamma (myLibImage, theGammaCorr) != FALSE;
+#else
+ (void )theGammaCorr;
+ return false;
+#endif
+}
--- /dev/null
+// Copyright (c) 2019 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_FreeImage_HeaderFile
+#define _Image_FreeImage_HeaderFile
+
+#include <Image_AlienPixMapI.hxx>
+
+struct FIBITMAP;
+
+//! Image class that implements file reading/writing operations using FreeImage library.
+//! Supported image formats:
+//! - *.bmp - bitmap image, lossless format without compression.
+//! - *.ppm - PPM (Portable Pixmap Format), lossless format without compression.
+//! - *.png - PNG (Portable Network Graphics) lossless format with compression.
+//! - *.jpg, *.jpe, *.jpeg - JPEG/JIFF (Joint Photographic Experts Group) lossy format (compressed with quality losses). YUV color space used (automatically converted from/to RGB).
+//! - *.tif, *.tiff - TIFF (Tagged Image File Format).
+//! - *.tga - TGA (Truevision Targa Graphic), lossless format.
+//! - *.gif - GIF (Graphical Interchange Format), lossy format. Color stored using palette (up to 256 distinct colors).
+//! - *.exr - OpenEXR high dynamic-range format (supports float pixel formats).
+class Image_FreeImage : public Image_AlienPixMapI
+{
+ DEFINE_STANDARD_RTTIEXT(Image_FreeImage, Image_AlienPixMapI)
+public:
+
+ //! Return TRUE if FreeImage library is available.
+ Standard_EXPORT static bool IsAvailable();
+
+ //! Return default rows order used by FreeImage library, which is Bottom-Up.
+ static bool IsTopDownDefault() { return false; }
+public:
+
+ //! Empty constructor.
+ Standard_EXPORT Image_FreeImage();
+
+ //! Destructor
+ Standard_EXPORT virtual ~Image_FreeImage();
+
+ using Image_AlienPixMapI::Load;
+
+ //! Read image data from stream.
+ Standard_EXPORT virtual bool Load (std::istream& theStream,
+ const TCollection_AsciiString& theFileName) Standard_OVERRIDE;
+
+ //! Read image data from memory buffer.
+ //! @param theData memory pointer to read from;
+ //! when NULL, function will attempt to open theFileName file
+ //! @param theLength memory buffer length
+ //! @param theFileName optional file name
+ Standard_EXPORT virtual bool Load (const Standard_Byte* theData,
+ Standard_Size theLength,
+ const TCollection_AsciiString& theFileName) Standard_OVERRIDE;
+
+ //! Write image data to file using file extension to determine compression format.
+ Standard_EXPORT virtual bool Save (const TCollection_AsciiString& theFileName) Standard_OVERRIDE;
+
+ //! Initialize image plane with required dimensions.
+ //! @param thePixelFormat if specified pixel format doesn't supported by image library
+ //! than nearest supported will be used instead!
+ //! @param theSizeX image width
+ //! @param theSizeY image height
+ //! @param theSizeRowBytes ignored parameter, 4-bytes alignment is enforced by FreeImage library
+ Standard_EXPORT virtual bool InitTrash (Image_Format thePixelFormat,
+ const Standard_Size theSizeX,
+ const Standard_Size theSizeY,
+ const Standard_Size theSizeRowBytes = 0) Standard_OVERRIDE;
+
+ //! Method correctly deallocate internal buffer.
+ Standard_EXPORT virtual void Clear() Standard_OVERRIDE;
+
+ //! Performs gamma correction on image.
+ //! theGamma - gamma value to use; a value of 1.0 leaves the image alone
+ Standard_EXPORT virtual bool AdjustGamma (Standard_Real theGammaCorr) Standard_OVERRIDE;
+
+public:
+
+ //! Create default instance of this class.
+ virtual Handle(Image_AlienPixMapI) createDefault() const Standard_OVERRIDE
+ {
+ return new Image_FreeImage();
+ }
+
+private:
+
+ //! Copying allowed only within Handles
+ Image_FreeImage (const Image_FreeImage& );
+ Image_FreeImage& operator= (const Image_FreeImage& );
+
+private:
+
+ FIBITMAP* myLibImage;
+
+};
+
+DEFINE_STANDARD_HANDLE(Image_FreeImage, Image_AlienPixMapI)
+
+#endif // _Image_FreeImage_HeaderFile
//! Setup scanlines order in memory - top-down or bottom-up.
//! Drawers should explicitly specify this value if current state IsTopDown() was ignored!
//! @param theIsTopDown top-down flag
- inline void SetTopDown (const bool theIsTopDown)
+ virtual void SetTopDown (bool theIsTopDown)
{
myData.SetTopDown (theIsTopDown);
}
--- /dev/null
+// Copyright (c) 2019 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.
+
+#if !defined(HAVE_FREEIMAGE) && defined(_WIN32)
+ #define HAVE_WINCODEC
+#endif
+
+#if defined(HAVE_WINCODEC)
+ //#include <initguid.h>
+ #include <wincodec.h>
+ #undef min
+ #undef max
+
+ #ifdef _MSC_VER
+ #pragma comment( lib, "Ole32.lib" )
+ #endif
+#endif
+
+#include <Image_WinCodec.hxx>
+
+#include <Message.hxx>
+#include <Message_Messenger.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <TCollection_ExtendedString.hxx>
+#include <OSD_OpenFile.hxx>
+#include <fstream>
+#include <algorithm>
+
+IMPLEMENT_STANDARD_RTTIEXT(Image_WinCodec, Image_AlienPixMapI)
+
+namespace
+{
+#if defined(HAVE_WINCODEC)
+
+ //! Return a zero GUID
+ static GUID getNullGuid()
+ {
+ GUID aGuid = { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
+ return aGuid;
+ }
+
+ //! Sentry over IUnknown pointer.
+ template<class T> class Image_ComPtr
+ {
+ public:
+ //! Empty constructor.
+ Image_ComPtr()
+ : myPtr (NULL) {}
+
+ //! Destructor.
+ ~Image_ComPtr()
+ {
+ Nullify();
+ }
+
+ //! Return TRUE if pointer is NULL.
+ bool IsNull() const { return myPtr == NULL; }
+
+ //! Release the pointer.
+ void Nullify()
+ {
+ if (myPtr != NULL)
+ {
+ myPtr->Release();
+ myPtr = NULL;
+ }
+ }
+
+ //! Return pointer for initialization.
+ T*& ChangePtr()
+ {
+ Standard_ASSERT_RAISE (myPtr == NULL, "Pointer cannot be initialized twice!");
+ return myPtr;
+ }
+
+ //! Return pointer.
+ T* get() { return myPtr; }
+
+ //! Return pointer.
+ T* operator->() { return get(); }
+
+ //! Cast handle to contained type
+ T& operator*() { return *get(); }
+
+ private:
+ T* myPtr;
+ };
+
+ //! Convert WIC GUID to Image_Format.
+ static Image_Format convertFromWicFormat (const WICPixelFormatGUID& theFormat)
+ {
+ if (theFormat == GUID_WICPixelFormat32bppBGRA)
+ {
+ return Image_Format_BGRA;
+ }
+ else if (theFormat == GUID_WICPixelFormat32bppBGR)
+ {
+ return Image_Format_BGR32;
+ }
+ else if (theFormat == GUID_WICPixelFormat24bppRGB)
+ {
+ return Image_Format_RGB;
+ }
+ else if (theFormat == GUID_WICPixelFormat24bppBGR)
+ {
+ return Image_Format_BGR;
+ }
+ else if (theFormat == GUID_WICPixelFormat8bppGray)
+ {
+ return Image_Format_Gray;
+ }
+ return Image_Format_UNKNOWN;
+ }
+
+ //! Convert Image_Format to WIC GUID.
+ static WICPixelFormatGUID convertToWicFormat (Image_Format theFormat)
+ {
+ switch (theFormat)
+ {
+ case Image_Format_BGRA: return GUID_WICPixelFormat32bppBGRA;
+ case Image_Format_BGR32: return GUID_WICPixelFormat32bppBGR;
+ case Image_Format_RGB: return GUID_WICPixelFormat24bppRGB;
+ case Image_Format_BGR: return GUID_WICPixelFormat24bppBGR;
+ case Image_Format_Gray: return GUID_WICPixelFormat8bppGray;
+ case Image_Format_Alpha: return GUID_WICPixelFormat8bppGray; // GUID_WICPixelFormat8bppAlpha
+ case Image_Format_GrayF: // GUID_WICPixelFormat32bppGrayFloat
+ case Image_Format_AlphaF:
+ case Image_Format_RGBAF: // GUID_WICPixelFormat128bppRGBAFloat
+ case Image_Format_RGBF: // GUID_WICPixelFormat96bppRGBFloat
+ case Image_Format_RGBA: // GUID_WICPixelFormat32bppRGBA
+ case Image_Format_RGB32: // GUID_WICPixelFormat32bppRGB
+ default:
+ return getNullGuid();
+ }
+ }
+
+#endif
+}
+
+// =======================================================================
+// function : IsAvailable
+// purpose :
+// =======================================================================
+bool Image_WinCodec::IsAvailable()
+{
+#if defined(HAVE_WINCODEC)
+ return true;
+#else
+ return false;
+#endif
+}
+
+// =======================================================================
+// function : Image_WinCodec
+// purpose :
+// =======================================================================
+Image_WinCodec::Image_WinCodec()
+{
+ SetTopDown (true);
+}
+
+// =======================================================================
+// function : ~Image_WinCodec
+// purpose :
+// =======================================================================
+Image_WinCodec::~Image_WinCodec()
+{
+ Clear();
+}
+
+// =======================================================================
+// function : InitTrash
+// purpose :
+// =======================================================================
+bool Image_WinCodec::InitTrash (Image_Format thePixelFormat,
+ const Standard_Size theSizeX,
+ const Standard_Size theSizeY,
+ const Standard_Size theSizeRowBytes)
+{
+ Clear();
+
+ Image_Format aFormat = thePixelFormat;
+ switch (aFormat)
+ {
+ case Image_Format_RGB:
+ aFormat = Image_Format_BGR;
+ break;
+ case Image_Format_RGB32:
+ aFormat = Image_Format_BGR32;
+ break;
+ case Image_Format_RGBA:
+ aFormat = Image_Format_BGRA;
+ break;
+ default:
+ break;
+ }
+
+ if (!base_type::InitTrash (aFormat, theSizeX, theSizeY, theSizeRowBytes))
+ {
+ return false;
+ }
+ SetTopDown (true);
+ return true;
+}
+
+// =======================================================================
+// function : Load
+// purpose :
+// =======================================================================
+bool Image_WinCodec::Load (const Standard_Byte* theData,
+ Standard_Size theLength,
+ const TCollection_AsciiString& theFileName)
+{
+ Clear();
+#if defined(HAVE_WINCODEC)
+ Image_ComPtr<IWICImagingFactory> aWicImgFactory;
+ CoInitializeEx (NULL, COINIT_MULTITHREADED);
+ if (CoCreateInstance (CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&aWicImgFactory.ChangePtr())) != S_OK)
+ {
+ Message::DefaultMessenger()->Send ("Error: cannot initialize WIC Imaging Factory", Message_Fail);
+ return false;
+ }
+
+ Image_ComPtr<IWICBitmapDecoder> aWicDecoder;
+ Image_ComPtr<IWICStream> aWicStream;
+ if (theData != NULL)
+ {
+ if (aWicImgFactory->CreateStream (&aWicStream.ChangePtr()) != S_OK
+ || aWicStream->InitializeFromMemory ((BYTE* )theData, (DWORD )theLength) != S_OK)
+ {
+ Message::DefaultMessenger()->Send ("Error: cannot initialize WIC Stream", Message_Fail);
+ return false;
+ }
+ if (aWicImgFactory->CreateDecoderFromStream (aWicStream.get(), NULL, WICDecodeMetadataCacheOnDemand, &aWicDecoder.ChangePtr()) != S_OK)
+ {
+ Message::DefaultMessenger()->Send ("Error: cannot create WIC Image Decoder", Message_Fail);
+ return false;
+ }
+ }
+ else
+ {
+ const TCollection_ExtendedString aFileNameW (theFileName);
+ if (aWicImgFactory->CreateDecoderFromFilename (aFileNameW.ToWideString(), NULL, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &aWicDecoder.ChangePtr()) != S_OK)
+ {
+ Message::DefaultMessenger()->Send ("Error: cannot create WIC Image Decoder", Message_Fail);
+ return false;
+ }
+ }
+
+ UINT aFrameCount = 0, aFrameSizeX = 0, aFrameSizeY = 0;
+ WICPixelFormatGUID aWicPixelFormat = getNullGuid();
+ Image_ComPtr<IWICBitmapFrameDecode> aWicFrameDecode;
+ if (aWicDecoder->GetFrameCount (&aFrameCount) != S_OK
+ || aFrameCount < 1
+ || aWicDecoder->GetFrame (0, &aWicFrameDecode.ChangePtr()) != S_OK
+ || aWicFrameDecode->GetSize (&aFrameSizeX, &aFrameSizeY) != S_OK
+ || aWicFrameDecode->GetPixelFormat (&aWicPixelFormat))
+ {
+ Message::DefaultMessenger()->Send ("Error: cannot get WIC Image Frame", Message_Fail);
+ return false;
+ }
+
+ Image_ComPtr<IWICFormatConverter> aWicConvertedFrame;
+ Image_Format aPixelFormat = convertFromWicFormat (aWicPixelFormat);
+ if (aPixelFormat == Image_Format_UNKNOWN)
+ {
+ aPixelFormat = Image_Format_RGB;
+ if (aWicImgFactory->CreateFormatConverter (&aWicConvertedFrame.ChangePtr()) != S_OK
+ || aWicConvertedFrame->Initialize (aWicFrameDecode.get(), convertToWicFormat (aPixelFormat), WICBitmapDitherTypeNone, NULL, 0.0f, WICBitmapPaletteTypeCustom) != S_OK)
+ {
+ Message::DefaultMessenger()->Send ("Error: cannot convert WIC Image Frame to RGB format", Message_Fail);
+ return false;
+ }
+ aWicFrameDecode.Nullify();
+ }
+
+ if (!base_type::InitTrash (aPixelFormat, aFrameSizeX, aFrameSizeY))
+ {
+ Message::DefaultMessenger()->Send ("Error: cannot initialize memory for image", Message_Fail);
+ return false;
+ }
+
+ IWICBitmapSource* aWicSrc = aWicFrameDecode.get();
+ if(!aWicConvertedFrame.IsNull())
+ {
+ aWicSrc = aWicConvertedFrame.get();
+ }
+ if (aWicSrc->CopyPixels (NULL, (UINT )SizeRowBytes(), (UINT )SizeBytes(), ChangeData()) != S_OK)
+ {
+ Message::DefaultMessenger()->Send ("Error: cannot copy pixels from WIC Image", Message_Fail);
+ return false;
+ }
+ SetTopDown (true);
+ return true;
+#else
+ (void )theData;
+ (void )theLength;
+ (void )theFileName;
+ Message::DefaultMessenger()->Send ("Error: WinCodec image library is unavailable", Message_Fail);
+ return false;
+#endif
+}
+
+// =======================================================================
+// function : Load
+// purpose :
+// =======================================================================
+bool Image_WinCodec::Load (std::istream& theStream,
+ const TCollection_AsciiString& theFilePath)
+{
+ return loadStreamToBuffer (theStream, theFilePath);
+}
+
+// =======================================================================
+// function : Save
+// purpose :
+// =======================================================================
+bool Image_WinCodec::Save (const TCollection_AsciiString& theFileName)
+{
+#if defined(HAVE_WINCODEC)
+ TCollection_AsciiString aFileNameLower = theFileName;
+ aFileNameLower.LowerCase();
+ GUID aFileFormat = getNullGuid();
+ if (aFileNameLower.EndsWith (".ppm"))
+ {
+ return savePPM (theFileName);
+ }
+ else if (aFileNameLower.EndsWith (".bmp"))
+ {
+ aFileFormat = GUID_ContainerFormatBmp;
+ }
+ else if (aFileNameLower.EndsWith (".png"))
+ {
+ aFileFormat = GUID_ContainerFormatPng;
+ }
+ else if (aFileNameLower.EndsWith (".jpg")
+ || aFileNameLower.EndsWith (".jpeg"))
+ {
+ aFileFormat = GUID_ContainerFormatJpeg;
+ }
+ else if (aFileNameLower.EndsWith (".tiff"))
+ {
+ aFileFormat = GUID_ContainerFormatTiff;
+ }
+ else if (aFileNameLower.EndsWith (".gif"))
+ {
+ aFileFormat = GUID_ContainerFormatGif;
+ }
+
+ if (aFileFormat == getNullGuid())
+ {
+ Message::DefaultMessenger()->Send ("Error: unsupported image format", Message_Fail);
+ return false;
+ }
+
+ Image_ComPtr<IWICImagingFactory> aWicImgFactory;
+ CoInitializeEx (NULL, COINIT_MULTITHREADED);
+ if (CoCreateInstance (CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&aWicImgFactory.ChangePtr())) != S_OK)
+ {
+ Message::DefaultMessenger()->Send ("Error: cannot initialize WIC Imaging Factory", Message_Fail);
+ return false;
+ }
+
+ Image_ComPtr<IWICStream> aWicFileStream;
+ Image_ComPtr<IWICBitmapEncoder> aWicEncoder;
+ const TCollection_ExtendedString aFileNameW (theFileName);
+ if (aWicImgFactory->CreateStream (&aWicFileStream.ChangePtr()) != S_OK
+ || aWicFileStream->InitializeFromFilename (aFileNameW.ToWideString(), GENERIC_WRITE) != S_OK)
+ {
+ Message::DefaultMessenger()->Send ("Error: cannot create WIC File Stream", Message_Fail);
+ return false;
+ }
+ if (aWicImgFactory->CreateEncoder (aFileFormat, NULL, &aWicEncoder.ChangePtr()) != S_OK
+ || aWicEncoder->Initialize (aWicFileStream.get(), WICBitmapEncoderNoCache) != S_OK)
+ {
+ Message::DefaultMessenger()->Send ("Error: cannot create WIC Encoder", Message_Fail);
+ return false;
+ }
+
+ const WICPixelFormatGUID aWicPixelFormat = convertToWicFormat (myImgFormat);
+ if (aWicPixelFormat == getNullGuid())
+ {
+ Message::DefaultMessenger()->Send ("Error: unsupported pixel format", Message_Fail);
+ return false;
+ }
+
+ WICPixelFormatGUID aWicPixelFormatRes = aWicPixelFormat;
+ Image_ComPtr<IWICBitmapFrameEncode> aWicFrameEncode;
+ if (aWicEncoder->CreateNewFrame (&aWicFrameEncode.ChangePtr(), NULL) != S_OK
+ || aWicFrameEncode->Initialize (NULL) != S_OK
+ || aWicFrameEncode->SetSize ((UINT )SizeX(), (UINT )SizeY()) != S_OK
+ || aWicFrameEncode->SetPixelFormat (&aWicPixelFormatRes) != S_OK)
+ {
+ Message::DefaultMessenger()->Send ("Error: cannot create WIC Frame", Message_Fail);
+ return false;
+ }
+
+ if (aWicPixelFormatRes != aWicPixelFormat)
+ {
+ Message::DefaultMessenger()->Send ("Error: pixel format is unsupported by image format", Message_Fail);
+ return false;
+ }
+
+ if (IsTopDown())
+ {
+ if (aWicFrameEncode->WritePixels ((UINT )SizeY(), (UINT )SizeRowBytes(), (UINT )SizeBytes(), (BYTE* )Data()) != S_OK)
+ {
+ Message::DefaultMessenger()->Send ("Error: cannot write pixels to WIC Frame", Message_Fail);
+ return false;
+ }
+ }
+ else
+ {
+ for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
+ {
+ if (aWicFrameEncode->WritePixels (1, (UINT )SizeRowBytes(), (UINT )SizeRowBytes(), (BYTE* )Row (aRow)) != S_OK)
+ {
+ Message::DefaultMessenger()->Send ("Error: cannot write pixels to WIC Frame", Message_Fail);
+ return false;
+ }
+ }
+ }
+
+ if (aWicFrameEncode->Commit() != S_OK
+ || aWicEncoder->Commit() != S_OK)
+ {
+ Message::DefaultMessenger()->Send ("Error: cannot commit data to WIC Frame", Message_Fail);
+ return false;
+ }
+ if (aWicFileStream->Commit (STGC_DEFAULT) != S_OK)
+ {
+ //Message::DefaultMessenger()->Send ("Error: cannot commit data to WIC File Stream", Message_Fail);
+ //return false;
+ }
+ return true;
+#else
+ (void )theFileName;
+ Message::DefaultMessenger()->Send ("Error: WinCodec image library is unavailable", Message_Fail);
+ return false;
+#endif
+}
--- /dev/null
+// Copyright (c) 2019 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_WinCodec_HeaderFile
+#define _Image_WinCodec_HeaderFile
+
+#include <Image_AlienPixMapI.hxx>
+
+//! Image class that implements file reading/writing operations using WinCodec image library.
+//! Supported image formats:
+//! - *.bmp, *.png, *.jpg, *.tiff, *.gif.
+class Image_WinCodec : public Image_AlienPixMapI
+{
+ DEFINE_STANDARD_RTTIEXT(Image_WinCodec, Image_AlienPixMapI)
+public:
+
+ //! Return TRUE if WinCodec library is available.
+ Standard_EXPORT static bool IsAvailable();
+
+ //! Return default rows order used by WinCodec library, which is Top-Down.
+ static bool IsTopDownDefault() { return true; }
+public:
+
+ //! Empty constructor.
+ Standard_EXPORT Image_WinCodec();
+
+ //! Destructor
+ Standard_EXPORT virtual ~Image_WinCodec();
+
+ using Image_AlienPixMapI::Load;
+
+ //! Read image data from stream.
+ Standard_EXPORT virtual bool Load (std::istream& theStream,
+ const TCollection_AsciiString& theFileName) Standard_OVERRIDE;
+
+ //! Read image data from memory buffer.
+ //! @param theData memory pointer to read from;
+ //! when NULL, function will attempt to open theFileName file
+ //! @param theLength memory buffer length
+ //! @param theFileName optional file name
+ Standard_EXPORT virtual bool Load (const Standard_Byte* theData,
+ Standard_Size theLength,
+ const TCollection_AsciiString& theFileName) Standard_OVERRIDE;
+
+ //! Write image data to file using file extension to determine compression format.
+ Standard_EXPORT virtual bool Save (const TCollection_AsciiString& theFileName) Standard_OVERRIDE;
+
+ //! Initialize image plane with required dimensions.
+ //! @param thePixelFormat if specified pixel format doesn't supported by image library
+ //! than nearest supported will be used instead!
+ //! @param theSizeX image width
+ //! @param theSizeY image height
+ //! @param theSizeRowBytes may be ignored by this class and required alignment will be used instead!
+ Standard_EXPORT virtual bool InitTrash (Image_Format thePixelFormat,
+ const Standard_Size theSizeX,
+ const Standard_Size theSizeY,
+ const Standard_Size theSizeRowBytes = 0) Standard_OVERRIDE;
+
+public:
+
+ //! Create default instance of this class.
+ virtual Handle(Image_AlienPixMapI) createDefault() const Standard_OVERRIDE
+ {
+ return new Image_WinCodec();
+ }
+
+private:
+
+ //! Copying allowed only within Handles
+ Image_WinCodec (const Image_WinCodec& );
+ Image_WinCodec& operator= (const Image_WinCodec& );
+
+};
+
+DEFINE_STANDARD_HANDLE(Image_WinCodec, Image_AlienPixMapI)
+
+#endif // _Image_WinCodec_HeaderFile