One, foreword

A ColorPicker is a ColorPicker. When it comes to color pickers, you will probably think of Photoshop, the most used should be design, for development, usually use color pickers are not many opportunities. If one day you need a color picker (mostly for custom colors) in your project, how do you get started? Today I will share with you the design and implementation of the color picker.

Two, color space

To implement a practical color picker, it is necessary to understand the color space. A color space, also known as a color model (also known as a color space or color system), is used to describe color in a generally acceptable manner under certain standards. About the color space, there are some links at the end of the article, which are the essence summary of the predecessors. In particular, the discussion in What’s the Difference between HSL, HSV and HSB in Color Space (zhihu’s answer) made me instantly enlightened after reading it.

This section mainly extracts some expressions of the gods, and to be sorted out. For the sake of reading experience, I will not attach the author one by one, see the link after the article.

2.1 RGB space

RGB is designed from the principle of color luminescence. Generally speaking, its color mixing mode is like having red, green and blue lights. When their lights overlap each other, the colors mix, and the brightness is equal to the sum of the two luminances. The red, green and blue channels are each divided into 256 levels of brightness, with the “lights” weakest at 0, which is off, and brightest at 255. When the gray values of three colors are the same, the gray tones of different gray values are generated, that is, when the gray values of three colors are 0, it is the darkest black tone; When all three colors are at a grayscale of 255, it is the brightest white hue.

2.2 HSB space

RGB is a machine-friendly color pattern, but it’s not human enough because our perception of color is often “What color? Bright or not? Light or dark?” . For example, we usually describe the color, “deep purple”, “light green”, “bright yellow”, “dark red”, one is to explain the basic color, the other is to describe the color itself. HSB(HSV) is based on RGB and is a more user-friendly representation. H(Hue) indicates the Hue. The value ranges from 0° to 360°. It is the base color. S(Saturation) is the Saturation range of 0-1 (0%-100%), indicating the purity of the color. B(Brightness) is the Brightness, with a range of 0-1 (0%-100%), indicating the perception of light. Brightness is also called Value in some places, so there is HSV, HSV and HSB are the same, they just have different names for brightness.

  • For each color of the hue ring, in the RGB space, at most two color channels (R, g, b) are greater than 0, so the color of the hue ring is the purest
  • Lightness determines the size of the three components of RBG, that is, the size of light, which is the difference between light and shade at the perception level.
  • For the color whose saturation is 0, r, g and b are equal. When the lightness is 0, it is black; when the lightness is 1, it is white; when the lightness is greater than 0 and less than 1, it is gray. When the saturation is 1, the color value depends only on the hue and lightness, and lightness only controls the size of the RGB component, so the color is pure; When the saturation is between 0 and 1, is a linear interpolation between a color with a saturation of 0 (black and white) and a color with a saturation of 1. The closer to 1, the purer the color.

2.3 lightness

First look at the HSB color model Picker in Photoshop, as shown in the figure below, THE HSB B (lightness) controls the amount of black mixed into the solid color, the higher the value, the less black, the higher the color lightness.

2.4 the saturation

As shown in the figure below, S (saturation) of HSB controls the amount of white mixed into the solid color. The farther to the right, the greater the value, the less white, and the higher the color purity.

2.5 hue

Hue refers to the external phase of color, it is under the light irradiation of different wavelengths, the human eye feels different colors, such as red, yellow, blue, etc. In HSL and HSV color space, H refers to the hue, with red as 0° (360°); Yellow is 60°; Green is 120°; Cyan is 180°; Blue is 240°; Magenta is 300 degrees.

As you can see from the figure above, from 0° to 360°, is a piecewise function, where each segment has a color component that is 0, one component that is 1, and the other component that is either 0 to 1 or 1 to 0.

2.6 HSB turns RGB

For the user, the HSB space is easier to adjust, but for the computer, rendering with RGB space is more convenient. The following is the conversion formula from HSB to RGB:

In the figure, H, S and V are hue, saturation and lightness respectively. With this set of formulas, we can understand where the hue bars in Section 2.5 came from. Hi = (int) (h/60) % 6. Let s=1, v=1, then p=0, q=1-f, t=f. When I = 0 (the first), (r, g, b) = (v, t, p) = (1, f, 0), and f = = h/h / 60 – hi 60, that is, in the first paragraph, r = 1, 60, g = h/b = 0; Special case: when h=60, r=1,g=1,b=0, mixed yellow. And so on. The other thing to notice is that when H is selected, the color is linear to S and V, which is important for the implementation of the color picker.

3. Design of color picker

3.1 Bar color picker

The netease APP is one of the few apps that require custom colors. Click “Personal Skin Peel -> Select Color”, and this interface will pop up:

In the middle of the page is a preview, and at the bottom is a predefined palette; At the end of the palette, there is a colorful picture, which can be switched to two color bars after clicking, as shown below:

The first color bar looks familiar. It is the hue mentioned earlier. The bottom one should be based on the selected hue, with saturation of 1 and lightness varying from 0 to 1. The two color bars are combined, and the colors range from the sides of the cylinder in Section 2.2. The value range is only a part of the color space, but it is a valuable part. Perhaps the designers at netease only wanted the user to choose bright colors, so they gave up the saturation adjustment in exchange for great simplicity.

3.2 Ring color picker

There are many open source Android color pickers, and HoloColorPicker is one of star’s most popular projects.

This project makes the hue into a ring, under the saturation and brightness adjustment, can be said to be a complete color picker (can select the color of the whole color space). Make the hue into a hue ring, which looks cooler than the hue bar, but takes up more space. Like netease Cloud music color selection, because to preview enough space, so can only use less space to occupy the color picker; Like this one occupies half of the screen design, not suitable for netease Cloud music this color scene.

3.3 PS color picker

Photoshop’s usual color pickers are a rectangular “saturation-Lightness” palette, and a hue bar (which can then be changed to a hue wheel by setting).

Photoshop as a professional image editing software, color picker is undoubtedly very powerful. At the same time, the area of the computer monitor is much larger than that of the mobile phone, and the selection accuracy of the mouse is also more accurate than that of the finger touch screen, so the color picker of Photoshop can be opened and opened to provide a variety of panels, showing comprehensive parameters.

Iv. Technical realization

Through the analysis of the first three sections, we can see that the key points of the color picker are: based on the HSB color space, the value of each HSB component can be adjusted through the bar, ring, rectangle and other coordinates to achieve the color selection.

The first problem to solve is the calculation of the transformation of the color space. Fortunately, the SDK’s Color class provides a way to convert between HSB(HSV) and RGB:

public static void colorToHSV(@ColorInt int color, @Size(3) float hsv[]) 

public static int HSVToColor(@Size(3) float hsv[])
Copy the code

And then the second problem that we have to solve is the drawing of coordinates. Also, the SDK provides a variety of shaders that make it easy to draw various coordinates. Let’s take an example.

4.1 Copy netease Cloud Music

Let’s start with the image:

Like netease Cloud Music, it is displayed in the lower panel with preset color palette. The last box of the color palette can jump to customize dark color. The difference is that there are more transparency and purity adjustments, so that the entire color space can be selected, as well as the alpha channel.

The key points of the above implementation are the hue, saturation (” purity “as title for the same font length), and the drawing of lightness. As mentioned earlier, the hue changes piecewise linearly, so we can use LinearGradient to draw.

public LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[],
            @Nullable float positions[], @NonNull TileMode tile) 
Copy the code

To benefit the LinearGradient color array, simply list the colors at the intersection of the segments:

private static final int[] COLORS = new int[] {
        0xFFFF0000.0xFFFFFF00.0xFF00FF00.0xFF00FFFF.0xFF0000FF.0xFFFF00FF.0xFFFF0000};Copy the code

As mentioned in section 2.6 above, after h is determined, the color is linearly related to S and V, so you can also draw saturation and lightness using LinearGradient. For example, to draw saturation, you simply calculate the color values when the second component of HSV (HSV [1], that is, S) is equal to 0 and 1 as parameters to the LinearGradient colors to draw the change in S (the color bar for saturation) for the current h.

    hsv[1] = 0f;
    colors[0] = Color.HSVToColor(hsv);
    hsv[1] = 1f;
    colors[1] = Color.HSVToColor(hsv);
Copy the code

Brightness is drawn in the same way.

4.2 imitation Photoshop

The hue at 0° and 360° corresponds to red, and the first place is connected, so many times it will be made into a hue ring (called a hue wheel in Photoshop). Saturation and lightness are more intuitive if combined into a two-dimensional coordinate, which is also the Photoshop solution.

To draw the hue ring, use another Shader:

 public SweepGradient(float cx, float cy,
            @NonNull @ColorInt int colors[], @Nullable float positions[])
Copy the code

Simply substitute the COLORS given in the previous section with the COLORS of the SweepGradient.

To synthesize saturation and lightness, use the ComposeShader:

private Shader getSVShader(a) {
    if (mValShader == null) {
        mValShader = new LinearGradient(
                mSVRect.left, mSVRect.top,
                mSVRect.left, mSVRect.bottom,
                Color.WHITE, Color.BLACK, Shader.TileMode.CLAMP);
    }

    if (mShaderHSV[0] != mHSV[0] || mComposeShader == null) {
        mShaderHSV[0] = mHSV[0];
        Shader satShader = new LinearGradient(
                mSVRect.left, mSVRect.top,
                mSVRect.right, mSVRect.top,
                Color.WHITE, Color.HSVToColor(mShaderHSV), Shader.TileMode.CLAMP);
        mComposeShader = new ComposeShader(mValShader, satShader, PorterDuff.Mode.MULTIPLY);
    }

    return mComposeShader;
}
Copy the code

The ComposeShader can combine two Shaders, because the color is linear to S and V, so you need to combine two Lineargradiens. The first LinearGradient goes from top left to bottom left, white to black; The second LinearGradient goes from top left to top right, from white to hue color. The effect is as follows:

Since the color picking part already takes up so much space, let’s use the rest of the space as a data panel; It also adds an edit box that allows you to manually input RGB colors and limits the input length to hexadecimal.

Five, the summary

In the two kinds of color pickers, it is more space-saving to select color by bar coordinates, while it is relatively intuitive to select color by ring and rectangle. Which one to use depends on the situation: if you want to preview in real time and the color picker doesn’t take up too much space, the first option is appropriate; If you’re making a color palette or something, it’s more efficient to use the second option.

Limited to space, in the implementation aspect did not speak very detailed, the reader can see the specific project code. Code link: github.com/No89757/Col…

What is the difference between HSL, HSV and HSB in color Space