コード例 #1
0
		public HistogramRgb () : base (3, 256)
		{
			visualColors = new ColorBgra[]{     
                                              ColorBgra.Blue,
                                              ColorBgra.Green,
                                              ColorBgra.Red
                                          };
		}
コード例 #2
0
		public abstract ColorBgra Apply (ColorBgra lhs, ColorBgra rhs);
コード例 #3
0
        public override ColorBgra GetPercentileColor(float fraction)
        {
            int[] perc = GetPercentile(fraction);

            return(ColorBgra.FromBgr((byte)(perc[0]), (byte)(perc[1]), (byte)(perc[2])));
        }
コード例 #4
0
        /// <summary>
        /// Blends the colors based on the given weight values.
        /// </summary>
        /// <param name="c">The array of color values.</param>
        /// <param name="w">The array of weight values.</param>
        /// <returns>
        /// Each color will be blended in proportionally to its weight value respective to 
        /// the total summation of the weight values.
        /// </returns>
        /// <remarks>
        /// "WAIP" stands for "weights, floating-point"</remarks>
        public static ColorBgra BlendColorsWFP(ColorBgra[] c, double[] w)
        {
            if (c.Length != w.Length)
            {
                throw new ArgumentException("c.Length != w.Length");
            }

            if (c.Length == 0)
            {
                return ColorBgra.FromUInt32(0);
            }

            double wsum = 0;
            double asum = 0;

            for (int i = 0; i < w.Length; ++i)
            {
                wsum += w[i];
                asum += (double)c[i].A * w[i];
            }

            double a = asum / wsum;
            double aMultWsum = a * wsum;

            double b;
            double g;
            double r;

            if (asum == 0)
            {
                b = 0;
                g = 0;
                r = 0;
            }
            else
            {
                b = 0;
                g = 0;
                r = 0;

                for (int i = 0; i < c.Length; ++i)
                {
                    b += (double)c[i].A * c[i].B * w[i];
                    g += (double)c[i].A * c[i].G * w[i];
                    r += (double)c[i].A * c[i].R * w[i];
                }

                b /= aMultWsum;
                g /= aMultWsum;
                r /= aMultWsum;
            }

            return ColorBgra.FromBgra((byte)b, (byte)g, (byte)r, (byte)a);
        }
コード例 #5
0
        /// <summary>
        /// Constructs a new ColorBgra instance from the values in the given Color instance.
        /// </summary>
//        public static ColorBgra FromColor(Color c)
//        {
//            return FromBgra(c.B, c.G, c.R, c.A);
//        }

        /// <summary>
        /// Converts this ColorBgra instance to a Color instance.
        /// </summary>
//        public Color ToColor()
//        {
//            return Color.FromArgb(A, R, G, B);
//        }

        /// <summary>
        /// Smoothly blends between two colors.
        /// </summary>
		public static ColorBgra Blend (ColorBgra ca, ColorBgra cb, byte cbAlpha)
		{
			uint caA = (uint)Utility.FastScaleByteByByte ((byte)(255 - cbAlpha), ca.A);
			uint cbA = (uint)Utility.FastScaleByteByByte (cbAlpha, cb.A);
			uint cbAT = caA + cbA;

			uint r;
			uint g;
			uint b;

			if (cbAT == 0) {
				r = 0;
				g = 0;
				b = 0;
			} else {
				r = ((ca.R * caA) + (cb.R * cbA)) / cbAT;
				g = ((ca.G * caA) + (cb.G * cbA)) / cbAT;
				b = ((ca.B * caA) + (cb.B * cbA)) / cbAT;
			}

			return ColorBgra.FromBgra ((byte)b, (byte)g, (byte)r, (byte)cbAT);
		}
コード例 #6
0
        /// <summary>
        /// Blends four colors together based on the given weight values.
        /// </summary>
        /// <returns>The blended color.</returns>
        /// <remarks>
        /// The weights should be 16-bit fixed point numbers that add up to 65536 ("1.0").
        /// 4W16IP means "4 colors, weights, 16-bit integer precision"
        /// </remarks>
        public static ColorBgra BlendColors4W16IP(ColorBgra c1, uint w1, ColorBgra c2, uint w2, ColorBgra c3, uint w3, ColorBgra c4, uint w4)
        {
#if DEBUG
            if ((w1 + w2 + w3 + w4) != 65536)
            {
                throw new ArgumentOutOfRangeException("w1 + w2 + w3 + w4 must equal 65536!");
            }
#endif

            const uint ww = 32768;
            uint af = (c1.A * w1) + (c2.A * w2) + (c3.A * w3) + (c4.A * w4);
            uint a = (af + ww) >> 16;

            uint b;
            uint g;
            uint r;

            if (a == 0)
            {
                b = 0;
                g = 0;
                r = 0;
            }
            else
            {
                b = (uint)((((long)c1.A * c1.B * w1) + ((long)c2.A * c2.B * w2) + ((long)c3.A * c3.B * w3) + ((long)c4.A * c4.B * w4)) / af);
                g = (uint)((((long)c1.A * c1.G * w1) + ((long)c2.A * c2.G * w2) + ((long)c3.A * c3.G * w3) + ((long)c4.A * c4.G * w4)) / af);
                r = (uint)((((long)c1.A * c1.R * w1) + ((long)c2.A * c2.R * w2) + ((long)c3.A * c3.R * w3) + ((long)c4.A * c4.R * w4)) / af);
            }

            return ColorBgra.FromBgra((byte)b, (byte)g, (byte)r, (byte)a);
        }
コード例 #7
0
 public abstract ColorBgra Apply(ColorBgra lhs, ColorBgra rhs);
コード例 #8
0
 /// <summary>
 /// Creates a new ColorBgra instance with the given color and alpha values.
 /// </summary>
 public static ColorBgra FromBgra(byte b, byte g, byte r, byte a)
 {
     ColorBgra color = new ColorBgra();
     color.Bgra = BgraToUInt32(b, g, r, a);
     return color;        
 }
コード例 #9
0
		/// <summary>
		/// Performs the actual work of rendering an effect. This overload represent a single pixel of the image.
		/// </summary>
		/// <param name="color">The color of the source surface pixel.</param>
		/// <returns>The color to be used for the destination pixel.</returns>
		protected virtual ColorBgra Render (ColorBgra color)
		{
			return color;
		}
コード例 #10
0
 public static Cairo.Color ToCairoColor(this ColorBgra color)
 {
     return(new Cairo.Color(color.R / 255d, color.G / 255d, color.B / 255d, color.A / 255d));
 }
コード例 #11
0
		/// <summary>
		/// Performs the actual work of rendering an effect. This overload represent a single line of the image. Do not call base.Render ().
		/// </summary>
		/// <param name="src">The source surface. DO NOT MODIFY.</param>
		/// <param name="dst">The destination surface.</param>
		/// <param name="length">The number of pixels to render.</param>
		protected unsafe virtual void Render (ColorBgra* src, ColorBgra* dst, int length)
		{
			while (length > 0) {
				*dst = Render (*src);
				++dst;
				++src;
				--length;
			}
		}
コード例 #12
0
		protected unsafe virtual void RenderLoop (ISurface surface, Rectangle roi, CancellationToken token, IRenderProgress progress)
		{
			var dst = new ColorBgra[surface.Height * surface.Width];

			fixed (ColorBgra* dst_ptr = dst) {
				var dst_wrap = new ColorBgraArrayWrapper (dst_ptr, surface.Width, surface.Height);

				surface.BeginUpdate ();
				dst_wrap.BeginUpdate ();

				OnBeginRender (surface, dst_wrap, roi);

				var completed_lines = new bool[roi.Height];
				var last_completed_index = 0;

				if (Settings.SingleThreaded || roi.Height <= 1) {
					for (var y = roi.Y; y <= roi.Bottom; ++y) {
						if (token.IsCancellationRequested)
							return;

						RenderLine (surface, dst_wrap, new Rectangle (roi.X, y, roi.Width, 1));

						completed_lines[y - roi.Top] = true;

						if (progress != null) {
							var last_y = FindLastCompletedLine (completed_lines, last_completed_index);
							last_completed_index = last_y;
							progress.CompletedRoi = new Rectangle (roi.X, roi.Y, roi.Width, last_y);
							progress.PercentComplete = (float)last_y / (float)roi.Height;
						}
					}
				} else {
					ParallelExtensions.OrderedFor (roi.Y, roi.Bottom + 1, token, (y) => {
						RenderLine (surface, dst_wrap, new Rectangle (roi.X, y, roi.Width, 1));

						completed_lines[y - roi.Top] = true;

						if (progress != null) {
							var last_y = FindLastCompletedLine (completed_lines, last_completed_index);
							last_completed_index = last_y;
							progress.CompletedRoi = new Rectangle (roi.X, roi.Y, roi.Width, last_y);
							progress.PercentComplete = (float)last_y / (float)roi.Height;
						}
					});
				}

				// Copy the result from our temp destination back into the source
				var op = new IdentityOp ();
				op.ApplyAsync (dst_wrap, surface, token).Wait ();

				surface.EndUpdate ();
				dst_wrap.EndUpdate ();
			}
		}
コード例 #13
0
        public void SetFromLeveledHistogram(HistogramRgb inputHistogram, LevelOp upo)
        {
            if (inputHistogram == null || upo == null)
            {
                return;
            }

            Clear();

            float[] before = new float[3];
            float[] slopes = new float[3];

            for (int c = 0; c < 3; c++)
            {
                long[] channelHistogramOutput = histogram[c];
                long[] channelHistogramInput  = inputHistogram.histogram[c];

                for (int v = 0; v <= 255; v++)
                {
                    ColorBgra after = ColorBgra.FromBgr((byte)v, (byte)v, (byte)v);

                    upo.UnApply(after, before, slopes);

                    if (after[c] > upo.ColorOutHigh[c] ||
                        after[c] < upo.ColorOutLow[c] ||
                        (int)Math.Floor(before[c]) < 0 ||
                        (int)Math.Ceiling(before[c]) > 255 ||
                        float.IsNaN(before[c]))
                    {
                        channelHistogramOutput[v] = 0;
                    }
                    else if (before[c] <= upo.ColorInLow[c])
                    {
                        channelHistogramOutput[v] = 0;

                        for (int i = 0; i <= upo.ColorInLow[c]; i++)
                        {
                            channelHistogramOutput[v] += channelHistogramInput[i];
                        }
                    }
                    else if (before[c] >= upo.ColorInHigh[c])
                    {
                        channelHistogramOutput[v] = 0;

                        for (int i = upo.ColorInHigh[c]; i < 256; i++)
                        {
                            channelHistogramOutput[v] += channelHistogramInput[i];
                        }
                    }
                    else
                    {
                        channelHistogramOutput[v] = (int)(slopes[c] * Utility.Lerp(
                                                              channelHistogramInput[(int)Math.Floor(before[c])],
                                                              channelHistogramInput[(int)Math.Ceiling(before[c])],
                                                              before[c] - Math.Floor(before[c])));
                    }
                }
            }

            OnHistogramUpdated();
        }
コード例 #14
0
		public static ColorBgra ToPintaColorBgra (this Cairo.Color color)
		{
			var c = new ColorBgra ();

			c.R = (byte)(color.R * 255);
			c.G = (byte)(color.G * 255);
			c.B = (byte)(color.B * 255);
			c.A = (byte)(color.A * 255);

			return c;
		}
コード例 #15
0
		public unsafe virtual void Apply (ColorBgra* ptr, int length)
		{
			unsafe {
				while (length > 0) {
					*ptr = Apply (*ptr);
					++ptr;
					--length;
				}
			}
		}
コード例 #16
0
		public static unsafe ColorBgra GetBilinearSampleWrapped (ISurface src, ColorBgra* srcDataPtr, int srcWidth, int srcHeight, float x, float y)
		{
			if (!Utility.IsNumber (x) || !Utility.IsNumber (y))
				return ColorBgra.Transparent;

			float u = x;
			float v = y;

			unchecked {
				int iu = (int)Math.Floor (u);
				uint sxfrac = (uint)(256 * (u - (float)iu));
				uint sxfracinv = 256 - sxfrac;

				int iv = (int)Math.Floor (v);
				uint syfrac = (uint)(256 * (v - (float)iv));
				uint syfracinv = 256 - syfrac;

				uint wul = (uint)(sxfracinv * syfracinv);
				uint wur = (uint)(sxfrac * syfracinv);
				uint wll = (uint)(sxfracinv * syfrac);
				uint wlr = (uint)(sxfrac * syfrac);

				int sx = iu;
				if (sx < 0)
					sx = (srcWidth - 1) + ((sx + 1) % srcWidth);
				else if (sx > (srcWidth - 1))
					sx = sx % srcWidth;

				int sy = iv;
				if (sy < 0)
					sy = (srcHeight - 1) + ((sy + 1) % srcHeight);
				else if (sy > (srcHeight - 1))
					sy = sy % srcHeight;

				int sleft = sx;
				int sright;

				if (sleft == (srcWidth - 1))
					sright = 0;
				else
					sright = sleft + 1;

				int stop = sy;
				int sbottom;

				if (stop == (srcHeight - 1))
					sbottom = 0;
				else
					sbottom = stop + 1;

				ColorBgra cul = src.GetPoint (sleft, stop);
				ColorBgra cur = src.GetPoint (sright, stop);
				ColorBgra cll = src.GetPoint (sleft, sbottom);
				ColorBgra clr = src.GetPoint (sright, sbottom);

				ColorBgra c = ColorBgra.BlendColors4W16IP (cul, wul, cur, wur, cll, wll, clr, wlr);

				return c;
			}
		}
コード例 #17
0
		public abstract ColorBgra Apply (ColorBgra color);
コード例 #18
0
 /// <summary>
 /// Constructs a new ColorBgra instance with the given 32-bit value.
 /// </summary>
 public static ColorBgra FromUInt32(UInt32 bgra)
 {
     ColorBgra color = new ColorBgra();
     color.Bgra = bgra;
     return color;
 }
コード例 #19
0
		public unsafe ColorBgraArrayWrapper (ColorBgra* data, int width, int height)
		{
			data_ptr = data;
			this.height = height;
			this.width = width;
		}
コード例 #20
0
        /// <summary>
        /// Linearly interpolates between two color values.
        /// </summary>
        /// <param name="from">The color value that represents 0 on the lerp number line.</param>
        /// <param name="to">The color value that represents 1 on the lerp number line.</param>
        /// <param name="frac">A value in the range [0, 1].</param>
        /// <remarks>
        /// This method does a simple lerp on each color value and on the alpha channel. It does
        /// not properly take into account the alpha channel's effect on color blending.
        /// </remarks>
        public static ColorBgra Lerp(ColorBgra from, ColorBgra to, double frac) 
        {
            ColorBgra ret = new ColorBgra();

            ret.B = (byte)ClampToByte(Lerp(from.B, to.B, frac));
            ret.G = (byte)ClampToByte(Lerp(from.G, to.G, frac));
            ret.R = (byte)ClampToByte(Lerp(from.R, to.R, frac));
            ret.A = (byte)ClampToByte(Lerp(from.A, to.A, frac));

            return ret;
        }
コード例 #21
0
		public unsafe abstract void Apply (ColorBgra* src, ColorBgra* dst, int length);
コード例 #22
0
        /// <summary>
        /// Blends the colors based on the given weight values.
        /// </summary>
        /// <param name="c">The array of color values.</param>
        /// <param name="w">The array of weight values.</param>
        /// <returns>
        /// The weights should be fixed point numbers. 
        /// The total summation of the weight values will be treated as "1.0".
        /// Each color will be blended in proportionally to its weight value respective to 
        /// the total summation of the weight values.
        /// </returns>
        /// <remarks>
        /// "WAIP" stands for "weights, arbitrary integer precision"</remarks>
        public static ColorBgra BlendColorsWAIP(ColorBgra[] c, uint[] w)
        {
            if (c.Length != w.Length)
            {
                throw new ArgumentException("c.Length != w.Length");
            }

            if (c.Length == 0)
            {
                return ColorBgra.FromUInt32(0);
            }

            long wsum = 0;
            long asum = 0;

            for (int i = 0; i < w.Length; ++i)
            {
                wsum += w[i];
                asum += c[i].A * w[i];
            }

            uint a = (uint)((asum + (wsum >> 1)) / wsum);

            long b;
            long g;
            long r;

            if (a == 0)
            {
                b = 0;
                g = 0;
                r = 0;
            }
            else
            {
                b = 0;
                g = 0;
                r = 0;

                for (int i = 0; i < c.Length; ++i)
                {
                    b += (long)c[i].A * c[i].B * w[i];
                    g += (long)c[i].A * c[i].G * w[i];
                    r += (long)c[i].A * c[i].R * w[i];
                }

                b /= asum;
                g /= asum;
                r /= asum;
            }

            return ColorBgra.FromUInt32((uint)b + ((uint)g << 8) + ((uint)r << 16) + ((uint)a << 24));
        }        
コード例 #23
0
		public virtual void Apply (ColorBgra* lhs, ColorBgra* rhs, ColorBgra* dst, int length)
		{
			unsafe {
				while (length > 0) {
					*dst = Apply (*lhs, *rhs);
					++dst;
					++lhs;
					++rhs;
					--length;
				}
			}
		}
コード例 #24
0
		/// <summary>
        /// Smoothly blends the given colors together, assuming equal weighting for each one.
        /// </summary>
        /// <param name="colors"></param>
        /// <param name="colorCount"></param>
        /// <returns></returns>
        public unsafe static ColorBgra Blend(ColorBgra* colors, int count)
        {
            if (count < 0)
            {
                throw new ArgumentOutOfRangeException("count must be 0 or greater");
            }

            if (count == 0)
            {
                return ColorBgra.Transparent;
            }

            ulong aSum = 0;

            for (int i = 0; i < count; ++i)
            {
                aSum += (ulong)colors[i].A;
            }

            byte b = 0;
            byte g = 0;
            byte r = 0;
            byte a = (byte)(aSum / (ulong)count);

            if (aSum != 0)
            {
                ulong bSum = 0;
                ulong gSum = 0;
                ulong rSum = 0;

                for (int i = 0; i < count; ++i)
                {
                    bSum += (ulong)(colors[i].A * colors[i].B);
                    gSum += (ulong)(colors[i].A * colors[i].G);
                    rSum += (ulong)(colors[i].A * colors[i].R);
                }

                b = (byte)(bSum / aSum);
                g = (byte)(gSum / aSum);
                r = (byte)(rSum / aSum);
            }

            return ColorBgra.FromBgra(b, g, r, a);
        }
コード例 #25
0
		public unsafe override void Apply (ColorBgra* src, ColorBgra* dst, int length)
		{
			unsafe {
				while (length > 0) {
					*dst = Apply (*dst, *src);
					++dst;
					++src;
					--length;
				}
			}
		}
コード例 #26
0
		public static unsafe SurfaceDiff Create (ISurface original, ISurface updated_surf, bool force = false)
		{
			if (original.Width != updated_surf.Width || original.Height != updated_surf.Height) {
				// If the surface changed size, only throw an error if the user forced the use of a diff.
				if (force) {
					throw new InvalidOperationException ("SurfaceDiff requires surfaces to be same size.");
				} else {
					return null;
				}
			}

			// Cache some pinvokes
			var orig_width = original.Width;
			var orig_height = original.Height;

#if DEBUG_DIFF
			Console.WriteLine ("Original surface size: {0}x{1}", orig_width, orig_height);
			System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
			timer.Start();
#endif

			// STEP 1 - Find the bounds of the changed pixels.
			var orig_ptr = (int*)original.GetRowAddress (0);
			var updated_ptr = (int*)updated_surf.GetRowAddress (0);

			DiffBounds diff_bounds = new DiffBounds (orig_width, orig_height);
			object diff_bounds_lock = new Object();

			// Split up the work among several threads, each of which processes one row at a time
			// and updates the bounds of the changed pixels it has seen so far. At the end, the
			// results from each thread are merged together to find the overall bounds of the changed
			// pixels.
			Parallel.For<DiffBounds>(0, orig_height, () => new DiffBounds (orig_width, orig_height),
                     		(row, loop, my_bounds) => {

					var offset = row * orig_width;
					var orig = orig_ptr + offset;
					var updated = updated_ptr + offset;
					bool change_in_row = false;

					for (int i = 0; i < orig_width; ++i) {
						if (*(orig++) != *(updated++)) {
							change_in_row = true;
							my_bounds.left = System.Math.Min(my_bounds.left, i);
							my_bounds.right = System.Math.Max(my_bounds.right, i);
						}				
					}

					if (change_in_row) {
						my_bounds.top = System.Math.Min(my_bounds.top, row);
						my_bounds.bottom = System.Math.Max(my_bounds.bottom, row);
					}

					return my_bounds;

			},	(my_bounds) => {
					lock (diff_bounds_lock) {
						diff_bounds.Merge (my_bounds);
					}
					return;
			});

			var bounds = new Rectangle (diff_bounds.left, diff_bounds.top,
			                                diff_bounds.right - diff_bounds.left + 1,
			                                diff_bounds.bottom - diff_bounds.top + 1);

#if DEBUG_DIFF
			Console.WriteLine ("Truncated surface size: {0}x{1}", bounds.Width, bounds.Height);
#endif

			// STEP 2 - Create a bitarray of whether each pixel in the bounds has changed, and count
			// how many changed pixels we need to store.
			var bitmask = new BitArray (bounds.Width * bounds.Height);
			int index = 0;
			int num_changed = 0;

			int bottom = bounds.Bottom;
			int right = bounds.Right;
			int bounds_x = bounds.X;
			int bounds_y = bounds.Y;

			for (int y = bounds_y; y <= bottom; ++y) {
				var offset = y * orig_width;
				var updated = updated_ptr + offset + bounds_x;
				var orig = orig_ptr + offset + bounds_x;

				for (int x = bounds_x; x <= right; ++x) {
					bool changed = *(orig++) != *(updated++);
					bitmask[index++] = changed;
					if (changed) {
						num_changed++;
					}
				}
			}			

			var savings = 100 - (float)num_changed / (float)(orig_width * orig_height) * 100;
#if DEBUG_DIFF
			Console.WriteLine ("Compressed bitmask: {0}/{1} = {2}%", num_changed, orig_height * orig_width, 100 - savings);
#endif

			if (!force && savings < MINIMUM_SAVINGS_PERCENT) {
#if DEBUG_DIFF
				Console.WriteLine ("Savings too small, returning null");
#endif
				return null;
			}

			// Store the old pixels.
			var pixels = new ColorBgra[num_changed];
			var new_ptr = (ColorBgra*)original.GetRowAddress (0);
			int mask_index = 0;

			fixed (ColorBgra* fixed_ptr = pixels) {
				var pixel_ptr = fixed_ptr;

				for (int y = bounds_y; y <= bottom; ++y) {
					var new_pixel_ptr = new_ptr + bounds_x + y * orig_width;

					for (int x = bounds_x; x <= right; ++x) {
						if (bitmask[mask_index++]) {
							*pixel_ptr++ = *new_pixel_ptr;
						}

						new_pixel_ptr++;
					}
				}
			}

#if DEBUG_DIFF
			timer.Stop();
			System.Console.WriteLine("SurfaceDiff time: " + timer.ElapsedMilliseconds);
#endif

			return new SurfaceDiff (bitmask, bounds, pixels);
		}
コード例 #27
0
 public override ColorBgra GetMeanColor()
 {
     float[] mean = GetMean();
     return(ColorBgra.FromBgr((byte)(mean[0] + 0.5f), (byte)(mean[1] + 0.5f), (byte)(mean[2] + 0.5f)));
 }