mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-09 13:22:24 +03:00
Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
77dba7664c |
@@ -1804,26 +1804,40 @@ static Standard_Boolean SaveBitmap (HBITMAP theHBitmap,
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
@@ -1,12 +1,18 @@
|
||||
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
|
File diff suppressed because it is too large
Load Diff
@@ -16,28 +16,29 @@
|
||||
#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.
|
||||
@@ -46,67 +47,64 @@ public:
|
||||
//! 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;
|
||||
|
||||
//! 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:
|
||||
|
||||
FIBITMAP* myLibImage;
|
||||
|
||||
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;
|
||||
|
||||
};
|
||||
|
||||
|
151
src/Image/Image_AlienPixMapI.cxx
Normal file
151
src/Image/Image_AlienPixMapI.cxx
Normal file
@@ -0,0 +1,151 @@
|
||||
// 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;
|
||||
}
|
98
src/Image/Image_AlienPixMapI.hxx
Normal file
98
src/Image/Image_AlienPixMapI.hxx
Normal file
@@ -0,0 +1,98 @@
|
||||
// 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
|
655
src/Image/Image_FreeImage.cxx
Normal file
655
src/Image/Image_FreeImage.cxx
Normal file
@@ -0,0 +1,655 @@
|
||||
// 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
|
||||
}
|
107
src/Image/Image_FreeImage.hxx
Normal file
107
src/Image/Image_FreeImage.hxx
Normal file
@@ -0,0 +1,107 @@
|
||||
// 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
|
@@ -174,7 +174,7 @@ public: //! @name low-level API for batch-processing (pixels reading / compariso
|
||||
//! 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);
|
||||
}
|
||||
|
451
src/Image/Image_WinCodec.cxx
Normal file
451
src/Image/Image_WinCodec.cxx
Normal file
@@ -0,0 +1,451 @@
|
||||
// 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
|
||||
}
|
87
src/Image/Image_WinCodec.hxx
Normal file
87
src/Image/Image_WinCodec.hxx
Normal file
@@ -0,0 +1,87 @@
|
||||
// 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
|
Reference in New Issue
Block a user