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.
21 #include <FreeImage.h>
24 #pragma comment( lib, "FreeImage.lib" )
28 #include <Image_AlienPixMap.hxx>
30 #include <TCollection_AsciiString.hxx>
36 static Image_PixMap::ImgFormat convertFromFreeFormat (FREE_IMAGE_TYPE theFormatFI,
37 FREE_IMAGE_COLOR_TYPE theColorTypeFI,
38 unsigned theBitsPerPixel)
42 case FIT_RGBF: return Image_PixMap::ImgRGBF;
43 case FIT_RGBAF: return Image_PixMap::ImgRGBAF;
44 case FIT_FLOAT: return Image_PixMap::ImgGrayF;
47 switch (theColorTypeFI)
51 return Image_PixMap::ImgGray;
55 if (Image_PixMap::IsBigEndianHost())
57 return (theBitsPerPixel == 32) ? Image_PixMap::ImgRGB32 : Image_PixMap::ImgRGB;
61 return (theBitsPerPixel == 32) ? Image_PixMap::ImgBGR32 : Image_PixMap::ImgBGR;
66 return Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
69 return Image_PixMap::ImgUNKNOWN;
73 return Image_PixMap::ImgUNKNOWN;
77 static FREE_IMAGE_TYPE convertToFreeFormat (Image_PixMap::ImgFormat theFormat)
81 case Image_PixMap::ImgGrayF:
83 case Image_PixMap::ImgRGBAF:
85 case Image_PixMap::ImgRGBF:
87 case Image_PixMap::ImgRGBA:
88 case Image_PixMap::ImgBGRA:
89 case Image_PixMap::ImgRGB32:
90 case Image_PixMap::ImgBGR32:
91 case Image_PixMap::ImgRGB:
92 case Image_PixMap::ImgBGR:
93 case Image_PixMap::ImgGray:
102 IMPLEMENT_STANDARD_HANDLE (Image_AlienPixMap, Image_PixMap)
103 IMPLEMENT_STANDARD_RTTIEXT(Image_AlienPixMap, Image_PixMap)
105 // =======================================================================
106 // function : Image_AlienPixMap
108 // =======================================================================
109 Image_AlienPixMap::Image_AlienPixMap()
115 // =======================================================================
116 // function : ~Image_AlienPixMap
118 // =======================================================================
119 Image_AlienPixMap::~Image_AlienPixMap()
124 // =======================================================================
125 // function : InitWrapper
127 // =======================================================================
128 bool Image_AlienPixMap::InitWrapper (ImgFormat,
138 // =======================================================================
139 // function : InitTrash
141 // =======================================================================
142 #ifdef HAVE_FREEIMAGE
143 bool Image_AlienPixMap::InitTrash (ImgFormat thePixelFormat,
144 const Standard_Size theSizeX,
145 const Standard_Size theSizeY,
146 const Standard_Size /*theSizeRowBytes*/)
149 FREE_IMAGE_TYPE aFormatFI = convertToFreeFormat (thePixelFormat);
150 int aBitsPerPixel = (int )Image_PixMap::SizePixelBytes (thePixelFormat) * 8;
151 if (aFormatFI == FIT_UNKNOWN)
153 aFormatFI = FIT_BITMAP;
157 FIBITMAP* anImage = FreeImage_AllocateT (aFormatFI, (int )theSizeX, (int )theSizeY, aBitsPerPixel);
158 Image_PixMap::ImgFormat aFormat = convertFromFreeFormat (FreeImage_GetImageType (anImage),
159 FreeImage_GetColorType (anImage),
160 FreeImage_GetBPP (anImage));
161 if (thePixelFormat == Image_PixMap::ImgBGR32
162 || thePixelFormat == Image_PixMap::ImgRGB32)
164 //FreeImage_SetTransparent (anImage, FALSE);
165 aFormat = (aFormat == Image_PixMap::ImgBGRA) ? Image_PixMap::ImgBGR32 : Image_PixMap::ImgRGB32;
168 Image_PixMap::InitWrapper (aFormat, FreeImage_GetBits (anImage),
169 FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
172 // assign image after wrapper initialization (virtual Clear() called inside)
173 myLibImage = anImage;
177 bool Image_AlienPixMap::InitTrash (ImgFormat thePixelFormat,
178 const Standard_Size theSizeX,
179 const Standard_Size theSizeY,
180 const Standard_Size theSizeRowBytes)
182 return Image_PixMap::InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes);
186 // =======================================================================
187 // function : InitCopy
189 // =======================================================================
190 bool Image_AlienPixMap::InitCopy (const Image_PixMap& theCopy)
192 if (&theCopy == this)
194 // self-copying disallowed
197 if (!InitTrash (theCopy.Format(), theCopy.SizeX(), theCopy.SizeY(), theCopy.SizeRowBytes()))
202 if (myImgFormat == theCopy.Format())
204 if (SizeRowBytes() == theCopy.SizeRowBytes()
205 && TopDownInc() == theCopy.TopDownInc())
207 // copy with one call
208 memcpy (ChangeData(), theCopy.Data(), std::min (SizeBytes(), theCopy.SizeBytes()));
213 const Standard_Size aRowSizeBytes = std::min (SizeRowBytes(), theCopy.SizeRowBytes());
214 for (Standard_Size aRow = 0; aRow < myData.SizeY; ++aRow)
216 memcpy (ChangeRow (aRow), theCopy.Row (aRow), aRowSizeBytes);
221 // pixel format conversion required
226 // =======================================================================
229 // =======================================================================
230 void Image_AlienPixMap::Clear()
232 Image_PixMap::Clear();
233 #ifdef HAVE_FREEIMAGE
234 if (myLibImage != NULL)
236 FreeImage_Unload (myLibImage);
242 // =======================================================================
245 // =======================================================================
246 #ifdef HAVE_FREEIMAGE
247 bool Image_AlienPixMap::Load (const TCollection_AsciiString& theImagePath)
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;
298 bool Image_AlienPixMap::Load (const TCollection_AsciiString&)
305 // =======================================================================
306 // function : savePPM
308 // =======================================================================
309 bool Image_AlienPixMap::savePPM (const TCollection_AsciiString& theFileName) const
317 FILE* aFile = fopen (theFileName.ToCString(), "wb");
324 fprintf (aFile, "P6\n%d %d\n255\n", (int )SizeX(), (int )SizeY());
325 fprintf (aFile, "# Image stored by OpenCASCADE framework in linear RGB colorspace\n");
328 Quantity_Color aColor;
329 Quantity_Parameter aDummy;
331 for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
333 for (Standard_Size aCol = 0; aCol < SizeY(); ++aCol)
335 // extremely SLOW but universal (implemented for all supported pixel formats)
336 aColor = PixelColor ((Standard_Integer )aCol, (Standard_Integer )aRow, aDummy);
337 aByte = Standard_Byte(aColor.Red() * 255.0); fwrite (&aByte, 1, 1, aFile);
338 aByte = Standard_Byte(aColor.Green() * 255.0); fwrite (&aByte, 1, 1, aFile);
339 aByte = Standard_Byte(aColor.Blue() * 255.0); fwrite (&aByte, 1, 1, aFile);
348 // =======================================================================
351 // =======================================================================
352 bool Image_AlienPixMap::Save (const TCollection_AsciiString& theFileName)
354 #ifdef HAVE_FREEIMAGE
355 if (myLibImage == NULL)
360 FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilename (theFileName.ToCString());
361 if (anImageFormat == FIF_UNKNOWN)
363 std::cerr << "Image_PixMap, image format doesn't supported!\n";
369 FreeImage_FlipVertical (myLibImage);
373 // FreeImage doesn't provide flexible format convertion API
374 // so we should perform multiple convertions in some cases!
375 FIBITMAP* anImageToDump = myLibImage;
376 switch (anImageFormat)
381 if (Format() == Image_PixMap::ImgBGR32
382 || Format() == Image_PixMap::ImgRGB32)
384 // stupid FreeImage treats reserved byte as alpha if some bytes not set to 0xFF
385 for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
387 for (Standard_Size aCol = 0; aCol < SizeX(); ++aCol)
389 myData.ChangeValue (aRow, aCol)[3] = 0xFF;
393 else if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
395 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
401 FIBITMAP* aTmpBitmap = myLibImage;
402 if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
404 aTmpBitmap = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
405 if (aTmpBitmap == NULL)
411 if (FreeImage_GetBPP (aTmpBitmap) != 24)
413 FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (aTmpBitmap);
414 if (aTmpBitmap != myLibImage)
416 FreeImage_Unload (aTmpBitmap);
418 if (aTmpBitmap24 == NULL)
422 aTmpBitmap = aTmpBitmap24;
425 // need convertion to image with pallete (requires 24bit bitmap)
426 anImageToDump = FreeImage_ColorQuantize (aTmpBitmap, FIQ_NNQUANT);
427 if (aTmpBitmap != myLibImage)
429 FreeImage_Unload (aTmpBitmap);
435 if (Format() == Image_PixMap::ImgGray)
437 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_FLOAT);
439 else if (Format() == Image_PixMap::ImgRGBA
440 || Format() == Image_PixMap::ImgBGRA)
442 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBAF);
446 FREE_IMAGE_TYPE aImgTypeFI = FreeImage_GetImageType (myLibImage);
447 if (aImgTypeFI != FIT_RGBF
448 && aImgTypeFI != FIT_RGBAF
449 && aImgTypeFI != FIT_FLOAT)
451 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBF);
458 if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
460 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
461 if (anImageToDump == NULL)
467 if (FreeImage_GetBPP (anImageToDump) != 24)
469 FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (anImageToDump);
470 if (anImageToDump != myLibImage)
472 FreeImage_Unload (anImageToDump);
474 if (aTmpBitmap24 == NULL)
478 anImageToDump = aTmpBitmap24;
484 if (anImageToDump == NULL)
489 bool isSaved = (FreeImage_Save (anImageFormat, anImageToDump, theFileName.ToCString()) != FALSE);
490 if (anImageToDump != myLibImage)
492 FreeImage_Unload (anImageToDump);
496 const Standard_Integer aLen = theFileName.Length();
497 if ((aLen >= 4) && (theFileName.Value (aLen - 3) == '.')
498 && strcasecmp( theFileName.ToCString() + aLen - 3, "ppm") == 0 )
500 return savePPM (theFileName);
502 std::cerr << "Image_PixMap, no image library available! Image saved in PPM format.\n";
503 return savePPM (theFileName);
507 // =======================================================================
508 // function : AdjustGamma
510 // =======================================================================
511 #ifdef HAVE_FREEIMAGE
512 Standard_EXPORT bool Image_AlienPixMap::AdjustGamma (const Standard_Real theGammaCorr)
514 return FreeImage_AdjustGamma (myLibImage, theGammaCorr) != FALSE;
517 Standard_EXPORT bool Image_AlienPixMap::AdjustGamma (const Standard_Real)