Beispiel #1
0
        /// <summary>
        /// Spreads the dithering to surrounding pixels according to the floyd steinberg algorithm
        /// </summary>
        /// <param name="original">the original pixel</param>
        /// <param name="palette">the color the original pixel was mapped to</param>
        /// <param name="ditherDistortionArray">a reference to the overlay array that keeps track of dither distortion</param>
        /// <param name="currentColumn">the column of the pixel</param>
        /// <param name="currentRow">the row of the pixel</param>
        /// <param name="width">the width of the image</param>
        /// <param name="height">the height of the image</param>
        void IDitherer.Dither(Models.Color original, Models.Color palette, Models.Color[] ditherDistortionArray, long currentColumn, long currentRow, long width, long height)
        {
            // Locks the reference to the dither distortion overlay
            lock (ditherDistortionArray)
            {
                var     offset    = currentRow * width + currentColumn;
                float[] distances = original - palette;

                // To the right
                if (currentColumn != width - 1)
                {
                    ditherDistortionArray[offset + 1] += Apply(distances, 7);;
                }
                // Row below
                if (currentRow != height - 1)
                {
                    // To the left
                    if (currentColumn != 0)
                    {
                        ditherDistortionArray[offset + width - 1] += Apply(distances, 3);
                    }
                    // Below
                    ditherDistortionArray[offset + width] += Apply(distances, 5);
                    // To the right
                    if (currentColumn != width - 1)
                    {
                        ditherDistortionArray[offset + width + 1] += Apply(distances, 1);
                    }
                }
            }
        }
        /// <summary>
        /// Visualize the palette
        /// </summary>
        /// <param name="height">height of the palette to be drawn in pixels</param>
        /// <param name="width">width of the palette to be drawn in pixels</param>
        /// <returns>a bitmap visualizing the palette</returns>
        public Bitmap VisualizePallet(int height, int width)
        {
            if (!imageStore.QuantizerReady)
            {
                throw new Exception("Quantizer not ready!");
            }

            Bitmap bmp = new Bitmap(width, height);

            using (Graphics g = Graphics.FromImage(bmp))
            {
                var palette    = imageStore.Quantizer.GetPalette();
                var pallet     = Cloner.DeepClone(palette);
                int maxRows    = System.Math.Max(pallet.Count / 16, 1);
                int maxColumns = System.Math.Min(pallet.Count, 16);
                int xDelta     = width / maxColumns;
                int yDelta     = height / maxRows;

                for (int row = 0; row < maxRows; row++)
                {
                    for (int column = 0; column < maxColumns; column++)
                    {
                        Models.Color         c     = pallet[row * 16 + column];
                        System.Drawing.Color color = System.Drawing.Color.FromArgb(255, (int)c.Channel1, (int)c.Channel2, (int)c.Channel3);
                        g.FillRectangle(new SolidBrush(color), column * xDelta, row * yDelta, (column + 1) * xDelta, (row + 1) * yDelta);
                    }
                }
            }

            return(bmp);
        }
Beispiel #3
0
        public string UpdateToDoColor(string Token, int ID, string ColorN)
        {
            string IP = Request.UserHostAddress;

            JwtToken      Jwt         = new JwtToken();
            TokenCheckObj TokenResult = Jwt.CheckToken(Token, IP);

            int Users_Id = Convert.ToInt32(TokenResult.Users_Id);

            Models.Color    ColorData  = new Models.Color();
            Models.ToDoList DoListData = new Models.ToDoList();

            object Result = null;

            if (TokenResult.Status)
            {
                ColorData           = db.Color.Where(a => a.Color_Name == ColorN).FirstOrDefault();
                DoListData          = db.ToDoList.Where(a => a.Owner_ID == Users_Id).Where(a => a.ID == ID).FirstOrDefault();
                DoListData.Color_ID = ColorData.ID;
                db.SaveChanges();
                Result = new { Status = true };
            }
            else
            {
                Result = new
                {
                    Status = false,
                    ErrMsg = TokenResult.ErrMsg
                };
            }

            string Output = JsonConvert.SerializeObject(Result);

            return(Output);
        }
Beispiel #4
0
        /// <summary>
        /// Draws a bitmap while applying dithering and/or quantization
        /// </summary>
        /// <returns>the altered bitmap</returns>
        public override Bitmap Draw()
        {
            if (!imageStore.QuantizerReady)
            {
                throw new Exception("The Quantizer was not ready yet.");
            }
            TotalError = 0;
            IDitherer  ditherer = imageStore.Ditherer;
            Bitmap     canvas;
            BitmapData sourceData;
            BitmapData targetData;
            int        width;
            int        height;

            lock (imageStore.Image)
            {
                width  = imageStore.Image.Width;
                height = imageStore.Image.Height;

                Rectangle bounds = Rectangle.FromLTRB(0, 0, imageStore.Image.Width, imageStore.Image.Height);

                // Lock source bits for reading
                sourceData = imageStore.Image.LockBits(bounds, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

                // Lock target bits for writing
                canvas     = new Bitmap(imageStore.Image.Width, imageStore.Image.Height, PixelFormat.Format8bppIndexed);
                targetData = canvas.LockBits(bounds, ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
            }

            // Copy the palette to the target bitmap
            CopyPalette(canvas);

            try
            {
                long           total            = width * height;
                Models.Color[] ditherDistortion = new Models.Color[total];

                LoopRows(width, height, sourceData, targetData, ditherDistortion, ditherer);

                AverageError = TotalError / total;
            }

            finally
            {
                lock (imageStore.Image)
                {
                    imageStore.Image.UnlockBits(sourceData);
                }
                canvas.UnlockBits(targetData);
            }

            return(canvas);
        }
        public ColorDetailPage()
        {
            InitializeComponent();

            var color = new Models.Color
            {
                ColorName       = "Color Name",
                ColorCodeString = "#008080"
            };

            viewModel      = new ColorDetailViewModel(color);
            BindingContext = viewModel;
        }
Beispiel #6
0
        /// <summary>
        /// Generate a task that writes to the target bitmap
        /// </summary>
        /// <param name="sourceOffset">the offset to the source bitmap in memory</param>
        /// <param name="targetOffset">the offset to the target bitmap in memory</param>
        /// <param name="width">the width of the image</param>
        /// <param name="height">the height of the image</param>
        /// <param name="row">the row this task has to process</param>
        /// <param name="behind">the behind constant of the ditherer</param>
        /// <param name="progress">the progress array, this will get updated as the task progresses, and is used for checking if this task can continue</param>
        /// <param name="ditherDistortion">the dither distortion overlay, this will be edited by this task</param>
        /// <param name="ditherer">the ditherer to be used</param>
        /// <returns>the task</returns>
        private Task GenerateTask(long sourceOffset, long targetOffset, int width, int height, int row, int behind, int[] progress, Models.Color[] ditherDistortion, IDitherer ditherer)
        {
            // Re initialize the source and target rows
            byte[] targetLine = new byte[width];
            int[]  sourceLine = new int[width];
            var    id         = row;


            Task t = new Task(() =>
            {
                Marshal.Copy(new IntPtr(sourceOffset), sourceLine, 0, width);

                for (int index = 0; index < width; index++)
                {
                    if (id != 0)
                    {
                        // Check if the task processing the row above ours is done dithering the pixel this task is processing
                        while (index > (progress[id - 1] - behind))
                        {
                            System.Threading.Thread.Sleep(1);
                        }
                    }
                    // Read the color from the source image
                    Color color = Color.FromArgb(sourceLine[index]);
                    // Add the dithering to the pixel
                    var colorAsColor = new Models.Color(color) + ditherDistortion[index + id * width];
                    // Get the index of the color closest to the dithered pixel
                    targetLine[index] = (byte)imageStore.Quantizer.GetPaletteIndex(colorAsColor);
                    // Get the distance to dither the other pixels!
                    var distance = System.Math.Sqrt(Util.Math.Distance(new Models.Color(color), imageStore.Quantizer.GetColorByIndex(targetLine[index])));
                    ditherer.Dither(colorAsColor, imageStore.Quantizer.GetColorByIndex(targetLine[index]), ditherDistortion, index, id, width, height);
                    TotalError += distance;
                    // Free up memory by deleting this entry in the dither distortion matrix
                    ditherDistortion[index + id * width] = null;
                    progress[id]++;
                }
                // Increase this significantly so task below this can get to the end
                progress[id] += width;

                Marshal.Copy(targetLine, 0, new IntPtr(targetOffset), width);
                // Update progress
                completed++;

                lock (ProgressUpdate)
                {
                    ProgressUpdate?.Invoke(this, new ProgressEventArgs((int)(completed / (float)height * 100)));
                }
            });

            return(t);
        }
        public static Models.Color Create(FakeDataContext context, byte id = 4, string name = "Chestnut")
        {
            Setup(context);

            var color = new Models.Color
            {
                Id   = id,
                Name = name
            };

            context.Colors.Add(color);

            return(color);
        }
Beispiel #8
0
 /// <summary>
 /// Process a line from the bitmap image
 /// </summary>
 /// <param name="width">the width of the image</param>
 /// <param name="height">the height of the image</param>
 /// <param name="row">the current row being processed</param>
 /// <param name="ditherDistortion">the dither distortion overlay</param>
 /// <param name="sourceLine">the source row of pixels</param>
 /// <param name="targetLine">the target row of pixels</param>
 /// <param name="ditherer">the ditherer to use</param>
 private void GenerateLine(int width, int height, int row, Models.Color[] ditherDistortion, int[] sourceLine, byte[] targetLine, IDitherer ditherer)
 {
     for (int index = 0; index < width; index++)
     {
         // Read the color from the source image
         Color color = Color.FromArgb(sourceLine[index]);
         // Add the dithering to the pixel
         var colorAsColor = new Models.Color(color) + ditherDistortion[index + row * width];
         // Get the index of the color closest to the dithered pixel
         targetLine[index] = (byte)imageStore.Quantizer.GetPaletteIndex(colorAsColor);
         // Get the distance to dither the other pixels!
         var distance = System.Math.Sqrt(Util.Math.Distance(new Models.Color(color), imageStore.Quantizer.GetColorByIndex(targetLine[index])));
         ditherer.Dither(colorAsColor, imageStore.Quantizer.GetColorByIndex(targetLine[index]), ditherDistortion, index, row, width, height);
         TotalError += distance;
     }
 }
Beispiel #9
0
        public async void AddColorAsync()
        {
            Models.Color c = new Models.Color
            {
                Colorcode = "#FF0000",
                Colorname = "Red",
            };

            try
            {
                await DataStore.AddAsync(c);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
        /// <summary>
        /// Get the index of the color closest to a given color in the palette
        /// </summary>
        /// <param name="c">the color to replace</param>
        /// <returns>the index of the closest color in the palette</returns>
        public virtual int GetPaletteIndex(Models.Color c)
        {
            // If the palette is not yet initialized, populate it with the colors
            if (palette.Count == 0)
            {
                PopulatePalette();
            }
            int index = 0;

            Models.Color bestColor = palette[0];
            // Loop over the palette to find the closest color
            for (int i = 0; i < palette.Count; i++)
            {
                if (Util.Math.Distance(palette[i], c) < Util.Math.Distance(bestColor, c))
                {
                    bestColor = palette[i];
                    index     = (byte)i;
                }
            }
            return(index);
        }
Beispiel #11
0
        /// <summary>
        /// Spawns tasks that will each write a line to the target bitmap
        /// </summary>
        /// <param name="height">the height of the bitmap</param>
        /// <param name="width">the width of the bitmap</param>
        /// <param name="sourceOffset">the offset of the source bitmap in memory</param>
        /// <param name="targetOffset">the offset of the target bitmap in memory</param>
        /// <param name="sourceStride">the stride of the source bitmap in memory</param>
        /// <param name="targetStride">the stride of the trarget bitmap in memory</param>
        /// <param name="ditherer">the ditherer to be used</param>
        /// <param name="behind">how many pixels to the left of the currently processed pixel the ditherer writes distortion to</param>
        /// <returns>A list of writing tasks</returns>
        private Task[] GetTasks(int height, int width, long sourceOffset, long targetOffset, long sourceStride, int targetStride, IDitherer ditherer, int behind)
        {
            Models.Color[] ditherDistortion = new Models.Color[width * height];

            // Keeps track of the progress of every task, so they can know when to start
            // since they have to leave enough time so they won't quantize before dithering is finished
            // this is what behind is used for
            int[]  progress = new int[height];
            Task[] tasks    = new Task[height];
            completed = 0;
            for (int row = 0; row < height; row++)
            {
                Task t = GenerateTask(sourceOffset, targetOffset, width, height, row, behind, progress, ditherDistortion, ditherer);

                tasks[row] = t;
                // Set ConfigureAwait to false, to avoid deadlocking
                t.ConfigureAwait(false);
                t.Start();
                sourceOffset += sourceStride;
                targetOffset += targetStride;
            }
            return(tasks);
        }
 /// <summary>
 /// Copy constructor
 /// </summary>
 /// <param name="c"></param>
 public Color(Models.Color c)
 {
     Channel1 = c.Channel1;
     Channel2 = c.Channel2;
     Channel3 = c.Channel3;
 }
 /// <summary>
 /// Calculates the squared euclidean distance between two colors
 /// </summary>
 /// <param name="color">the first color</param>
 /// <param name="other">the second color</param>
 /// <returns>an integer representing the distance in euclidean space</returns>
 public static int Distance(Models.Color color, Models.Color other)
 {
     return((int)((color.Channel1 - other.Channel1) * (color.Channel1 - other.Channel1) + (color.Channel2 - other.Channel2) * (color.Channel2 - other.Channel2) + (color.Channel3 - other.Channel3) * (color.Channel3 - other.Channel3)));
 }
        /// <summary>
        /// Spreads the dithering to surrounding pixels according to the Jarvis Judice Ninke algorithm
        /// </summary>
        /// <param name="original">the original pixel</param>
        /// <param name="palette">the color the original pixel was mapped to</param>
        /// <param name="ditherDistortionArray">a reference to the overlay array that keeps track of dither distortion</param>
        /// <param name="currentColumn">the column of the pixel</param>
        /// <param name="currentRow">the row of the pixel</param>
        /// <param name="width">the width of the image</param>
        /// <param name="height">the height of the image</param>
        public void Dither(Models.Color original, Models.Color palette, Models.Color[] ditherDistortionArray, long currentColumn, long currentRow, long width, long height)
        {
            lock (ditherDistortionArray)
            {
                var     offset    = currentRow * width + currentColumn;
                float[] distances = original - palette;

                // Same row
                if (currentColumn < width - 1)
                {
                    ditherDistortionArray[offset + 1] += Apply(distances, 7);
                    if (currentColumn < (width - 2))
                    {
                        ditherDistortionArray[offset + 2] += Apply(distances, 5);
                    }
                }

                // Row below
                if (currentRow < height - 1)
                {
                    // Center
                    ditherDistortionArray[offset + width] += Apply(distances, 7);

                    // To the left
                    if (currentColumn > 0)
                    {
                        ditherDistortionArray[offset + width - 1] += Apply(distances, 5);
                        if (currentColumn > 1)
                        {
                            ditherDistortionArray[offset + width - 2] += Apply(distances, 3);
                        }
                    }

                    // To the right
                    if (currentColumn < (width - 1))
                    {
                        ditherDistortionArray[offset + width + 1] += Apply(distances, 5);
                        if (currentColumn < (width - 2))
                        {
                            ditherDistortionArray[offset + width + 2] += Apply(distances, 3);
                        }
                    }

                    // 2 rows below
                    if (currentRow < (height - 2))
                    {
                        // Center
                        ditherDistortionArray[offset + 2 * width] += Apply(distances, 5);

                        // To the left
                        if (currentColumn > 0)
                        {
                            ditherDistortionArray[offset + 2 * width - 1] += Apply(distances, 3);
                            if (currentColumn > 1)
                            {
                                ditherDistortionArray[offset + 2 * width - 2] += Apply(distances, 1);
                            }
                        }

                        // To the right
                        if (currentColumn < (width - 1))
                        {
                            ditherDistortionArray[offset + 2 * width + 1] += Apply(distances, 3);
                            if (currentColumn < (width - 2))
                            {
                                ditherDistortionArray[offset + 2 * width + 2] += Apply(distances, 1);
                            }
                        }
                    }
                }
            }
        }