/// <summary> /// Function responsible for averaging color within the given positions /// </summary> /// <param name="gs">DataStream object - comes from screen capture</param> /// <param name="channel"></param> /// <param name="pixelColorTreshold"></param> /// <returns></returns> public Color AverageScreenRGBfromChannel(DataStream gs, LightChannel channel, int pixelColorTreshold) { // Byte definition for pixel byte[] bu = new byte[4]; // End values for RGB int r = 0; int g = 0; int b = 0; int i = 1; // Temporary values for RGB int temp_r = 0; int temp_g = 0; int temp_b = 0; // For every position we have within our channel // loop through it foreach (long pos in channel.positions) { // Get details for current screen position gs.Position = pos; gs.Read(bu, 0, 4); // Assign result to temporary variables temp_r = bu[2]; temp_g = bu[1]; temp_b = bu[0]; // Check if our color is within minial required treshold. // If black we dont need it :) if ((temp_r + temp_g + temp_b) > pixelColorTreshold) { r += temp_r; g += temp_g; b += temp_b; // Increment the count of accounted colors i++; } } r = r / i != 0 ? r / i : 1; g = g / i != 0 ? g / i : 1; b = b / i != 0 ? b / i : 1; channel.R = r; channel.G = g; channel.B = b; return(Color.FromArgb(1, 1, 1)); }
/// <summary> /// calculates channels with defined precision /// </summary> /// <param name="channel">Ambichannel object containing parameters for calculations</param> /// <param name="precision">How many positions we will take to get average RGB color of perimeter</param> /// <param name="ScreenXsize">Screen width</param> public void SetUpChannelPositions(LightChannel channel, int precision, int ScreenXsize) { //Forumla na obliczenie pozycji piksela //przy pomocy "graphics stream" // // Index = (x + y * screenwidth) * SizeOf(Pixel) // // pos = (x+y*screenwidth) * 4 // // 4 - poniewaz kazdy pixel ma 4 kanaly ARGB kazdy z 1 byte // // Current position int current_pos = 0; // REMOVE ALL PREVIOUS POSTIONS channel.positions.Clear(); // This is where all the magic happens: calculate the average RGB for (int j = channel.MinY; j <= channel.MaxY; j += precision) { for (int i = channel.MinX; i <= channel.MaxX; i += precision) { //current_pos = (4 * j * ScreenXsize) + (4 * i); current_pos = (i + j * ScreenXsize) * 4; channel.positions.Add(current_pos); // [CHECK] if we do not exceed max if ((i + precision) > channel.MaxX) { i = channel.MaxX; } } // [CHECK] if we do not exceed max if ((j + precision) > channel.MaxY) { j = channel.MaxY; } } }
/// <summary> /// Metoda odpowiedzialna za stworzenie kanalow /// </summary> /// <param name="LightChannels"></param> /// <returns></returns> private void Create_Light_Channels() { List <LightChannel> temp_list = new List <LightChannel>(); // Lista uzywana do przechowania wynikow zwracanych do aplikacji // Zmiennie definiujace maxymalne wartosci X/Y dla tworzenia kanalow int Channels_Begin_X = 0, Channels_Begin_Y = 0, Channels_Stop_X = 0, Channels_Stop_Y = 0, Channel_X = 0, Channel_Y = 0, Channel_X_Width = 0, Channel_Y_Height = 0; #region Channels - TOP LightChannelBase channelBase_rows = new LightChannelBase(); /* * Zaczynamy od ustalenia wartosci wyznaczajacych nasze kanaly. Jako , ze obliczylismy juz granice / corner padding mozemy po prostu wyznaczyc * sobie punkty skrajne i na podstawie ilosci kanalow wyznaczyc obramowania */ channelBase_rows.Stop_X = max_right; // channelBase_rows.Start_X = min_left; // channelBase_rows.Start_Y = Screen_Min_Y; channelBase_rows.Height = (Screen_Max_Y * Channel_Depth_Size_Rows) / 100; // channelBase_rows.Width = (channelBase_rows.Stop_X - channelBase_rows.Start_X) / Channels_top; // channelBase_rows.Stop_Y = channelBase_rows.Start_Y + channelBase_rows.Height; /* * Ustalamy pozycje startowa X */ Channel_X = channelBase_rows.Start_X; /* * Obliczamy kanaly na podstawie danych , ktore juz mamy */ for (int r = 0; r < Channels_top; r++) { LightChannel testAmbilightChannel = new LightChannel { MinX = Channel_X, // Ta wartosc sie zmienia i jest inkrementowana --- MinY = channelBase_rows.Start_Y, MaxX = Channel_X + channelBase_rows.Width - 1, // Ta wartosc sie zmienia i jest inkrementowana --- MaxY = channelBase_rows.Stop_Y, // Na podstawie bordero'w ustalamy maxymalny Y positions = new Collection <long>(), Location = ChannelPosition.Top, Height = channelBase_rows.Height, Width = channelBase_rows.Width }; temp_list.Add(testAmbilightChannel); // Dodajemy do naszej listy kanalow Channel_X += channelBase_rows.Width; // Dodajemy odpowiednio dlugosc kanalu aby nastepny sie poprawnie zaczynal } var debug = ""; #endregion #region Channels - RIGHT LightChannelBase channelBase_columns = new LightChannelBase(); /* * Zaczynamy od ustalenia wartosci wyznaczajacych nasze kanaly. Jako , ze obliczylismy juz granice / corner padding mozemy po prostu wyznaczyc * sobie punkty skrajne i na podstawie ilosci kanalow wyznaczyc obramowania */ channelBase_columns.Stop_X = Screen_Max_X; // Ok channelBase_columns.Start_X = Screen_Max_X - ((Screen_Max_X * Channel_Depth_Size_Columns) / 100); // Ok // channelBase_columns.Start_Y = min_top; // Ok channelBase_columns.Stop_Y = max_bottom; // Ok channelBase_columns.Height = (channelBase_columns.Stop_Y - channelBase_columns.Start_Y) / Channels_right; // Ok channelBase_columns.Width = channelBase_columns.Stop_X - channelBase_columns.Start_X; // Ok /* * Ustalamy pozycje startowe X oraz Y dla pierwszego kanalu */ Channel_Y = channelBase_columns.Start_Y; /* * Obliczamy kanaly na podstawie danych , ktore juz mamy */ for (int r = 0; r < Channels_right; r++) { LightChannel testAmbilightChannel = new LightChannel { MinX = channelBase_columns.Start_X, MinY = Channel_Y, // Ta wartosc sie zmienia i jest inkrementowana --- MaxX = channelBase_columns.Stop_X, MaxY = Channel_Y + channelBase_columns.Height - 1, // Ta wartosc sie zmienia i jest inkrementowana --- positions = new Collection <long>(), Location = ChannelPosition.Right, Height = channelBase_columns.Height, Width = channelBase_columns.Width }; temp_list.Add(testAmbilightChannel); // Dodajemy do naszej listy kanalow Channel_Y += channelBase_columns.Height; // Dodajemy odpowiednio dlugosc kanalu aby nastepny sie poprawnie zaczynal } #endregion #region Channels - BOTTOM /* * Zaczynamy od ustalenia wartosci wyznaczajacych nasze kanaly. Jako , ze obliczylismy juz granice / corner padding mozemy po prostu wyznaczyc * sobie punkty skrajne i na podstawie ilosci kanalow wyznaczyc obramowania */ channelBase_rows.Start_Y = Screen_Max_Y - channelBase_rows.Height; channelBase_rows.Width = (channelBase_rows.Stop_X - channelBase_rows.Start_X) / Channels_bottom; channelBase_rows.Stop_Y = Screen_Max_Y; /* * Ustalamy pozycje startowa X */ Channel_X = channelBase_rows.Stop_X; /* * Obliczamy kanaly na podstawie danych , ktore juz mamy */ for (int r = 0; r < Channels_bottom; r++) { LightChannel testAmbilightChannel = new LightChannel { MaxX = Channel_X, // Ta wartosc sie zmienia i jest inkrementowana --- MinY = channelBase_rows.Start_Y, MinX = Channel_X - channelBase_rows.Width + 1, // Ta wartosc sie zmienia i jest inkrementowana --- MaxY = channelBase_rows.Stop_Y, // Na podstawie bordero'w ustalamy maxymalny Y positions = new Collection <long>(), Location = ChannelPosition.Bottom, Height = channelBase_rows.Height, Width = channelBase_rows.Width }; temp_list.Add(testAmbilightChannel); // Dodajemy do naszej listy kanalow Channel_X -= channelBase_rows.Width; // Dodajemy odpowiednio dlugosc kanalu aby nastepny sie poprawnie zaczynal } #endregion #region Channels - LEFT /* * Zaczynamy od ustalenia wartosci wyznaczajacych nasze kanaly. Jako , ze obliczylismy juz granice / corner padding mozemy po prostu wyznaczyc * sobie punkty skrajne i na podstawie ilosci kanalow wyznaczyc obramowania */ channelBase_columns.Stop_X = ((Screen_Max_X * Channel_Depth_Size_Columns) / 100); // OK channelBase_columns.Start_X = Screen_Min_X; // Ok channelBase_columns.Start_Y = min_top; // Ok channelBase_columns.Stop_Y = max_bottom; // Ok channelBase_columns.Height = (channelBase_columns.Stop_Y - channelBase_columns.Start_Y) / Channels_left; // Ok channelBase_columns.Width = channelBase_columns.Stop_X - channelBase_columns.Start_X; // Ok /* * Ustalamy pozycje startowe X oraz Y dla pierwszego kanalu */ Channel_Y = channelBase_columns.Stop_Y; /* * Obliczamy kanaly na podstawie danych , ktore juz mamy */ for (int r = 0; r < Channels_left; r++) { LightChannel testAmbilightChannel = new LightChannel { MinX = channelBase_columns.Start_X, MaxY = Channel_Y, // Ta wartosc sie zmienia i jest inkrementowana --- MaxX = channelBase_columns.Stop_X, MinY = Channel_Y - channelBase_columns.Height + 1, // Ta wartosc sie zmienia i jest inkrementowana --- positions = new Collection <long>(), Location = ChannelPosition.Left, Height = channelBase_columns.Height, Width = channelBase_columns.Width }; temp_list.Add(testAmbilightChannel); // Dodajemy do naszej listy kanalow Channel_Y -= channelBase_columns.Height; // Dodajemy odpowiednio dlugosc kanalu aby nastepny sie poprawnie zaczynal } #endregion this.LightChannels = temp_list; }
/// <summary> /// Function to adjust colors that are dominant within specified area! /// </summary> /// <param name="channel">Ambi Channel</param> /// <param name="adjustment">what should be the default adjustment</param> public void AdjustAverageRGB(LightChannel channel, int adjustment) { if (channel.R >= channel.G && channel.R >= channel.B) { // Red is the most dominant if (channel.G >= channel.B) { // Red > Green > Blue channel.R += adjustment * (channel.R - channel.G); channel.B -= adjustment * (channel.G - channel.B); } else { // Red > Blue > Green channel.R += adjustment * (channel.R - channel.B); channel.G -= adjustment * (channel.B - channel.G); } } else if (channel.G >= channel.B && channel.G >= channel.R) { // Green is the most dominant if (channel.R >= channel.B) { // Green > Red > Blue channel.G += adjustment * (channel.G - channel.R); channel.B -= adjustment * (channel.R - channel.B); } else { // Green > Blue > Red channel.G += adjustment * (channel.G - channel.B); channel.R -= adjustment * (channel.B - channel.R); } } else { // Blue is the most dominant if (channel.R >= channel.G) { // Blue > Red > Green channel.B += adjustment * (channel.B - channel.R); channel.G -= adjustment * (channel.R - channel.G); } else { // Blue > Green > Red channel.B += adjustment * (channel.B - channel.G); channel.R -= adjustment * (channel.G - channel.R); } } // Check red bounds if (channel.R > 255) { channel.R = 255; } //else if (process && r < MinRed) r = MinRed; else if (channel.R < 0) { channel.R = 0; } // Check green bounds if (channel.G > 255) { channel.G = 255; } //else if (process && g < MinGreen) g = MinGreen; else if (channel.G < 0) { channel.G = 0; } // Check blue bounds if (channel.B > 255) { channel.B = 255; } //else if (process && b < MinBlue) b = MinBlue; else if (channel.B < 0) { channel.B = 0; } }