| 2376 | } |
| 2377 | |
| 2378 | void CColorCopDlg::OnPopupColorConverttograyscale() { |
| 2379 | CString strStatus; |
| 2380 | |
| 2381 | // Converts the current color to grayscale. |
| 2382 | // |
| 2383 | // If R, G, and B are already equal, the color is already gray. |
| 2384 | if ((m_Reddec == m_Greendec) && (m_Greendec == m_Bluedec)) { |
| 2385 | strStatus.LoadString(IDS_COLOR_GRAY); |
| 2386 | SetStatusBarText(strStatus); |
| 2387 | } else { |
| 2388 | strStatus.LoadString(IDS_COLOR_CONVERT_GRAY); |
| 2389 | SetStatusBarText(strStatus); |
| 2390 | |
| 2391 | // |
| 2392 | // grayscale values have identical R, G, B values. |
| 2393 | // |
| 2394 | // This implementation uses the "lightness" definition from HSL: |
| 2395 | // L = (max(R,G,B) + min(R,G,B)) / 2 |
| 2396 | // |
| 2397 | // This picks the midpoint on the neutral axis between the darkest |
| 2398 | // and brightest channel. After this desaturation, the RGB channels |
| 2399 | // all receive the same value, producing a grayscale color. |
| 2400 | // |
| 2401 | |
| 2402 | // Compute channel extrema in int. |
| 2403 | const int Max = std::max({m_Reddec, m_Greendec, m_Bluedec}); |
| 2404 | const int Min = std::min({m_Reddec, m_Greendec, m_Bluedec}); |
| 2405 | |
| 2406 | // Compute grayscale lightness in int. |
| 2407 | const int L = (Min + Max) / 2; |
| 2408 | |
| 2409 | // Apply grayscale value to all channels. |
| 2410 | m_Reddec = L; |
| 2411 | m_Greendec = L; |
| 2412 | m_Bluedec = L; |
| 2413 | |
| 2414 | // Push updated values to UI and recalc dependent fields. |
| 2415 | UpdateData(false); |
| 2416 | OnconvertRGB(); |
| 2417 | OnCopytoclip(); |
| 2418 | } |
| 2419 | return; |
| 2420 | } |
| 2421 | |
| 2422 | void CColorCopDlg::OnFileAbout() { |
| 2423 | CAboutDlg dlg; |
nothing calls this directly
no outgoing calls
no test coverage detected