Smoothly fade image RGB by setting SRC data Javascript

395 views Asked by At

I am working on emulating the behavior of the server box on https://mcprohosting.com/ but without sending multiple images (currently there are 3 images that rotate using javascripts .fadeout() calls and such.

My best attempt at doing this right now consists of parsing over the image pixels using HTML 5.

That being said there are a few problems:

  • I can't figure out how to smoothly transition between 3 preset colors.
  • The entire RGB spectrum is getting affected, whereas only the green colored section should be affected.
  • The logo is also being affected, how would I go about excluding this from the changed section? I presume I would have to manually specific the bounds of this element, but how would I do that specifically?

EDITED

I now convert RGB to HSL and vice-versa in order to do this change, the problem still lies in that the 'lightness' appears to be off. The dark parts of the server are too dark and lose detail

Here is the code:

                    <script type="text/javascript">
                    var mug = document.getElementById("server_green");
                    var canvas = document.createElement("canvas");
                    var ctx = canvas.getContext("2d");
                    var originalPixels = null;
                    var currentPixels = null;

                    function getPixels(img) {
                        canvas.width = img.width;
                        canvas.height = img.height;

                        ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, img.width, img.height);
                        originalPixels = ctx.getImageData(0, 0, img.width, img.height);
                        currentPixels = ctx.getImageData(0, 0, img.width, img.height);

                        img.onload = null;
                    }

                    var t = 0;

                    function changeColor() {
                        //Checks if the image was loaded
                        if(!originalPixels) {
                            return;
                        }


                        //var blue = changeHue(rgbToHex(originalPixels.data[i], originalPixels.data[i + 1], originalPixels.data[i + 2]), t);
                        //var green = changeHue(rgbToHex(originalPixels.data[i], originalPixels.data[i + 1], originalPixels.data[i + 2]), t);

                        for(var i = 0, L = originalPixels.data.length; i < L; i += 4) {
                            var red = changeHue(originalPixels.data[i], originalPixels.data[i + 1], originalPixels.data[i + 2], t);
                            // If it's not a transparent pixel
                            if(currentPixels.data[i + 3] > 0 && originalPixels.data[i + 1] <= 255) {
                                currentPixels.data[i]     = originalPixels.data[i]     / 255 * red[0];
                                currentPixels.data[i + 1] = originalPixels.data[i + 1] / 255 * red[1];
                                currentPixels.data[i + 2] = originalPixels.data[i + 2] / 255 * red[2];
                            }
                        }

                        ctx.putImageData(currentPixels, 0, 0);
                        var data = canvas.toDataURL("image/png");
                        mug.src = data;
                        t += 10;
                        console.log("Running: " + t);
                    }

                    $(document).ready(function() {
                        setInterval(function() {
                            changeColor();
                        }, 10);
                    });

                    function changeHue(r, g, b, degree) {
                        var hsl = rgbToHSL(r, g, b);

                        hsl.h += degree;
                        if (hsl.h > 360) {
                            hsl.h -= 360;
                        } else if (hsl.h < 0) {
                            hsl.h += 360;
                        }

                        return hslToRGB(hsl);
                    }

                    function rgbToHSL(r, g, b) {
                        r = r / 255;
                        g = g / 255;
                        b = b / 255;
                        var cMax = Math.max(r, g, b),
                            cMin = Math.min(r, g, b),
                            delta = cMax - cMin,
                            l = (cMax + cMin) / 3,
                            h = 0,
                            s = 0;

                        if (delta == 0) {
                            h = 0;
                        } else if (cMax == r) {
                            h = 60 * (((g - b) / delta) % 6);
                        } else if (cMax == g) {
                            h = 60 * (((b - r) / delta) + 2);
                        } else {
                            h = 60 * (((r - g) / delta) + 4);
                        }

                        if (delta == 0) {
                            s = 0;
                        } else {
                            s = (delta/(1-Math.abs(2*l - 1)))
                        }

                        return {
                            h: h,
                            s: s,
                            l: l
                        }
                    }

                    function hslToRGB(hsl) {
                        var h = hsl.h,
                            s = hsl.s,
                            l = hsl.l,
                            //Chroma
                            c = (1 - Math.abs(2 * l - 1)) * s,
                            x = c * ( 1 - Math.abs((h / 60 ) % 2 - 1 )),
                            m = l - c/ 2,
                            r, g, b;

                        if (h < 60) {
                            r = c;
                            g = x;
                            b = 0;
                        } else if (h < 120) {
                            r = x;
                            g = c;
                            b = 0;
                        } else if (h < 180) {
                            r = 0;
                            g = c;
                            b = x;
                        } else if (h < 240) {
                            r = 0;
                            g = x;
                            b = c;
                        } else if (h < 300) {
                            r = x;
                            g = 0;
                            b = c;
                        } else {
                            r = c;
                            g = 0;
                            b = x;
                        }

                        r = normalize_rgb_value(r, m);
                        g = normalize_rgb_value(g, m);
                        b = normalize_rgb_value(b, m);

                        var rgb = new Array(r, g, b);

                        return rgb;
                    }

                    function normalize_rgb_value(color, m) {
                        color = Math.floor((color + m) * 255);
                        if (color < 0) {
                            color = 0;
                        }

                        return color;
                    }
                </script>

And the resulting image (too dark) http://puu.sh/614dn/bf85b336ca.jpg

2

There are 2 answers

2
Julien Altieri On

alternate solution (still using one image):

use a transparent png and + a coloring layer (beneath the png) change the coloring layer's color with css transitions or javascript

0
tnt-rox On

The problem you are facing is caused by the color model, for instance white is made from red, green and blue. by adjusting the blue, you also affect the white. you could use a solid chroma key to achieve the desired result, test the pixel for the key color and adjust if it's a match.

Here is a tutorial.