mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-16 10:08:36 +03:00
0031956: Visualization - provide Image_AlienPixMap::Save() writing into a memory buffer instead of a file
Added two new Image_AlienPixMap::Save() overloads, taking std::ostream or memory buffer arguments.
This commit is contained in:
parent
6aa053ae00
commit
b47b7e69f7
@ -135,6 +135,10 @@ namespace
|
|||||||
Image_FreeImageStream (std::istream& theStream)
|
Image_FreeImageStream (std::istream& theStream)
|
||||||
: myIStream (&theStream), myOStream (NULL), myInitPos (theStream.tellg()) {}
|
: myIStream (&theStream), myOStream (NULL), myInitPos (theStream.tellg()) {}
|
||||||
|
|
||||||
|
//! Construct wrapper over output stream.
|
||||||
|
Image_FreeImageStream (std::ostream& theStream)
|
||||||
|
: myIStream (NULL), myOStream (&theStream), myInitPos (theStream.tellp()) {}
|
||||||
|
|
||||||
//! Get io object.
|
//! Get io object.
|
||||||
FreeImageIO GetFiIO() const
|
FreeImageIO GetFiIO() const
|
||||||
{
|
{
|
||||||
@ -143,12 +147,15 @@ namespace
|
|||||||
if (myIStream != NULL)
|
if (myIStream != NULL)
|
||||||
{
|
{
|
||||||
anIo.read_proc = readProc;
|
anIo.read_proc = readProc;
|
||||||
anIo.seek_proc = seekProc;
|
anIo.seek_proc = seekProcIn;
|
||||||
anIo.tell_proc = tellProc;
|
anIo.tell_proc = tellProcIn;
|
||||||
}
|
}
|
||||||
if (myOStream != NULL)
|
if (myOStream != NULL)
|
||||||
{
|
{
|
||||||
anIo.write_proc = writeProc;
|
anIo.write_proc = writeProc;
|
||||||
|
// seek and tell are also used for saving in some formats (.tif for example)
|
||||||
|
anIo.seek_proc = seekProcOut;
|
||||||
|
anIo.tell_proc = tellProcOut;
|
||||||
}
|
}
|
||||||
return anIo;
|
return anIo;
|
||||||
}
|
}
|
||||||
@ -183,7 +190,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Simulate fseek().
|
//! Simulate fseek().
|
||||||
static int DLL_CALLCONV seekProc (fi_handle theHandle, long theOffset, int theOrigin)
|
static int DLL_CALLCONV seekProcIn (fi_handle theHandle, long theOffset, int theOrigin)
|
||||||
{
|
{
|
||||||
Image_FreeImageStream* aThis = (Image_FreeImageStream* )theHandle;
|
Image_FreeImageStream* aThis = (Image_FreeImageStream* )theHandle;
|
||||||
if (aThis->myIStream == NULL)
|
if (aThis->myIStream == NULL)
|
||||||
@ -216,13 +223,53 @@ namespace
|
|||||||
return isSeekDone ? 0 : -1;
|
return isSeekDone ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int DLL_CALLCONV seekProcOut (fi_handle theHandle, long theOffset, int theOrigin)
|
||||||
|
{
|
||||||
|
Image_FreeImageStream* aThis = (Image_FreeImageStream* )theHandle;
|
||||||
|
if (aThis->myOStream == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSeekDone = false;
|
||||||
|
switch (theOrigin)
|
||||||
|
{
|
||||||
|
case SEEK_SET:
|
||||||
|
if (aThis->myOStream->seekp ((std::streamoff )aThis->myInitPos + theOffset, std::ios::beg))
|
||||||
|
{
|
||||||
|
isSeekDone = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SEEK_CUR:
|
||||||
|
if (aThis->myOStream->seekp (theOffset, std::ios::cur))
|
||||||
|
{
|
||||||
|
isSeekDone = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SEEK_END:
|
||||||
|
if (aThis->myOStream->seekp (theOffset, std::ios::end))
|
||||||
|
{
|
||||||
|
isSeekDone = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return isSeekDone ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
//! Simulate ftell().
|
//! Simulate ftell().
|
||||||
static long DLL_CALLCONV tellProc (fi_handle theHandle)
|
static long DLL_CALLCONV tellProcIn (fi_handle theHandle)
|
||||||
{
|
{
|
||||||
Image_FreeImageStream* aThis = (Image_FreeImageStream* )theHandle;
|
Image_FreeImageStream* aThis = (Image_FreeImageStream* )theHandle;
|
||||||
const long aPos = aThis->myIStream != NULL ? (long )(aThis->myIStream->tellg() - aThis->myInitPos) : 0;
|
const long aPos = aThis->myIStream != NULL ? (long )(aThis->myIStream->tellg() - aThis->myInitPos) : 0;
|
||||||
return aPos;
|
return aPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static long DLL_CALLCONV tellProcOut (fi_handle theHandle)
|
||||||
|
{
|
||||||
|
Image_FreeImageStream* aThis = (Image_FreeImageStream* )theHandle;
|
||||||
|
const long aPos = aThis->myOStream != NULL ? (long )(aThis->myOStream->tellp() - aThis->myInitPos) : 0;
|
||||||
|
return aPos;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
std::istream* myIStream;
|
std::istream* myIStream;
|
||||||
std::ostream* myOStream;
|
std::ostream* myOStream;
|
||||||
@ -238,6 +285,37 @@ namespace
|
|||||||
return aGuid;
|
return aGuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Returns GUID of image format from file name
|
||||||
|
static GUID getFileFormatFromName (const TCollection_AsciiString& theFileName)
|
||||||
|
{
|
||||||
|
TCollection_AsciiString aFileNameLower = theFileName;
|
||||||
|
aFileNameLower.LowerCase();
|
||||||
|
GUID aFileFormat = getNullGuid();
|
||||||
|
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")
|
||||||
|
|| aFileNameLower.EndsWith (".tif"))
|
||||||
|
{
|
||||||
|
aFileFormat = GUID_ContainerFormatTiff;
|
||||||
|
}
|
||||||
|
else if (aFileNameLower.EndsWith (".gif"))
|
||||||
|
{
|
||||||
|
aFileFormat = GUID_ContainerFormatGif;
|
||||||
|
}
|
||||||
|
return aFileFormat;
|
||||||
|
}
|
||||||
|
|
||||||
//! Sentry over IUnknown pointer.
|
//! Sentry over IUnknown pointer.
|
||||||
template<class T> class Image_ComPtr
|
template<class T> class Image_ComPtr
|
||||||
{
|
{
|
||||||
@ -346,7 +424,11 @@ namespace
|
|||||||
// purpose :
|
// purpose :
|
||||||
// =======================================================================
|
// =======================================================================
|
||||||
Image_AlienPixMap::Image_AlienPixMap()
|
Image_AlienPixMap::Image_AlienPixMap()
|
||||||
|
#ifdef HAVE_WINCODEC
|
||||||
|
: myPalette (NULL)
|
||||||
|
#else
|
||||||
: myLibImage (NULL)
|
: myLibImage (NULL)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
SetTopDown (false);
|
SetTopDown (false);
|
||||||
}
|
}
|
||||||
@ -505,6 +587,12 @@ void Image_AlienPixMap::Clear()
|
|||||||
FreeImage_Unload (myLibImage);
|
FreeImage_Unload (myLibImage);
|
||||||
myLibImage = NULL;
|
myLibImage = NULL;
|
||||||
}
|
}
|
||||||
|
#elif defined(HAVE_WINCODEC)
|
||||||
|
if (myPalette != NULL)
|
||||||
|
{
|
||||||
|
myPalette->Release();
|
||||||
|
myPalette = NULL;
|
||||||
|
}
|
||||||
#elif defined(__EMSCRIPTEN__)
|
#elif defined(__EMSCRIPTEN__)
|
||||||
if (myLibImage != NULL)
|
if (myLibImage != NULL)
|
||||||
{
|
{
|
||||||
@ -535,7 +623,7 @@ bool Image_AlienPixMap::IsTopDownDefault()
|
|||||||
// =======================================================================
|
// =======================================================================
|
||||||
#ifdef HAVE_FREEIMAGE
|
#ifdef HAVE_FREEIMAGE
|
||||||
bool Image_AlienPixMap::Load (const Standard_Byte* theData,
|
bool Image_AlienPixMap::Load (const Standard_Byte* theData,
|
||||||
Standard_Size theLength,
|
const Standard_Size theLength,
|
||||||
const TCollection_AsciiString& theImagePath)
|
const TCollection_AsciiString& theImagePath)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
@ -705,7 +793,7 @@ bool Image_AlienPixMap::Load (std::istream& theStream,
|
|||||||
|
|
||||||
#elif defined(HAVE_WINCODEC)
|
#elif defined(HAVE_WINCODEC)
|
||||||
bool Image_AlienPixMap::Load (const Standard_Byte* theData,
|
bool Image_AlienPixMap::Load (const Standard_Byte* theData,
|
||||||
Standard_Size theLength,
|
const Standard_Size theLength,
|
||||||
const TCollection_AsciiString& theFileName)
|
const TCollection_AsciiString& theFileName)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
@ -751,7 +839,7 @@ bool Image_AlienPixMap::Load (const Standard_Byte* theData,
|
|||||||
|| aFrameCount < 1
|
|| aFrameCount < 1
|
||||||
|| aWicDecoder->GetFrame (0, &aWicFrameDecode.ChangePtr()) != S_OK
|
|| aWicDecoder->GetFrame (0, &aWicFrameDecode.ChangePtr()) != S_OK
|
||||||
|| aWicFrameDecode->GetSize (&aFrameSizeX, &aFrameSizeY) != S_OK
|
|| aWicFrameDecode->GetSize (&aFrameSizeX, &aFrameSizeY) != S_OK
|
||||||
|| aWicFrameDecode->GetPixelFormat (&aWicPixelFormat))
|
|| aWicFrameDecode->GetPixelFormat (&aWicPixelFormat) != S_OK)
|
||||||
{
|
{
|
||||||
Message::SendFail ("Error: cannot get WIC Image Frame");
|
Message::SendFail ("Error: cannot get WIC Image Frame");
|
||||||
return false;
|
return false;
|
||||||
@ -768,7 +856,6 @@ bool Image_AlienPixMap::Load (const Standard_Byte* theData,
|
|||||||
Message::SendFail ("Error: cannot convert WIC Image Frame to RGB format");
|
Message::SendFail ("Error: cannot convert WIC Image Frame to RGB format");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
aWicFrameDecode.Nullify();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Image_PixMap::InitTrash (aPixelFormat, aFrameSizeX, aFrameSizeY))
|
if (!Image_PixMap::InitTrash (aPixelFormat, aFrameSizeX, aFrameSizeY))
|
||||||
@ -777,17 +864,37 @@ bool Image_AlienPixMap::Load (const Standard_Byte* theData,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TCollection_AsciiString aFileNameLower = theFileName;
|
||||||
|
aFileNameLower.LowerCase();
|
||||||
|
if (aFileNameLower.EndsWith (".gif")
|
||||||
|
&& (aWicImgFactory->CreatePalette (&myPalette) != S_OK
|
||||||
|
|| aWicFrameDecode->CopyPalette (myPalette) != S_OK))
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot get palette for GIF image");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
IWICBitmapSource* aWicSrc = aWicFrameDecode.get();
|
IWICBitmapSource* aWicSrc = aWicFrameDecode.get();
|
||||||
if(!aWicConvertedFrame.IsNull())
|
if(!aWicConvertedFrame.IsNull())
|
||||||
{
|
{
|
||||||
aWicSrc = aWicConvertedFrame.get();
|
aWicSrc = aWicConvertedFrame.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IWICBitmapFlipRotator* aRotator;
|
||||||
|
bool isTopDown = true;
|
||||||
|
if (aWicImgFactory->CreateBitmapFlipRotator (&aRotator) == S_OK
|
||||||
|
&& aRotator->Initialize (aWicSrc, WICBitmapTransformFlipVertical) == S_OK)
|
||||||
|
{
|
||||||
|
isTopDown = false;
|
||||||
|
aWicSrc = aRotator;
|
||||||
|
}
|
||||||
|
|
||||||
if (aWicSrc->CopyPixels (NULL, (UINT )SizeRowBytes(), (UINT )SizeBytes(), ChangeData()) != S_OK)
|
if (aWicSrc->CopyPixels (NULL, (UINT )SizeRowBytes(), (UINT )SizeBytes(), ChangeData()) != S_OK)
|
||||||
{
|
{
|
||||||
Message::SendFail ("Error: cannot copy pixels from WIC Image");
|
Message::SendFail ("Error: cannot copy pixels from WIC Image");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SetTopDown (true);
|
SetTopDown (isTopDown);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool Image_AlienPixMap::Load (std::istream& theStream,
|
bool Image_AlienPixMap::Load (std::istream& theStream,
|
||||||
@ -824,7 +931,7 @@ bool Image_AlienPixMap::Load (std::istream& ,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool Image_AlienPixMap::Load (const Standard_Byte* theData,
|
bool Image_AlienPixMap::Load (const Standard_Byte* theData,
|
||||||
Standard_Size theLength,
|
const Standard_Size theLength,
|
||||||
const TCollection_AsciiString& theImagePath)
|
const TCollection_AsciiString& theImagePath)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
@ -857,7 +964,7 @@ bool Image_AlienPixMap::Load (std::istream& ,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool Image_AlienPixMap::Load (const Standard_Byte* ,
|
bool Image_AlienPixMap::Load (const Standard_Byte* ,
|
||||||
Standard_Size ,
|
const Standard_Size ,
|
||||||
const TCollection_AsciiString& )
|
const TCollection_AsciiString& )
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
@ -907,11 +1014,52 @@ bool Image_AlienPixMap::savePPM (const TCollection_AsciiString& theFileName) con
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : convertData
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
#ifdef HAVE_WINCODEC
|
||||||
|
static bool convertData (const Image_AlienPixMap& theSrcPixMapData,
|
||||||
|
const WICPixelFormatGUID& theFormat,
|
||||||
|
IWICImagingFactory& theWicImgFactory,
|
||||||
|
Image_PixMapData& theDstPixMapData)
|
||||||
|
{
|
||||||
|
const UINT aSizeRowBytes = (UINT)theSrcPixMapData.SizeRowBytes();
|
||||||
|
const UINT aSizeBytes = (UINT)theSrcPixMapData.SizeBytes();
|
||||||
|
|
||||||
|
Image_ComPtr<IWICBitmap> anSrcImg;
|
||||||
|
Image_ComPtr<IWICFormatConverter> aWicFormatConverter;
|
||||||
|
HRESULT anHResult = theWicImgFactory.CreateBitmapFromMemory ((UINT)theSrcPixMapData.SizeX(), (UINT)theSrcPixMapData.SizeY(),
|
||||||
|
convertToWicFormat (theSrcPixMapData.Format()),
|
||||||
|
aSizeRowBytes, aSizeBytes,
|
||||||
|
(BYTE*)theSrcPixMapData.Data(), &anSrcImg.ChangePtr());
|
||||||
|
if (anHResult != S_OK
|
||||||
|
|| theWicImgFactory.CreateFormatConverter (&aWicFormatConverter.ChangePtr()) != S_OK
|
||||||
|
|| aWicFormatConverter->Initialize (anSrcImg.get(), theFormat, WICBitmapDitherTypeNone, theSrcPixMapData.GetPalette(), 0.0f, WICBitmapPaletteTypeCustom) != S_OK)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot convert WIC Image Frame to required format");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
theDstPixMapData.Init (Image_PixMap::DefaultAllocator(), 1, theSrcPixMapData.SizeXYZ(), aSizeRowBytes, NULL);
|
||||||
|
|
||||||
|
if (aWicFormatConverter->CopyPixels (NULL, aSizeRowBytes, aSizeBytes, theDstPixMapData.ChangeData()) != S_OK)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot copy pixels from WIC Image");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// =======================================================================
|
// =======================================================================
|
||||||
// function : Save
|
// function : Save
|
||||||
// purpose :
|
// purpose :
|
||||||
// =======================================================================
|
// =======================================================================
|
||||||
bool Image_AlienPixMap::Save (const TCollection_AsciiString& theFileName)
|
bool Image_AlienPixMap::Save (Standard_Byte* theBuffer,
|
||||||
|
const Standard_Size theLength,
|
||||||
|
const TCollection_AsciiString& theFileName)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_FREEIMAGE
|
#ifdef HAVE_FREEIMAGE
|
||||||
if (myLibImage == NULL)
|
if (myLibImage == NULL)
|
||||||
@ -939,10 +1087,399 @@ bool Image_AlienPixMap::Save (const TCollection_AsciiString& theFileName)
|
|||||||
SetTopDown (false);
|
SetTopDown (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FIBITMAP* anImageToDump = getImageToDump (anImageFormat);
|
||||||
|
|
||||||
|
if (anImageToDump == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSaved = false;
|
||||||
|
if (theBuffer != NULL)
|
||||||
|
{
|
||||||
|
// a memory buffer wrapped by FreeImage is read only (images can be loaded but not be saved)
|
||||||
|
// so we call FreeImage_OpenMemory() with default arguments and just memcpy in requsted buffer.
|
||||||
|
FIMEMORY* aFiMem = FreeImage_OpenMemory();
|
||||||
|
isSaved = (FreeImage_SaveToMemory (anImageFormat, anImageToDump, aFiMem) != FALSE);
|
||||||
|
BYTE* aData = NULL;
|
||||||
|
DWORD aSize;
|
||||||
|
FreeImage_AcquireMemory (aFiMem, &aData, &aSize);
|
||||||
|
if (aSize > theLength)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: memory buffer too small for storing image");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy (theBuffer, aData, aSize);
|
||||||
|
FreeImage_CloseMemory (aFiMem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
isSaved = (FreeImage_SaveU (anImageFormat, anImageToDump, aFileNameW.ToWideString ()) != FALSE);
|
||||||
|
#else
|
||||||
|
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();
|
||||||
|
if (aFileNameLower.EndsWith (".ppm"))
|
||||||
|
{
|
||||||
|
return savePPM (theFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
GUID aFileFormat = getFileFormatFromName (theFileName);
|
||||||
|
if (aFileFormat == getNullGuid())
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: unsupported image format");
|
||||||
|
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::SendFail ("Error: cannot initialize WIC Imaging Factory");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WICPixelFormatGUID aWicPixelFormat = convertToWicFormat (myImgFormat);
|
||||||
|
if (aWicPixelFormat == getNullGuid())
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: unsupported pixel format");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image_PixMapData* aPixMapData = &myData;
|
||||||
|
Image_PixMapData aConvertedData;
|
||||||
|
if (aFileFormat == GUID_ContainerFormatGif)
|
||||||
|
{
|
||||||
|
aWicPixelFormat = GUID_WICPixelFormat8bppIndexed;
|
||||||
|
convertData (*this, aWicPixelFormat, *aWicImgFactory, aConvertedData);
|
||||||
|
aPixMapData = &aConvertedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image_ComPtr<IWICStream> aWicStream;
|
||||||
|
Image_ComPtr<IWICBitmapEncoder> aWicEncoder;
|
||||||
|
const TCollection_ExtendedString aFileNameW (theFileName);
|
||||||
|
if (theBuffer != NULL)
|
||||||
|
{
|
||||||
|
if (aWicImgFactory->CreateStream (&aWicStream.ChangePtr()) != S_OK
|
||||||
|
|| aWicStream->InitializeFromMemory (theBuffer,(DWORD )theLength) != S_OK)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot create WIC Memory Stream");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (aWicImgFactory->CreateStream (&aWicStream.ChangePtr()) != S_OK
|
||||||
|
|| aWicStream->InitializeFromFilename (aFileNameW.ToWideString(), GENERIC_WRITE) != S_OK)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot create WIC File Stream");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (aWicImgFactory->CreateEncoder (aFileFormat, NULL, &aWicEncoder.ChangePtr()) != S_OK
|
||||||
|
|| aWicEncoder->Initialize (aWicStream.get(), WICBitmapEncoderNoCache) != S_OK)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot create WIC Encoder");
|
||||||
|
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::SendFail ("Error: cannot create WIC Frame");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aFileFormat == GUID_ContainerFormatGif
|
||||||
|
&& (myPalette == NULL
|
||||||
|
|| aWicFrameEncode->SetPalette (myPalette) != S_OK))
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot set palette");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aWicPixelFormatRes != aWicPixelFormat)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: pixel format is unsupported by image format");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsTopDown())
|
||||||
|
{
|
||||||
|
if (aWicFrameEncode->WritePixels ((UINT )SizeY(), (UINT )SizeRowBytes(), (UINT )SizeBytes(), (BYTE* )aPixMapData->Data()) != S_OK)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot write pixels to WIC Frame");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
|
||||||
|
{
|
||||||
|
if (aWicFrameEncode->WritePixels (1, (UINT )SizeRowBytes(), (UINT )SizeRowBytes(), (BYTE* )aPixMapData->Row (aRow)) != S_OK)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot write pixels to WIC Frame");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (aWicFrameEncode->Commit() != S_OK
|
||||||
|
|| aWicEncoder->Commit() != S_OK)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot commit data to WIC Frame");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (aWicStream->Commit (STGC_DEFAULT) != S_OK)
|
||||||
|
{
|
||||||
|
//Message::Send ("Error: cannot commit data to WIC File Stream", Message_Fail);
|
||||||
|
//return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
if (theBuffer != NULL)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: no image library available");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const Standard_Integer aLen = theFileName.Length();
|
||||||
|
if ((aLen >= 4) && (theFileName.Value (aLen - 3) == '.')
|
||||||
|
&& strcasecmp( theFileName.ToCString() + aLen - 3, "ppm") == 0 )
|
||||||
|
{
|
||||||
|
return savePPM (theFileName);
|
||||||
|
}
|
||||||
|
Message::SendTrace ("Image_PixMap, no image library available! Image saved in PPM format");
|
||||||
|
return savePPM (theFileName);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Image_AlienPixMap::Save (std::ostream& theStream, const TCollection_AsciiString& theExtension)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_FREEIMAGE
|
||||||
|
if (myLibImage == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
const TCollection_ExtendedString anExtW (theExtension.ToCString(), Standard_True);
|
||||||
|
FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilenameU (anExtW.ToWideString());
|
||||||
|
#else
|
||||||
|
FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilename (theExtension.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
FIBITMAP* anImageToDump = getImageToDump (anImageFormat);
|
||||||
|
|
||||||
|
if (anImageToDump == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSaved = false;
|
||||||
|
Image_FreeImageStream aStream (theStream);
|
||||||
|
FreeImageIO anIO = aStream.GetFiIO();
|
||||||
|
|
||||||
|
isSaved = (FreeImage_SaveToHandle(anImageFormat, anImageToDump, &anIO, &aStream) != FALSE);
|
||||||
|
|
||||||
|
if (anImageToDump != myLibImage)
|
||||||
|
{
|
||||||
|
FreeImage_Unload (anImageToDump);
|
||||||
|
}
|
||||||
|
return isSaved;
|
||||||
|
#elif defined(HAVE_WINCODEC)
|
||||||
|
GUID aFileFormat = getFileFormatFromName (theExtension);
|
||||||
|
if (aFileFormat == getNullGuid())
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: unsupported image format");
|
||||||
|
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::SendFail ("Error: cannot initialize WIC Imaging Factory");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WICPixelFormatGUID aWicPixelFormat = convertToWicFormat (myImgFormat);
|
||||||
|
if (aWicPixelFormat == getNullGuid())
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: unsupported pixel format");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image_PixMapData* aPixMapData = &myData;
|
||||||
|
Image_PixMapData aConvertedData;
|
||||||
|
if (aFileFormat == GUID_ContainerFormatGif)
|
||||||
|
{
|
||||||
|
aWicPixelFormat = GUID_WICPixelFormat8bppIndexed;
|
||||||
|
convertData (*this, aWicPixelFormat, *aWicImgFactory, aConvertedData);
|
||||||
|
aPixMapData = &aConvertedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
Image_ComPtr<IStream> aStream;
|
||||||
|
Image_ComPtr<IWICBitmapEncoder> aWicEncoder;
|
||||||
|
|
||||||
|
if (CreateStreamOnHGlobal (NULL, Standard_True, &aStream.ChangePtr()) != S_OK)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot create Stream on global");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aWicImgFactory->CreateEncoder (aFileFormat, NULL, &aWicEncoder.ChangePtr()) != S_OK
|
||||||
|
|| aWicEncoder->Initialize (aStream.get(), WICBitmapEncoderNoCache) != S_OK)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot create WIC Encoder");
|
||||||
|
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::SendFail ("Error: cannot create WIC Frame");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aFileFormat == GUID_ContainerFormatGif
|
||||||
|
&& (myPalette == NULL
|
||||||
|
|| aWicFrameEncode->SetPalette (myPalette) != S_OK))
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot set palette");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aWicPixelFormatRes != aWicPixelFormat)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: pixel format is unsupported by image format");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsTopDown())
|
||||||
|
{
|
||||||
|
if (aWicFrameEncode->WritePixels ((UINT )SizeY(), (UINT )SizeRowBytes(), (UINT )SizeBytes(), (BYTE* )aPixMapData->Data()) != S_OK)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot write pixels to WIC Frame");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
|
||||||
|
{
|
||||||
|
if (aWicFrameEncode->WritePixels (1, (UINT )SizeRowBytes(), (UINT )SizeRowBytes(), (BYTE* )aPixMapData->Row (aRow)) != S_OK)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot write pixels to WIC Frame");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (aWicFrameEncode->Commit() != S_OK
|
||||||
|
|| aWicEncoder->Commit() != S_OK)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot commit data to WIC Frame");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (aStream->Commit (STGC_DEFAULT) != S_OK)
|
||||||
|
{
|
||||||
|
//Message::Send ("Error: cannot commit data to Stream", Message_Fail);
|
||||||
|
//return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WIC doesn't have the way to encode image directly in std::ostream
|
||||||
|
// so we use a workaround to transfer data from IStream to std::ostream
|
||||||
|
STATSTG aStat;
|
||||||
|
if (aStream->Stat (&aStat, STATFLAG_NONAME) != S_OK)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot get stat from stream");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
HGLOBAL aMem;
|
||||||
|
if (GetHGlobalFromStream (aStream.get(), &aMem) != S_OK)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot get global from stream");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPVOID aData = GlobalLock (aMem);
|
||||||
|
if (aData == NULL)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot lock global");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!theStream.write ((const char* )aData, aStat.cbSize.QuadPart))
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot write data to ostream");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (GlobalUnlock (aMem) == 0 && GetLastError() != NO_ERROR)
|
||||||
|
{
|
||||||
|
Message::SendFail ("Error: cannot unlock global");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
Message::SendFail ("Error: no image library available");
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// =======================================================================
|
||||||
|
// function : AdjustGamma
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
bool Image_AlienPixMap::AdjustGamma (const Standard_Real theGammaCorr)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_FREEIMAGE
|
||||||
|
return FreeImage_AdjustGamma (myLibImage, theGammaCorr) != FALSE;
|
||||||
|
#else
|
||||||
|
(void )theGammaCorr;
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_FREEIMAGE
|
||||||
|
// =======================================================================
|
||||||
|
// function : GetImageToDump
|
||||||
|
// purpose :
|
||||||
|
// =======================================================================
|
||||||
|
FIBITMAP* Image_AlienPixMap::getImageToDump (const Standard_Integer theFormat)
|
||||||
|
{
|
||||||
|
FIBITMAP* anImageToDump = myLibImage;
|
||||||
// FreeImage doesn't provide flexible format conversion API
|
// FreeImage doesn't provide flexible format conversion API
|
||||||
// so we should perform multiple conversions in some cases!
|
// so we should perform multiple conversions in some cases!
|
||||||
FIBITMAP* anImageToDump = myLibImage;
|
switch (theFormat)
|
||||||
switch (anImageFormat)
|
|
||||||
{
|
{
|
||||||
case FIF_PNG:
|
case FIF_PNG:
|
||||||
case FIF_BMP:
|
case FIF_BMP:
|
||||||
@ -973,7 +1510,7 @@ bool Image_AlienPixMap::Save (const TCollection_AsciiString& theFileName)
|
|||||||
aTmpBitmap = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
|
aTmpBitmap = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
|
||||||
if (aTmpBitmap == NULL)
|
if (aTmpBitmap == NULL)
|
||||||
{
|
{
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -986,7 +1523,7 @@ bool Image_AlienPixMap::Save (const TCollection_AsciiString& theFileName)
|
|||||||
}
|
}
|
||||||
if (aTmpBitmap24 == NULL)
|
if (aTmpBitmap24 == NULL)
|
||||||
{
|
{
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
aTmpBitmap = aTmpBitmap24;
|
aTmpBitmap = aTmpBitmap24;
|
||||||
}
|
}
|
||||||
@ -1031,7 +1568,7 @@ bool Image_AlienPixMap::Save (const TCollection_AsciiString& theFileName)
|
|||||||
anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
|
anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
|
||||||
if (anImageToDump == NULL)
|
if (anImageToDump == NULL)
|
||||||
{
|
{
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1044,170 +1581,13 @@ bool Image_AlienPixMap::Save (const TCollection_AsciiString& theFileName)
|
|||||||
}
|
}
|
||||||
if (aTmpBitmap24 == NULL)
|
if (aTmpBitmap24 == NULL)
|
||||||
{
|
{
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
anImageToDump = aTmpBitmap24;
|
anImageToDump = aTmpBitmap24;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return anImageToDump;
|
||||||
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
|
#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")
|
|
||||||
|| aFileNameLower.EndsWith (".tif"))
|
|
||||||
{
|
|
||||||
aFileFormat = GUID_ContainerFormatTiff;
|
|
||||||
}
|
|
||||||
else if (aFileNameLower.EndsWith (".gif"))
|
|
||||||
{
|
|
||||||
aFileFormat = GUID_ContainerFormatGif;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aFileFormat == getNullGuid())
|
|
||||||
{
|
|
||||||
Message::SendFail ("Error: unsupported image format");
|
|
||||||
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::SendFail ("Error: cannot initialize WIC Imaging Factory");
|
|
||||||
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::SendFail ("Error: cannot create WIC File Stream");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (aWicImgFactory->CreateEncoder (aFileFormat, NULL, &aWicEncoder.ChangePtr()) != S_OK
|
|
||||||
|| aWicEncoder->Initialize (aWicFileStream.get(), WICBitmapEncoderNoCache) != S_OK)
|
|
||||||
{
|
|
||||||
Message::SendFail ("Error: cannot create WIC Encoder");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const WICPixelFormatGUID aWicPixelFormat = convertToWicFormat (myImgFormat);
|
|
||||||
if (aWicPixelFormat == getNullGuid())
|
|
||||||
{
|
|
||||||
Message::SendFail ("Error: unsupported pixel format");
|
|
||||||
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::SendFail ("Error: cannot create WIC Frame");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aWicPixelFormatRes != aWicPixelFormat)
|
|
||||||
{
|
|
||||||
Message::SendFail ("Error: pixel format is unsupported by image format");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsTopDown())
|
|
||||||
{
|
|
||||||
if (aWicFrameEncode->WritePixels ((UINT )SizeY(), (UINT )SizeRowBytes(), (UINT )SizeBytes(), (BYTE* )Data()) != S_OK)
|
|
||||||
{
|
|
||||||
Message::SendFail ("Error: cannot write pixels to WIC Frame");
|
|
||||||
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::SendFail ("Error: cannot write pixels to WIC Frame");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aWicFrameEncode->Commit() != S_OK
|
|
||||||
|| aWicEncoder->Commit() != S_OK)
|
|
||||||
{
|
|
||||||
Message::SendFail ("Error: cannot commit data to WIC Frame");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (aWicFileStream->Commit (STGC_DEFAULT) != S_OK)
|
|
||||||
{
|
|
||||||
//Message::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);
|
|
||||||
}
|
|
||||||
Message::SendTrace ("Image_PixMap, no image library available! Image saved in PPM format");
|
|
||||||
return savePPM (theFileName);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// =======================================================================
|
|
||||||
// function : AdjustGamma
|
|
||||||
// purpose :
|
|
||||||
// =======================================================================
|
|
||||||
bool Image_AlienPixMap::AdjustGamma (const Standard_Real theGammaCorr)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_FREEIMAGE
|
|
||||||
return FreeImage_AdjustGamma (myLibImage, theGammaCorr) != FALSE;
|
|
||||||
#else
|
|
||||||
(void )theGammaCorr;
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include <Image_PixMap.hxx>
|
#include <Image_PixMap.hxx>
|
||||||
|
|
||||||
class TCollection_AsciiString;
|
class TCollection_AsciiString;
|
||||||
|
struct IWICPalette;
|
||||||
struct FIBITMAP;
|
struct FIBITMAP;
|
||||||
|
|
||||||
//! Image class that support file reading/writing operations using auxiliary image library.
|
//! Image class that support file reading/writing operations using auxiliary image library.
|
||||||
@ -57,21 +58,41 @@ public:
|
|||||||
const TCollection_AsciiString& theFileName);
|
const TCollection_AsciiString& theFileName);
|
||||||
|
|
||||||
//! Read image data from memory buffer.
|
//! Read image data from memory buffer.
|
||||||
//! @param theData memory pointer to read from;
|
//! @param[in] theData memory pointer to read from;
|
||||||
//! when NULL, function will attempt to open theFileName file
|
//! when NULL, function will attempt to open theFileName file
|
||||||
//! @param theLength memory buffer length
|
//! @param[in] theLength memory buffer length
|
||||||
//! @param theFileName optional file name
|
//! @param[in] theFileName optional file name
|
||||||
Standard_EXPORT bool Load (const Standard_Byte* theData,
|
Standard_EXPORT bool Load (const Standard_Byte* theData,
|
||||||
Standard_Size theLength,
|
const Standard_Size theLength,
|
||||||
const TCollection_AsciiString& theFileName);
|
const TCollection_AsciiString& theFileName);
|
||||||
|
|
||||||
//! Write image data to file using file extension to determine compression format.
|
//! Write image data to file.
|
||||||
Standard_EXPORT bool Save (const TCollection_AsciiString& theFileName);
|
//! @param[in] theFileName file name to save
|
||||||
|
bool Save (const TCollection_AsciiString& theFileName)
|
||||||
|
{
|
||||||
|
return Save (NULL, 0, theFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Write image data to stream.
|
||||||
|
//! @param[out] theStream stream where to write
|
||||||
|
//! @param[in] theExtension image format
|
||||||
|
Standard_EXPORT bool Save (std::ostream& theStream,
|
||||||
|
const TCollection_AsciiString& theExtension);
|
||||||
|
|
||||||
|
//! Write image data to file or memory buffer using file extension to determine format.
|
||||||
|
//! @param[out] theBuffer buffer pointer where to write
|
||||||
|
//! when NULL, function write image data to theFileName file
|
||||||
|
//! @param[in] theLength memory buffer length
|
||||||
|
//! @param[in] theFileName file name to save;
|
||||||
|
//! when theBuffer isn't NULL used only to determine format
|
||||||
|
Standard_EXPORT bool Save (Standard_Byte* theBuffer,
|
||||||
|
const Standard_Size theLength,
|
||||||
|
const TCollection_AsciiString& theFileName);
|
||||||
|
|
||||||
//! Initialize image plane with required dimensions.
|
//! Initialize image plane with required dimensions.
|
||||||
//! thePixelFormat - if specified pixel format doesn't supported by image library
|
//! @param[in] thePixelFormat if specified pixel format doesn't supported by image library
|
||||||
//! than nearest supported will be used instead!
|
//! than nearest supported will be used instead!
|
||||||
//! theSizeRowBytes - may be ignored by this class and required alignment will be used instead!
|
//! @param[in] theSizeRowBytes may be ignored by this class and required alignment will be used instead!
|
||||||
Standard_EXPORT virtual bool InitTrash (Image_Format thePixelFormat,
|
Standard_EXPORT virtual bool InitTrash (Image_Format thePixelFormat,
|
||||||
const Standard_Size theSizeX,
|
const Standard_Size theSizeX,
|
||||||
const Standard_Size theSizeY,
|
const Standard_Size theSizeY,
|
||||||
@ -84,12 +105,13 @@ public:
|
|||||||
Standard_EXPORT virtual void Clear() Standard_OVERRIDE;
|
Standard_EXPORT virtual void Clear() Standard_OVERRIDE;
|
||||||
|
|
||||||
//! Performs gamma correction on image.
|
//! Performs gamma correction on image.
|
||||||
//! theGamma - gamma value to use; a value of 1.0 leaves the image alone
|
//! @param[in] theGamma - gamma value to use; a value of 1.0 leaves the image alone
|
||||||
Standard_EXPORT bool AdjustGamma (const Standard_Real theGammaCorr);
|
Standard_EXPORT bool AdjustGamma (const Standard_Real theGammaCorr);
|
||||||
|
|
||||||
private:
|
#if !defined(HAVE_FREEIMAGE) && defined(_WIN32)
|
||||||
|
//! Returns image palette.
|
||||||
FIBITMAP* myLibImage;
|
IWICPalette* GetPalette() const { return myPalette; }
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -108,6 +130,13 @@ private:
|
|||||||
//! Built-in PPM export
|
//! Built-in PPM export
|
||||||
Standard_EXPORT bool savePPM (const TCollection_AsciiString& theFileName) const;
|
Standard_EXPORT bool savePPM (const TCollection_AsciiString& theFileName) const;
|
||||||
|
|
||||||
|
FIBITMAP* getImageToDump (const Standard_Integer theFormat);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
FIBITMAP* myLibImage;
|
||||||
|
IWICPalette* myPalette;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_STANDARD_HANDLE(Image_AlienPixMap, Image_PixMap)
|
DEFINE_STANDARD_HANDLE(Image_AlienPixMap, Image_PixMap)
|
||||||
|
@ -387,11 +387,11 @@ static Standard_Integer OCC361bug (Draw_Interpretor& di, Standard_Integer nb, co
|
|||||||
//function : OCC30182
|
//function : OCC30182
|
||||||
//purpose : Testing different interfaces of Image_AlienPixMap::Load()
|
//purpose : Testing different interfaces of Image_AlienPixMap::Load()
|
||||||
//=======================================================================
|
//=======================================================================
|
||||||
static Standard_Integer OCC30182 (Draw_Interpretor& , Standard_Integer theNbArgs, const char** theArgVec)
|
static Standard_Integer OCC30182 (Draw_Interpretor& di, Standard_Integer theNbArgs, const char** theArgVec)
|
||||||
{
|
{
|
||||||
if (ViewerTest::CurrentView().IsNull())
|
if (ViewerTest::CurrentView().IsNull())
|
||||||
{
|
{
|
||||||
std::cout << "Error: no active view\n";
|
di << "Error: no active view\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,13 +430,13 @@ static Standard_Integer OCC30182 (Draw_Interpretor& , Standard_Integer theNbArgs
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "Syntax error at '" << anArg << "'\n";
|
di << "Syntax error at '" << anArg << "'\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (anImgPath.IsEmpty())
|
if (anImgPath.IsEmpty())
|
||||||
{
|
{
|
||||||
std::cout << "Syntax error: wrong number of arguments\n";
|
di << "Syntax error: wrong number of arguments\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -454,7 +454,7 @@ static Standard_Integer OCC30182 (Draw_Interpretor& , Standard_Integer theNbArgs
|
|||||||
std::shared_ptr<std::istream> aFile = aFileSystem->OpenIStream (anImgPath, std::ios::in | std::ios::binary);
|
std::shared_ptr<std::istream> aFile = aFileSystem->OpenIStream (anImgPath, std::ios::in | std::ios::binary);
|
||||||
if (aFile.get() == NULL)
|
if (aFile.get() == NULL)
|
||||||
{
|
{
|
||||||
std::cout << "Syntax error: image file '" << anImgPath << "' cannot be found\n";
|
di << "Syntax error: image file '" << anImgPath << "' cannot be found\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (anOffset != 0)
|
if (anOffset != 0)
|
||||||
@ -469,13 +469,13 @@ static Standard_Integer OCC30182 (Draw_Interpretor& , Standard_Integer theNbArgs
|
|||||||
aFile->seekg (anOffset);
|
aFile->seekg (anOffset);
|
||||||
if (aLen <= 0)
|
if (aLen <= 0)
|
||||||
{
|
{
|
||||||
std::cout << "Syntax error: wrong offset\n";
|
di << "Syntax error: wrong offset\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
NCollection_Array1<Standard_Byte> aBuff (1, aLen);
|
NCollection_Array1<Standard_Byte> aBuff (1, aLen);
|
||||||
if (!aFile->read ((char* )&aBuff.ChangeFirst(), aBuff.Size()))
|
if (!aFile->read ((char* )&aBuff.ChangeFirst(), aBuff.Size()))
|
||||||
{
|
{
|
||||||
std::cout << "Error: unable to read file\n";
|
di << "Error: unable to read file\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (!anImage->Load (&aBuff.ChangeFirst(), aBuff.Size(), anImgPath))
|
if (!anImage->Load (&aBuff.ChangeFirst(), aBuff.Size(), anImgPath))
|
||||||
@ -510,6 +510,107 @@ static Standard_Integer OCC30182 (Draw_Interpretor& , Standard_Integer theNbArgs
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=======================================================================
|
||||||
|
//function : OCC31956
|
||||||
|
//purpose : Testing Image_AlienPixMap::Save() overload for saving into a memory buffer or stream
|
||||||
|
//=======================================================================
|
||||||
|
static Standard_Integer OCC31956 (Draw_Interpretor& di, Standard_Integer theNbArgs, const char** theArgVec)
|
||||||
|
{
|
||||||
|
if (ViewerTest::CurrentView().IsNull())
|
||||||
|
{
|
||||||
|
di << "Error: no active view\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (theNbArgs != 3 && theNbArgs != 5)
|
||||||
|
{
|
||||||
|
di << "Syntax error: wrong number of arguments\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool useStream = false;
|
||||||
|
TCollection_AsciiString aTempImgPath;
|
||||||
|
if (theNbArgs == 5)
|
||||||
|
{
|
||||||
|
TCollection_AsciiString anArg (theArgVec[3]);
|
||||||
|
anArg.LowerCase();
|
||||||
|
if (anArg == "-stream")
|
||||||
|
{
|
||||||
|
useStream = true;
|
||||||
|
aTempImgPath = theArgVec[4];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
di << "Syntax error at '" << anArg << "'\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TCollection_AsciiString aPrsName, anImgPath;
|
||||||
|
aPrsName = theArgVec[1];
|
||||||
|
anImgPath = theArgVec[2];
|
||||||
|
Handle(Image_AlienPixMap) anImage = new Image_AlienPixMap();
|
||||||
|
const Handle(OSD_FileSystem)& aFileSystem = OSD_FileSystem::DefaultFileSystem();
|
||||||
|
opencascade::std::shared_ptr<std::istream> aFile = aFileSystem->OpenIStream (anImgPath, std::ios::in | std::ios::binary);
|
||||||
|
if (aFile.get() == NULL)
|
||||||
|
{
|
||||||
|
di << "Syntax error: image file '" << anImgPath << "' cannot be found\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
aFile->seekg (0, std::ios::end);
|
||||||
|
Standard_Integer aLen = (Standard_Integer )aFile->tellg();
|
||||||
|
aFile->seekg (0);
|
||||||
|
if (!anImage->Load (*aFile, anImgPath))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle(Image_AlienPixMap) aControlImg = new Image_AlienPixMap();
|
||||||
|
if (useStream)
|
||||||
|
{
|
||||||
|
opencascade::std::shared_ptr<std::ostream> aTempFile = aFileSystem->OpenOStream (aTempImgPath, std::ios::out | std::ios::binary);
|
||||||
|
if (aTempFile.get() == NULL)
|
||||||
|
{
|
||||||
|
di << "Error: image file '" << aTempImgPath << "' cannot be open\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!anImage->Save (*aTempFile, aTempImgPath))
|
||||||
|
{
|
||||||
|
di << "Error: failed saving file using stream '" << aTempImgPath << "'\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
aTempFile.reset();
|
||||||
|
aControlImg->Load (aTempImgPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NCollection_Array1<Standard_Byte> aBuff (1, aLen + 2048);
|
||||||
|
if (!anImage->Save (&aBuff.ChangeFirst(), aBuff.Size(), anImgPath))
|
||||||
|
{
|
||||||
|
di << "Error: failed saving file using buffer'" << anImgPath << "'\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
aControlImg->Load (&aBuff.ChangeFirst(), aBuff.Size(), anImgPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
TopoDS_Shape aShape = BRepPrimAPI_MakeBox (100.0 * aControlImg->Ratio(), 100.0, 1.0).Shape();
|
||||||
|
Handle(AIS_Shape) aPrs = new AIS_Shape (aShape);
|
||||||
|
aPrs->SetDisplayMode (AIS_Shaded);
|
||||||
|
aPrs->Attributes()->SetupOwnShadingAspect();
|
||||||
|
const Handle(Graphic3d_AspectFillArea3d)& anAspect = aPrs->Attributes()->ShadingAspect()->Aspect();
|
||||||
|
anAspect->SetShadingModel (Graphic3d_TOSM_UNLIT);
|
||||||
|
anAspect->SetTextureMapOn (true);
|
||||||
|
anAspect->SetTextureMap (new Graphic3d_Texture2D(aControlImg));
|
||||||
|
if (aControlImg->IsTopDown())
|
||||||
|
{
|
||||||
|
anAspect->TextureMap()->GetParams()->SetTranslation (Graphic3d_Vec2 (0.0f, -1.0f));
|
||||||
|
anAspect->TextureMap()->GetParams()->SetScale (Graphic3d_Vec2 (1.0f, -1.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewerTest::Display (aPrsName, aPrs, true, true);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void QABugs::Commands_1(Draw_Interpretor& theCommands) {
|
void QABugs::Commands_1(Draw_Interpretor& theCommands) {
|
||||||
const char *group = "QABugs";
|
const char *group = "QABugs";
|
||||||
|
|
||||||
@ -527,5 +628,7 @@ void QABugs::Commands_1(Draw_Interpretor& theCommands) {
|
|||||||
theCommands.Add ("OCC30182",
|
theCommands.Add ("OCC30182",
|
||||||
"OCC30182 name image [-offset Start] [-fileName] [-stream] [-memory]\n"
|
"OCC30182 name image [-offset Start] [-fileName] [-stream] [-memory]\n"
|
||||||
"Decodes image either by passing file name, file stream or memory stream", __FILE__, OCC30182, group);
|
"Decodes image either by passing file name, file stream or memory stream", __FILE__, OCC30182, group);
|
||||||
|
theCommands.Add ("OCC31956", "OCC31956 name image [-stream tempImage]\n"
|
||||||
|
"Loads image and saves it into memory buffer or stream then loads it back", __FILE__, OCC31956, group);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
41
tests/v3d/bugs/bug31956
Normal file
41
tests/v3d/bugs/bug31956
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
puts "============"
|
||||||
|
puts "0031956: Visualization - provide Image_AlienPixMap::Save() writing into a memory buffer instead of a file"
|
||||||
|
puts "============"
|
||||||
|
puts ""
|
||||||
|
|
||||||
|
set anImg1 [locate_data_file chataignier.gif]
|
||||||
|
set anImg2 [locate_data_file hatch_1.png]
|
||||||
|
|
||||||
|
pload VISUALIZATION QAcommands
|
||||||
|
vclear
|
||||||
|
vinit View1
|
||||||
|
vtop
|
||||||
|
|
||||||
|
OCC30182 t $anImg1 -fileName; vfit
|
||||||
|
vdump $imagedir/${casename}_1.png
|
||||||
|
|
||||||
|
OCC30182 t $anImg2 -fileName; vfit
|
||||||
|
vdump $imagedir/${casename}_2.png
|
||||||
|
|
||||||
|
vclear
|
||||||
|
|
||||||
|
OCC31956 t $anImg1; vfit
|
||||||
|
vdump $imagedir/${casename}_test_1.png
|
||||||
|
|
||||||
|
OCC31956 t $anImg2; vfit
|
||||||
|
vdump $imagedir/${casename}_test_2.png
|
||||||
|
|
||||||
|
vclear
|
||||||
|
|
||||||
|
OCC31956 t $anImg1 -stream $imagedir/${casename}_temp_1.gif; vfit
|
||||||
|
vdump $imagedir/${casename}_test_1s.png
|
||||||
|
|
||||||
|
OCC31956 t $anImg2 -stream $imagedir/${casename}_temp_2.png; vfit
|
||||||
|
vdump $imagedir/${casename}_test_2s.png
|
||||||
|
|
||||||
|
if { [diffimage $imagedir/${casename}_test_1.png $imagedir/${casename}_1.png -toleranceOfColor 0.1] != 0 } { puts "Error difference in 1st image" }
|
||||||
|
if { [diffimage $imagedir/${casename}_test_2.png $imagedir/${casename}_2.png -toleranceOfColor 0.1] != 0 } { puts "Error difference in 2nd image" }
|
||||||
|
|
||||||
|
if { [diffimage $imagedir/${casename}_test_1s.png $imagedir/${casename}_1.png -toleranceOfColor 0.1] != 0 } { puts "Error difference in 1st image (using stream)" }
|
||||||
|
if { [diffimage $imagedir/${casename}_test_2s.png $imagedir/${casename}_2.png -toleranceOfColor 0.1] != 0 } { puts "Error difference in 2nd image (using stream)" }
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user