3899367c0ad551108701644f3ebc91b22c81dc60
[occt.git] / src / Graphic3d / Graphic3d_MarkerImage.cxx
1 // Created on: 2013-06-25
2 // Created by: Dmitry BOBYLEV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <Graphic3d_MarkerImage.hxx>
17
18 #include <Image_PixMap.hxx>
19 #include <Standard_Atomic.hxx>
20 #include <TColStd_HArray1OfByte.hxx>
21
22 namespace
23 {
24   static volatile Standard_Integer THE_MARKER_IMAGE_COUNTER = 0;
25 };
26
27
28 // =======================================================================
29 // function : Graphic3d_MarkerImage
30 // purpose  :
31 // =======================================================================
32 Graphic3d_MarkerImage::Graphic3d_MarkerImage (const Handle(Image_PixMap)& theImage)
33 : myBitMap (NULL),
34   myImage  (theImage),
35   myImageAlpha (NULL),
36   myMargin (1),
37   myWidth  ((Standard_Integer )theImage->Width()),
38   myHeight ((Standard_Integer )theImage->Height())
39 {
40   myImageId = TCollection_AsciiString ("Graphic3d_MarkerImage_")
41             + TCollection_AsciiString (Standard_Atomic_Increment (&THE_MARKER_IMAGE_COUNTER));
42
43   myImageAlphaId = TCollection_AsciiString ("Graphic3d_MarkerImageAlpha_")
44                  + TCollection_AsciiString (THE_MARKER_IMAGE_COUNTER);
45 }
46
47 // =======================================================================
48 // function : Graphic3d_MarkerImage
49 // purpose  :
50 // =======================================================================
51 Graphic3d_MarkerImage::Graphic3d_MarkerImage (const Handle(TColStd_HArray1OfByte)& theBitMap,
52                                               const Standard_Integer& theWidth,
53                                               const Standard_Integer& theHeight)
54 : myBitMap (theBitMap),
55   myImage  (NULL),
56   myImageAlpha (NULL),
57   myMargin (1),
58   myWidth  (theWidth),
59   myHeight (theHeight)
60 {
61   myImageId = TCollection_AsciiString ("Graphic3d_MarkerImage_")
62             + TCollection_AsciiString (Standard_Atomic_Increment (&THE_MARKER_IMAGE_COUNTER));
63
64   myImageAlphaId = TCollection_AsciiString ("Graphic3d_MarkerImageAlpha_")
65                  + TCollection_AsciiString (THE_MARKER_IMAGE_COUNTER);
66 }
67
68 // =======================================================================
69 // function : GetBitMapArray
70 // purpose  :
71 // =======================================================================
72 Handle(TColStd_HArray1OfByte) Graphic3d_MarkerImage::GetBitMapArray (const Standard_Real& theAlphaValue) const
73 {
74   if (!myBitMap.IsNull())
75   {
76     return myBitMap;
77   }
78
79   Handle(TColStd_HArray1OfByte) aBitMap;
80   if (myImage.IsNull())
81   {
82     return aBitMap;
83   }
84
85   const Standard_Integer aNumOfBytesInRow = (Standard_Integer )(myImage->Width() / 8) + (myImage->Width() % 8 ? 1 : 0);
86   const Standard_Integer aNumOfBytes      = (Standard_Integer )(aNumOfBytesInRow * myImage->Height());
87   const Standard_Integer aHeight = (Standard_Integer )myImage->Height();
88   const Standard_Integer aWidth  = (Standard_Integer )myImage->Width();
89   aBitMap = new TColStd_HArray1OfByte (0, aNumOfBytes - 1);
90   aBitMap->Init (0);
91   for (Standard_Integer aRow = 0; aRow < aHeight; aRow++)
92   {
93     for (Standard_Integer aColumn = 0; aColumn < aWidth; aColumn++)
94     {
95       Quantity_Parameter anAlphaValue;
96       Quantity_Color aColor = myImage->PixelColor (aColumn, aRow, anAlphaValue);
97       Standard_Boolean aBitOn = Standard_False;
98
99       if (myImage->Format() == Image_PixMap::ImgAlpha)
100       {
101         aBitOn = anAlphaValue > theAlphaValue;
102       }
103       else if (myImage->Format() == Image_PixMap::ImgGray)
104       {
105         aBitOn = aColor.Red() > theAlphaValue;
106       }
107       else
108       {
109         aBitOn = anAlphaValue > theAlphaValue;
110       }
111
112       Standard_Integer anIndex = aNumOfBytesInRow * aRow + aColumn / 8;
113       aBitMap->SetValue (anIndex, (Standard_Byte)(aBitMap->Value (anIndex) + 
114                                                   (aBitOn ? (0x80 >> (aColumn % 8)) : 0)));
115     }
116   }
117
118   return aBitMap;
119 }
120
121 // =======================================================================
122 // function : GetImage
123 // purpose  :
124 // =======================================================================
125 const Handle(Image_PixMap)& Graphic3d_MarkerImage::GetImage()
126 {
127   if (!myImage.IsNull())
128   {
129     return myImage;
130   }
131
132   if (myBitMap.IsNull())
133   {
134     return myImage;
135   }
136
137   // Converting a byte array to bitmap image. Row and column offsets are used
138   // to store bitmap in a square image, so the image will not be stretched
139   // when rendering with point sprites.
140   const Standard_Integer aNumOfBytesInRow = myWidth / 8 + (myWidth % 8 ? 1 : 0);
141   const Standard_Integer aSize            = Max (myWidth, myHeight);
142   const Standard_Integer aRowOffset       = (aSize - myHeight) / 2 + myMargin;
143   const Standard_Integer aColumnOffset    = (aSize - myWidth ) / 2 + myMargin;
144   const Standard_Integer aLowerIndex      = myBitMap->Lower();
145
146   myImage = new Image_PixMap();
147   myImage->InitZero (Image_PixMap::ImgAlpha, aSize + myMargin * 2, aSize + myMargin * 2);
148   for (Standard_Integer aRowIter = 0; aRowIter < myHeight; aRowIter++)
149   {
150     Standard_Byte* anImageRow = myImage->ChangeRow (aRowIter + aRowOffset);
151     for (Standard_Integer aColumnIter = 0; aColumnIter < myWidth; aColumnIter++)
152     {
153       Standard_Boolean aBitOn = myBitMap->Value (aLowerIndex + aNumOfBytesInRow * aRowIter + aColumnIter / 8) & (0x80 >> (aColumnIter % 8));
154       anImageRow[aColumnIter + aColumnOffset] = aBitOn ? 255 : 0;
155     }
156   }
157
158   return myImage;
159 }
160
161 // =======================================================================
162 // function : GetImageAlpha
163 // purpose  :
164 // =======================================================================
165 const Handle(Image_PixMap)& Graphic3d_MarkerImage::GetImageAlpha()
166 {
167   if (!myImageAlpha.IsNull())
168   {
169     return myImageAlpha;
170   }
171
172   if (!myImage.IsNull())
173   {
174     if (myImage->Format() == Image_PixMap::ImgGray
175      || myImage->Format() == Image_PixMap::ImgAlpha)
176     {
177       myImageAlpha = myImage;
178     }
179     else
180     {
181       myImageAlpha = new Image_PixMap();
182       myImageAlpha->InitZero (Image_PixMap::ImgAlpha, myImage->Width(), myImage->Height());
183       myImageAlpha->SetTopDown (Standard_False);
184       Quantity_Parameter anAlpha;
185       for (Standard_Size aRowIter = 0; aRowIter < myImage->Height(); aRowIter++)
186       {
187         Standard_Byte* anImageRow = myImageAlpha->ChangeRow (aRowIter);
188         for (Standard_Size aColumnIter = 0; aColumnIter < myImage->Width(); aColumnIter++)
189         {
190           myImage->PixelColor ((Standard_Integer)aColumnIter, (Standard_Integer)aRowIter, anAlpha);
191           anImageRow[aColumnIter] = Standard_Byte (255.0 * anAlpha);
192         }
193       }
194     }
195   }
196
197   return myImageAlpha;
198 }
199
200 // =======================================================================
201 // function : GetImageId
202 // purpose  :
203 // =======================================================================
204 const TCollection_AsciiString& Graphic3d_MarkerImage::GetImageId() const
205 {
206   return myImageId;
207 }
208
209 // =======================================================================
210 // function : GetImageAlphaId
211 // purpose  :
212 // =======================================================================
213 const TCollection_AsciiString& Graphic3d_MarkerImage::GetImageAlphaId() const
214 {
215   return myImageAlphaId;
216 }
217
218 // =======================================================================
219 // function : GetTextureSize
220 // purpose  :
221 // =======================================================================
222 void Graphic3d_MarkerImage::GetTextureSize (Standard_Integer& theWidth,
223                                             Standard_Integer& theHeight) const
224 {
225   theWidth  = myWidth;
226   theHeight = myHeight;
227 }