Code Monkey home page Code Monkey logo

palette's People

Contributors

adriencaccia avatar bors[bot] avatar brandondong avatar cguta avatar clarfonthey avatar darakshan avatar dependabot[bot] avatar dlfelps avatar dtolnay avatar evq avatar finomnis avatar fu5ha avatar gymore-io avatar homu avatar ivordir avatar jameslzhu avatar lunacookies avatar masonium avatar mb64 avatar mitchmindtree avatar mswift42 avatar nevergivinup avatar nicolasklenert avatar ogeon avatar okaneco avatar peterhatch avatar rafaelbeckel avatar soenkehahn avatar tomcur avatar veykril avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

palette's Issues

Collect the operation traits in a module

The operation traits, such as Mix and Hue, are starting to pile up, so I thought it would be useful to create a sort of traits or prelude or ops module for easy glob inclusion. They can still also be available from the crate root.

Add support for transparency when deriving FromColor and IntoColor

A custom color can't have transparency at the moment. A part of the problem is that it's not possible to implement From for Alpha<MyColor, T>. A possible solution is to add a #[palette_alpha] attribute that marks the alpha component in the custom color struct and extend the derive code to use this when implementing From and Into, to preserve the transparency.

Equal Trait

Should partial equality be customized for each color to be within a tolerance level? Or maybe have a separate ColorEqual trait.

It will be better than the current macro which cannot take hues into account and it will definitely help in the tests.

I am not sure about its use case other than the tests. Another issue is selecting the right tolerance level.

Add a flexible color conversion interface

...something which is more flexible than From and Into, that allows user defined conversion functions. As sketched in #6:

That would look like this (pseudocode):

let my_rgb = Rgb::new(0.5, 0.3, 0.7);
let my_foo: FooColor = my_rgb.convert::<FooColor>(|channels|{
  let a = some_calc(channels[0], channels[2]);
  let b = some_cals(channels[1], channels[2]);
  FooColor::new(a,b)
});

Then you can also offer official standard profiles and just do s.th. like

let my_cmyk = my_rgb.convert::<Cmyk>(Cmyk::Profiles::ISOUncoded_v2);

Add documentation

This looks like an exciting library, and I'd love to see documentation!

(Hoping you'll see this issue as an encouragement rather than a criticism.)

Change remaining arithmetic operator implementations to output Self::Output

The implementations of Add, Sub, Mul and Div for some of the colors have been changed to output Self::Output (basically ColorType<<T as Add<T>>::Output> instead of just ColorType<T>). Not that it matter too much which one is used, but consistency is important and outputting T is an unnecessary restriction.

Common RGB struct

Have a common rgb struct

struct RgbColor<RgbVariant, WP, T> {
    r: T,
    g: T,
    b: T,
    _color_space: PhantomData<RGBVariant>,
    _white_point: PhantomData<WP>,
}

then we can define the individual colors as

const Rgb = RgbColor<LinearSrgbSpace, D65, T>
const Srgb = RgbColor<SrgbSpace, D65, T>
const AdobeRgb = RgbColor<AdobeSpace, D65, T>

conversions will be

impl<RgbVariant, WP,T: Float> From<RgbColor<RgbVariant, WP,T>> for Xyz<T> {
    fn from(rgb: Rgb<T>) -> Xyz<T> {
      let conv_matrix = RgbVariant::get_matrix();
      let wp_xyz = WP::get_xyz();


        Xyz {
           .... calculations
        }
    }
}

impl<RgbVariant, WP,T: Float> From<Xyz<T>> for RgbColor<RgbVariant, WP,T> {
    fn from(xyz: Rgb<T>) -> RgbColor<RgbVariant, WP,T> {
      let conv_matrix = RgbVariant::get_matrix();
      let wp_xyz = WP::get_xyz();


        Rgb {
           .... calculations
        }
    }
}

Add raw light spectrum to XYZ conversion

Hi!

Would it be interesting to add support for spectrum to XYZ conversions?

The spectrum can be represented as a [f32; XXX] (XXX depending on the sampling of the spectrum). Where the f32 values are the intensities (in arbitrary units), for each wavelength from ~400 to ~800 nm. Then the XYZ coordinates are a matter of simple matrix multiplication, given the XYZ weights.

The weights are available on different websites (http://www.cvrl.org/cie.htm)
There is also analytic aproximations (http://jcgt.org/published/0002/02/01/paper.pdf)

I've already started a POC, so I might submit a pull request (the code is not that clean yet though).

Tell me what you think about this.

Rgb variants

Do we use a trait based solution for the Rgb variants, we have atleast 3 variants so far Adobe Rgb, sRgb and linear sRgb (maybe use linear sRgb as the default Rgb variant).

Opening this issue to keep track of it. We need to implement other changes before we come back to this.

Color Enum with Rgb Variants and White Point changes

How to handle color macro with rgb variant and white point changes?

Currently

enum Color<T:Float> {
  Lab(Lab<T>),
  Rgb(Rgb<T>),
  Hsl(Hsl<T>),
  Xyz(Xyz<T>),
 .. etc
}

With proposed changes it becomes

enum Color<RGB: RgbVariant, WP:WhitePoint, T:Float> {
  Lab(Lab<WP, T>),
  Rgb(Rgb<RGB, WP,T>),
  Hsl(Hsl<V, WP, T>),
  Xyz(Xyz<T>),
 .. etc
}

So for example for Color::Xyz, we will still have to specify the RgbType and WP even though we do not use it. Is there any alternative?

Lab and Lch values

Continuing discussion from #48.

Lab values are currently scaled, L by 100 and a and b by 128. Even though a and b are unbound, typical ranges are -128 to 128.

By my limited research so far, I have not seen scaled lab values used ( unlike rgb which is usually assumed in the range 0-1 ). For example Conversion formula's, Color Difference formula's and most research papers assume unscaled lab values (I am happy to be corrected on this).

Right now using the lab spaces implies unnecessary scaling when used practically. So I am proposing that the Lab values should be changed to be unscaled. Same for Lch values.

If the decision is to still scale the value, we should provide a new_from_unscaled and into_unscaled function, to get values in and out.

Find a good way to decouple the alpha channel

Having the alpha channel being affected by operations as arithmetics isn't always what you want, so it would be nice if it can be separated from the color types in a good, convenient and intuitive enough way. This is also useful for when the alpha channel is insignificant (always 1.0), to save some space. I have been thinking about an Alpha<C> wrapper type along these lines:

struct Alpha<C> {
    pub color: C,
    pub alpha: f32,
}

impl<C: Mix> Mix for Alpha<C> {
    //...
}

//etc.

and maybe even make it dereference as the color type C. I don't know if this will end up being too inconvenient or not, and better solutions are always welcome. I'll see if I can figure something else out before making a test implementation.

use macros for float conversions

Define three macros


macro_rules! flt {
    ($x: expr) => {
        T::from($x).unwrap()
    };
}

macro_rules! f_0 {
    () => (T::zero());
}

macro_rules! f_1 {
    () => (T::one());
}

The the equation become easier to read

x: T::from(X_N).unwrap() * f_inv((T::one() / T::from(116.0).unwrap()) *
    (lab.l * T::from(100.0).unwrap() + T::from(16.0).unwrap()) +
    (T::one() / T::from(500.0).unwrap()) * lab.a * T::from(128.0).unwrap()),
y: T::from(Y_N).unwrap() * f_inv((T::one() / T::from(116.0).unwrap()) *
    (lab.l * T::from(100.0).unwrap() + T::from(16.0).unwrap())),
z: T::from(Z_N).unwrap() * f_inv((T::one() / T::from(116.0).unwrap()) *
    (lab.l * T::from(100.0).unwrap() + T::from(16.0).unwrap()) -
    (T::one() / T::from(200.0).unwrap()) * lab.b * T::from(128.0).unwrap()),

x: rgb.red * T::from(0.4124).unwrap() + rgb.green * T::from(0.3576).unwrap() + rgb.blue * T::from(0.1805).unwrap(),
y: rgb.red * T::from(0.2126).unwrap() + rgb.green * T::from(0.7152).unwrap() + rgb.blue * T::from(0.0722).unwrap(),
z: rgb.red * T::from(0.0193).unwrap() + rgb.green * T::from(0.1192).unwrap() + rgb.blue * T::from(0.9505).unwrap(),

becomes


x: flt!(X_N) * f_inv((f_1!() / flt!(116.0)) *
    (lab.l * flt!(100.0) + flt!(16.0)) +
    (f_1!() / flt!(500.0)) * lab.a * flt!(128.0)),
y: flt!(Y_N) * f_inv((f_1!() / flt!(116.0)) *
    (lab.l * flt!(100.0) + flt!(16.0))),
z: flt!(Z_N) * f_inv((f_1!() / flt!(116.0)) *
    (lab.l * flt!(100.0) + flt!(16.0)) -
    (f_1!() / flt!(200.0)) * lab.b * flt!(128.0)),

x: rgb.red * flt!(0.4124) + rgb.green * flt!(0.3576) + rgb.blue * flt!(0.1805),
y: rgb.red * flt!(0.2126) + rgb.green * flt!(0.7152) + rgb.blue * flt!(0.0722),
z: rgb.red * flt!(0.0193) + rgb.green * flt!(0.1192) + rgb.blue * flt!(0.9505),

Named colors

A collection of named color constants (i.e. the named CSS and HTML colors) may be good to have. It should be possible to choose what kind of gamma correction they are assumed have when converting them to a linear RGB value.

Color arithmetics

Being able to do some basic math with colors is often useful, so it should be supported. This is just element wise arithmetics, so it's more naive than blending and can usually be applied to any color space.

Project Status?

I see that Palette has had a lot of work done to it over the last year since the last published version, some of it not being backwards compatible.

Are there any estimates for how long until the next published version? Or perhaps publish a beta version?

I've used the master branch in my own projects without any serious issue, however crates with git deps cannot be published, so I'd be forced to work with the old published version of Palette or instruct users to use a Cargo [replace] section.

Make it possible to specify a custom white point

Some color conversions depends on a white point, and Palette is currently making some assumptions in this area. Avoiding these assumptions would of course allow a lot more freedom, so it would be nice to find a good way to customize which white point to use when converting. Even better if it was encoded into the color types, themselves, when relevant.

Remove the Color type

It's unwieldy to implement, hides things unnecessarily, and I suspect that it's not as useful as I initially thought it would be. It feels like it does more harm than good.

HSL in sRGB space

I may be reading things wrong in the specs, but I believe that the version of HSL that CSS supports is in fact HSL in sRGB space, not linear HSL.

It'd be nice if we had an option to store this type of HSL without hackishly converting an Hsl to an Rgb and then copying the components from the Rgb into an Srgb. Again, if I'm wrong and this is actually linear Hsl, feel free to ignore this use case.

Ranges for CIE color spaces

For XYZ, both http://www.easyrgb.com/ and http://www.brucelindbloom.com/index.html?ColorCalculator.html show z as 1.088830 for srgb(1,1,1).

The is_valid() method for xyz assumes a range of [0-1].

For Lab, both http://www.easyrgb.com/ and http://www.brucelindbloom.com/index.html?ColorCalculator.html have values above 1 and also negative. For example, srgb(1,0.5,1) -> lab(72.087 ,65.181, -42.228)

The is_valid() method for lab assumes a range of [0-1].

Not sure what the correct range is. Opening this issue for tracking this.

Need for HueType

I was trying the Hsl type and it seems inconsistent with the rest of the library.

  1. All the other colors take floats for new, but hsl needs Hsl::new((240.0).into(), 0.0, 0.0)

  2. You input the hue as 240, but you cannot use hsl.hue, you need to use hsl.hue.to_positive_degrees(). I have been looking at this code for past few weeks and I made this mistake. This is going to be a very common issue. There is no compile error, but the code will not work as expected.

  3. I don't see the need for hsl + 0.1. I would rather this be a compile time error, because this is most likely a typo. The values are not on the same scale and does not make sense.

What do you think of removing the huetype and storing the hues as 0-360 floats? I understand that HueType avoids some issues in the code, but maybe we can mitigate it by using more test cases?

Add support for HWB color model

I was reading through the CSS level 4 color module to see what's coming up and came across a new color model: HWB. It was a total love at first sight. It works allowing you to select a hue and then mix in whiteness and blackness.

Support for it in this library would be great.

Make it possible to dervie Pixel

It should check for #[repr(C)] and that all non-zero sized properties are of the same type. There is no straight forward way to detect zero sized types, so an attribute for marking zero sized properties is probably necessary. There should also be asserts that checks the sizes (some are already in place).

Common conversion trait

Since most color space conversions are through Xyz space, we can have a common conversion trait

trait XyzConversion {
   fn to_xyz();
   fn from_xyz();
}

and then we can auto imply all conversions

impl<T: XyzConversion,U: XzyConversion> From<T> for U {
  ...
}

instead of manually specifying hsl -> lab, rgb -> lab etc. and the corresponding inverses.

Consider converting hue types to numbers within [0, 360) instead of (-180, 180]

Numbers within [0, 360) degrees seems to be more common when working with hues, but the trigonometric functions in Rust gives negative angles instead of angles above 180 degrees. The big question is which one to adopt for our hues. Note that this is only relevant when printing a hue type or when converting it to a "regular" number (e.g. in impl Into<f32>).

Blending

There should be support for the common blending functions, like add, subtract, screen, overlay, etc. This may be restricted to RGB, unless it's intuitive in other spaces as well.

Conversion Tests

Need to add tests for conversions to make sure there are no regressions. For color enum, alpha and individual colors.

Issue while LCH -> RGB conversion

I had an RGB pixel which i wanted to shift the hue by 180 , so I initially converted the color to LCH and then did a hue shift on it , and converted it back to RGB . The converted RGB values are way out of bounds .

let dominant_color: self::rgb::RGB<u8> = viewer.get_prominent_color( width, height); let lch_color: Lch = Rgb::from(Srgb::new(dominant_color.r as f32,dominant_color.g as f32,dominant_color.b as f32)).into(); let new_color: Rgb = lch_color.shift_hue(180.0.into()).into();

Dominant Color : RGB { r: 175, g: 180, b: 171 }
lch_color : Lch { l: 70.13459, chroma: 3.5053592, hue: LabHue(130.76137) }
hueshifted : Rgb { red: 232155.52, green: 217398.52, blue: 245035.61 }

Slicing gradients

Being able to take a slice of a gradient is quite useful for various reasons. Adding support for some kind of padding may also be nice.

Redesign the pixel encoding procedure

Something that has been growing in my mind for a few days is the idea of changing the way colors are encoded into pixel friendly formats. The current procedure may look like this:

let linear = Rgb::new(1.0, 0.3, 0.6);
let srgb = Srgb::from_linear(linear);
let pixel: [u8; 3] = srgb.to_pixel();

or, using a shortcut:

let linear = Rgb::new(1.0, 0.3, 0.6);
let pixel: [u8; 3] = Srgb::linear_to_pixel(linear);

There's also the case where a simple custom gamma exponent can be used:

let linear = Rgb::new(1.0, 0.3, 0.6);
let pixel: [u8; 3] = GammaRgb::linear_to_pixel(linear, 2.2);

This is fine and all, but it's not really easy to use in a general way:

  1. There's no common trait or type for encoded colors.
  2. The alpha component is baked into the color type.
  3. GammaRgb has a variable gamma exponent, which makes it very different from other encodings, and impossible to fully express as a simple type.

This problem is tightly connected to #31, where a general RGB type is proposed. The way GammaRgb is structures interferes with that proposal, since it has an additional gamma component, besides the usual red, green and blue. I'm therefore proposing that we redesign the way pixel encoding works to make it more friendly towards the idea of a more generalized RGB type. I would also like to extend this to other RGB related color spaces, such as HSV, HSL, Luma and HWB. These can all be seen as input types and they are, often enough, defined in terms of already encoded RGB.

The initial proposal is to keep linear and encoded types separate. The purpose of this library is to strongly encourage a linear work flow and this can easily be achieved by only implementing operations on the linear variant. There was a proposal, by @sidred, to have marker type parameters, such as Rgb<Linear, Srgb, ...> and Rgb<Gamma, Srgb, ...>, but recent problems with such marker parameters, as well as the additional complexity of extra type parameters, makes that method less attractive.

The separation of linear and encoded colors, using two different structs, will come with a bit of duplication, but the duplication will mainly be restricted to construction and fields. The linear variants will implement the operation traits, while the encoded variants will be focused on packing and converting data. Here is an example of how it may look when combined with #31:

pub trait RgbEncoding {
    ///Encode a color component.
    fn encode<T: Float>(value: T) -> T;

    ///Decode a color component.
    fn decode<T: Float>(value: T) -> T;
}

pub trait RgbPrimaries {
    //get red, green, blue primaries, etc.
}

///Marker type, which both defines a set of primaries and an encoding
pub struct Srgb;

impl  RgbEncoding for Srgb {
    //...
}

impl  RgbPrimaries for Srgb {
    //...
}

struct LinearRgb<Prim: RgbPrimaries = Srgb, ...> {
    //..
    primaries: PhantomType<Prim>,
}

struct Rgb<Enc: RgbEncoding = Srgb, ...> {
    //..
    primaries: PhantomType<Enc>,
}

Encodings and primaries are often strongly connected to each other, which is why the same type can be used for both. The problem with this is that it's hard to decouple them, but that's hopefully rare enough to make this more good than bad. The only problem left is the GammaRgb. Its variable gamma component makes it incompatible with the above pattern, and having floating point values as type parameters is nothing but a (bad?) dream at this stage. We can, however, make more assumptions and add more escape hatches. I'm therefore proposing the addition of the probably most common gamma exponent, 2.2, as an encoding type, and the extension of the above RgbEncoding that makes it possible for an encoding to map to any set of primaries:

pub trait RgbEncoding {
    type Primaries: RgbPrimaries;

    ///Encode a color component.
    fn encode<T: Float>(value: T) -> T;

    ///Decode a color component.
    fn decode<T: Float>(value: T) -> T;
}

///Gamma exponent 2.2, with any primaries.
struct Gamma22<P: RgbPrimaries>;

impl<P: RgbPrimaries> RgbEncoding for Primaries<P>
    type Primaries = P;

    //...
}

impl  RgbEncoding for Srgb {
    type Primaries = Srgb;
    //...
}

fn main() {
    let encoded = Rgb::<Gamma22<Srgb>>::new(...);
    let linear = encoded.to_linear(); //Gives LinearRgb<Srgb>
}

The preferred primaries can then be fetched from the associated Primaries type when converting from encoded to linear. Now, what about those other gamma values? That's where we need escape hatches. One such escape hatch could be to keep the old GammaRgb type around. It may be a bit unwieldy, but it works. An other is to just have a straight-to-pixel conversion, like the *::linear_to_pixel function in the current design. More suggestions are welcome here.

The last question is what encoded types are allowed to do. My proposal is "basically nothing", since I'm still strongly in favor of keeping them strictly separated from linear types. This is to minimize any risk of mistaking non-linear values for linear and forcing the user to make an explicit conversion between them. The minimal set of functions I can think of at the moment is:

impl<E: RgbEncoding, ...> Rgb<E, ...> {
    fn new(red: T, green: T, blue: T) -> Rgb<E, ...> {...}
    fn new_u8(red: u8, green: u8, blue: u8) -> Rgb<E, ...> {...}
    fn from_pixel<P: RgbPixel<T>>(pixel: P) -> Rgb<E, ...> {...}
    fn to_pixel<P: RgbPixel<T>>(&self) -> P {...}
    fn from_linear<C: Into<LinearRgb<E::Primaries, ...>>(color: C) -> Rgb<E, ...> {...}
    fn to_linear<C: From<LinearRgb<E::Primaries, ...>>(&self) -> C {...}

    //Useful addition
    fn linear_to_pixel<C: Into<LinearRgb<E::Primaries, ...>, P: RgbPixel<T>>(color: C) -> P {
        Rgb<E, ...>::from_linear(color).to_pixel()
    }
}

These can, of course, be tweaked and changed. Some of these functions would be nice as a general encoding trait, but that's quite complex and may be better discussed at a later stage.

Something this proposal hasn't touched, so far, is what to do with the alpha component. I think it would be best to make use of the Alpha type, but I haven't figured out exactly how, so that question remains open.

An other open question is type aliases for common RGB types, such as AdobeRgb. One idea is to not alias sRGB, and only implement new for Rgb<Srgb, D65, T>, similar to how it's done with only D65 today. An other is to alias all of them and not pick a default.

Change normalize function

fn normalize_angle_division(mut deg: f32) -> f32 {
    let c360 = 360.0_f32;
    deg - ((deg / c360).floor() * c360)

}

Faster than using mod and as fast as while. No slowdown for large numbers. Putting it here so I don't forget.

Support for serde (de)serialization of color types

I'm currently using palette in a downstream crate where I'd like to allow the user to serialize and deserialize custom Themes - a set of styling defaults including some color types from palette. I'm hoping to avoid writing custom implementations of the serde traits in favour of adding the necessary derives to palette itself where others may also find this useful. Perhaps this could be added as an opt-in feature similarly to cgmath, petgraph and others do?

Munsell color system

The Munsell color system may be an interesting addition from a more artistic point of view. RIT provides some data files that may be used to convert from Munsell to xyY, but I haven't found any clear terms of use for those, but the colors themselves are not copyrighted and it looks like it's under a section of free-to-use stuff. That will need more investigation, since we must consider possible commercial use of this library.

Embedding a Munsell database into the library may be quite a bit of bloat, so this should probably be included as an opt-in feature.

Add from_components and into_components methods to colors

This would replace the old from_pixel and into_pixel methods on Rgb and it should be implemented on all color types, except for Color where it doesn't make sense. They should take/output tuples with the color components in the same order as in new.

The reason for adding them is that tuples are convenient when destructuring and also a somewhat common storage format. From<(...)> and Into<(...)> could also be implemented.

Allow more than just f32 colors

I can be useful for some applications to have colors that are based on other numerical types than just f32. Most probably for the sake of higher precision or lower memory usage. It would therefore be good to support more than just f32, and preferably in a generic way. We can still keep f32 as the default.

CMYK

It would be cool to be able to convert to an from CMYK :)

Color profile support

Add some sort of support for ICC profiles. Could be statically embedded, fully dynamic or both. This will make things like accurate CMYK possible, as discussed in #6.

xyY color space

It's common and useful. We will probably need it sooner or later, anyway.

Converting from a wider gamut to a smaller one should return an option

This is real confusing:

extern crate palette;
use palette::*;

fn main() {
    let foo = Lab {l: 1., a: -1., b: 0.};
    assert!(foo.is_valid());
    assert!(Rgb::from(foo).is_valid());
}
enolan at Behemoth in ~/mystuff/code/palettebug  
$ cargo run
     Running `target/debug/palettebug`
thread '<main>' panicked at 'assertion failed: Rgb::from(foo).is_valid()', main.rs:7
Process didn't exit successfully: `target/debug/palettebug` (exit code: 101)

I assumed it was a bug in the conversion routine, but it's just that Lab* is wider than sRGB. Returning an option type, assert!ing when the input is outside the target color space, or clamping the output value would all be preferable to the current situation.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.