Example #1
0
        /// <summary>
        /// scanner worker thread
        /// </summary>
        protected void Scanner()
        {
            var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
                                           Screen.PrimaryScreen.Bounds.Height,
                                           PixelFormat.Format32bppArgb);

            var bmpResized = new Bitmap((int)(bmpScreenshot.Width * quality), (int)(bmpScreenshot.Height * quality));

            uint w = (uint)bmpResized.Width, h = (uint)bmpResized.Height;


            // Create a graphics object from the bitmap.
            var gfxScreenshot = Graphics.FromImage(bmpScreenshot);

            uint     framecount = 0;
            DateTime dtStart    = DateTime.Now;

            int ttkey = 0; /*Time until next keyframe is captured*/

            while (bRun)
            {
                Size sScreenshot = Screen.PrimaryScreen.Bounds.Size;

                if (ttkey == 0)
                {
                    //Keyframe - take complete screenshot.
                    gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
                                                 Screen.PrimaryScreen.Bounds.Y,
                                                 0,
                                                 0,
                                                 sScreenshot,
                                                 CopyPixelOperation.SourceCopy);

                    ttkey = 15; /*15 frames till next keyframe*/
                }
                else
                {
                    /* only snapshot center of screen*/
                    Size sCrop = new Size((int)(sScreenshot.Width * 0.25), (int)(sScreenshot.Height * 0.25));

                    sScreenshot.Height -= sCrop.Height;
                    sScreenshot.Width  -= sCrop.Width;

                    // Take the screenshot from the upper left corner to the right bottom corner.
                    gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X + sCrop.Width / 2,
                                                 Screen.PrimaryScreen.Bounds.Y + sCrop.Height / 2,
                                                 0 + sCrop.Width / 2,
                                                 0 + sCrop.Height / 2,
                                                 sScreenshot,
                                                 CopyPixelOperation.SourceCopy);

                    ttkey--; /*decrement time till next keyframe*/
                }

                ResizeImage(bmpScreenshot, bmpResized);

                double r = 0, g = 0, b = 0,
                       strongR = 0, strongG = 0, strongB = 0;
                UInt32 cPixels = 0, strongC = 0;
                double sumLuma = 0;

                /*Calculate average ARGB Values.
                 *  One could possibly improve performance of scanning pixels by directly access bitmap bytes
                 *  but as the biggest slice of scan time is lost during CopyFromScreen its disregarded for now*/
                for (uint y = 0; y < h; y++)
                {
                    uint numBlackPixelsInRow = 0;//if the entire row is black, this is propaby a black frame
                    for (uint x = 0; x < w; x++)
                    {
                        ColorRGB clr = new ColorRGB(bmpResized.GetPixel((int)x, (int)y));

                        if (clr.L < 0.005)
                        {
                            numBlackPixelsInRow++;
                        }


                        //if (clr.L > 0.005 && clr.L < 0.95) /*Dont account for pitch black or plain white.*/
                        {
                            cPixels++;

                            r += clr.R;
                            g += clr.G;
                            b += clr.B;

                            sumLuma += clr.L;

                            if (clr.S > 0.3f)
                            {/*This pixel is neiter black or white and so somwhat strongly saturated*/
                                strongR += clr.R;
                                strongG += clr.G;
                                strongB += clr.B;
                                strongC++;
                            }
                        }
                    }

                    if (numBlackPixelsInRow == w) /*Entire row was black*/
                    {
                        cPixels -= (uint)w;       /*Kinda remove the black row.*/
                    }
                }


                r /= cPixels;
                g /= cPixels;
                b /= cPixels;

                if (strongC > 0)
                {
                    strongR /= strongC;
                    strongG /= strongC;
                    strongB /= strongC;
                }

                lock (this)
                {
                    avarageSaturatedColor = Color.FromArgb(
                        255,
                        Math.Max(0, Math.Min(255, (int)strongR)),
                        Math.Max(0, Math.Min(255, (int)strongG)),
                        Math.Max(0, Math.Min(255, (int)strongB))
                        );

                    /*Current avarage screen colour becomes setpoint for lighting*/
                    avarageColor = Color.FromArgb(
                        255,
                        Math.Max(0, Math.Min(255, (int)r)),
                        Math.Max(0, Math.Min(255, (int)g)),
                        Math.Max(0, Math.Min(255, (int)b))
                        );

                    avarageLuminuosity = (float)(sumLuma / cPixels);
                }


                System.Threading.Thread.Sleep(10);
            }
        }
Example #2
0
        // Given H,S,L,A in range of 0-1
        // Returns a Color (RGB struct) in range of 0-255
        public static ColorRGB FromHSLA(double H, double S, double L, double A)
        {
            double v;
            double r, g, b;

            if (A > 1.0)
            {
                A = 1.0;
            }

            r = L;   // default to gray
            g = L;
            b = L;
            v = (L <= 0.5) ? (L * (1.0 + S)) : (L + S - L * S);
            if (v > 0)
            {
                double m;
                double sv;
                int    sextant;
                double fract, vsf, mid1, mid2;

                m       = L + L - v;
                sv      = (v - m) / v;
                H      *= 6.0;
                sextant = (int)H;
                fract   = H - sextant;
                vsf     = v * sv * fract;
                mid1    = m + vsf;
                mid2    = v - vsf;
                switch (sextant)
                {
                case 0:
                    r = v;
                    g = mid1;
                    b = m;
                    break;

                case 1:
                    r = mid2;
                    g = v;
                    b = m;
                    break;

                case 2:
                    r = m;
                    g = v;
                    b = mid1;
                    break;

                case 3:
                    r = m;
                    g = mid2;
                    b = v;
                    break;

                case 4:
                    r = mid1;
                    g = m;
                    b = v;
                    break;

                case 5:
                    r = v;
                    g = m;
                    b = mid2;
                    break;
                }
            }
            ColorRGB rgb = new ColorRGB();

            rgb.R = Convert.ToByte(r * 255.0f);
            rgb.G = Convert.ToByte(g * 255.0f);
            rgb.B = Convert.ToByte(b * 255.0f);
            rgb.A = Convert.ToByte(A * 255.0f);
            return(rgb);
        }
Example #3
0
        protected void LightSetterProcess()
        {
            while (bRun)
            {
                System.Threading.Thread.Sleep(10);

                State setState;

                switch (Settings.scanMethod)
                {
                case ScanMethod.HueBoost:
                {         /*methodb*/
                    ColorRGB huedColor = new ColorRGB(scanner.AvarageSaturatedColor);
                    //ColorRGB totalColor = new ColorRGB(scanner.AvarageColor);
                    float luma = scanner.AvarageLuma;
                    setState = new State()
                    {
                        hue            = (ushort)(huedColor.H * ushort.MaxValue),
                        sat            = (byte)(huedColor.S * 255),
                        bri            = (byte)(luma * 255),
                        on             = true,
                        transitiontime = Settings.transitiontime
                    };

                    break;
                }

                case ScanMethod.Avarage:
                {
                    //total avarages
                    ColorRGB c = new ColorRGB(scanner.AvarageColor);
                    setState = new State()
                    {
                        hue            = (ushort)(c.H * ushort.MaxValue),
                        sat            = (byte)(c.S * 255),
                        bri            = (byte)(c.L * 255),
                        on             = true,
                        transitiontime = Settings.transitiontime
                    };
                    break;
                }

                case ScanMethod.LumaOnly:
                    setState = new State()
                    {
                        bri            = (byte)(scanner.AvarageLuma * 255),
                        on             = true,
                        transitiontime = Settings.transitiontime
                    };
                    break;

                default:
                {
                    throw new Exception("Unexpected scanmode in settings");
                }
                }

                /*Do luma boost/reduction and limit min max light levels*/
                setState.bri = (byte)Math.Max(Settings.minLight, Math.Min((float)setState.bri * Settings.luminuosity, Settings.maxLight));

                /*Do sat boost/reduction*/
                if (Settings.saturation != 1)
                {
                    setState.sat = (byte)Math.Max(0, Math.Min((float)setState.sat * Settings.saturation, 255));
                }

                /*Decide if change shall be send to the bridge*/
                bool bSendUpdate = false;

                if (lastState == null) /*Send update if none sent yet*/
                {
                    bSendUpdate = true;
                }
                else if (DateTime.Now.Second % 5 == 0) /*Force send update every 5 seconds*/
                {
                    bSendUpdate = true;
                }
                else /*Decide if scene changes are big enough to send an update*/
                {
                    float delta = 0;
                    delta += Math.Abs(((float)lastState.bri - (float)setState.bri) / Byte.MaxValue);
                    delta += Math.Abs(((float)lastState.hue - (float)setState.hue) / ushort.MaxValue);
                    delta += Math.Abs(((float)lastState.sat - (float)setState.sat) / Byte.MaxValue);
                    delta /= 3;
                    if (delta >= Settings.minDelta)
                    {
                        bSendUpdate = true;
                    }
                }

                if (bSendUpdate)
                {
                    lastState = setState;
                    foreach (int lid in Settings.lights)
                    {
                        bridge.SetLightState(lid.ToString(), setState);
                    }

                    foreach (int gid in Settings.groups)
                    {
                        HueLib_base.Action a = new HueLib_base.Action();
                        a.on  = true;
                        a.sat = setState.sat;
                        a.hue = setState.hue;
                        a.bri = setState.bri;

                        bridge.SetGroupAction(gid.ToString(), a);
                    }

                    lock (this)
                        lightUpdatesSent++;
                }
            }
        }