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