14e853af4c8acf916e881fcbc0a5bc2c7143efbb
[occt.git] / src / Graphic3d / Graphic3d_MarkerImage.cxx
1 // Created on: 2013-06-25
2 // Created by: Dmitry BOBYLEV
3 // Copyright (c) 2013 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 #include <Graphic3d_MarkerImage.hxx>
21
22 #include <Image_PixMap.hxx>
23 #include <Standard_Atomic.hxx>
24 #include <TColStd_HArray1OfByte.hxx>
25
26 namespace
27 {
28   static volatile Standard_Integer THE_MARKER_IMAGE_COUNTER = 0;
29 };
30
31 IMPLEMENT_STANDARD_HANDLE (Graphic3d_MarkerImage, Standard_Transient)
32 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_MarkerImage, Standard_Transient)
33
34 // =======================================================================
35 // function : Graphic3d_MarkerImage
36 // purpose  :
37 // =======================================================================
38 Graphic3d_MarkerImage::Graphic3d_MarkerImage (const Handle(Image_PixMap)& theImage)
39 : myBitMap (NULL),
40   myImage  (theImage),
41   myImageAlpha (NULL),
42   myMargin (1),
43   myWidth  ((Standard_Integer )theImage->Width()),
44   myHeight ((Standard_Integer )theImage->Height())
45 {
46   myImageId = TCollection_AsciiString ("Graphic3d_MarkerImage_")
47             + TCollection_AsciiString (Standard_Atomic_Increment (&THE_MARKER_IMAGE_COUNTER));
48
49   myImageAlphaId = TCollection_AsciiString ("Graphic3d_MarkerImageAlpha_")
50                  + TCollection_AsciiString (THE_MARKER_IMAGE_COUNTER);
51 }
52
53 // =======================================================================
54 // function : Graphic3d_MarkerImage
55 // purpose  :
56 // =======================================================================
57 Graphic3d_MarkerImage::Graphic3d_MarkerImage (const Handle(TColStd_HArray1OfByte)& theBitMap,
58                                               const Standard_Integer& theWidth,
59                                               const Standard_Integer& theHeight)
60 : myBitMap (theBitMap),
61   myImage  (NULL),
62   myImageAlpha (NULL),
63   myMargin (1),
64   myWidth  (theWidth),
65   myHeight (theHeight)
66 {
67   myImageId = TCollection_AsciiString ("Graphic3d_MarkerImage_")
68             + TCollection_AsciiString (Standard_Atomic_Increment (&THE_MARKER_IMAGE_COUNTER));
69
70   myImageAlphaId = TCollection_AsciiString ("Graphic3d_MarkerImageAlpha_")
71                  + TCollection_AsciiString (THE_MARKER_IMAGE_COUNTER);
72 }
73
74 // =======================================================================
75 // function : GetBitMapArray
76 // purpose  :
77 // =======================================================================
78 Handle(TColStd_HArray1OfByte) Graphic3d_MarkerImage::GetBitMapArray (const Standard_Real& theAlphaValue) const
79 {
80   if (!myBitMap.IsNull())
81   {
82     return myBitMap;
83   }
84
85   Handle(TColStd_HArray1OfByte) aBitMap;
86   if (myImage.IsNull())
87   {
88     return aBitMap;
89   }
90
91   const Standard_Integer aNumOfBytesInRow = (Standard_Integer )(myImage->Width() / 8) + (myImage->Width() % 8 ? 1 : 0);
92   const Standard_Integer aNumOfBytes      = (Standard_Integer )(aNumOfBytesInRow * myImage->Height());
93   const Standard_Integer aHeight = (Standard_Integer )myImage->Height();
94   const Standard_Integer aWidth  = (Standard_Integer )myImage->Width();
95   aBitMap = new TColStd_HArray1OfByte (0, aNumOfBytes - 1);
96   aBitMap->Init (0);
97   for (Standard_Integer aRow = 0; aRow < aHeight; aRow++)
98   {
99     for (Standard_Integer aColumn = 0; aColumn < aWidth; aColumn++)
100     {
101       Quantity_Parameter anAlphaValue;
102       Quantity_Color aColor = myImage->PixelColor (aColumn, aRow, anAlphaValue);
103       Standard_Boolean aBitOn = Standard_False;
104
105       if (myImage->Format() == Image_PixMap::ImgGray)
106       {
107         aBitOn = aColor.Red() > theAlphaValue;
108       }
109       else
110       {
111         aBitOn = anAlphaValue > theAlphaValue;
112       }
113
114       aBitMap->ChangeValue (aNumOfBytesInRow * aRow + aColumn / 8) += 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::ImgGray, 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     {
176       myImageAlpha = myImage;
177     }
178     else
179     {
180       myImageAlpha = new Image_PixMap();
181       myImageAlpha->InitZero (Image_PixMap::ImgGray, myImage->Width(), myImage->Height());
182       myImageAlpha->SetTopDown (Standard_False);
183       Quantity_Parameter anAlpha;
184       for (Standard_Integer aRowIter = 0; aRowIter < myImage->Height(); aRowIter++)
185       {
186         Standard_Byte* anImageRow = myImageAlpha->ChangeRow (aRowIter);
187         for (Standard_Integer aColumnIter = 0; aColumnIter < myImage->Width(); aColumnIter++)
188         {
189           myImage->PixelColor (aColumnIter, aRowIter, anAlpha);
190           anImageRow[aColumnIter] = Standard_Byte (255.0 * anAlpha);
191         }
192       }
193     }
194   }
195
196   return myImageAlpha;
197 }
198
199 // =======================================================================
200 // function : GetImageId
201 // purpose  :
202 // =======================================================================
203 const TCollection_AsciiString& Graphic3d_MarkerImage::GetImageId() const
204 {
205   return myImageId;
206 }
207
208 // =======================================================================
209 // function : GetImageAlphaId
210 // purpose  :
211 // =======================================================================
212 const TCollection_AsciiString& Graphic3d_MarkerImage::GetImageAlphaId() const
213 {
214   return myImageAlphaId;
215 }
216
217 // =======================================================================
218 // function : GetTextureSize
219 // purpose  :
220 // =======================================================================
221 void Graphic3d_MarkerImage::GetTextureSize (Standard_Integer& theWidth,
222                                             Standard_Integer& theHeight) const
223 {
224   theWidth  = myWidth;
225   theHeight = myHeight;
226 }