simdope

8.0.1Β β€’Β PublicΒ β€’Β Published

Introducing SIMDope 8.0.0: The Rocket-Fast Color Processing King-Size library in JavaScript

Knock, knock, unleash the Power of Exceptional Color Handling with -> Unparalleled Speed <-

MIT License

SIMDope Branding Logo

🎨 Blend, Simplify, and Categorize Colors Like Never Before!

Bringing 250K colors (still manageable) down to a "BEST" manageable 25K with methods such as .simplify(ex: 1.6), or categorize skin tones using the (Boolean) property of Color's instances named .skin and other ones into clusters of 64, 256, or even 4096 possibilities, utilizing the .rgbaon[6,8,12,16]bits, and witness the magic of simplification and categorization like never before!

πŸš€ Incomparable Speed and Efficiency!

Experience unparalleled speed with the ability to process 2M operations a second, reducing ~103K colors down to 624 in just 162ms on an average "Intel I5" (CPU) equipped computer - an achievement of 2M+ OPS / SEC. that redefines the boundaries of traditional JavaScript!

SIMDope Performance NPM Downloads

πŸ“Š Transform 3D Color Data (r, g, b) to 1D Arrays!

Employ Lebesgue, Hilbert, and Moore algorithms to convert complex 3D color sets into neatly ordered 1D arrays, navigating through various hues, tones, saturations, chroma, and luminosity with finesse. SIMDope offers the only authentic way to navigate through complex color sets with such ease and precision! See: colors.get_deduplicated_sorted_uint32a(limit=200, background="#FFFFFFFF", algorithm="lebesgue")

_get_most_used_color_sorted_well_html5 = (simdopeColors) => {
    "use strict";
    // Optional "but" faaaaster as it recycles it (being a sequencial operation, only one isntance of "Color" is needed).
    var recycolor = new SIMDopeColor(new ArrayBuffer(4)), categories = new Map();
    for(var i = 0; i < simdopeColors.length; i++) {
        // Give you access to all properties and method of Color's instance
        recycolor = simdopeColors.get_element(i, recycolor);
        // Simplify the color of 320% (YEAH FAAAST)
        recycolor.simplify(3.2);
        // The color "i" is in the category being N (64 possibilities using 6 bits)
        // 4, 6, 8, 12, 16 BITS RESULTS IN (16, 64, 256, 4096, 65536) CATEGORIES
        categories.set(i, recycolor.rgbaon6bits);
        // = CLUSTERING METHOD FASTER THAN A thunderbolt being faster than a "TR-3B"
    }
    // Constants like "limit" is simply ignoring less redundant ones before sorting them (after "background" enabling us to ignore alpha) with the fine tuned and chosen "algorithm".
    var LIMIT = 999, BACKGROUND = "#FFFFFFFF", ALGORITHM = ["hilbert", "moore", "lebesgue"][Math.floor(Math.random() * 3 - 0.1)];
    // List of colors, given a uint32array's buffer, we get a SIMDope's Colors' instance right back into our JS code
    var colors = new SIMDopeColors(simdopeColors.get_deduplicated_sorted_uint32a(LIMIT, BACKGROUND, ALGORITHM).buffer);
    // Array of hexadecimal colors in the starting block
    var hexs1D = [], arrayTemp = [], hexs2D = new Array(64).fill([]);
    // Filling the 2D "list" with our champion's hexadecimal outputs
    for(var i = 0; i < LIMIT; i++) {
        recycolor = colors.get_element(i, recycolor);
        if(recycolor.is_not_skin()){ // Ignoring skin toned colours
            arrayTemp = hexs2D[recycolor.rgbaon6bits]; // Select the color's cluster
            arrayTemp.push(recycolor.hex); // Add color's "HEX" value to one of the 64 clusters
        }
    }
    // Returning an array of HTML5/CSS3 (ready) colors from a two dimension array of clusters with hexadecimal colors
    hexs1D = Array.prototype.concat.apply([], hexs2D);
    return hexs1D;
};

SIMDope Sorting Colors

How to Integrate SIMDope into Your Projects

npm install simdope

Importing the Library

Browser

// Use the file located in /dist/browser.min.js for proper polyfill support (pre-Chrome 61.0)
var Color = window.SIMDOPE.Color;
var Colors = window.SIMDOPE.Colors;

NodeJS

// simdope/dist/index.min.js is also available
import { Color, Colors } from "simdope";

NEW (AWESOME) FEATURE V.6+ => "SIMDopeCreate(mode)"

// simdope/dist/index.min.js is also available
import { SIMDopeCreate, SIMDopeCreateConfAdd, SIMDopeCreateConfRemove } from "simdope";
// Exemple
var MODE = SIMDopeCreateConfAdd({
    "create": {
        "new_of": true,
        "new_uint32": true
    },
    "properties": {},
    "methods": {
        "get_use_element": true,
        "set_tail": true,
        "is_dark": true,
        "blend_first_with": true,
        "blend_first_with_tails": true
    }
}), SIMDOPE = SIMDopeCreate(MODE), Color = SIMDOPE.Color;
var color = Color.new_uint32(0x0D00CDBF); // Blue 25% transparent

// DEFAULT (Slower because it is a big class)
var SIMDopeObjectConf = {
    "create": {
        "new_zero": true,
        "new_splat": true,
        "new_of": true,
        "new_safe_of": true,
        "new_from": true,
        "new_array": true,
        "new_array_safe": true,
        "new_uint32": true,
        "new_uint32b": true,
        "new_hsla": true,
        "new_hex": true,
        "new_hex_name": true
    },
    "properties": {
        "tail": true,
        "pos": true,
        "hilbert": true,
        "lebesgue": true,
        "moore": true,
        "uint32": true,
        "uint32b": true,
        "hex": true,
        "ycbcra": true,
        "laba": true,
        "hsla": true,
        "rgbaon4bits": true,
        "rgbaon6bits": true,
        "rgbaon8bits": true,
        "rgbaon12bits": true,
        "rgbaon16bits": true,
        "skin": true
    },
    "methods": {
        "set": true,
        "set_from_array": true,
        "simplify": true,
        "set_from_simdope": true,
        "set_from_buffer": true,
        "get_tail_opacity": true,
        "get_tail_opacity_and_reset": true,
        "get_tail": true,
        "get_tail_and_reset": true,
        "reset_tail": true,
        "set_tail": true,
        "normalize": true,
        "set_out_of": true,
        "get_subarray": true,
        "get_slice": true,
        "get_buffer": true,
        "is_skin": true,
        "is_not_skin": true,
        "sum_rgba": true,
        "sum_rgb": true,
        "average_rgb": true,
        "is_dark": true,
        "is_fully_transparent": true,
        "is_fully_opaque": true,
        "is_not_fully_transparent": true,
        "is_not_fully_opaque": true,
        "match_with": true,
        "euclidean_match_with": true,
        "manhattan_match_with": true,
        "cie76_match_with": true,
        "set_r": true,
        "set_g": true,
        "set_b": true,
        "set_a": true,
        "to_greyscale": true,
        "to_greyscale_luma": true,
        "multiply_a_255": true,
        "copy": true,
        "get_difference_with": true,
        "merge_with_a_fixed": true,
        "blend_first_with": true,
        "blend_all": true,
        "blend_all_with_tails": true,
        "blend_with": true,
        "blend_first_with_tails": true,
        "get_deduplicated_sorted_uint32a": true,
        "get_element": true,
        "get_new_element": true,
        "get_use_element": true
    }
};

How to use SIMDope.Color?

πŸ”§ Functions, Methods, and Properties of SIMDope.Color

Instantiate an object of the single color class

// We often use a uint32array just as: new Uint32Array(imagedata.data.buffer)
// Better just put the uint32array inside the constructor Colors using the class named: Color
Color(with_main_buffer, offset_4bytes_optional) // Uint8Array.of(127, 95, 0, 255) as "r, g, b, a" works too
Color.new_zero()
Color.new_of(r, g, b, a)
Color.new_safe_of(r, g, b, a)
Color.new_from(agbr_array)
Color.new_array(rgba_array)
Color.new_array_safe(rgba_array)
Color.new_uint32(uint32) 
Color.new_uint32b(uint32b)
Color.new_hsla(h, s, l, a)
Color.new_hex(hex_anything)

πŸ” Color's Properties:

Property Description
color.r Red component (readonly)
color.g Green component (readonly)
color.b Blue component (readonly)
color.a Alpha component (readonly)
color.uint32 Integer representation (readonly)
color.uint32b Integer representation (readonly)
color.hex Hex representation (readonly)
color.hsla HSLA representation (readonly)
color.lab LAB color space (readonly)
color.ycbcra YCbCrA color representation (readonly)
color.skin Indicates if the color matches skin tones (Boolean)
color.tail Utility for chaining multiple colors before blending
color.hilbert Indicates the 1D (uint32) index of the RGB coordinates
color.moore Indicates the 1D (uint32) index of the RGB coordinates
color.lebesgue Indicates the 1D (uint32) index of the RGB coordinates
color.rgbaon4bits RGBA on 4 bits representation (readonly)
color.rgbaon6bits RGBA on 6 bits representation (readonly)
color.rgbaon8bits RGBA on 8 bits representation (readonly)
color.rgbaon12bits RGBA on 12 bits representation (readonly)
color.offset Offset of the color data (readonly)
color.buffer_ Primary buffer (private; use methods for access)
color.subarray_ Provides a "pointer" instance without copying data (private)
color.slice_ Clones the data into a new Uint8Array (private)

πŸ” Color's Methods:

Get:

Method Description
color.get_buffer( ) Retrieve the primary buffer
color.get_subarray( ) Access the "pointer" instance of the color data
color.get_slice( ) Clone and retrieve the color data
color.sum_rgba( ) Sum of RGBA values
color.sum_rgb( ) Sum of RGB values
color.is_dark( ) Check if color is dark
color.is_skin( ) Check if color matches skin tones
color.is_fully_transparent( ) Check if color is fully transparent
color.is_fully_opaque( ) Check if color is fully opaque
color.is_not_skin( ) Check if color doesn't match skin tones
color.is_not_fully_transparent( ) Check if color isn't fully transparent
color.is_not_fully_opaque( ) Check if color isn't fully opaque

Set:

Method Description
color.set(with_buffer ) Set the color using (Uint8Array or ArrayBuffer)
color.set_from_simdope(color ) Set a color from a Color instance
color.set_from_array(new Uint8Array(4) ) Set the color from an RGBA
color.set_from_buffer(with_buffer, offset_four_bytes ) Reuse the instanced object
color.set_tail(simdope_instance, premultiply_alpha_255_optional ) Set a tail
color.simplify(divider ) Peg the color (e.g., 1.6, 2, 3.2)
color.blend_with(another_color, strength_on_255, should_return_transparent, is_alpha_addition ) Blend
color.blend_first_with(another_color, strength_on_255, should_return_transparent, is_alpha_addition ) Blend
color.blend_first_with_tails(is_alpha_addition ) Blend color with tails then deletes tail links
color.match_with(another_color, threshold_on_255 ) Match color
color.manhattan_match_with(another_color, threshold_float_optional ) Match color using Manhattan algorithm (Return a Boolean or a Float if no threshold is given)
color.euclidean_match_with(another_color, threshold_float_optional ) Match color using Euclidean algorithm (Return a Boolean or a Float if no threshold is given)
color.cie76_match_with(another_color, threshold_float_optional ) Match color using CIE76 algorithm (Return a Boolean or a Float if no threshold is given)
color.set_r(r ) Set red component to r
color.set_g(g ) Set green component to g
color.set_b(b ) Set blue component to b
color.set_a(a ) Set alpha component to a
color.to_greyscale( ) Convert color to greyscale
color.to_greyscale_luma( ) Convert color to greyscale using luma

πŸ” Color's Functions:

Function Description
Color.with_r(color, r ) Create a new color instance using color with specified red component r
Color.with_g(color, g ) Create a new color instance using color with specified green component g
Color.with_b(color, b ) Create a new color instance using color with specified blue component b
Color.with_a(color, a ) Create a new color instance using color with specified alpha component a
Color.with_inverse(color ) Create a new color instance with inverted colors of color
Color.with_match(color_a, color_b, threshold_on_255 ) Match two colors color_a and color_b with a threshold threshold_on_255
Color.blend(color_a, color_b, strength_on_one, should_return_transparent, is_alpha_addition ) Blend two colors color_a and color_b with strength_on_one, should_return_transparent, and is_alpha_addition

Please, look at the source code to know more about other cool ways of using it ...

How to use SIMDope.Colors?

πŸ”§ Functions, Methods, and Properties of SIMDope.Colors

πŸ” Colors' Properties:

Property Description
colors.length Number of colors in the list (readonly)
colors.buffer Buffer containing the color data (readonly)

πŸ” Colors' Methods:

Get:

Method Parameters Description
colors.get_element(index, old_color_object_optional_faster ) index: Position of color in the list
old_color_object_optional_faster: (Optional) Previous color object for faster access
Retrieve the color at a specified index. When you get an element and apply changes, it updates the color within your list's buffer.
colors.get_new_element(index) index: Position of color in the list Retrieve the color at a specified index. When you get an element and apply changes, it updates the color within your list's buffer.
colors.get_use_element(index, old_color_object_optional_faster ) index: Position of color in the list
old_color_object_optional_faster: (Required) Previous color object for faster access
Retrieve the color at a specified index. When you get an element and apply changes, it updates the color within your list's buffer.
colors.subarray_uint32(start, end ) start: Start index
end: End index
Get a subarray from the Uint32Array representation.
colors.slice_uint32(start, end ) start: Start index
end: End index
Get a slice from the Uint32Array representation.
colors.subarray_uint8(start, end ) start: Start index
end: End index
Get a subarray from the Uint8Array representation.
colors.slice_uint8(start, end ) start: Start index
end: End index
Get a slice from the Uint8Array representation.
colors.get_hex() None List all the hexadecimal values of each colors within the Colors' instance.
colors.get_properties(key) key: ("hex", "r", "skin", or any other property...) Return an array of the properties of all colors.
colors.get_deduplicated_uint32a( ) None Removes duplicate uint32 entries. May need polyfills for older browsers.
colors.get_deduplicated_sorted_uint32a(limit, background, algorithm ) Optional Use a high-performance 8bits curve algorithm (one of "hilbert", "moore", "lebesgue")

Set:

Method Parameters Description
colors.set_element(index, color_object ) index: Position in the list to set the color
color_object: The color object to set
Set a color at the specified index
colors.buffer_setUint8(index, number ) index: Position in the buffer to set the byte
number: Byte value to set
Set a byte in the buffer
colors.buffer_setUint32(index, number ) index: Position in the buffer to set the Uint32 value
number: Uint32 value to set
Set a Uint32 value in the buffer

How it should be used (LOOK HERE)

var white = Color.new_of(255, 255, 255, 255);
var green = Color.new_of(0, 255, 0, 255);
var red = Color.new_of(255, 0, 0, 255);

var simdope_my_colors = Colors(imagedata);
    // That rewrite the inner data of our array but also white if we don't copy it
    simdope_my_colors.get_element(0).blend_with(white.copy(), 192, false, false);
    simdope_my_colors.get_element(1).blend_with(white, 0.25*255, false, false) ;

simdope_my_colors.get_element(2)
    .blend_with(white.copy(), 0.25*255, false, true)
    .blend_with(green.copy(), 0.75*255, false, true)
    .blend_with(red.copy(), 0.25*255, false, true)
    
var purple = simdope_my_colors.get_element(2);
var purple_copy = purple.copy();
var purple_hex = purple.hex;
var purple_uint32 = purple.uint32;
var is_purple_dark = purple.is_dark();
var is_purple_dark_but_from_hex = Color.new_hex(purple_hex).is_dark();
var purple_alpha_but_from_uint32 = Color.new_uint32(purple_uint32).a;

var some_uint32array_colors = simdope_my_colors.subarray_uint32(0, 3);
var some_colors = new Colors(some_uint32array_colors.buffer);

  some_colors.set_uint32_element(0, purple.uint32);
  some_colors.set_uint32_element(1, purple.uint32);

For more usage scenarios than those which follows, explore the source code.

  • You can write a quantization algorithm using it that can detect skin tones quickly and simplify millions of colors fast benefiting clustering using rgbaonXbits.
  • You can make a rendering engine which re-use Color's instance and link them through the tail property before blending them modifying the first one only as if you were using layers with a Colors' (list) + Color's (current) instance per layer.
  • You can simply detect which contrast color to use depending on a given color Color.new_hex("greenyellow").is_dark() ? "white": "black";.
  • You can sort colors within a palette using new Colors(colors.get_deduplicated_sorted_uint32a(200, Color.new_hex("white"), "lebesgue").buffer).get_properties("hex").

Please refer to the source code for additional information and advanced usage scenarios.

About me

"Philosophy is the science of estimating values, yet technology is the value of estimating science. My design is my voice while my code is my weapon of choice..."

I am (sometimes) open to work^^ ==> https://www.linkedin.com/in/matias-affolter/

Package Sidebar

Install

npm i simdope

Weekly Downloads

10

Version

8.0.1

License

MIT

Unpacked Size

322 kB

Total Files

17

Last publish

Collaborators

  • asaitama