// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
-#ifdef HAVE_CONFIG_H
- #include <config.h>
+#if !defined(HAVE_FREEIMAGE) && defined(_WIN32)
+ #define HAVE_WINCODEC
#endif
#ifdef HAVE_FREEIMAGE
#ifdef _MSC_VER
#pragma comment( lib, "FreeImage.lib" )
#endif
+#elif defined(HAVE_WINCODEC)
+ #include <wincodec.h>
+ // prevent warnings on MSVC10
+ #include <Standard_WarningsDisable.hxx>
+ #include <Standard_TypeDef.hxx>
+ #include <Standard_WarningsRestore.hxx>
+ #undef min
+ #undef max
+
+ #ifdef _MSC_VER
+ #pragma comment(lib, "Ole32.lib")
+ #endif
#endif
#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>
-#ifdef HAVE_FREEIMAGE
+IMPLEMENT_STANDARD_RTTIEXT(Image_AlienPixMap,Image_PixMap)
+
namespace
{
- static Image_PixMap::ImgFormat convertFromFreeFormat (FREE_IMAGE_TYPE theFormatFI,
- FREE_IMAGE_COLOR_TYPE theColorTypeFI,
- unsigned theBitsPerPixel)
+#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_PixMap::ImgRGBF;
- case FIT_RGBAF: return Image_PixMap::ImgRGBAF;
- case FIT_FLOAT: return Image_PixMap::ImgGrayF;
+ 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_PixMap::ImgGray;
+ return Image_Format_Gray;
}
case FIC_RGB:
{
if (Image_PixMap::IsBigEndianHost())
{
- return (theBitsPerPixel == 32) ? Image_PixMap::ImgRGB32 : Image_PixMap::ImgRGB;
+ return (theBitsPerPixel == 32) ? Image_Format_RGB32 : Image_Format_RGB;
}
else
{
- return (theBitsPerPixel == 32) ? Image_PixMap::ImgBGR32 : Image_PixMap::ImgBGR;
+ return (theBitsPerPixel == 32) ? Image_Format_BGR32 : Image_Format_BGR;
}
}
case FIC_RGBALPHA:
{
- return Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
+ return Image_PixMap::IsBigEndianHost() ? Image_Format_RGBA : Image_Format_BGRA;
}
default:
- return Image_PixMap::ImgUNKNOWN;
+ return Image_Format_UNKNOWN;
}
}
default:
- return Image_PixMap::ImgUNKNOWN;
+ return Image_Format_UNKNOWN;
}
}
- static FREE_IMAGE_TYPE convertToFreeFormat (Image_PixMap::ImgFormat theFormat)
+ static FREE_IMAGE_TYPE convertToFreeFormat (Image_Format theFormat)
{
switch (theFormat)
{
- case Image_PixMap::ImgGrayF:
+ case Image_Format_GrayF:
+ case Image_Format_AlphaF:
return FIT_FLOAT;
- case Image_PixMap::ImgRGBAF:
+ case Image_Format_RGBAF:
return FIT_RGBAF;
- case Image_PixMap::ImgRGBF:
+ case Image_Format_RGBF:
return FIT_RGBF;
- case Image_PixMap::ImgRGBA:
- case Image_PixMap::ImgBGRA:
- case Image_PixMap::ImgRGB32:
- case Image_PixMap::ImgBGR32:
- case Image_PixMap::ImgRGB:
- case Image_PixMap::ImgBGR:
- case Image_PixMap::ImgGray:
+ 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;
}
}
-};
-#endif
-IMPLEMENT_STANDARD_HANDLE (Image_AlienPixMap, Image_PixMap)
-IMPLEMENT_STANDARD_RTTIEXT(Image_AlienPixMap, Image_PixMap)
+ //! 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;
+ }
+
+ //! 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 : Image_AlienPixMap
// function : InitWrapper
// purpose :
// =======================================================================
-bool Image_AlienPixMap::InitWrapper (ImgFormat,
+bool Image_AlienPixMap::InitWrapper (Image_Format,
Standard_Byte*,
const Standard_Size,
const Standard_Size,
// purpose :
// =======================================================================
#ifdef HAVE_FREEIMAGE
-bool Image_AlienPixMap::InitTrash (ImgFormat thePixelFormat,
+bool Image_AlienPixMap::InitTrash (Image_Format thePixelFormat,
const Standard_Size theSizeX,
const Standard_Size theSizeY,
const Standard_Size /*theSizeRowBytes*/)
}
FIBITMAP* anImage = FreeImage_AllocateT (aFormatFI, (int )theSizeX, (int )theSizeY, aBitsPerPixel);
- Image_PixMap::ImgFormat aFormat = convertFromFreeFormat (FreeImage_GetImageType (anImage),
- FreeImage_GetColorType (anImage),
- FreeImage_GetBPP (anImage));
- if (thePixelFormat == Image_PixMap::ImgBGR32
- || thePixelFormat == Image_PixMap::ImgRGB32)
+ 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_PixMap::ImgBGRA) ? Image_PixMap::ImgBGR32 : Image_PixMap::ImgRGB32;
+ aFormat = (aFormat == Image_Format_BGRA) ? Image_Format_BGR32 : Image_Format_RGB32;
}
Image_PixMap::InitWrapper (aFormat, FreeImage_GetBits (anImage),
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)
+ {
+ 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 (!Image_PixMap::InitTrash (aFormat, theSizeX, theSizeY, theSizeRowBytes))
+ {
+ return false;
+ }
+ SetTopDown (true);
+ return true;
+}
#else
-bool Image_AlienPixMap::InitTrash (ImgFormat thePixelFormat,
+bool Image_AlienPixMap::InitTrash (Image_Format thePixelFormat,
const Standard_Size theSizeX,
const Standard_Size theSizeY,
const Standard_Size theSizeRowBytes)
#endif
}
+// =======================================================================
+// function : IsTopDownDefault
+// purpose :
+// =======================================================================
+bool Image_AlienPixMap::IsTopDownDefault()
+{
+#ifdef HAVE_FREEIMAGE
+ return false;
+#elif defined(HAVE_WINCODEC)
+ return true;
+#else
+ return false;
+#endif
+}
+
// =======================================================================
// function : Load
// purpose :
// =======================================================================
#ifdef HAVE_FREEIMAGE
-bool Image_AlienPixMap::Load (const TCollection_AsciiString& theImagePath)
+bool Image_AlienPixMap::Load (const Standard_Byte* theData,
+ Standard_Size theLength,
+ const TCollection_AsciiString& theImagePath)
{
Clear();
- FREE_IMAGE_FORMAT aFIF = FreeImage_GetFileType (theImagePath.ToCString(), 0);
+
+#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
}
if ((aFIF == FIF_UNKNOWN) || !FreeImage_FIFSupportsReading (aFIF))
{
- // unsupported image format
+ ::Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error: image '") + theImagePath + "' has unsupported file format.",
+ Message_Fail);
+ if (aFiMem != NULL)
+ {
+ FreeImage_CloseMemory (aFiMem);
+ }
return false;
}
aLoadFlags = ICO_MAKEALPHA;
}
- FIBITMAP* anImage = FreeImage_Load (aFIF, theImagePath.ToCString(), aLoadFlags);
+ 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_PixMap::ImgFormat aFormat = convertFromFreeFormat (FreeImage_GetImageType (anImage),
- FreeImage_GetColorType (anImage),
- FreeImage_GetBPP (anImage));
- if (aFormat == Image_PixMap::ImgUNKNOWN)
+ Image_Format aFormat = Image_Format_UNKNOWN;
+ if (FreeImage_GetBPP (anImage) == 1)
{
- //anImage = FreeImage_ConvertTo24Bits (anImage);
+ FIBITMAP* aTmpImage = FreeImage_ConvertTo8Bits (anImage);
+ FreeImage_Unload (anImage);
+ anImage = aTmpImage;
+ }
+ if (anImage != NULL)
+ {
+ aFormat = convertFromFreeFormat (FreeImage_GetImageType(anImage),
+ FreeImage_GetColorType(anImage),
+ FreeImage_GetBPP (anImage));
+ if (aFormat == Image_Format_UNKNOWN)
+ {
+ FIBITMAP* aTmpImage = FreeImage_ConvertTo24Bits (anImage);
+ FreeImage_Unload (anImage);
+ anImage = aTmpImage;
+ if (anImage != NULL)
+ {
+ aFormat = convertFromFreeFormat (FreeImage_GetImageType(anImage),
+ FreeImage_GetColorType(anImage),
+ FreeImage_GetBPP (anImage));
+ }
+ }
+ }
+ if (aFormat == Image_Format_UNKNOWN)
+ {
+ ::Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error: image '") + theImagePath + "' has unsupported pixel format.",
+ Message_Fail);
return false;
}
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;
+ }
+
+ return Load (&aBuff.ChangeFirst(), aBuff.Size(), theFilePath);
+}
#else
-bool Image_AlienPixMap::Load (const TCollection_AsciiString&)
+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
}
// Open file
- FILE* aFile = fopen (theFileName.ToCString(), "wb");
+ FILE* aFile = OSD_OpenFile (theFileName.ToCString(), "wb");
if (aFile == NULL)
{
return false;
fprintf (aFile, "# Image stored by OpenCASCADE framework in linear RGB colorspace\n");
// Write pixel data
- Quantity_Color aColor;
- Quantity_Parameter aDummy;
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)
- aColor = PixelColor ((Standard_Integer )aCol, (Standard_Integer )aRow, aDummy);
- aByte = Standard_Byte(aColor.Red() * 255.0); fwrite (&aByte, 1, 1, aFile);
- aByte = Standard_Byte(aColor.Green() * 255.0); fwrite (&aByte, 1, 1, aFile);
- aByte = Standard_Byte(aColor.Blue() * 255.0); fwrite (&aByte, 1, 1, aFile);
+ 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);
}
}
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;
}
SetTopDown (false);
}
- // FreeImage doesn't provide flexible format convertion API
- // so we should perform multiple convertions in some cases!
+ // 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_PixMap::ImgBGR32
- || Format() == Image_PixMap::ImgRGB32)
+ 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)
aTmpBitmap = aTmpBitmap24;
}
- // need convertion to image with pallete (requires 24bit bitmap)
+ // need conversion to image with palette (requires 24bit bitmap)
anImageToDump = FreeImage_ColorQuantize (aTmpBitmap, FIQ_NNQUANT);
if (aTmpBitmap != myLibImage)
{
}
break;
}
+ case FIF_HDR:
case FIF_EXR:
{
- if (Format() == Image_PixMap::ImgGray)
+ if (Format() == Image_Format_Gray
+ || Format() == Image_Format_Alpha)
{
anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_FLOAT);
}
- else if (Format() == Image_PixMap::ImgRGBA
- || Format() == Image_PixMap::ImgBGRA)
+ else if (Format() == Image_Format_RGBA
+ || Format() == Image_Format_BGRA)
{
anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBAF);
}
return false;
}
- bool isSaved = (FreeImage_Save (anImageFormat, anImageToDump, theFileName.ToCString()) != 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"))
+ {
+ 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
const Standard_Integer aLen = theFileName.Length();
if ((aLen >= 4) && (theFileName.Value (aLen - 3) == '.')
{
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
}
// function : AdjustGamma
// purpose :
// =======================================================================
-#ifdef HAVE_FREEIMAGE
-Standard_EXPORT bool Image_AlienPixMap::AdjustGamma (const Standard_Real theGammaCorr)
+bool Image_AlienPixMap::AdjustGamma (const Standard_Real theGammaCorr)
{
+#ifdef HAVE_FREEIMAGE
return FreeImage_AdjustGamma (myLibImage, theGammaCorr) != FALSE;
-}
#else
-Standard_EXPORT bool Image_AlienPixMap::AdjustGamma (const Standard_Real)
-{
- return false;
-}
+ (void )theGammaCorr;
+ return false;
#endif
+}