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