[English](./README.md) | Simplified Chinese

# @ray-js/image-color-picking

[![latest](https://img.shields.io/npm/v/@ray-js/image-color-picking/latest.svg)](https://www.npmjs.com/package/@ray-js/image-color-picking) [![download](https://img.shields.io/npm/dt/@ray-js/image-color-picking.svg)](https://www.npmjs.com/package/@ray-js/image-color-picking)

> Image color picking
> Internally obtains the pixel color of the image through a canvas, and then calculates several colors that appear more frequently and are not very close to each other through aggregation algorithms.

## Installation

```sh
$ npm install @ray-js/image-color-picking
// or
$ yarn add @ray-js/image-color-picking
```

## Usage

### Basic Usage

1. Import the `ImageColorPicker` component and place it on the page. Since the component internally obtains colors through a canvas, a component must be present on the page as the basis for obtaining colors, and the id should be passed as `image-color-picking` by default.
2. Import the `imageColorPicking` method and pass in the file path to get the main colors. The `pickNum` attribute can control the number of main colors extracted.
3. The `imageColorPickingDestroy` method can clear the cache queue when the component is destroyed.

```tsx
import {
  imageColorPicking,
  ImageColorPicker,
  chooseCropImageSync,
  imageColorPickingDestroy,
} from '@ray-js/image-color-picking';
import React, { useEffect } from 'react';
import { View } from '@ray-js/ray';

const Demo = () => {
  useEffect(() => {
    return () => {
      // Destroy the component cache queue supported from version 1.1.0
      imageColorPickingDestroy();
    };
  }, []);

  const run = async () => {
    // Call app capability to select local mobile image path
    const path = await chooseCropImageSync();
    // cancel
    if (typeof path !== 'string') return;
    // Get main colors
    const colors = await imageColorPicking({
      path,
      pickNum: 8,
    });
    console.log(colors, '--obtained colors');
  };

  return (
    <>
      <View onClick={run}>Click to execute</View>
      <ImageColorPicker id="image-color-picking" />
    </>
  );
};
```

### Custom id and Passing Base64 Usage

1. Set different ids such as `my-custom` through the component mounted on the page. Therefore, when calling the `imageColorPicking` method, the corresponding `selector` attribute also needs to be passed to enable the method to access this component instance.
2. Use the `readImgSync` method to convert the image path from the mobile device into base64 format, and then send it to the internal component for execution using the `imageColorPicking` method and return the colors.

```tsx
import {
  imageColorPicking,
  ImageColorPicker,
  chooseCropImageSync,
  readImgSync,
  imageColorPickingDestroy,
} from '@ray-js/image-color-picking';
import React, { useEffect } from 'react';
import { View } from '@ray-js/ray';

const Demo = () => {
  useEffect(() => {
    return () => {
      // Destroy the component cache queue supported from version 1.1.0
      imageColorPickingDestroy();
    };
  }, []);

  const run = async () => {
    // Call app capability to select an image
    const path = await chooseCropImageSync();
    // cancel
    if (typeof path !== 'string') return;
    // Convert the image in the mobile device into base64
    const fileBase64: string = await readImgSync(path);
    // Get main colors
    const colors = await imageColorPicking({
      base64: fileBase64,
      // Custom id
      selector: '#my-custom',
      // Brighten colors
      isPrimary: false,
      pickNum: 8,
      // Disable color sorting
      isSort: false,
    });
    console.log(colors, '--obtained colors');
  };

  return (
    <>
      <View onClick={run}>Click to execute</View>
      <ImageColorPicker id="my-custom" />
    </>
  );
};
```

### Split Image Color Picking `v1.1.0`

The `splitImage` parameter can segment the image for recognition. By default, when passed true, it is 2 rows and 4 columns.

```tsx
import {
  imageColorPicking,
  ImageColorPicker,
  chooseCropImageSync,
  imageColorPickingDestroy,
} from '@ray-js/image-color-picking';
import React, { useEffect } from 'react';
import { View } from '@ray-js/ray';

const Demo = () => {
  useEffect(() => {
    return () => {
      // Destroy the component cache queue supported from version 1.1.0
      imageColorPickingDestroy();
    };
  }, []);

  const run = async () => {
    const path = await chooseCropImageSync();
    // cancel
    if (typeof path !== 'string') return;
    const colors = await imageColorPicking({
      path,
      splitImage: {
        // Enable split mode
        cols: 10,
        rows: 10,
      },
    });
    console.log(colors, '--obtained split colors');
  };

  return (
    <>
      <View onClick={run}>Click to execute</View>
      <ImageColorPicker id="image-color-picking" />
    </>
  );
};
```

### Filter Duplicate Colors `v1.1.1`

The `filterDuplicate` parameter can filter out duplicate or similar colors. When set to `true`, only unique colors will be returned. For example, if an image has only one color, even if `pickNum` is 8, only one color will be returned.

```tsx
import {
  imageColorPicking,
  ImageColorPicker,
  chooseCropImageSync,
  imageColorPickingDestroy,
} from '@ray-js/image-color-picking';
import React, { useEffect, useState } from 'react';
import { View } from '@ray-js/ray';

const Demo = () => {
  const [colors, setColors] = useState<string[]>([]);

  useEffect(() => {
    return () => {
      // Destroy the component cache queue
      imageColorPickingDestroy();
    };
  }, []);

  const run = async () => {
    const path = await chooseCropImageSync();
    // cancel
    if (typeof path !== 'string') return;
    const result = await imageColorPicking({
      path,
      selector: '#my-custom2',
      pickNum: 8,
      // Filter duplicate colors
      filterDuplicate: true,
    });
    setColors(result);
    console.log(result, '--obtained colors');
  };

  return (
    <>
      <View onClick={run}>Click to execute</View>
      <ImageColorPicker id="my-custom2" />
      <View>Color count: {colors.length}</View>
      <View style={{ display: 'flex', gap: 8 }}>
        {colors.map((item, index) => (
          <View
            key={index}
            style={{
              background: item,
              height: 50,
              flex: 1,
            }}
          />
        ))}
      </View>
    </>
  );
};
```

## Methods and Types

| Parameter                         | Description                                                                                                                                                           | Type                                                                                                         |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| ImageColorPicker                  | The supporting component for obtaining the image resource color, needs to be used with `imageColorPicking`                                                            | _ImgCanvasProps & { id: string }_                                                                            |
| imageColorPicking                 | The supporting method for obtaining the image resource color, needs to be used with `ImageColorPicker`                                                                | _(currOptions: ImageColorPickingOption = {}): Promise\<string[]>_                                            |
| chooseCropImageSync               | Method to get local images from the mobile device, implemented based on `chooseCropImage`, wrapped into a promise with additional permission logic                    | _(sourceType?: "album" \| "camera"): Promise\<string \| { errorMsg: string; errorCode: string \| number; }>_ |
| chooseImageSync                   | The method for obtaining local images from the mobile phone is based on `chooseImage`, encapsulated into a promise, and includes additional permission request logic. | _(sourceType?: "album" \| "camera"): Promise\<string \| { errorMsg: string; errorCode: string \| number; }>_ |
| readImgSync                       | Reads local mobile image resources and converts them into base64 format                                                                                               | _(path: string): Promise\<string>_                                                                           |
| imageColorPickingDestroy `v1.1.0` | Destroys the component cache queue                                                                                                                                    | _(selector?: string): void_                                                                                  |

### ImgCanvasProps

| Parameter                | Description                                                                                                                                                                                                                           | Type                                         | Default Value                |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | ---------------------------- |
| path                     | Local mobile file path                                                                                                                                                                                                                | _string_                                     | `''`                         |
| canvasId                 | Custom canvas id                                                                                                                                                                                                                      | _string_                                     | `image-color-picking-canvas` |
| base64                   | Image base64 string                                                                                                                                                                                                                   | _string_                                     | -                            |
| pickNum                  | Number of colors extracted                                                                                                                                                                                                            | _number_                                     | `5`                          |
| isPrimary                | Whether to maintain the original color. If false, the component will brighten internal colors when they are too dark                                                                                                                  | _boolean_                                    | `true`                       |
| isSort `v1.1.0`          | Should the extracted colors be sorted by their color values?                                                                                                                                                                          | _boolean_                                    | `true`                       |
| filterDuplicate `v1.1.1` | Whether to filter duplicate colors. If true, only unique colors will be returned (even if pickNum is larger)                                                                                                                          | _boolean_                                    | `false`                      |
| splitImage `v1.1.0`      | Whether to split the image for color recognition. When passed true, the default is 2 rows and 4 columns, dividing the image into 8 segments with one color identified for each segment; custom segmentation rules can also be defined | _boolean \| { cols: number; rows: number; }_ | -                            |
| onColorsChange           | Callback for color changes                                                                                                                                                                                                            | _(colors: string[]) => void_                 | -                            |

### ImageColorPickingOption

| Parameter                | Description                                                                                                                                                                                                                           | Type                                         | Default Value                |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | ---------------------------- |
| selector                 | The id of the component must start with `#`                                                                                                                                                                                           | _string_                                     | `#image-color-picking`       |
| path                     | Local mobile file path                                                                                                                                                                                                                | _string_                                     | -                            |
| canvasId                 | Custom canvas id, automatically appending `-canvas` suffix based on the `selector` property                                                                                                                                           | _string_                                     | `image-color-picking-canvas` |
| base64                   | Image base64 string                                                                                                                                                                                                                   | _string_                                     | -                            |
| pickNum                  | Number of colors extracted                                                                                                                                                                                                            | _number_                                     | -                            |
| isPrimary                | Whether to maintain the original color. The component will brighten internal colors by default; if turned off, true needs to be passed                                                                                                | _boolean_                                    | -                            |
| isSort `v1.1.0`          | Whether to sort the extracted colors                                                                                                                                                                                                  | _boolean_                                    | `true`                       |
| filterDuplicate `v1.1.1` | Whether to filter duplicate colors. If true, only unique colors will be returned (even if pickNum is larger)                                                                                                                          | _boolean_                                    | `false`                      |
| splitImage `v1.1.0`      | Whether to split the image for color recognition. When passed true, the default is 2 rows and 4 columns, dividing the image into 8 segments with one color identified for each segment; custom segmentation rules can also be defined | _boolean \| { cols: number; rows: number; }_ | -                            |
| context                  | Pass `this` when using in native mini-programs; no need to pass when using in ray                                                                                                                                                     | _any_                                        | -                            |