0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[occt.git] / src / Image / Image_AlienPixMap.cxx
CommitLineData
692613e5 1// Created on: 2010-09-16
2// Created by: KGV
973c2be1 3// Copyright (c) 2010-2014 OPEN CASCADE SAS
692613e5 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
692613e5 6//
d5f74e42 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
973c2be1 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.
692613e5 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
692613e5 15
a975e06e 16#if !defined(HAVE_FREEIMAGE) && defined(_WIN32)
17 #define HAVE_WINCODEC
18#endif
19
692613e5 20#ifdef HAVE_FREEIMAGE
21 #include <FreeImage.h>
22
23 #ifdef _MSC_VER
24 #pragma comment( lib, "FreeImage.lib" )
25 #endif
a975e06e 26#elif defined(HAVE_WINCODEC)
27 //#include <initguid.h>
28 #include <wincodec.h>
29 #undef min
30 #undef max
692613e5 31#endif
32
33#include <Image_AlienPixMap.hxx>
34#include <gp.hxx>
0c015ee2 35#include <Message.hxx>
36#include <Message_Messenger.hxx>
692613e5 37#include <TCollection_AsciiString.hxx>
7aa1b65c 38#include <TCollection_ExtendedString.hxx>
94708556 39#include <OSD_OpenFile.hxx>
692613e5 40#include <fstream>
a096a7a5 41#include <algorithm>
692613e5 42
f5f4ebd0 43IMPLEMENT_STANDARD_RTTIEXT(Image_AlienPixMap,Image_PixMap)
44
692613e5 45namespace
46{
a975e06e 47#ifdef HAVE_FREEIMAGE
dc858f4c 48 static Image_Format convertFromFreeFormat (FREE_IMAGE_TYPE theFormatFI,
49 FREE_IMAGE_COLOR_TYPE theColorTypeFI,
50 unsigned theBitsPerPixel)
692613e5 51 {
52 switch (theFormatFI)
53 {
dc858f4c 54 case FIT_RGBF: return Image_Format_RGBF;
55 case FIT_RGBAF: return Image_Format_RGBAF;
56 case FIT_FLOAT: return Image_Format_GrayF;
692613e5 57 case FIT_BITMAP:
58 {
59 switch (theColorTypeFI)
60 {
61 case FIC_MINISBLACK:
62 {
dc858f4c 63 return Image_Format_Gray;
692613e5 64 }
65 case FIC_RGB:
66 {
67 if (Image_PixMap::IsBigEndianHost())
68 {
dc858f4c 69 return (theBitsPerPixel == 32) ? Image_Format_RGB32 : Image_Format_RGB;
692613e5 70 }
71 else
72 {
dc858f4c 73 return (theBitsPerPixel == 32) ? Image_Format_BGR32 : Image_Format_BGR;
692613e5 74 }
75 }
76 case FIC_RGBALPHA:
77 {
dc858f4c 78 return Image_PixMap::IsBigEndianHost() ? Image_Format_RGBA : Image_Format_BGRA;
692613e5 79 }
80 default:
dc858f4c 81 return Image_Format_UNKNOWN;
692613e5 82 }
83 }
84 default:
dc858f4c 85 return Image_Format_UNKNOWN;
692613e5 86 }
87 }
88
dc858f4c 89 static FREE_IMAGE_TYPE convertToFreeFormat (Image_Format theFormat)
692613e5 90 {
91 switch (theFormat)
92 {
dc858f4c 93 case Image_Format_GrayF:
94 case Image_Format_AlphaF:
692613e5 95 return FIT_FLOAT;
dc858f4c 96 case Image_Format_RGBAF:
692613e5 97 return FIT_RGBAF;
dc858f4c 98 case Image_Format_RGBF:
692613e5 99 return FIT_RGBF;
dc858f4c 100 case Image_Format_RGBA:
101 case Image_Format_BGRA:
102 case Image_Format_RGB32:
103 case Image_Format_BGR32:
104 case Image_Format_RGB:
105 case Image_Format_BGR:
106 case Image_Format_Gray:
107 case Image_Format_Alpha:
692613e5 108 return FIT_BITMAP;
109 default:
110 return FIT_UNKNOWN;
111 }
112 }
a975e06e 113#elif defined(HAVE_WINCODEC)
692613e5 114
a975e06e 115 //! Return a zero GUID
116 static GUID getNullGuid()
117 {
118 GUID aGuid = { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };
119 return aGuid;
120 }
121
122 //! Sentry over IUnknown pointer.
123 template<class T> class Image_ComPtr
124 {
125 public:
126 //! Empty constructor.
127 Image_ComPtr()
128 : myPtr (NULL) {}
129
130 //! Destructor.
131 ~Image_ComPtr()
132 {
133 Nullify();
134 }
135
136 //! Return TRUE if pointer is NULL.
137 bool IsNull() const { return myPtr == NULL; }
138
139 //! Release the pointer.
140 void Nullify()
141 {
142 if (myPtr != NULL)
143 {
144 myPtr->Release();
145 myPtr = NULL;
146 }
147 }
148
149 //! Return pointer for initialization.
150 T*& ChangePtr()
151 {
152 Standard_ASSERT_RAISE (myPtr == NULL, "Pointer cannot be initialized twice!");
153 return myPtr;
154 }
155
156 //! Return pointer.
157 T* get() { return myPtr; }
158
159 //! Return pointer.
160 T* operator->() { return get(); }
161
162 //! Cast handle to contained type
163 T& operator*() { return *get(); }
164
165 private:
166 T* myPtr;
167 };
168
169 //! Convert WIC GUID to Image_Format.
170 static Image_Format convertFromWicFormat (const WICPixelFormatGUID& theFormat)
171 {
172 if (theFormat == GUID_WICPixelFormat32bppBGRA)
173 {
174 return Image_Format_BGRA;
175 }
176 else if (theFormat == GUID_WICPixelFormat32bppBGR)
177 {
178 return Image_Format_BGR32;
179 }
180 else if (theFormat == GUID_WICPixelFormat24bppRGB)
181 {
182 return Image_Format_RGB;
183 }
184 else if (theFormat == GUID_WICPixelFormat24bppBGR)
185 {
186 return Image_Format_BGR;
187 }
188 else if (theFormat == GUID_WICPixelFormat8bppGray)
189 {
190 return Image_Format_Gray;
191 }
192 return Image_Format_UNKNOWN;
193 }
194
195 //! Convert Image_Format to WIC GUID.
196 static WICPixelFormatGUID convertToWicFormat (Image_Format theFormat)
197 {
198 switch (theFormat)
199 {
200 case Image_Format_BGRA: return GUID_WICPixelFormat32bppBGRA;
201 case Image_Format_BGR32: return GUID_WICPixelFormat32bppBGR;
202 case Image_Format_RGB: return GUID_WICPixelFormat24bppRGB;
203 case Image_Format_BGR: return GUID_WICPixelFormat24bppBGR;
204 case Image_Format_Gray: return GUID_WICPixelFormat8bppGray;
205 case Image_Format_Alpha: return GUID_WICPixelFormat8bppGray; // GUID_WICPixelFormat8bppAlpha
206 case Image_Format_GrayF: // GUID_WICPixelFormat32bppGrayFloat
207 case Image_Format_AlphaF:
208 case Image_Format_RGBAF: // GUID_WICPixelFormat128bppRGBAFloat
209 case Image_Format_RGBF: // GUID_WICPixelFormat96bppRGBFloat
210 case Image_Format_RGBA: // GUID_WICPixelFormat32bppRGBA
211 case Image_Format_RGB32: // GUID_WICPixelFormat32bppRGB
212 default:
213 return getNullGuid();
214 }
215 }
216
217#endif
218}
692613e5 219
220// =======================================================================
221// function : Image_AlienPixMap
222// purpose :
223// =======================================================================
224Image_AlienPixMap::Image_AlienPixMap()
225: myLibImage (NULL)
226{
227 SetTopDown (false);
228}
229
230// =======================================================================
231// function : ~Image_AlienPixMap
232// purpose :
233// =======================================================================
234Image_AlienPixMap::~Image_AlienPixMap()
235{
236 Clear();
237}
238
239// =======================================================================
240// function : InitWrapper
241// purpose :
242// =======================================================================
dc858f4c 243bool Image_AlienPixMap::InitWrapper (Image_Format,
35e08fe8 244 Standard_Byte*,
245 const Standard_Size,
246 const Standard_Size,
247 const Standard_Size)
692613e5 248{
249 Clear();
250 return false;
251}
252
253// =======================================================================
254// function : InitTrash
255// purpose :
256// =======================================================================
498ce76b 257#ifdef HAVE_FREEIMAGE
dc858f4c 258bool Image_AlienPixMap::InitTrash (Image_Format thePixelFormat,
692613e5 259 const Standard_Size theSizeX,
260 const Standard_Size theSizeY,
498ce76b 261 const Standard_Size /*theSizeRowBytes*/)
692613e5 262{
263 Clear();
692613e5 264 FREE_IMAGE_TYPE aFormatFI = convertToFreeFormat (thePixelFormat);
265 int aBitsPerPixel = (int )Image_PixMap::SizePixelBytes (thePixelFormat) * 8;
266 if (aFormatFI == FIT_UNKNOWN)
267 {
268 aFormatFI = FIT_BITMAP;
269 aBitsPerPixel = 24;
270 }
271
272 FIBITMAP* anImage = FreeImage_AllocateT (aFormatFI, (int )theSizeX, (int )theSizeY, aBitsPerPixel);
dc858f4c 273 Image_Format aFormat = convertFromFreeFormat (FreeImage_GetImageType(anImage),
274 FreeImage_GetColorType(anImage),
275 FreeImage_GetBPP (anImage));
276 if (thePixelFormat == Image_Format_BGR32
277 || thePixelFormat == Image_Format_RGB32)
692613e5 278 {
279 //FreeImage_SetTransparent (anImage, FALSE);
dc858f4c 280 aFormat = (aFormat == Image_Format_BGRA) ? Image_Format_BGR32 : Image_Format_RGB32;
692613e5 281 }
282
283 Image_PixMap::InitWrapper (aFormat, FreeImage_GetBits (anImage),
284 FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
285 SetTopDown (false);
286
287 // assign image after wrapper initialization (virtual Clear() called inside)
288 myLibImage = anImage;
289 return true;
498ce76b 290}
a975e06e 291#elif defined(HAVE_WINCODEC)
292bool Image_AlienPixMap::InitTrash (Image_Format thePixelFormat,
293 const Standard_Size theSizeX,
294 const Standard_Size theSizeY,
295 const Standard_Size theSizeRowBytes)
296{
297 Clear();
298 Image_Format aFormat = thePixelFormat;
299 switch (aFormat)
300 {
301 case Image_Format_RGB:
302 aFormat = Image_Format_BGR;
303 break;
304 case Image_Format_RGB32:
305 aFormat = Image_Format_BGR32;
306 break;
307 case Image_Format_RGBA:
308 aFormat = Image_Format_BGRA;
309 break;
310 default:
311 break;
312 }
313
314 if (!Image_PixMap::InitTrash (aFormat, theSizeX, theSizeY, theSizeRowBytes))
315 {
316 return false;
317 }
318 SetTopDown (true);
319 return true;
320}
692613e5 321#else
dc858f4c 322bool Image_AlienPixMap::InitTrash (Image_Format thePixelFormat,
498ce76b 323 const Standard_Size theSizeX,
324 const Standard_Size theSizeY,
325 const Standard_Size theSizeRowBytes)
326{
692613e5 327 return Image_PixMap::InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes);
692613e5 328}
498ce76b 329#endif
692613e5 330
331// =======================================================================
3c3131a0 332// function : InitCopy
692613e5 333// purpose :
334// =======================================================================
335bool Image_AlienPixMap::InitCopy (const Image_PixMap& theCopy)
336{
337 if (&theCopy == this)
338 {
339 // self-copying disallowed
340 return false;
341 }
342 if (!InitTrash (theCopy.Format(), theCopy.SizeX(), theCopy.SizeY(), theCopy.SizeRowBytes()))
343 {
344 return false;
345 }
346
347 if (myImgFormat == theCopy.Format())
348 {
ca0c0b11 349 if (SizeRowBytes() == theCopy.SizeRowBytes()
350 && TopDownInc() == theCopy.TopDownInc())
692613e5 351 {
352 // copy with one call
ca0c0b11 353 memcpy (ChangeData(), theCopy.Data(), std::min (SizeBytes(), theCopy.SizeBytes()));
692613e5 354 return true;
355 }
356
357 // copy row-by-row
ca0c0b11 358 const Standard_Size aRowSizeBytes = std::min (SizeRowBytes(), theCopy.SizeRowBytes());
359 for (Standard_Size aRow = 0; aRow < myData.SizeY; ++aRow)
692613e5 360 {
361 memcpy (ChangeRow (aRow), theCopy.Row (aRow), aRowSizeBytes);
362 }
363 return true;
364 }
365
366 // pixel format conversion required
367 Clear();
368 return false;
369}
370
371// =======================================================================
372// function : Clear
373// purpose :
374// =======================================================================
ca0c0b11 375void Image_AlienPixMap::Clear()
692613e5 376{
ca0c0b11 377 Image_PixMap::Clear();
692613e5 378#ifdef HAVE_FREEIMAGE
379 if (myLibImage != NULL)
380 {
381 FreeImage_Unload (myLibImage);
382 myLibImage = NULL;
383 }
384#endif
385}
386
387// =======================================================================
388// function : Load
389// purpose :
390// =======================================================================
35e08fe8 391#ifdef HAVE_FREEIMAGE
692613e5 392bool Image_AlienPixMap::Load (const TCollection_AsciiString& theImagePath)
393{
394 Clear();
7aa1b65c 395
396#ifdef _WIN32
a975e06e 397 const TCollection_ExtendedString aFileNameW (theImagePath);
fb0b0531 398 FREE_IMAGE_FORMAT aFIF = FreeImage_GetFileTypeU (aFileNameW.ToWideString(), 0);
7aa1b65c 399#else
692613e5 400 FREE_IMAGE_FORMAT aFIF = FreeImage_GetFileType (theImagePath.ToCString(), 0);
7aa1b65c 401#endif
692613e5 402 if (aFIF == FIF_UNKNOWN)
403 {
404 // no signature? try to guess the file format from the file extension
405 aFIF = FreeImage_GetFIFFromFilename (theImagePath.ToCString());
406 }
407 if ((aFIF == FIF_UNKNOWN) || !FreeImage_FIFSupportsReading (aFIF))
408 {
0c015ee2 409 TCollection_AsciiString aMessage = "Error: image file '";
410 aMessage.AssignCat (theImagePath);
411 aMessage.AssignCat ("' has unsupported file format.");
412 ::Message::DefaultMessenger()->Send (aMessage, Message_Fail);
692613e5 413 return false;
414 }
415
416 int aLoadFlags = 0;
417 if (aFIF == FIF_GIF)
418 {
419 // 'Play' the GIF to generate each frame (as 32bpp) instead of returning raw frame data when loading
420 aLoadFlags = GIF_PLAYBACK;
421 }
422 else if (aFIF == FIF_ICO)
423 {
424 // convert to 32bpp and create an alpha channel from the AND-mask when loading
425 aLoadFlags = ICO_MAKEALPHA;
426 }
427
7aa1b65c 428#ifdef _WIN32
fb0b0531 429 FIBITMAP* anImage = FreeImage_LoadU (aFIF, aFileNameW.ToWideString(), aLoadFlags);
7aa1b65c 430#else
431 FIBITMAP* anImage = FreeImage_Load (aFIF, theImagePath.ToCString(), aLoadFlags);
432#endif
692613e5 433 if (anImage == NULL)
434 {
0c015ee2 435 TCollection_AsciiString aMessage = "Error: image file '";
436 aMessage.AssignCat (theImagePath);
437 aMessage.AssignCat ("' is missing or invalid.");
438 ::Message::DefaultMessenger()->Send (aMessage, Message_Fail);
692613e5 439 return false;
440 }
441
dc858f4c 442 Image_Format aFormat = convertFromFreeFormat (FreeImage_GetImageType(anImage),
443 FreeImage_GetColorType(anImage),
444 FreeImage_GetBPP (anImage));
445 if (aFormat == Image_Format_UNKNOWN)
692613e5 446 {
447 //anImage = FreeImage_ConvertTo24Bits (anImage);
0c015ee2 448 TCollection_AsciiString aMessage = "Error: image file '";
449 aMessage.AssignCat (theImagePath);
450 aMessage.AssignCat ("' has unsupported pixel format.");
451 ::Message::DefaultMessenger()->Send (aMessage, Message_Fail);
692613e5 452 return false;
453 }
454
455 Image_PixMap::InitWrapper (aFormat, FreeImage_GetBits (anImage),
456 FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
457 SetTopDown (false);
458
459 // assign image after wrapper initialization (virtual Clear() called inside)
460 myLibImage = anImage;
461 return true;
35e08fe8 462}
a975e06e 463#elif defined(HAVE_WINCODEC)
464bool Image_AlienPixMap::Load (const TCollection_AsciiString& theImagePath)
465{
466 Clear();
467
468 IWICImagingFactory* aWicImgFactory = NULL;
469 CoInitializeEx (NULL, COINIT_MULTITHREADED);
470 if (CoCreateInstance (CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&aWicImgFactory)) != S_OK)
471 {
472 Message::DefaultMessenger()->Send ("Error: cannot initialize WIC Imaging Factory", Message_Fail);
473 return false;
474 }
475
476 Image_ComPtr<IWICBitmapDecoder> aWicDecoder;
477 const TCollection_ExtendedString aFileNameW (theImagePath);
478 if (aWicImgFactory->CreateDecoderFromFilename (aFileNameW.ToWideString(), NULL, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &aWicDecoder.ChangePtr()) != S_OK)
479 {
480 Message::DefaultMessenger()->Send ("Error: cannot create WIC Image Decoder", Message_Fail);
481 return false;
482 }
483
484 UINT aFrameCount = 0, aFrameSizeX = 0, aFrameSizeY = 0;
485 WICPixelFormatGUID aWicPixelFormat = getNullGuid();
486 Image_ComPtr<IWICBitmapFrameDecode> aWicFrameDecode;
487 if (aWicDecoder->GetFrameCount (&aFrameCount) != S_OK
488 || aFrameCount < 1
489 || aWicDecoder->GetFrame (0, &aWicFrameDecode.ChangePtr()) != S_OK
490 || aWicFrameDecode->GetSize (&aFrameSizeX, &aFrameSizeY) != S_OK
491 || aWicFrameDecode->GetPixelFormat (&aWicPixelFormat))
492 {
493 Message::DefaultMessenger()->Send ("Error: cannot get WIC Image Frame", Message_Fail);
494 return false;
495 }
496
497 Image_ComPtr<IWICFormatConverter> aWicConvertedFrame;
498 Image_Format aPixelFormat = convertFromWicFormat (aWicPixelFormat);
499 if (aPixelFormat == Image_Format_UNKNOWN)
500 {
501 aPixelFormat = Image_Format_RGB;
502 if (aWicImgFactory->CreateFormatConverter (&aWicConvertedFrame.ChangePtr()) != S_OK
503 || aWicConvertedFrame->Initialize (aWicFrameDecode.get(), convertToWicFormat (aPixelFormat), WICBitmapDitherTypeNone, NULL, 0.0f, WICBitmapPaletteTypeCustom) != S_OK)
504 {
505 Message::DefaultMessenger()->Send ("Error: cannot convert WIC Image Frame to RGB format", Message_Fail);
506 return false;
507 }
508 aWicFrameDecode.Nullify();
509 }
510
511 if (!Image_PixMap::InitTrash (aPixelFormat, aFrameSizeX, aFrameSizeY))
512 {
513 Message::DefaultMessenger()->Send ("Error: cannot initialize memory for image", Message_Fail);
514 return false;
515 }
516
517 IWICBitmapSource* aWicSrc = aWicFrameDecode.get();
518 if(!aWicConvertedFrame.IsNull())
519 {
520 aWicSrc = aWicConvertedFrame.get();
521 }
522 if (aWicSrc->CopyPixels (NULL, (UINT )SizeRowBytes(), (UINT )SizeBytes(), ChangeData()) != S_OK)
523 {
524 Message::DefaultMessenger()->Send ("Error: cannot copy pixels from WIC Image", Message_Fail);
525 return false;
526 }
527 SetTopDown (true);
528 return true;
529}
692613e5 530#else
35e08fe8 531bool Image_AlienPixMap::Load (const TCollection_AsciiString&)
532{
533 Clear();
692613e5 534 return false;
692613e5 535}
35e08fe8 536#endif
692613e5 537
538// =======================================================================
539// function : savePPM
540// purpose :
541// =======================================================================
542bool Image_AlienPixMap::savePPM (const TCollection_AsciiString& theFileName) const
543{
544 if (IsEmpty())
545 {
546 return false;
547 }
548
549 // Open file
94708556 550 FILE* aFile = OSD_OpenFile (theFileName.ToCString(), "wb");
692613e5 551 if (aFile == NULL)
552 {
553 return false;
554 }
555
556 // Write header
557 fprintf (aFile, "P6\n%d %d\n255\n", (int )SizeX(), (int )SizeY());
558 fprintf (aFile, "# Image stored by OpenCASCADE framework in linear RGB colorspace\n");
559
560 // Write pixel data
692613e5 561 Standard_Byte aByte;
562 for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
563 {
a7b491fc 564 for (Standard_Size aCol = 0; aCol < SizeX(); ++aCol)
692613e5 565 {
566 // extremely SLOW but universal (implemented for all supported pixel formats)
e958a649 567 const Quantity_ColorRGBA aColor = PixelColor ((Standard_Integer )aCol, (Standard_Integer )aRow);
568 aByte = Standard_Byte(aColor.GetRGB().Red() * 255.0); fwrite (&aByte, 1, 1, aFile);
569 aByte = Standard_Byte(aColor.GetRGB().Green() * 255.0); fwrite (&aByte, 1, 1, aFile);
570 aByte = Standard_Byte(aColor.GetRGB().Blue() * 255.0); fwrite (&aByte, 1, 1, aFile);
692613e5 571 }
572 }
573
574 // Close file
575 fclose (aFile);
576 return true;
577}
578
579// =======================================================================
580// function : Save
581// purpose :
582// =======================================================================
583bool Image_AlienPixMap::Save (const TCollection_AsciiString& theFileName)
584{
585#ifdef HAVE_FREEIMAGE
586 if (myLibImage == NULL)
587 {
588 return false;
589 }
590
7aa1b65c 591#ifdef _WIN32
592 const TCollection_ExtendedString aFileNameW (theFileName.ToCString(), Standard_True);
fb0b0531 593 FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilenameU (aFileNameW.ToWideString());
7aa1b65c 594#else
692613e5 595 FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilename (theFileName.ToCString());
7aa1b65c 596#endif
692613e5 597 if (anImageFormat == FIF_UNKNOWN)
598 {
0797d9d3 599#ifdef OCCT_DEBUG
692613e5 600 std::cerr << "Image_PixMap, image format doesn't supported!\n";
63c629aa 601#endif
692613e5 602 return false;
603 }
604
605 if (IsTopDown())
606 {
607 FreeImage_FlipVertical (myLibImage);
608 SetTopDown (false);
609 }
610
dc858f4c 611 // FreeImage doesn't provide flexible format conversion API
612 // so we should perform multiple conversions in some cases!
692613e5 613 FIBITMAP* anImageToDump = myLibImage;
614 switch (anImageFormat)
615 {
616 case FIF_PNG:
617 case FIF_BMP:
618 {
dc858f4c 619 if (Format() == Image_Format_BGR32
620 || Format() == Image_Format_RGB32)
692613e5 621 {
622 // stupid FreeImage treats reserved byte as alpha if some bytes not set to 0xFF
692613e5 623 for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
624 {
625 for (Standard_Size aCol = 0; aCol < SizeX(); ++aCol)
626 {
ca0c0b11 627 myData.ChangeValue (aRow, aCol)[3] = 0xFF;
692613e5 628 }
629 }
630 }
631 else if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
632 {
633 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
634 }
635 break;
636 }
637 case FIF_GIF:
638 {
639 FIBITMAP* aTmpBitmap = myLibImage;
640 if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
641 {
642 aTmpBitmap = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
643 if (aTmpBitmap == NULL)
644 {
645 return false;
646 }
647 }
648
649 if (FreeImage_GetBPP (aTmpBitmap) != 24)
650 {
651 FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (aTmpBitmap);
652 if (aTmpBitmap != myLibImage)
653 {
654 FreeImage_Unload (aTmpBitmap);
655 }
656 if (aTmpBitmap24 == NULL)
657 {
658 return false;
659 }
660 aTmpBitmap = aTmpBitmap24;
661 }
662
dc858f4c 663 // need conversion to image with palette (requires 24bit bitmap)
692613e5 664 anImageToDump = FreeImage_ColorQuantize (aTmpBitmap, FIQ_NNQUANT);
665 if (aTmpBitmap != myLibImage)
666 {
667 FreeImage_Unload (aTmpBitmap);
668 }
669 break;
670 }
38d90bb3 671 case FIF_HDR:
692613e5 672 case FIF_EXR:
673 {
dc858f4c 674 if (Format() == Image_Format_Gray
675 || Format() == Image_Format_Alpha)
692613e5 676 {
677 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_FLOAT);
678 }
dc858f4c 679 else if (Format() == Image_Format_RGBA
680 || Format() == Image_Format_BGRA)
692613e5 681 {
682 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBAF);
683 }
684 else
685 {
686 FREE_IMAGE_TYPE aImgTypeFI = FreeImage_GetImageType (myLibImage);
687 if (aImgTypeFI != FIT_RGBF
688 && aImgTypeFI != FIT_RGBAF
689 && aImgTypeFI != FIT_FLOAT)
690 {
691 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBF);
692 }
693 }
694 break;
695 }
696 default:
697 {
698 if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
699 {
700 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
701 if (anImageToDump == NULL)
702 {
703 return false;
704 }
705 }
706
707 if (FreeImage_GetBPP (anImageToDump) != 24)
708 {
709 FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (anImageToDump);
710 if (anImageToDump != myLibImage)
711 {
712 FreeImage_Unload (anImageToDump);
713 }
714 if (aTmpBitmap24 == NULL)
715 {
716 return false;
717 }
718 anImageToDump = aTmpBitmap24;
719 }
720 break;
721 }
722 }
723
724 if (anImageToDump == NULL)
725 {
726 return false;
727 }
728
7aa1b65c 729#ifdef _WIN32
fb0b0531 730 bool isSaved = (FreeImage_SaveU (anImageFormat, anImageToDump, aFileNameW.ToWideString()) != FALSE);
7aa1b65c 731#else
732 bool isSaved = (FreeImage_Save (anImageFormat, anImageToDump, theFileName.ToCString()) != FALSE);
733#endif
692613e5 734 if (anImageToDump != myLibImage)
735 {
736 FreeImage_Unload (anImageToDump);
737 }
738 return isSaved;
a975e06e 739
740#elif defined(HAVE_WINCODEC)
741
742 TCollection_AsciiString aFileNameLower = theFileName;
743 aFileNameLower.LowerCase();
744 GUID aFileFormat = getNullGuid();
745 if (aFileNameLower.EndsWith (".ppm"))
746 {
747 return savePPM (theFileName);
748 }
749 else if (aFileNameLower.EndsWith (".bmp"))
750 {
751 aFileFormat = GUID_ContainerFormatBmp;
752 }
753 else if (aFileNameLower.EndsWith (".png"))
754 {
755 aFileFormat = GUID_ContainerFormatPng;
756 }
757 else if (aFileNameLower.EndsWith (".jpg")
758 || aFileNameLower.EndsWith (".jpeg"))
759 {
760 aFileFormat = GUID_ContainerFormatJpeg;
761 }
762 else if (aFileNameLower.EndsWith (".tiff"))
763 {
764 aFileFormat = GUID_ContainerFormatTiff;
765 }
766 else if (aFileNameLower.EndsWith (".gif"))
767 {
768 aFileFormat = GUID_ContainerFormatGif;
769 }
770
771 if (aFileFormat == getNullGuid())
772 {
773 Message::DefaultMessenger()->Send ("Error: unsupported image format", Message_Fail);
774 return false;
775 }
776
777 IWICImagingFactory* aWicImgFactory = NULL;
778 CoInitializeEx (NULL, COINIT_MULTITHREADED);
779 if (CoCreateInstance (CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&aWicImgFactory)) != S_OK)
780 {
781 Message::DefaultMessenger()->Send ("Error: cannot initialize WIC Imaging Factory", Message_Fail);
782 return false;
783 }
784
785 Image_ComPtr<IWICStream> aWicFileStream;
786 Image_ComPtr<IWICBitmapEncoder> aWicEncoder;
787 const TCollection_ExtendedString aFileNameW (theFileName);
788 if (aWicImgFactory->CreateStream (&aWicFileStream.ChangePtr()) != S_OK
789 || aWicFileStream->InitializeFromFilename (aFileNameW.ToWideString(), GENERIC_WRITE) != S_OK)
790 {
791 Message::DefaultMessenger()->Send ("Error: cannot create WIC File Stream", Message_Fail);
792 return false;
793 }
794 if (aWicImgFactory->CreateEncoder (aFileFormat, NULL, &aWicEncoder.ChangePtr()) != S_OK
795 || aWicEncoder->Initialize (aWicFileStream.get(), WICBitmapEncoderNoCache) != S_OK)
796 {
797 Message::DefaultMessenger()->Send ("Error: cannot create WIC Encoder", Message_Fail);
798 return false;
799 }
800
801 const WICPixelFormatGUID aWicPixelFormat = convertToWicFormat (myImgFormat);
802 if (aWicPixelFormat == getNullGuid())
803 {
804 Message::DefaultMessenger()->Send ("Error: unsupported pixel format", Message_Fail);
805 return false;
806 }
807
808 WICPixelFormatGUID aWicPixelFormatRes = aWicPixelFormat;
809 Image_ComPtr<IWICBitmapFrameEncode> aWicFrameEncode;
810 if (aWicEncoder->CreateNewFrame (&aWicFrameEncode.ChangePtr(), NULL) != S_OK
811 || aWicFrameEncode->Initialize (NULL) != S_OK
812 || aWicFrameEncode->SetSize ((UINT )SizeX(), (UINT )SizeY()) != S_OK
813 || aWicFrameEncode->SetPixelFormat (&aWicPixelFormatRes) != S_OK)
814 {
815 Message::DefaultMessenger()->Send ("Error: cannot create WIC Frame", Message_Fail);
816 return false;
817 }
818
819 if (aWicPixelFormatRes != aWicPixelFormat)
820 {
821 Message::DefaultMessenger()->Send ("Error: pixel format is unsupported by image format", Message_Fail);
822 return false;
823 }
824
825 if (IsTopDown())
826 {
827 if (aWicFrameEncode->WritePixels ((UINT )SizeY(), (UINT )SizeRowBytes(), (UINT )SizeBytes(), (BYTE* )Data()) != S_OK)
828 {
829 Message::DefaultMessenger()->Send ("Error: cannot write pixels to WIC Frame", Message_Fail);
830 return false;
831 }
832 }
833 else
834 {
835 for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
836 {
837 if (aWicFrameEncode->WritePixels (1, (UINT )SizeRowBytes(), (UINT )SizeRowBytes(), (BYTE* )Row (aRow)) != S_OK)
838 {
839 Message::DefaultMessenger()->Send ("Error: cannot write pixels to WIC Frame", Message_Fail);
840 return false;
841 }
842 }
843 }
844
845 if (aWicFrameEncode->Commit() != S_OK
846 || aWicEncoder->Commit() != S_OK)
847 {
848 Message::DefaultMessenger()->Send ("Error: cannot commit data to WIC Frame", Message_Fail);
849 return false;
850 }
851 if (aWicFileStream->Commit (STGC_DEFAULT) != S_OK)
852 {
853 //Message::DefaultMessenger()->Send ("Error: cannot commit data to WIC File Stream", Message_Fail);
854 //return false;
855 }
856 return true;
692613e5 857#else
858 const Standard_Integer aLen = theFileName.Length();
859 if ((aLen >= 4) && (theFileName.Value (aLen - 3) == '.')
29cb310a 860 && strcasecmp( theFileName.ToCString() + aLen - 3, "ppm") == 0 )
692613e5 861 {
862 return savePPM (theFileName);
863 }
0797d9d3 864#ifdef OCCT_DEBUG
692613e5 865 std::cerr << "Image_PixMap, no image library available! Image saved in PPM format.\n";
63c629aa 866#endif
692613e5 867 return savePPM (theFileName);
868#endif
869}
870
871// =======================================================================
872// function : AdjustGamma
873// purpose :
874// =======================================================================
7aa1b65c 875bool Image_AlienPixMap::AdjustGamma (const Standard_Real theGammaCorr)
692613e5 876{
7aa1b65c 877#ifdef HAVE_FREEIMAGE
692613e5 878 return FreeImage_AdjustGamma (myLibImage, theGammaCorr) != FALSE;
879#else
7aa1b65c 880 (void )theGammaCorr;
881 return false;
35e08fe8 882#endif
7aa1b65c 883}