Skip to content

Color picker - Lab format: use roundoff optional #13603#42986

Merged
vanzue merged 3 commits intomicrosoft:mainfrom
ruthiesun:ruthiesun/rounded-cielab-format
Feb 27, 2026
Merged

Color picker - Lab format: use roundoff optional #13603#42986
vanzue merged 3 commits intomicrosoft:mainfrom
ruthiesun:ruthiesun/rounded-cielab-format

Conversation

@ruthiesun
Copy link
Copy Markdown
Contributor

@ruthiesun ruthiesun commented Oct 27, 2025

Summary of the Pull Request

The default CIELab format rounds the values to two decimal places, which is a degree of precision that isn't always needed. This PR adds an optional formatting character (i) to the three CIELab format parameters, which rounds the value to the nearest integer.

PR Checklist

Detailed Description of the Pull Request / Additional comments

In the case where a or b get rounded to -0 (e.g. -0.0001 rounds to -0), the negative sign gets removed. However, I noticed during testing that the default format (rounding to two decimal places) retains the negative sign in these situations (see third screenshot). I can a) revert to keeping the -0 for the new rounding behavior, b) change -0 to 0 for other rounded values, or c) leave it as-is. Also open to suggestions.

I can update the docs as well, if we're happy with the approach.

Validation Steps Performed

  • Settings: Can change the default CIELab format to display rounded values
  • Settings: Can create a custom format with rounded CIELab values
  • Color Picker: Rounded values are displayed when hovering and as a saved color
powertoys-cielab powertoys-cielab-selected powertoys-cielab-selected-0

@ruthiesun
Copy link
Copy Markdown
Contributor Author

@microsoft-github-policy-service agree

@niels9001
Copy link
Copy Markdown
Collaborator

/azp run

@niels9001 niels9001 added 0.98 and removed In for .97 labels Feb 24, 2026
@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@vanzue
Copy link
Copy Markdown
Contributor

vanzue commented Feb 25, 2026

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an optional integer-rounding formatter for CIELab components in Color Picker formats, and updates the Settings UI help so users can discover/use the new formatter.

Changes:

  • Extends ColorFormatHelper to support an i format suffix for %Lc/%Ca/%Cb to round CIELab values to whole numbers.
  • Updates the Settings UI Color Format Editor to show the new CIELab-specific formatter option.
  • Updates localized help strings to describe CIELab formatting options.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

File Description
src/settings-ui/Settings.UI/Strings/en-us/Resources.resw Updates help text and adds a new localized description for integer rounding.
src/settings-ui/Settings.UI/SettingsXAML/Controls/ColorFormatEditor.xaml.cs Populates a new CIELab formatter list (adds i) and renames the RGBA formatter list control.
src/settings-ui/Settings.UI/SettingsXAML/Controls/ColorFormatEditor.xaml Adds UI elements to display the CIELab formatter list and adjusts helpline text blocks accordingly.
src/common/ManagedCommon/ColorFormatHelper.cs Implements the i formatter behavior for CIELab output via a shared formatting helper.

Comment on lines +599 to +602
case 'i':
double roundedColorPercentValue = Math.Round(colorPercentValue);
if (roundedColorPercentValue == 0)
{
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Math.Round(colorPercentValue) uses midpoint rounding-to-even by default. For a user-facing “rounded to nearest integer” option this can be surprising for *.5 values (e.g., 74.5 -> 74). Consider explicitly choosing a midpoint mode (commonly AwayFromZero) so rounding matches typical expectations.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be ok in this scenario

Comment on lines +595 to +598
private static string ColorPercentFormatted(double colorPercentValue, char paramFormat, int defaultDecimalDigits)
{
switch (paramFormat)
{
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new i formatter for %Lc/%Ca/%Cb is behavior-changing but doesn’t appear to have unit coverage. There are existing ColorPicker unit tests for default format output; please add tests that assert integer rounding (and edge cases like negative values near 0) to prevent regressions.

Copilot generated this review using guidance from repository custom instructions.
Comment on lines +595 to +612
private static string ColorPercentFormatted(double colorPercentValue, char paramFormat, int defaultDecimalDigits)
{
switch (paramFormat)
{
case 'i':
double roundedColorPercentValue = Math.Round(colorPercentValue);
if (roundedColorPercentValue == 0)
{
// convert -0 to 0
roundedColorPercentValue = 0.0;
}

return roundedColorPercentValue.ToString(CultureInfo.InvariantCulture);
default:
return Math.Round(colorPercentValue, defaultDecimalDigits).ToString(CultureInfo.InvariantCulture);
}
}

Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ColorPercentFormatted is now used for CIELab L/a/b values but doesn’t actually apply a percent transformation (no *100, no % sign). Consider renaming the helper to reflect what it does (round/format a double) to avoid confusing future callers.

Suggested change
private static string ColorPercentFormatted(double colorPercentValue, char paramFormat, int defaultDecimalDigits)
{
switch (paramFormat)
{
case 'i':
double roundedColorPercentValue = Math.Round(colorPercentValue);
if (roundedColorPercentValue == 0)
{
// convert -0 to 0
roundedColorPercentValue = 0.0;
}
return roundedColorPercentValue.ToString(CultureInfo.InvariantCulture);
default:
return Math.Round(colorPercentValue, defaultDecimalDigits).ToString(CultureInfo.InvariantCulture);
}
}
/// <summary>
/// Formats a color component value according to the specified format.
/// This helper performs rounding only and does not apply any percent transformation
/// (no multiplication by 100 and no percent sign is added).
/// </summary>
private static string FormatColorComponent(double value, char paramFormat, int defaultDecimalDigits)
{
switch (paramFormat)
{
case 'i':
double roundedValue = Math.Round(value);
if (roundedValue == 0)
{
// convert -0 to 0
roundedValue = 0.0;
}
return roundedValue.ToString(CultureInfo.InvariantCulture);
default:
return Math.Round(value, defaultDecimalDigits).ToString(CultureInfo.InvariantCulture);
}
}
/// <summary>
/// Formats a color value that was historically treated as a "percent" value.
/// This method does not apply a percent transformation; it simply rounds and formats
/// the provided value. Use <see cref="FormatColorComponent"/> for new code.
/// </summary>
[Obsolete("ColorPercentFormatted does not apply a percent transformation. Use FormatColorComponent instead.")]
private static string ColorPercentFormatted(double colorPercentValue, char paramFormat, int defaultDecimalDigits)
{
return FormatColorComponent(colorPercentValue, paramFormat, defaultDecimalDigits);
}

Copilot uses AI. Check for mistakes.
<value>rounded to the nearest integer</value>
</data>
<data name="ColorFormatEditorHelpline4.Text" xml:space="preserve">
<value>Example: %ReX means red value in hex uppercase two digits format.</value>
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The updated help text introduces a Lab-specific formatter (i), but the only example shown is still %ReX (RGB). Consider adding a Lab example (e.g., how to use i with %Lc/%Ca/%Cb) and/or stating the default (two decimal places) when no formatter is provided, so the new option is discoverable.

Suggested change
<value>Example: %ReX means red value in hex uppercase two digits format.</value>
<value>Example: %ReX means red value in hex uppercase two digits format. %Li means lightness value formatted as an integer using the Lab-specific 'i' formatter. When no formatter is provided (for example, %L, %Ca or %Cb), the value is shown with two decimal places by default.</value>

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@vanzue vanzue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified locally

@vanzue vanzue enabled auto-merge (squash) February 25, 2026 06:48
@niels9001 niels9001 self-requested a review February 27, 2026 22:12
@vanzue vanzue merged commit 3e1b07f into microsoft:main Feb 27, 2026
15 checks passed
@drms
Copy link
Copy Markdown

drms commented Feb 28, 2026

Looking forward to the implementation released in next PT version. Thanks

@zateutsch zateutsch added this to the PowerToys 0.98 milestone Mar 4, 2026
@zateutsch zateutsch added the Product-Color Picker All things around the Color Picker utility label Mar 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

0.98 Product-Color Picker All things around the Color Picker utility

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Color picker - Lab format: use roundoff optional

6 participants