0024157: Parallelization of assembly part of BO
[occt.git] / src / Image / Image_AlienPixMap.cxx
CommitLineData
692613e5 1// Created on: 2010-09-16
2// Created by: KGV
3// Copyright (c) 2010-2012 OPEN CASCADE SAS
4//
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.
9//
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.
12//
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.
19
20#ifdef HAVE_CONFIG_H
21 #include <config.h>
22#endif
23
24#ifdef HAVE_FREEIMAGE
25 #include <FreeImage.h>
26
27 #ifdef _MSC_VER
28 #pragma comment( lib, "FreeImage.lib" )
29 #endif
30#endif
31
32#include <Image_AlienPixMap.hxx>
33#include <gp.hxx>
34#include <TCollection_AsciiString.hxx>
35#include <fstream>
36
37#ifdef HAVE_FREEIMAGE
38namespace
39{
40 static Image_PixMap::ImgFormat convertFromFreeFormat (FREE_IMAGE_TYPE theFormatFI,
41 FREE_IMAGE_COLOR_TYPE theColorTypeFI,
42 unsigned theBitsPerPixel)
43 {
44 switch (theFormatFI)
45 {
46 case FIT_RGBF: return Image_PixMap::ImgRGBF;
47 case FIT_RGBAF: return Image_PixMap::ImgRGBAF;
48 case FIT_FLOAT: return Image_PixMap::ImgGrayF;
49 case FIT_BITMAP:
50 {
51 switch (theColorTypeFI)
52 {
53 case FIC_MINISBLACK:
54 {
55 return Image_PixMap::ImgGray;
56 }
57 case FIC_RGB:
58 {
59 if (Image_PixMap::IsBigEndianHost())
60 {
61 return (theBitsPerPixel == 32) ? Image_PixMap::ImgRGB32 : Image_PixMap::ImgRGB;
62 }
63 else
64 {
65 return (theBitsPerPixel == 32) ? Image_PixMap::ImgBGR32 : Image_PixMap::ImgBGR;
66 }
67 }
68 case FIC_RGBALPHA:
69 {
70 return Image_PixMap::IsBigEndianHost() ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA;
71 }
72 default:
73 return Image_PixMap::ImgUNKNOWN;
74 }
75 }
76 default:
77 return Image_PixMap::ImgUNKNOWN;
78 }
79 }
80
81 static FREE_IMAGE_TYPE convertToFreeFormat (Image_PixMap::ImgFormat theFormat)
82 {
83 switch (theFormat)
84 {
85 case Image_PixMap::ImgGrayF:
86 return FIT_FLOAT;
87 case Image_PixMap::ImgRGBAF:
88 return FIT_RGBAF;
89 case Image_PixMap::ImgRGBF:
90 return FIT_RGBF;
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:
98 return FIT_BITMAP;
99 default:
100 return FIT_UNKNOWN;
101 }
102 }
103};
104#endif
105
106IMPLEMENT_STANDARD_HANDLE (Image_AlienPixMap, Image_PixMap)
107IMPLEMENT_STANDARD_RTTIEXT(Image_AlienPixMap, Image_PixMap)
108
109// =======================================================================
110// function : Image_AlienPixMap
111// purpose :
112// =======================================================================
113Image_AlienPixMap::Image_AlienPixMap()
114: myLibImage (NULL)
115{
116 SetTopDown (false);
117}
118
119// =======================================================================
120// function : ~Image_AlienPixMap
121// purpose :
122// =======================================================================
123Image_AlienPixMap::~Image_AlienPixMap()
124{
125 Clear();
126}
127
128// =======================================================================
129// function : InitWrapper
130// purpose :
131// =======================================================================
35e08fe8 132bool Image_AlienPixMap::InitWrapper (ImgFormat,
133 Standard_Byte*,
134 const Standard_Size,
135 const Standard_Size,
136 const Standard_Size)
692613e5 137{
138 Clear();
139 return false;
140}
141
142// =======================================================================
143// function : InitTrash
144// purpose :
145// =======================================================================
498ce76b 146#ifdef HAVE_FREEIMAGE
692613e5 147bool Image_AlienPixMap::InitTrash (ImgFormat thePixelFormat,
148 const Standard_Size theSizeX,
149 const Standard_Size theSizeY,
498ce76b 150 const Standard_Size /*theSizeRowBytes*/)
692613e5 151{
152 Clear();
692613e5 153 FREE_IMAGE_TYPE aFormatFI = convertToFreeFormat (thePixelFormat);
154 int aBitsPerPixel = (int )Image_PixMap::SizePixelBytes (thePixelFormat) * 8;
155 if (aFormatFI == FIT_UNKNOWN)
156 {
157 aFormatFI = FIT_BITMAP;
158 aBitsPerPixel = 24;
159 }
160
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)
167 {
168 //FreeImage_SetTransparent (anImage, FALSE);
169 aFormat = (aFormat == Image_PixMap::ImgBGRA) ? Image_PixMap::ImgBGR32 : Image_PixMap::ImgRGB32;
170 }
171
172 Image_PixMap::InitWrapper (aFormat, FreeImage_GetBits (anImage),
173 FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
174 SetTopDown (false);
175
176 // assign image after wrapper initialization (virtual Clear() called inside)
177 myLibImage = anImage;
178 return true;
498ce76b 179}
692613e5 180#else
498ce76b 181bool Image_AlienPixMap::InitTrash (ImgFormat thePixelFormat,
182 const Standard_Size theSizeX,
183 const Standard_Size theSizeY,
184 const Standard_Size theSizeRowBytes)
185{
692613e5 186 return Image_PixMap::InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes);
692613e5 187}
498ce76b 188#endif
692613e5 189
190// =======================================================================
3c3131a0 191// function : InitCopy
692613e5 192// purpose :
193// =======================================================================
194bool Image_AlienPixMap::InitCopy (const Image_PixMap& theCopy)
195{
196 if (&theCopy == this)
197 {
198 // self-copying disallowed
199 return false;
200 }
201 if (!InitTrash (theCopy.Format(), theCopy.SizeX(), theCopy.SizeY(), theCopy.SizeRowBytes()))
202 {
203 return false;
204 }
205
206 if (myImgFormat == theCopy.Format())
207 {
208 if (myData.mySizeRowBytes == theCopy.SizeRowBytes()
209 && myData.myTopToDown == theCopy.TopDownInc())
210 {
211 // copy with one call
212 memcpy (myData.myDataPtr, theCopy.Data(), theCopy.SizeBytes());
213 return true;
214 }
215
216 // copy row-by-row
217 const Standard_Size aRowSizeBytes = (myData.mySizeRowBytes > theCopy.SizeRowBytes())
218 ? theCopy.SizeRowBytes() : myData.mySizeRowBytes;
219 for (Standard_Size aRow = 0; aRow < myData.mySizeY; ++aRow)
220 {
221 memcpy (ChangeRow (aRow), theCopy.Row (aRow), aRowSizeBytes);
222 }
223 return true;
224 }
225
226 // pixel format conversion required
227 Clear();
228 return false;
229}
230
231// =======================================================================
232// function : Clear
233// purpose :
234// =======================================================================
235void Image_AlienPixMap::Clear (ImgFormat thePixelFormat)
236{
237 Image_PixMap::Clear (thePixelFormat);
238#ifdef HAVE_FREEIMAGE
239 if (myLibImage != NULL)
240 {
241 FreeImage_Unload (myLibImage);
242 myLibImage = NULL;
243 }
244#endif
245}
246
247// =======================================================================
248// function : Load
249// purpose :
250// =======================================================================
35e08fe8 251#ifdef HAVE_FREEIMAGE
692613e5 252bool Image_AlienPixMap::Load (const TCollection_AsciiString& theImagePath)
253{
254 Clear();
692613e5 255 FREE_IMAGE_FORMAT aFIF = FreeImage_GetFileType (theImagePath.ToCString(), 0);
256 if (aFIF == FIF_UNKNOWN)
257 {
258 // no signature? try to guess the file format from the file extension
259 aFIF = FreeImage_GetFIFFromFilename (theImagePath.ToCString());
260 }
261 if ((aFIF == FIF_UNKNOWN) || !FreeImage_FIFSupportsReading (aFIF))
262 {
263 // unsupported image format
264 return false;
265 }
266
267 int aLoadFlags = 0;
268 if (aFIF == FIF_GIF)
269 {
270 // 'Play' the GIF to generate each frame (as 32bpp) instead of returning raw frame data when loading
271 aLoadFlags = GIF_PLAYBACK;
272 }
273 else if (aFIF == FIF_ICO)
274 {
275 // convert to 32bpp and create an alpha channel from the AND-mask when loading
276 aLoadFlags = ICO_MAKEALPHA;
277 }
278
279 FIBITMAP* anImage = FreeImage_Load (aFIF, theImagePath.ToCString(), aLoadFlags);
280 if (anImage == NULL)
281 {
282 return false;
283 }
284
285 Image_PixMap::ImgFormat aFormat = convertFromFreeFormat (FreeImage_GetImageType (anImage),
286 FreeImage_GetColorType (anImage),
287 FreeImage_GetBPP (anImage));
288 if (aFormat == Image_PixMap::ImgUNKNOWN)
289 {
290 //anImage = FreeImage_ConvertTo24Bits (anImage);
291 return false;
292 }
293
294 Image_PixMap::InitWrapper (aFormat, FreeImage_GetBits (anImage),
295 FreeImage_GetWidth (anImage), FreeImage_GetHeight (anImage), FreeImage_GetPitch (anImage));
296 SetTopDown (false);
297
298 // assign image after wrapper initialization (virtual Clear() called inside)
299 myLibImage = anImage;
300 return true;
35e08fe8 301}
692613e5 302#else
35e08fe8 303bool Image_AlienPixMap::Load (const TCollection_AsciiString&)
304{
305 Clear();
692613e5 306 return false;
692613e5 307}
35e08fe8 308#endif
692613e5 309
310// =======================================================================
311// function : savePPM
312// purpose :
313// =======================================================================
314bool Image_AlienPixMap::savePPM (const TCollection_AsciiString& theFileName) const
315{
316 if (IsEmpty())
317 {
318 return false;
319 }
320
321 // Open file
322 FILE* aFile = fopen (theFileName.ToCString(), "wb");
323 if (aFile == NULL)
324 {
325 return false;
326 }
327
328 // Write header
329 fprintf (aFile, "P6\n%d %d\n255\n", (int )SizeX(), (int )SizeY());
330 fprintf (aFile, "# Image stored by OpenCASCADE framework in linear RGB colorspace\n");
331
332 // Write pixel data
333 Quantity_Color aColor;
334 Quantity_Parameter aDummy;
335 Standard_Byte aByte;
336 for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
337 {
338 for (Standard_Size aCol = 0; aCol < SizeY(); ++aCol)
339 {
340 // extremely SLOW but universal (implemented for all supported pixel formats)
6a7d83c4 341 aColor = PixelColor ((Standard_Integer )aCol, (Standard_Integer )aRow, aDummy);
692613e5 342 aByte = Standard_Byte(aColor.Red() * 255.0); fwrite (&aByte, 1, 1, aFile);
343 aByte = Standard_Byte(aColor.Green() * 255.0); fwrite (&aByte, 1, 1, aFile);
344 aByte = Standard_Byte(aColor.Blue() * 255.0); fwrite (&aByte, 1, 1, aFile);
345 }
346 }
347
348 // Close file
349 fclose (aFile);
350 return true;
351}
352
353// =======================================================================
354// function : Save
355// purpose :
356// =======================================================================
357bool Image_AlienPixMap::Save (const TCollection_AsciiString& theFileName)
358{
359#ifdef HAVE_FREEIMAGE
360 if (myLibImage == NULL)
361 {
362 return false;
363 }
364
365 FREE_IMAGE_FORMAT anImageFormat = FreeImage_GetFIFFromFilename (theFileName.ToCString());
366 if (anImageFormat == FIF_UNKNOWN)
367 {
368 std::cerr << "Image_PixMap, image format doesn't supported!\n";
369 return false;
370 }
371
372 if (IsTopDown())
373 {
374 FreeImage_FlipVertical (myLibImage);
375 SetTopDown (false);
376 }
377
378 // FreeImage doesn't provide flexible format convertion API
379 // so we should perform multiple convertions in some cases!
692613e5 380 FIBITMAP* anImageToDump = myLibImage;
381 switch (anImageFormat)
382 {
383 case FIF_PNG:
384 case FIF_BMP:
385 {
386 if (Format() == Image_PixMap::ImgBGR32
387 || Format() == Image_PixMap::ImgRGB32)
388 {
389 // stupid FreeImage treats reserved byte as alpha if some bytes not set to 0xFF
390 Image_PixMapData<Image_ColorRGB32>& aData = Image_PixMap::EditData<Image_ColorRGB32>();
391 for (Standard_Size aRow = 0; aRow < SizeY(); ++aRow)
392 {
393 for (Standard_Size aCol = 0; aCol < SizeX(); ++aCol)
394 {
395 aData.ChangeValue (aRow, aCol).a_() = 0xFF;
396 }
397 }
398 }
399 else if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
400 {
401 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
402 }
403 break;
404 }
405 case FIF_GIF:
406 {
407 FIBITMAP* aTmpBitmap = myLibImage;
408 if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
409 {
410 aTmpBitmap = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
411 if (aTmpBitmap == NULL)
412 {
413 return false;
414 }
415 }
416
417 if (FreeImage_GetBPP (aTmpBitmap) != 24)
418 {
419 FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (aTmpBitmap);
420 if (aTmpBitmap != myLibImage)
421 {
422 FreeImage_Unload (aTmpBitmap);
423 }
424 if (aTmpBitmap24 == NULL)
425 {
426 return false;
427 }
428 aTmpBitmap = aTmpBitmap24;
429 }
430
431 // need convertion to image with pallete (requires 24bit bitmap)
432 anImageToDump = FreeImage_ColorQuantize (aTmpBitmap, FIQ_NNQUANT);
433 if (aTmpBitmap != myLibImage)
434 {
435 FreeImage_Unload (aTmpBitmap);
436 }
437 break;
438 }
439 case FIF_EXR:
440 {
441 if (Format() == Image_PixMap::ImgGray)
442 {
443 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_FLOAT);
444 }
445 else if (Format() == Image_PixMap::ImgRGBA
446 || Format() == Image_PixMap::ImgBGRA)
447 {
448 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBAF);
449 }
450 else
451 {
452 FREE_IMAGE_TYPE aImgTypeFI = FreeImage_GetImageType (myLibImage);
453 if (aImgTypeFI != FIT_RGBF
454 && aImgTypeFI != FIT_RGBAF
455 && aImgTypeFI != FIT_FLOAT)
456 {
457 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_RGBF);
458 }
459 }
460 break;
461 }
462 default:
463 {
464 if (FreeImage_GetImageType (myLibImage) != FIT_BITMAP)
465 {
466 anImageToDump = FreeImage_ConvertToType (myLibImage, FIT_BITMAP);
467 if (anImageToDump == NULL)
468 {
469 return false;
470 }
471 }
472
473 if (FreeImage_GetBPP (anImageToDump) != 24)
474 {
475 FIBITMAP* aTmpBitmap24 = FreeImage_ConvertTo24Bits (anImageToDump);
476 if (anImageToDump != myLibImage)
477 {
478 FreeImage_Unload (anImageToDump);
479 }
480 if (aTmpBitmap24 == NULL)
481 {
482 return false;
483 }
484 anImageToDump = aTmpBitmap24;
485 }
486 break;
487 }
488 }
489
490 if (anImageToDump == NULL)
491 {
492 return false;
493 }
494
495 bool isSaved = (FreeImage_Save (anImageFormat, anImageToDump, theFileName.ToCString()) != FALSE);
496 if (anImageToDump != myLibImage)
497 {
498 FreeImage_Unload (anImageToDump);
499 }
500 return isSaved;
501#else
502 const Standard_Integer aLen = theFileName.Length();
503 if ((aLen >= 4) && (theFileName.Value (aLen - 3) == '.')
29cb310a 504 && strcasecmp( theFileName.ToCString() + aLen - 3, "ppm") == 0 )
692613e5 505 {
506 return savePPM (theFileName);
507 }
508 std::cerr << "Image_PixMap, no image library available! Image saved in PPM format.\n";
509 return savePPM (theFileName);
510#endif
511}
512
513// =======================================================================
514// function : AdjustGamma
515// purpose :
516// =======================================================================
35e08fe8 517#ifdef HAVE_FREEIMAGE
692613e5 518Standard_EXPORT bool Image_AlienPixMap::AdjustGamma (const Standard_Real theGammaCorr)
519{
692613e5 520 return FreeImage_AdjustGamma (myLibImage, theGammaCorr) != FALSE;
35e08fe8 521}
692613e5 522#else
35e08fe8 523Standard_EXPORT bool Image_AlienPixMap::AdjustGamma (const Standard_Real)
524{
525 return false;
692613e5 526}
35e08fe8 527#endif