973c2be1 |
1 | // Created on: 2014-07-18 |
692613e5 |
2 | // Created by: Kirill GAVRILOV |
973c2be1 |
3 | // Copyright (c) 2014 OPEN CASCADE SAS |
b311480e |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
b311480e |
6 | // |
973c2be1 |
7 | // This library is free software; you can redistribute it and / or modify it |
8 | // under the terms of the GNU Lesser General Public 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. |
b311480e |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
b311480e |
15 | |
692613e5 |
16 | #include <Image_PixMap.hxx> |
17 | |
185e6ec0 |
18 | #ifdef _MSC_VER |
5edb1ac3 |
19 | #include <malloc.h> |
185e6ec0 |
20 | #elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1) |
692613e5 |
21 | #include <mm_malloc.h> |
185e6ec0 |
22 | #else |
23 | extern "C" int posix_memalign (void** thePtr, size_t theAlign, size_t theBytesCount); |
498ce577 |
24 | #endif |
7fd59977 |
25 | |
692613e5 |
26 | template<typename TypePtr> |
27 | inline TypePtr MemAllocAligned (const Standard_Size& theBytesCount, |
28 | const Standard_Size& theAlign = 16) |
29 | { |
30 | #if defined(_MSC_VER) |
31 | return (TypePtr )_aligned_malloc (theBytesCount, theAlign); |
185e6ec0 |
32 | #elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1) |
692613e5 |
33 | return (TypePtr ) _mm_malloc (theBytesCount, theAlign); |
185e6ec0 |
34 | #else |
35 | void* aPtr; |
36 | if (posix_memalign (&aPtr, theAlign, theBytesCount)) |
37 | { |
38 | aPtr = NULL; |
39 | } |
40 | return (TypePtr )aPtr; |
692613e5 |
41 | #endif |
42 | } |
7fd59977 |
43 | |
692613e5 |
44 | inline void MemFreeAligned (void* thePtrAligned) |
45 | { |
46 | #if defined(_MSC_VER) |
47 | _aligned_free (thePtrAligned); |
185e6ec0 |
48 | #elif (defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 1) |
692613e5 |
49 | _mm_free (thePtrAligned); |
185e6ec0 |
50 | #else |
51 | free (thePtrAligned); |
692613e5 |
52 | #endif |
53 | } |
7fd59977 |
54 | |
692613e5 |
55 | IMPLEMENT_STANDARD_HANDLE (Image_PixMap, Standard_Transient) |
56 | IMPLEMENT_STANDARD_RTTIEXT(Image_PixMap, Standard_Transient) |
7fd59977 |
57 | |
692613e5 |
58 | // ======================================================================= |
59 | // function : Image_PixMap |
60 | // purpose : |
61 | // ======================================================================= |
62 | Image_PixMap::Image_PixMap() |
63 | : myImgFormat (Image_PixMap::ImgGray), |
64 | myIsOwnPointer (true) |
65 | { |
66 | memset (&myData, 0, sizeof(myData)); |
67 | myData.mySizeBPP = 1; |
f823def0 |
68 | myData.myTopToDown = Standard_Size(-1); |
692613e5 |
69 | setFormat (Image_PixMap::ImgGray); |
70 | } |
7fd59977 |
71 | |
692613e5 |
72 | // ======================================================================= |
73 | // function : ~Image_PixMap |
74 | // purpose : |
75 | // ======================================================================= |
76 | Image_PixMap::~Image_PixMap() |
77 | { |
78 | Clear(); |
79 | } |
7fd59977 |
80 | |
692613e5 |
81 | Standard_Size Image_PixMap::SizePixelBytes (const Image_PixMap::ImgFormat thePixelFormat) |
7fd59977 |
82 | { |
692613e5 |
83 | switch (thePixelFormat) |
7fd59977 |
84 | { |
692613e5 |
85 | case ImgGrayF: |
86 | return sizeof(float); |
87 | case ImgRGBAF: |
88 | case ImgBGRAF: |
89 | return sizeof(float) * 4; |
90 | case ImgRGBF: |
91 | case ImgBGRF: |
92 | return sizeof(float) * 3; |
93 | case ImgRGBA: |
94 | case ImgBGRA: |
95 | return 4; |
96 | case ImgRGB32: |
97 | case ImgBGR32: |
98 | return 4; |
99 | case ImgRGB: |
100 | case ImgBGR: |
101 | return 3; |
102 | case ImgGray: |
7fd59977 |
103 | default: |
692613e5 |
104 | return 1; |
7fd59977 |
105 | } |
7fd59977 |
106 | } |
107 | |
692613e5 |
108 | // ======================================================================= |
109 | // function : setFormat |
110 | // purpose : |
111 | // ======================================================================= |
112 | void Image_PixMap::setFormat (Image_PixMap::ImgFormat thePixelFormat) |
7fd59977 |
113 | { |
692613e5 |
114 | myImgFormat = thePixelFormat; |
115 | myData.mySizeBPP = SizePixelBytes (myImgFormat); |
7fd59977 |
116 | } |
117 | |
692613e5 |
118 | // ======================================================================= |
119 | // function : setTopDown |
120 | // purpose : |
121 | // ======================================================================= |
122 | void Image_PixMap::setTopDown() |
7fd59977 |
123 | { |
692613e5 |
124 | myData.myTopRowPtr = ((myData.myTopToDown == 1 || myData.myDataPtr == NULL) |
125 | ? myData.myDataPtr : (myData.myDataPtr + myData.mySizeRowBytes * (myData.mySizeY - 1))); |
7fd59977 |
126 | } |
127 | |
692613e5 |
128 | // ======================================================================= |
129 | // function : InitWrapper |
130 | // purpose : |
131 | // ======================================================================= |
132 | bool Image_PixMap::InitWrapper (Image_PixMap::ImgFormat thePixelFormat, |
133 | Standard_Byte* theDataPtr, |
134 | const Standard_Size theSizeX, |
135 | const Standard_Size theSizeY, |
136 | const Standard_Size theSizeRowBytes) |
7fd59977 |
137 | { |
692613e5 |
138 | Clear (thePixelFormat); |
139 | if ((theSizeX == 0) || (theSizeY == 0) || (theDataPtr == NULL)) |
7fd59977 |
140 | { |
692613e5 |
141 | return false; |
7fd59977 |
142 | } |
692613e5 |
143 | myData.mySizeX = theSizeX; |
144 | myData.mySizeY = theSizeY; |
145 | myData.mySizeRowBytes = (theSizeRowBytes != 0) ? theSizeRowBytes : (theSizeX * myData.mySizeBPP); |
146 | myData.myDataPtr = theDataPtr; |
147 | myIsOwnPointer = false; |
148 | setTopDown(); |
149 | return true; |
150 | } |
7fd59977 |
151 | |
692613e5 |
152 | // ======================================================================= |
153 | // function : InitTrash |
154 | // purpose : |
155 | // ======================================================================= |
156 | bool Image_PixMap::InitTrash (Image_PixMap::ImgFormat thePixelFormat, |
157 | const Standard_Size theSizeX, |
158 | const Standard_Size theSizeY, |
159 | const Standard_Size theSizeRowBytes) |
160 | { |
161 | Clear (thePixelFormat); |
162 | if ((theSizeX == 0) || (theSizeY == 0)) |
7fd59977 |
163 | { |
692613e5 |
164 | return false; |
7fd59977 |
165 | } |
692613e5 |
166 | myData.mySizeX = theSizeX; |
167 | myData.mySizeY = theSizeY; |
168 | myData.mySizeRowBytes = myData.mySizeX * myData.mySizeBPP; |
169 | if (theSizeRowBytes > myData.mySizeRowBytes) |
7fd59977 |
170 | { |
692613e5 |
171 | // use argument only if it greater |
172 | myData.mySizeRowBytes = theSizeRowBytes; |
7fd59977 |
173 | } |
692613e5 |
174 | myData.myDataPtr = MemAllocAligned<Standard_Byte*> (SizeBytes()); |
175 | myIsOwnPointer = true; |
176 | setTopDown(); |
177 | return myData.myDataPtr != NULL; |
7fd59977 |
178 | } |
179 | |
692613e5 |
180 | // ======================================================================= |
181 | // function : InitZero |
182 | // purpose : |
183 | // ======================================================================= |
184 | bool Image_PixMap::InitZero (Image_PixMap::ImgFormat thePixelFormat, |
185 | const Standard_Size theSizeX, |
186 | const Standard_Size theSizeY, |
187 | const Standard_Size theSizeRowBytes, |
188 | const Standard_Byte theValue) |
7fd59977 |
189 | { |
692613e5 |
190 | if (!InitTrash (thePixelFormat, theSizeX, theSizeY, theSizeRowBytes)) |
191 | { |
192 | return false; |
193 | } |
194 | memset (myData.myDataPtr, (int )theValue, SizeBytes()); |
195 | return true; |
7fd59977 |
196 | } |
197 | |
692613e5 |
198 | // ======================================================================= |
199 | // function : InitCopy |
200 | // purpose : |
201 | // ======================================================================= |
202 | bool Image_PixMap::InitCopy (const Image_PixMap& theCopy) |
7fd59977 |
203 | { |
692613e5 |
204 | if (&theCopy == this) |
7fd59977 |
205 | { |
692613e5 |
206 | // self-copying disallowed |
207 | return false; |
7fd59977 |
208 | } |
692613e5 |
209 | if (InitTrash (theCopy.myImgFormat, theCopy.myData.mySizeX, theCopy.myData.mySizeY, theCopy.myData.mySizeRowBytes)) |
210 | { |
211 | memcpy (myData.myDataPtr, theCopy.myData.myDataPtr, theCopy.SizeBytes()); |
212 | return true; |
213 | } |
214 | return false; |
7fd59977 |
215 | } |
216 | |
85e096c3 |
217 | // ======================================================================= |
692613e5 |
218 | // function : Clear |
85e096c3 |
219 | // purpose : |
220 | // ======================================================================= |
692613e5 |
221 | void Image_PixMap::Clear (Image_PixMap::ImgFormat thePixelFormat) |
85e096c3 |
222 | { |
692613e5 |
223 | if (myIsOwnPointer && (myData.myDataPtr != NULL)) |
224 | { |
225 | MemFreeAligned (myData.myDataPtr); |
226 | } |
227 | myData.myDataPtr = myData.myTopRowPtr = NULL; |
228 | myIsOwnPointer = true; |
229 | myData.mySizeX = myData.mySizeY = myData.mySizeRowBytes = 0; |
230 | setFormat (thePixelFormat); |
85e096c3 |
231 | } |
232 | |
233 | // ======================================================================= |
234 | // function : PixelColor |
235 | // purpose : |
236 | // ======================================================================= |
237 | Quantity_Color Image_PixMap::PixelColor (const Standard_Integer theX, |
238 | const Standard_Integer theY, |
239 | Quantity_Parameter& theAlpha) const |
7fd59977 |
240 | { |
692613e5 |
241 | if (IsEmpty() || |
242 | theX < 0 || (Standard_Size )theX >= myData.mySizeX || |
243 | theY < 0 || (Standard_Size )theY >= myData.mySizeY) |
7fd59977 |
244 | { |
85e096c3 |
245 | theAlpha = 0.0; // transparent |
7fd59977 |
246 | return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB); |
247 | } |
692613e5 |
248 | |
249 | switch (myImgFormat) |
7fd59977 |
250 | { |
692613e5 |
251 | case ImgGrayF: |
252 | { |
253 | const Standard_ShortReal& aPixel = Value<Standard_ShortReal> (theY, theX); |
254 | theAlpha = 1.0; // opaque |
255 | return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel)), |
256 | Quantity_Parameter (Standard_Real (aPixel)), |
257 | Quantity_Parameter (Standard_Real (aPixel)), |
258 | Quantity_TOC_RGB); |
692613e5 |
259 | } |
260 | case ImgRGBAF: |
261 | { |
262 | const Image_ColorRGBAF& aPixel = Value<Image_ColorRGBAF> (theY, theX); |
263 | theAlpha = aPixel.a(); |
264 | return Quantity_Color (Quantity_Parameter (aPixel.r()), |
265 | Quantity_Parameter (aPixel.g()), |
266 | Quantity_Parameter (aPixel.b()), |
267 | Quantity_TOC_RGB); |
268 | } |
269 | case ImgBGRAF: |
270 | { |
271 | const Image_ColorBGRAF& aPixel = Value<Image_ColorBGRAF> (theY, theX); |
272 | theAlpha = aPixel.a(); |
273 | return Quantity_Color (Quantity_Parameter (aPixel.r()), |
274 | Quantity_Parameter (aPixel.g()), |
275 | Quantity_Parameter (aPixel.b()), |
276 | Quantity_TOC_RGB); |
277 | } |
278 | case ImgRGBF: |
279 | { |
280 | const Image_ColorRGBF& aPixel = Value<Image_ColorRGBF> (theY, theX); |
281 | theAlpha = 1.0; // opaque |
282 | return Quantity_Color (Quantity_Parameter (aPixel.r()), |
283 | Quantity_Parameter (aPixel.g()), |
284 | Quantity_Parameter (aPixel.b()), |
285 | Quantity_TOC_RGB); |
286 | } |
287 | case ImgBGRF: |
7fd59977 |
288 | { |
692613e5 |
289 | const Image_ColorBGRF& aPixel = Value<Image_ColorBGRF> (theY, theX); |
290 | theAlpha = 1.0; // opaque |
291 | return Quantity_Color (Quantity_Parameter (aPixel.r()), |
292 | Quantity_Parameter (aPixel.g()), |
293 | Quantity_Parameter (aPixel.b()), |
294 | Quantity_TOC_RGB); |
295 | } |
296 | case ImgRGBA: |
297 | { |
298 | const Image_ColorRGBA& aPixel = Value<Image_ColorRGBA> (theY, theX); |
299 | theAlpha = Standard_Real (aPixel.a()) / 255.0; |
300 | return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0), |
301 | Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0), |
302 | Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0), |
303 | Quantity_TOC_RGB); |
304 | } |
305 | case ImgBGRA: |
306 | { |
307 | const Image_ColorBGRA& aPixel = Value<Image_ColorBGRA> (theY, theX); |
308 | theAlpha = Standard_Real (aPixel.a()) / 255.0; |
309 | return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0), |
310 | Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0), |
311 | Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0), |
312 | Quantity_TOC_RGB); |
313 | } |
314 | case ImgRGB32: |
315 | { |
316 | const Image_ColorRGB32& aPixel = Value<Image_ColorRGB32> (theY, theX); |
317 | theAlpha = 1.0; // opaque |
318 | return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0), |
319 | Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0), |
320 | Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0), |
321 | Quantity_TOC_RGB); |
322 | } |
323 | case ImgBGR32: |
324 | { |
325 | const Image_ColorBGR32& aPixel = Value<Image_ColorBGR32> (theY, theX); |
326 | theAlpha = 1.0; // opaque |
327 | return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0), |
328 | Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0), |
329 | Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0), |
330 | Quantity_TOC_RGB); |
331 | } |
332 | case ImgRGB: |
333 | { |
334 | const Image_ColorRGB& aPixel = Value<Image_ColorRGB> (theY, theX); |
335 | theAlpha = 1.0; // opaque |
336 | return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0), |
337 | Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0), |
338 | Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0), |
339 | Quantity_TOC_RGB); |
340 | } |
341 | case ImgBGR: |
342 | { |
343 | const Image_ColorBGR& aPixel = Value<Image_ColorBGR> (theY, theX); |
344 | theAlpha = 1.0; // opaque |
345 | return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel.r()) / 255.0), |
346 | Quantity_Parameter (Standard_Real (aPixel.g()) / 255.0), |
347 | Quantity_Parameter (Standard_Real (aPixel.b()) / 255.0), |
348 | Quantity_TOC_RGB); |
349 | } |
350 | case ImgGray: |
351 | { |
352 | const Standard_Byte& aPixel = Value<Standard_Byte> (theY, theX); |
353 | theAlpha = 1.0; // opaque |
354 | return Quantity_Color (Quantity_Parameter (Standard_Real (aPixel) / 255.0), |
355 | Quantity_Parameter (Standard_Real (aPixel) / 255.0), |
356 | Quantity_Parameter (Standard_Real (aPixel) / 255.0), |
357 | Quantity_TOC_RGB); |
358 | } |
359 | default: |
360 | { |
361 | // not supported image type |
362 | theAlpha = 0.0; // transparent |
363 | return Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB); |
7fd59977 |
364 | } |
365 | } |
7fd59977 |
366 | } |