@@ -56,10 +56,11 @@ void DrawBitmap(CDC *pDC, int x, int y, CBitmap *pBitmap)
5656 * @brief Duplicate a bitmap and make it dark
5757 * @param pDC [in] Device context
5858 * @param pBitmap [in] the bitmap to darken
59+ * @param radius [in]
5960 * @param lighten [in] make bitmap lighten if ligthen is true
6061 * @return The bitmap object
6162 */
62- CBitmap *GetDarkenedBitmap (CDC *pDC, CBitmap *pBitmap, bool lighten)
63+ CBitmap *GetDarkenedBitmap (CDC *pDC, CBitmap *pBitmap, int radius, bool lighten)
6364{
6465 CDC dcMem;
6566 dcMem.CreateCompatibleDC (pDC);
@@ -73,7 +74,7 @@ CBitmap *GetDarkenedBitmap(CDC *pDC, CBitmap *pBitmap, bool lighten)
7374 BITMAPINFO bi;
7475 bi.bmiHeader .biSize = sizeof (bi.bmiHeader );
7576 bi.bmiHeader .biWidth = bm.bmWidth ;
76- bi.bmiHeader .biHeight = bm.bmHeight ;
77+ bi.bmiHeader .biHeight = - bm.bmHeight ;
7778 bi.bmiHeader .biPlanes = 1 ;
7879 bi.bmiHeader .biBitCount = 32 ;
7980 bi.bmiHeader .biCompression = 0 ;
@@ -86,77 +87,156 @@ CBitmap *GetDarkenedBitmap(CDC *pDC, CBitmap *pBitmap, bool lighten)
8687 auto pbuf = std::make_unique<BYTE[]>(bi.bmiHeader .biSizeImage );
8788 GetDIBits (dcMem.m_hDC , (HBITMAP)*pBitmapDarkened, 0 , bm.bmHeight , pbuf.get (), &bi, DIB_RGB_COLORS);
8889
90+ radius = std::clamp (radius, 0 , static_cast <int >((std::min)(bm.bmWidth / 3 , bm.bmHeight / 3 )));
91+
8992 if (!lighten)
9093 {
91- for (int x = 0 ; x < bm.bmWidth ; x++)
92- {
93- double b = 0.85 + (0.10 * sin (acos ((double )x / bm.bmWidth *2.0 - 1.0 )));
94- for (int y = 1 ; y < bm.bmHeight - 1 ; y++)
94+ auto darkenInner = [&pbuf, &bm](int left, int top, int right, int bottom)
95+ {
96+ for (int x = left; x < right; x++)
97+ {
98+ double b = 0.85 + (0.10 * sin (acos ((double )x / bm.bmWidth *2.0 - 1.0 )));
99+ for (int y = top; y < bottom; y++)
100+ {
101+ {
102+ int i = x * 4 + y * bm.bmWidth * 4 ;
103+ pbuf[i] = (BYTE)(pbuf[i] * 0.95 );
104+ pbuf[i + 1 ] = (BYTE)(pbuf[i + 1 ] * b);
105+ pbuf[i + 2 ] = (BYTE)(pbuf[i + 2 ] * b);
106+ }
107+ }
108+ }
109+
110+ };
111+ auto darkenCorner = [&pbuf, &bm](int left, int top, int right, int bottom, int cx, int cy, int radius)
112+ {
113+ auto sqr = [](double x) { return x * x; };
114+ for (int x = left; x < right; x++)
115+ {
116+ const double b = 0.85 + (0.10 * sin (acos ((double )x / bm.bmWidth *2.0 - 1.0 )));
117+ for (int y = top; y < bottom; y++)
118+ {
119+ int i = x * 4 + y * bm.bmWidth * 4 ;
120+ const double dist = std::sqrt (sqr (x - cx) + sqr (y - cy)) - static_cast <double >(radius);
121+ if (dist < 0 )
122+ {
123+ pbuf[i] = (BYTE)(pbuf[i] * 0.95 );
124+ pbuf[i + 1 ] = (BYTE)(pbuf[i + 1 ] * b);
125+ pbuf[i + 2 ] = (BYTE)(pbuf[i + 2 ] * b);
126+ }
127+ else if (dist <= 1.0 )
128+ {
129+ pbuf[i] = (BYTE)(pbuf[i] * (0.95 + 0.05 * dist));
130+ pbuf[i + 1 ] = (BYTE)(pbuf[i + 1 ] * (0.9 + 0.1 * dist));
131+ pbuf[i + 2 ] = (BYTE)(pbuf[i + 2 ] * (0.9 + 0.1 * dist));
132+ }
133+ }
134+ }
135+ };
136+ auto darkenTopBottomEdge = [&pbuf, &bm](int y, int left, int right)
95137 {
96- int i = x * 4 + y * bm.bmWidth * 4 ;
97- pbuf[i] = (BYTE)(pbuf[i] * 0.95 );
98- pbuf[i + 1 ] = (BYTE)(pbuf[i + 1 ] * b);
99- pbuf[i + 2 ] = (BYTE)(pbuf[i + 2 ] * b);
100- }
101- }
102- for (int x = 0 ; x < bm.bmWidth ; x++)
103- {
104- int i = x * 4 + 0 * bm.bmWidth * 4 ;
105- pbuf[i] = (BYTE)(pbuf[i] * 0.95 );
106- pbuf[i + 1 ] = (BYTE)(pbuf[i + 1 ] * 0.9 );
107- pbuf[i + 2 ] = (BYTE)(pbuf[i + 2 ] * 0.9 );
108- i = x * 4 + (bm.bmHeight - 1 ) * bm.bmWidth * 4 ;
109- pbuf[i] = (BYTE)(pbuf[i] * 0.95 );
110- pbuf[i + 1 ] = (BYTE)(pbuf[i + 1 ] * 0.9 );
111- pbuf[i + 2 ] = (BYTE)(pbuf[i + 2 ] * 0.9 );
112- }
113- for (int y = 0 ; y < bm.bmHeight ; y++)
114- {
115- int i = 0 * 4 + y * bm.bmWidth * 4 ;
116- pbuf[i] = (BYTE)(pbuf[i] * 0.95 );
117- pbuf[i + 1 ] = (BYTE)(pbuf[i + 1 ] * 0.9 );
118- pbuf[i + 2 ] = (BYTE)(pbuf[i + 2 ] * 0.9 );
119- i = (bm.bmWidth - 1 ) * 4 + y * bm.bmWidth * 4 ;
120- pbuf[i] = (BYTE)(pbuf[i] * 0.95 );
121- pbuf[i + 1 ] = (BYTE)(pbuf[i + 1 ] * 0.9 );
122- pbuf[i + 2 ] = (BYTE)(pbuf[i + 2 ] * 0.9 );
123- }
138+ for (int x = left; x < right; x++)
139+ {
140+ int i = x * 4 + y * bm.bmWidth * 4 ;
141+ pbuf[i] = (BYTE)(pbuf[i] * 0.95 );
142+ pbuf[i + 1 ] = (BYTE)(pbuf[i + 1 ] * 0.9 );
143+ pbuf[i + 2 ] = (BYTE)(pbuf[i + 2 ] * 0.9 );
144+ }
145+ };
146+ auto darkenLeftRightEdge = [&pbuf, &bm](int x, int top, int bottom)
147+ {
148+ for (int y = top; y < bottom; y++)
149+ {
150+ int i = x * 4 + y * bm.bmWidth * 4 ;
151+ pbuf[i] = (BYTE)(pbuf[i] * 0.95 );
152+ pbuf[i + 1 ] = (BYTE)(pbuf[i + 1 ] * 0.85 );
153+ pbuf[i + 2 ] = (BYTE)(pbuf[i + 2 ] * 0.85 );
154+ }
155+ };
156+ darkenInner (radius, 1 , bm.bmWidth - radius, radius);
157+ darkenInner (radius, bm.bmHeight - radius, bm.bmWidth - radius, bm.bmHeight - 1 );
158+ darkenInner (1 , radius, bm.bmWidth - 1 , bm.bmHeight - radius);
159+ darkenCorner (0 , 0 , radius, radius, radius, radius, radius);
160+ darkenCorner (bm.bmWidth - radius, 0 , bm.bmWidth , radius, bm.bmWidth - radius - 1 , radius, radius);
161+ darkenCorner (0 , bm.bmHeight - radius, radius, bm.bmHeight , radius, bm.bmHeight - radius - 1 , radius);
162+ darkenCorner (bm.bmWidth - radius, bm.bmHeight - radius, bm.bmWidth , bm.bmHeight , bm.bmWidth - radius - 1 , bm.bmHeight - radius - 1 , radius);
163+ darkenTopBottomEdge (0 , radius, bm.bmWidth - radius);
164+ darkenTopBottomEdge (bm.bmHeight - 1 , radius, bm.bmWidth - radius);
165+ darkenLeftRightEdge (0 , radius, bm.bmHeight - radius);
166+ darkenLeftRightEdge (bm.bmWidth - 1 , radius, bm.bmHeight - radius);
124167 }
125168 else
126169 {
127- for (int x = 0 ; x < bm.bmWidth ; x++)
128- {
129- int b = static_cast <int >(12.0 + (20.0 * sin (acos ((double )x / bm.bmWidth *2.0 - 1.0 ))));
130- for (int y = 1 ; y < bm.bmHeight - 1 ; y++)
170+ auto lightenInner = [&pbuf, &bm](int left, int top, int right, int bottom)
171+ {
172+ for (int x = left; x < right; x++)
173+ {
174+ int b = static_cast <int >(12.0 + (20.0 * sin (acos ((double )x / bm.bmWidth *2.0 - 1.0 ))));
175+ for (int y = top; y < bottom; y++)
176+ {
177+ int i = x * 4 + y * bm.bmWidth * 4 ;
178+ pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40 , 255 ));
179+ pbuf[i + 1 ] = (BYTE)((std::min)(pbuf[i + 1 ] + b, 255 ));
180+ pbuf[i + 2 ] = (BYTE)((std::min)(pbuf[i + 2 ] + b, 255 ));
181+ }
182+ }
183+ };
184+ auto lightenCorner = [&pbuf, &bm](int left, int top, int right, int bottom, int cx, int cy, int radius)
185+ {
186+ auto sqr = [](double x) { return x * x; };
187+ for (int x = left; x < right; x++)
188+ {
189+ int b = static_cast <int >(12.0 + (20.0 * sin (acos ((double )x / bm.bmWidth *2.0 - 1.0 ))));
190+ for (int y = top; y < bottom; y++)
191+ {
192+ int i = x * 4 + y * bm.bmWidth * 4 ;
193+ const double dist = std::sqrt (sqr (x - cx) + sqr (y - cy)) - static_cast <double >(radius);
194+ if (dist < 0 )
195+ {
196+ pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40 , 255 ));
197+ pbuf[i + 1 ] = (BYTE)((std::min)(pbuf[i + 1 ] + b, 255 ));
198+ pbuf[i + 2 ] = (BYTE)((std::min)(pbuf[i + 2 ] + b, 255 ));
199+ }
200+ else if (dist <= 1.0 )
201+ {
202+ pbuf[i] = (BYTE)((std::min)(pbuf[i] + (BYTE)(40 * (1.0 - dist)), 255 ));
203+ pbuf[i + 1 ] = (BYTE)((std::min)(pbuf[i + 1 ] + (BYTE)(32 * (1.0 - dist)), 255 ));
204+ pbuf[i + 2 ] = (BYTE)((std::min)(pbuf[i + 2 ] + (BYTE)(32 * (1.0 - dist)), 255 ));
205+ }
206+ }
207+ }
208+ };
209+ auto lightenTopBottomEdge = [&pbuf, &bm](int y, int left, int right)
210+ {
211+ for (int x = left; x < right; x++)
212+ {
213+ int i = x * 4 + y * bm.bmWidth * 4 ;
214+ pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40 , 255 ));
215+ pbuf[i + 1 ] = (BYTE)((std::min)(pbuf[i + 1 ] + 32 , 255 ));
216+ pbuf[i + 2 ] = (BYTE)((std::min)(pbuf[i + 2 ] + 32 , 255 ));
217+ }
218+ };
219+ auto lightenLeftRightEdge = [&pbuf, &bm](int x, int top, int bottom)
131220 {
132- int i = x * 4 + y * bm.bmWidth * 4 ;
133- pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40 , 255 ));
134- pbuf[i + 1 ] = (BYTE)((std::min)(pbuf[i + 1 ] + b, 255 ));
135- pbuf[i + 2 ] = (BYTE)((std::min)(pbuf[i + 2 ] + b, 255 ));
136- }
137- }
138- for (int x = 0 ; x < bm.bmWidth ; x++)
139- {
140- int i = x * 4 + 0 * bm.bmWidth * 4 ;
141- pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40 , 255 ));
142- pbuf[i + 1 ] = (BYTE)((std::min)(pbuf[i + 1 ] + 32 , 255 ));
143- pbuf[i + 2 ] = (BYTE)((std::min)(pbuf[i + 2 ] + 32 , 255 ));
144- i = x * 4 + (bm.bmHeight - 1 ) * bm.bmWidth * 4 ;
145- pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40 , 255 ));
146- pbuf[i + 1 ] = (BYTE)((std::min)(pbuf[i + 1 ] + 32 , 255 ));
147- pbuf[i + 2 ] = (BYTE)((std::min)(pbuf[i + 2 ] + 32 , 255 ));
148- }
149- for (int y = 0 ; y < bm.bmHeight ; y++)
150- {
151- int i = 0 * 4 + y * bm.bmWidth * 4 ;
152- pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40 , 255 ));
153- pbuf[i + 1 ] = (BYTE)((std::min)(pbuf[i + 1 ] + 32 , 255 ));
154- pbuf[i + 2 ] = (BYTE)((std::min)(pbuf[i + 2 ] + 32 , 255 ));
155- i = (bm.bmWidth - 1 ) * 4 + y * bm.bmWidth * 4 ;
156- pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40 , 255 ));
157- pbuf[i + 1 ] = (BYTE)((std::min)(pbuf[i + 1 ] + 32 , 255 ));
158- pbuf[i + 2 ] = (BYTE)((std::min)(pbuf[i + 2 ] + 32 , 255 ));
159- }
221+ for (int y = top; y < bottom; y++)
222+ {
223+ int i = x * 4 + y * bm.bmWidth * 4 ;
224+ pbuf[i] = (BYTE)((std::min)(pbuf[i] + 40 , 255 ));
225+ pbuf[i + 1 ] = (BYTE)((std::min)(pbuf[i + 1 ] + 32 , 255 ));
226+ pbuf[i + 2 ] = (BYTE)((std::min)(pbuf[i + 2 ] + 32 , 255 ));
227+ }
228+ };
229+ lightenInner (radius, 1 , bm.bmWidth - radius, radius);
230+ lightenInner (radius, bm.bmHeight - radius, bm.bmWidth - radius, bm.bmHeight - 1 );
231+ lightenInner (1 , radius, bm.bmWidth - 1 , bm.bmHeight - radius);
232+ lightenCorner (0 , 0 , radius, radius, radius, radius, radius);
233+ lightenCorner (bm.bmWidth - radius, 0 , bm.bmWidth , radius, bm.bmWidth - radius - 1 , radius, radius);
234+ lightenCorner (0 , bm.bmHeight - radius, radius, bm.bmHeight , radius, bm.bmHeight - radius - 1 , radius);
235+ lightenCorner (bm.bmWidth - radius, bm.bmHeight - radius, bm.bmWidth , bm.bmHeight , bm.bmWidth - radius - 1 , bm.bmHeight - radius - 1 , radius);
236+ lightenTopBottomEdge (0 , radius, bm.bmWidth - radius);
237+ lightenTopBottomEdge (bm.bmHeight - 1 , radius, bm.bmWidth - radius);
238+ lightenLeftRightEdge (0 , radius, bm.bmHeight - radius);
239+ lightenLeftRightEdge (bm.bmWidth - 1 , radius, bm.bmHeight - radius);
160240 }
161241
162242 SetDIBits (dcMem.m_hDC , (HBITMAP)*pBitmapDarkened, 0 , bm.bmHeight , pbuf.get (), &bi, DIB_RGB_COLORS);
0 commit comments