1 // Created on: 2010-09-16
3 // Copyright (c) 2010-2012 OPEN CASCADE SAS
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
25 #include <FreeImage.h>
28 #pragma comment( lib, "FreeImage.lib" )
32 #include <Image_AlienPixMap.hxx>
34 #include <TCollection_AsciiString.hxx>
40 static Image_PixMap::ImgFormat convertFromFreeFormat (FREE_IMAGE_TYPE theFormatFI,
41 FREE_IMAGE_COLOR_TYPE theColorTypeFI,
42 unsigned theBitsPerPixel)
46 case FIT_RGBF: return Image_PixMap::ImgRGBF;
47 case FIT_RGBAF: return Image_PixMap::ImgRGBAF;
48 case FIT_FLOAT: return Image_PixMap::ImgGrayF;
51 switch (theColorTypeFI)
55 return Image_PixMap::ImgGray;
59 if (Image_PixMap::IsBigEndianHost())
61 return (theBitsPerPixel == 32) ? Image_PixMap::ImgRGB32 : Image_PixMap::ImgRGB;
65 return (theBitsPerPixel == 32) ? Image_PixMap::ImgBGR32 : Image_PixMap::ImgBGR;
70 return Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
73 return Image_PixMap::ImgUNKNOWN;
77 return Image_PixMap::ImgUNKNOWN;
81 static FREE_IMAGE_TYPE convertToFreeFormat (Image_PixMap::ImgFormat theFormat)
85 case Image_PixMap::ImgGrayF:
87 case Image_PixMap::ImgRGBAF:
89 case Image_PixMap::ImgRGBF:
91 case Image_PixMap::ImgRGBA:
92 case Image_PixMap::ImgBGRA:
93 case Image_PixMap::ImgRGB32:
94 case Image_PixMap::ImgBGR32:
95 case Image_PixMap::ImgRGB:
96 case Image_PixMap::ImgBGR:
97 case Image_PixMap::ImgGray:
106 IMPLEMENT_STANDARD_HANDLE (Image_AlienPixMap, Image_PixMap)
107 IMPLEMENT_STANDARD_RTTIEXT(Image_AlienPixMap, Image_PixMap)
109 // =======================================================================
110 // function : Image_AlienPixMap
112 // =======================================================================
113 Image_AlienPixMap::Image_AlienPixMap()
119 // =======================================================================
120 // function : ~Image_AlienPixMap
122 // =======================================================================
123 Image_AlienPixMap::~Image_AlienPixMap()
128 // =======================================================================
129 // function : InitWrapper
131 // =======================================================================
132 bool Image_AlienPixMap::InitWrapper (ImgFormat thePixelFormat,
133 Standard_Byte* theDataPtr,
134 const Standard_Size theSizeX,
135 const Standard_Size theSizeY,
136 const Standard_Size theSizeRowBytes)
142 // =======================================================================
143 // function : InitTrash
145 // =======================================================================
146 bool Image_AlienPixMap::InitTrash (ImgFormat thePixelFormat,
147 const Standard_Size theSizeX,
148 const Standard_Size theSizeY,
149 const Standard_Size theSizeRowBytes)
152 #ifdef HAVE_FREEIMAGE
153 FREE_IMAGE_TYPE aFormatFI = convertToFreeFormat (thePixelFormat);
154 int aBitsPerPixel = (int )Image_PixMap::SizePixelBytes (thePixelFormat) * 8;
155 if (aFormatFI == FIT_UNKNOWN)
157 aFormatFI = FIT_BITMAP;
161 FIBITMAP* anImage = FreeImage_AllocateT (aFormatFI, (int )theSizeX, (int )theSizeY, aBitsPerPixel);
162 Image_PixMap::ImgFormat aFormat = convertFromFreeFormat (FreeImage_GetImageType (anImage),
163 FreeImage_GetColorType (anImage),
164 FreeImage_GetBPP (anImage));
165 if (thePixelFormat == Image_PixMap::ImgBGR32
166 || thePixelFormat == Image_PixMap::ImgRGB32)
168 //FreeImage_SetTransparent (anImage, FALSE);
169 aFormat = (aFormat == Image_PixMap::ImgBGRA) ? Image_PixMap::ImgBGR32 : Image_PixMap::ImgRGB32;
172 Image_PixMap::InitWrapper (aFormat, FreeImage_GetBits (anImage),
173 FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
176 // assign image after wrapper initialization (virtual Clear() called inside)
177 myLibImage = anImage;
180 return Image_PixMap::InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes);
184 // =======================================================================
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 (myData.mySizeRowBytes == theCopy.SizeRowBytes()
203 && myData.myTopToDown == theCopy.TopDownInc())
205 // copy with one call
206 memcpy (myData.myDataPtr, theCopy.Data(), theCopy.SizeBytes());
211 const Standard_Size aRowSizeBytes = (myData.mySizeRowBytes > theCopy.SizeRowBytes())
212 ? theCopy.SizeRowBytes() : myData.mySizeRowBytes;
213 for (Standard_Size aRow = 0; aRow < myData.mySizeY; ++aRow)
215 memcpy (ChangeRow (aRow), theCopy.Row (aRow), aRowSizeBytes);
220 // pixel format conversion required
225 // =======================================================================
228 // =======================================================================
229 void Image_AlienPixMap::Clear (ImgFormat thePixelFormat)
231 Image_PixMap::Clear (thePixelFormat);
232 #ifdef HAVE_FREEIMAGE
233 if (myLibImage != NULL)
235 FreeImage_Unload (myLibImage);
241 // =======================================================================
244 // =======================================================================
245 bool Image_AlienPixMap::Load (const TCollection_AsciiString& theImagePath)
248 #ifdef HAVE_FREEIMAGE
250 FREE_IMAGE_FORMAT aFIF = FreeImage_GetFileType (theImagePath.ToCString(), 0);
251 if (aFIF == FIF_UNKNOWN)
253 // no signature? try to guess the file format from the file extension
254 aFIF = FreeImage_GetFIFFromFilename (theImagePath.ToCString());
256 if ((aFIF == FIF_UNKNOWN) || !FreeImage_FIFSupportsReading (aFIF))
258 // unsupported image format
265 // 'Play' the GIF to generate each frame (as 32bpp) instead of returning raw frame data when loading
266 aLoadFlags = GIF_PLAYBACK;
268 else if (aFIF == FIF_ICO)
270 // convert to 32bpp and create an alpha channel from the AND-mask when loading
271 aLoadFlags = ICO_MAKEALPHA;
274 FIBITMAP* anImage = FreeImage_Load (aFIF, theImagePath.ToCString(), aLoadFlags);
280 Image_PixMap::ImgFormat aFormat = convertFromFreeFormat (FreeImage_GetImageType (anImage),
281 FreeImage_GetColorType (anImage),
282 FreeImage_GetBPP (anImage));
283 if (aFormat == Image_PixMap::ImgUNKNOWN)
285 //anImage = FreeImage_ConvertTo24Bits (anImage);
289 Image_PixMap::InitWrapper (aFormat, FreeImage_GetBits (anImage),
290 FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
293 // assign image after wrapper initialization (virtual Clear() called inside)
294 myLibImage = anImage;
301 // =======================================================================
302 // function : savePPM
304 // =======================================================================
305 bool Image_AlienPixMap::savePPM (const TCollection_AsciiString& theFileName) const
313 FILE* aFile = fopen (theFileName.ToCString(), "wb");
320 fprintf (aFile, "P6\n%d %d\n255\n", (int )SizeX(), (int )SizeY());
321 fprintf (aFile, "# Image stored by OpenCASCADE framework in linear RGB colorspace\n");
324 Quantity_Color aColor;
325 Quantity_Parameter aDummy;
327 for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
329 for (Standard_Size aCol = 0; aCol < SizeY(); ++aCol)
331 // extremely SLOW but universal (implemented for all supported pixel formats)
332 aColor = PixelColor (aCol, aRow, aDummy);
333 aByte = Standard_Byte(aColor.Red() * 255.0); fwrite (&aByte, 1, 1, aFile);
334 aByte = Standard_Byte(aColor.Green() * 255.0); fwrite (&aByte, 1, 1, aFile);
335 aByte = Standard_Byte(aColor.Blue() * 255.0); fwrite (&aByte, 1, 1, aFile);
344 // =======================================================================
347 // =======================================================================
348 bool Image_AlienPixMap::Save (const TCollection_AsciiString& theFileName)
350 #ifdef HAVE_FREEIMAGE
351 if (myLibImage == NULL)
356 FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilename (theFileName.ToCString());
357 if (anImageFormat == FIF_UNKNOWN)
359 std::cerr << "Image_PixMap, image format doesn't supported!\n";
365 FreeImage_FlipVertical (myLibImage);
369 // FreeImage doesn't provide flexible format convertion API
370 // so we should perform multiple convertions in some cases!
371 Standard_Boolean isCopied = Standard_False;
372 FIBITMAP* anImageToDump = myLibImage;
373 switch (anImageFormat)
378 if (Format() == Image_PixMap::ImgBGR32
379 || Format() == Image_PixMap::ImgRGB32)
381 // stupid FreeImage treats reserved byte as alpha if some bytes not set to 0xFF
382 Image_PixMapData<Image_ColorRGB32>& aData = Image_PixMap::EditData<Image_ColorRGB32>();
383 for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
385 for (Standard_Size aCol = 0; aCol < SizeX(); ++aCol)
387 aData.ChangeValue (aRow, aCol).a_() = 0xFF;
391 else if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
393 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
399 FIBITMAP* aTmpBitmap = myLibImage;
400 if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
402 aTmpBitmap = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
403 if (aTmpBitmap == NULL)
409 if (FreeImage_GetBPP (aTmpBitmap) != 24)
411 FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (aTmpBitmap);
412 if (aTmpBitmap != myLibImage)
414 FreeImage_Unload (aTmpBitmap);
416 if (aTmpBitmap24 == NULL)
420 aTmpBitmap = aTmpBitmap24;
423 // need convertion to image with pallete (requires 24bit bitmap)
424 anImageToDump = FreeImage_ColorQuantize (aTmpBitmap, FIQ_NNQUANT);
425 if (aTmpBitmap != myLibImage)
427 FreeImage_Unload (aTmpBitmap);
433 if (Format() == Image_PixMap::ImgGray)
435 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_FLOAT);
437 else if (Format() == Image_PixMap::ImgRGBA
438 || Format() == Image_PixMap::ImgBGRA)
440 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBAF);
444 FREE_IMAGE_TYPE aImgTypeFI = FreeImage_GetImageType (myLibImage);
445 if (aImgTypeFI != FIT_RGBF
446 && aImgTypeFI != FIT_RGBAF
447 && aImgTypeFI != FIT_FLOAT)
449 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBF);
456 if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
458 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
459 if (anImageToDump == NULL)
465 if (FreeImage_GetBPP (anImageToDump) != 24)
467 FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (anImageToDump);
468 if (anImageToDump != myLibImage)
470 FreeImage_Unload (anImageToDump);
472 if (aTmpBitmap24 == NULL)
476 anImageToDump = aTmpBitmap24;
482 if (anImageToDump == NULL)
487 bool isSaved = (FreeImage_Save (anImageFormat, anImageToDump, theFileName.ToCString()) != FALSE);
488 if (anImageToDump != myLibImage)
490 FreeImage_Unload (anImageToDump);
494 const Standard_Integer aLen = theFileName.Length();
495 if ((aLen >= 4) && (theFileName.Value (aLen - 3) == '.')
496 && TCollection_AsciiString::ISSIMILAR (theFileName.SubString (aLen - 2, aLen), "ppm"))
498 return savePPM (theFileName);
500 std::cerr << "Image_PixMap, no image library available! Image saved in PPM format.\n";
501 return savePPM (theFileName);
505 // =======================================================================
506 // function : AdjustGamma
508 // =======================================================================
509 Standard_EXPORT bool Image_AlienPixMap::AdjustGamma (const Standard_Real theGammaCorr)
511 #ifdef HAVE_FREEIMAGE
512 return FreeImage_AdjustGamma (myLibImage, theGammaCorr) != FALSE;