1 // Created on: 2010-09-16
3 // Copyright (c) 2010-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
17 #include <FreeImage.h>
20 #pragma comment( lib, "FreeImage.lib" )
24 #include <Image_AlienPixMap.hxx>
26 #include <TCollection_AsciiString.hxx>
27 #include <TCollection_ExtendedString.hxx>
34 static Image_PixMap::ImgFormat convertFromFreeFormat (FREE_IMAGE_TYPE theFormatFI,
35 FREE_IMAGE_COLOR_TYPE theColorTypeFI,
36 unsigned theBitsPerPixel)
40 case FIT_RGBF: return Image_PixMap::ImgRGBF;
41 case FIT_RGBAF: return Image_PixMap::ImgRGBAF;
42 case FIT_FLOAT: return Image_PixMap::ImgGrayF;
45 switch (theColorTypeFI)
49 return Image_PixMap::ImgGray;
53 if (Image_PixMap::IsBigEndianHost())
55 return (theBitsPerPixel == 32) ? Image_PixMap::ImgRGB32 : Image_PixMap::ImgRGB;
59 return (theBitsPerPixel == 32) ? Image_PixMap::ImgBGR32 : Image_PixMap::ImgBGR;
64 return Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
67 return Image_PixMap::ImgUNKNOWN;
71 return Image_PixMap::ImgUNKNOWN;
75 static FREE_IMAGE_TYPE convertToFreeFormat (Image_PixMap::ImgFormat theFormat)
79 case Image_PixMap::ImgGrayF:
81 case Image_PixMap::ImgRGBAF:
83 case Image_PixMap::ImgRGBF:
85 case Image_PixMap::ImgRGBA:
86 case Image_PixMap::ImgBGRA:
87 case Image_PixMap::ImgRGB32:
88 case Image_PixMap::ImgBGR32:
89 case Image_PixMap::ImgRGB:
90 case Image_PixMap::ImgBGR:
91 case Image_PixMap::ImgGray:
100 IMPLEMENT_STANDARD_HANDLE (Image_AlienPixMap, Image_PixMap)
101 IMPLEMENT_STANDARD_RTTIEXT(Image_AlienPixMap, Image_PixMap)
103 // =======================================================================
104 // function : Image_AlienPixMap
106 // =======================================================================
107 Image_AlienPixMap::Image_AlienPixMap()
113 // =======================================================================
114 // function : ~Image_AlienPixMap
116 // =======================================================================
117 Image_AlienPixMap::~Image_AlienPixMap()
122 // =======================================================================
123 // function : InitWrapper
125 // =======================================================================
126 bool Image_AlienPixMap::InitWrapper (ImgFormat,
136 // =======================================================================
137 // function : InitTrash
139 // =======================================================================
140 #ifdef HAVE_FREEIMAGE
141 bool Image_AlienPixMap::InitTrash (ImgFormat thePixelFormat,
142 const Standard_Size theSizeX,
143 const Standard_Size theSizeY,
144 const Standard_Size /*theSizeRowBytes*/)
147 FREE_IMAGE_TYPE aFormatFI = convertToFreeFormat (thePixelFormat);
148 int aBitsPerPixel = (int )Image_PixMap::SizePixelBytes (thePixelFormat) * 8;
149 if (aFormatFI == FIT_UNKNOWN)
151 aFormatFI = FIT_BITMAP;
155 FIBITMAP* anImage = FreeImage_AllocateT (aFormatFI, (int )theSizeX, (int )theSizeY, aBitsPerPixel);
156 Image_PixMap::ImgFormat aFormat = convertFromFreeFormat (FreeImage_GetImageType (anImage),
157 FreeImage_GetColorType (anImage),
158 FreeImage_GetBPP (anImage));
159 if (thePixelFormat == Image_PixMap::ImgBGR32
160 || thePixelFormat == Image_PixMap::ImgRGB32)
162 //FreeImage_SetTransparent (anImage, FALSE);
163 aFormat = (aFormat == Image_PixMap::ImgBGRA) ? Image_PixMap::ImgBGR32 : Image_PixMap::ImgRGB32;
166 Image_PixMap::InitWrapper (aFormat, FreeImage_GetBits (anImage),
167 FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
170 // assign image after wrapper initialization (virtual Clear() called inside)
171 myLibImage = anImage;
175 bool Image_AlienPixMap::InitTrash (ImgFormat thePixelFormat,
176 const Standard_Size theSizeX,
177 const Standard_Size theSizeY,
178 const Standard_Size theSizeRowBytes)
180 return Image_PixMap::InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes);
184 // =======================================================================
185 // function : InitCopy
187 // =======================================================================
188 bool Image_AlienPixMap::InitCopy (const Image_PixMap& theCopy)
190 if (&theCopy == this)
192 // self-copying disallowed
195 if (!InitTrash (theCopy.Format(), theCopy.SizeX(), theCopy.SizeY(), theCopy.SizeRowBytes()))
200 if (myImgFormat == theCopy.Format())
202 if (SizeRowBytes() == theCopy.SizeRowBytes()
203 && TopDownInc() == theCopy.TopDownInc())
205 // copy with one call
206 memcpy (ChangeData(), theCopy.Data(), std::min (SizeBytes(), theCopy.SizeBytes()));
211 const Standard_Size aRowSizeBytes = std::min (SizeRowBytes(), theCopy.SizeRowBytes());
212 for (Standard_Size aRow = 0; aRow < myData.SizeY; ++aRow)
214 memcpy (ChangeRow (aRow), theCopy.Row (aRow), aRowSizeBytes);
219 // pixel format conversion required
224 // =======================================================================
227 // =======================================================================
228 void Image_AlienPixMap::Clear()
230 Image_PixMap::Clear();
231 #ifdef HAVE_FREEIMAGE
232 if (myLibImage != NULL)
234 FreeImage_Unload (myLibImage);
240 // =======================================================================
243 // =======================================================================
244 #ifdef HAVE_FREEIMAGE
245 bool Image_AlienPixMap::Load (const TCollection_AsciiString& theImagePath)
250 const TCollection_ExtendedString aFileNameW (theImagePath.ToCString(), Standard_True);
251 FREE_IMAGE_FORMAT aFIF = FreeImage_GetFileTypeU ((const wchar_t* )aFileNameW.ToExtString(), 0);
253 FREE_IMAGE_FORMAT aFIF = FreeImage_GetFileType (theImagePath.ToCString(), 0);
255 if (aFIF == FIF_UNKNOWN)
257 // no signature? try to guess the file format from the file extension
258 aFIF = FreeImage_GetFIFFromFilename (theImagePath.ToCString());
260 if ((aFIF == FIF_UNKNOWN) || !FreeImage_FIFSupportsReading (aFIF))
262 // unsupported image format
269 // 'Play' the GIF to generate each frame (as 32bpp) instead of returning raw frame data when loading
270 aLoadFlags = GIF_PLAYBACK;
272 else if (aFIF == FIF_ICO)
274 // convert to 32bpp and create an alpha channel from the AND-mask when loading
275 aLoadFlags = ICO_MAKEALPHA;
279 FIBITMAP* anImage = FreeImage_LoadU (aFIF, (const wchar_t* )aFileNameW.ToExtString(), aLoadFlags);
281 FIBITMAP* anImage = FreeImage_Load (aFIF, theImagePath.ToCString(), aLoadFlags);
288 Image_PixMap::ImgFormat aFormat = convertFromFreeFormat (FreeImage_GetImageType (anImage),
289 FreeImage_GetColorType (anImage),
290 FreeImage_GetBPP (anImage));
291 if (aFormat == Image_PixMap::ImgUNKNOWN)
293 //anImage = FreeImage_ConvertTo24Bits (anImage);
297 Image_PixMap::InitWrapper (aFormat, FreeImage_GetBits (anImage),
298 FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
301 // assign image after wrapper initialization (virtual Clear() called inside)
302 myLibImage = anImage;
306 bool Image_AlienPixMap::Load (const TCollection_AsciiString&)
313 // =======================================================================
314 // function : savePPM
316 // =======================================================================
317 bool Image_AlienPixMap::savePPM (const TCollection_AsciiString& theFileName) const
326 const TCollection_ExtendedString aFileNameW (theFileName.ToCString(), Standard_True);
327 FILE* aFile = _wfopen ((const wchar_t* )aFileNameW.ToExtString(), L"wb");
329 FILE* aFile = fopen (theFileName.ToCString(), "wb");
337 fprintf (aFile, "P6\n%d %d\n255\n", (int )SizeX(), (int )SizeY());
338 fprintf (aFile, "# Image stored by OpenCASCADE framework in linear RGB colorspace\n");
341 Quantity_Color aColor;
342 Quantity_Parameter aDummy;
344 for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
346 for (Standard_Size aCol = 0; aCol < SizeX(); ++aCol)
348 // extremely SLOW but universal (implemented for all supported pixel formats)
349 aColor = PixelColor ((Standard_Integer )aCol, (Standard_Integer )aRow, aDummy);
350 aByte = Standard_Byte(aColor.Red() * 255.0); fwrite (&aByte, 1, 1, aFile);
351 aByte = Standard_Byte(aColor.Green() * 255.0); fwrite (&aByte, 1, 1, aFile);
352 aByte = Standard_Byte(aColor.Blue() * 255.0); fwrite (&aByte, 1, 1, aFile);
361 // =======================================================================
364 // =======================================================================
365 bool Image_AlienPixMap::Save (const TCollection_AsciiString& theFileName)
367 #ifdef HAVE_FREEIMAGE
368 if (myLibImage == NULL)
374 const TCollection_ExtendedString aFileNameW (theFileName.ToCString(), Standard_True);
375 FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilenameU ((const wchar_t* )aFileNameW.ToExtString());
377 FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilename (theFileName.ToCString());
379 if (anImageFormat == FIF_UNKNOWN)
381 std::cerr << "Image_PixMap, image format doesn't supported!\n";
387 FreeImage_FlipVertical (myLibImage);
391 // FreeImage doesn't provide flexible format convertion API
392 // so we should perform multiple convertions in some cases!
393 FIBITMAP* anImageToDump = myLibImage;
394 switch (anImageFormat)
399 if (Format() == Image_PixMap::ImgBGR32
400 || Format() == Image_PixMap::ImgRGB32)
402 // stupid FreeImage treats reserved byte as alpha if some bytes not set to 0xFF
403 for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
405 for (Standard_Size aCol = 0; aCol < SizeX(); ++aCol)
407 myData.ChangeValue (aRow, aCol)[3] = 0xFF;
411 else if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
413 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
419 FIBITMAP* aTmpBitmap = myLibImage;
420 if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
422 aTmpBitmap = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
423 if (aTmpBitmap == NULL)
429 if (FreeImage_GetBPP (aTmpBitmap) != 24)
431 FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (aTmpBitmap);
432 if (aTmpBitmap != myLibImage)
434 FreeImage_Unload (aTmpBitmap);
436 if (aTmpBitmap24 == NULL)
440 aTmpBitmap = aTmpBitmap24;
443 // need convertion to image with pallete (requires 24bit bitmap)
444 anImageToDump = FreeImage_ColorQuantize (aTmpBitmap, FIQ_NNQUANT);
445 if (aTmpBitmap != myLibImage)
447 FreeImage_Unload (aTmpBitmap);
453 if (Format() == Image_PixMap::ImgGray)
455 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_FLOAT);
457 else if (Format() == Image_PixMap::ImgRGBA
458 || Format() == Image_PixMap::ImgBGRA)
460 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBAF);
464 FREE_IMAGE_TYPE aImgTypeFI = FreeImage_GetImageType (myLibImage);
465 if (aImgTypeFI != FIT_RGBF
466 && aImgTypeFI != FIT_RGBAF
467 && aImgTypeFI != FIT_FLOAT)
469 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBF);
476 if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
478 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
479 if (anImageToDump == NULL)
485 if (FreeImage_GetBPP (anImageToDump) != 24)
487 FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (anImageToDump);
488 if (anImageToDump != myLibImage)
490 FreeImage_Unload (anImageToDump);
492 if (aTmpBitmap24 == NULL)
496 anImageToDump = aTmpBitmap24;
502 if (anImageToDump == NULL)
508 bool isSaved = (FreeImage_SaveU (anImageFormat, anImageToDump, (const wchar_t* )aFileNameW.ToExtString()) != FALSE);
510 bool isSaved = (FreeImage_Save (anImageFormat, anImageToDump, theFileName.ToCString()) != FALSE);
512 if (anImageToDump != myLibImage)
514 FreeImage_Unload (anImageToDump);
518 const Standard_Integer aLen = theFileName.Length();
519 if ((aLen >= 4) && (theFileName.Value (aLen - 3) == '.')
520 && strcasecmp( theFileName.ToCString() + aLen - 3, "ppm") == 0 )
522 return savePPM (theFileName);
524 std::cerr << "Image_PixMap, no image library available! Image saved in PPM format.\n";
525 return savePPM (theFileName);
529 // =======================================================================
530 // function : AdjustGamma
532 // =======================================================================
533 bool Image_AlienPixMap::AdjustGamma (const Standard_Real theGammaCorr)
535 #ifdef HAVE_FREEIMAGE
536 return FreeImage_AdjustGamma (myLibImage, theGammaCorr) != FALSE;