Nadesłany przez Tomasz Lubiński, 26 września 2019 12:09
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.Pobierz pełne rozwiązanie.
Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.
akcent/Form1.cs:
//Akcent kolorystyczny //(c) 2019 by Tomasz Lubinski //www.algorytm.org using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Drawing.Imaging; namespace Akcent { public partial class Form1 : Form { /// <summary> /// Obraz zrodlowy /// </summary> private Image source; private int bytesPerPixel; /// <summary> /// Zainicjuj /// </summary> public Form1() { source = null; InitializeComponent(); } /// <summary> /// Wczytaj obraz /// </summary> private void wczytaj_Click(object sender, EventArgs e) { OpenFileDialog dlg = new OpenFileDialog(); dlg.Title = "Otwórz obraz"; dlg.Filter = "pliki jpg (*.jpg)|*.jpg"; if (dlg.ShowDialog() == DialogResult.OK) { source = new Bitmap(dlg.OpenFile()); bytesPerPixel = Image.GetPixelFormatSize(source.PixelFormat) / 8; picture.Image = new Bitmap(dlg.OpenFile()); picture.Height = picture.Image.Height; picture.Width = picture.Image.Width; this.ClientSize = new System.Drawing.Size(Math.Max(picture.Width + 32, 374), picture.Height + 155); info.Text = "Wskaż na zdjęciu kolor do zaakcentowania"; } dlg.Dispose(); } /// <summary> /// Konwertuj RGB to HSV /// </summary> /// <param name="hue">output H (hue) from HSV (0-359)</param> /// <param name="sat">output S (saturation) from HSV (0-1)</param> /// <param name="val">output V (value) from HSV (0-1)</param> /// <param name="red">input R (red) from RGB (0-1)</param> /// <param name="grn">input G (gree) from RGB (0-1)</param> /// <param name="blu">input B (blue) from RGB (0-1)</param> private void RGB2HSV(out double hue, out double sat, out double val, double red, double grn, double blu) { double x, f, i; x = Math.Min(Math.Min(red, grn), blu); val = Math.Max(Math.Max(red, grn), blu); if (x == val) { hue = 0; sat = 0; } else { f = (red == x) ? grn-blu : ((grn == x) ? blu-red : red-grn); i = (red == x) ? 3 : ((grn == x) ? 5 : 1); hue = (i-f/(val-x))*60 % 360; sat = ((val-x)/val); } } /// <summary> /// Akcent kolorystyczny /// </summary> private void obraz_MouseDown(object sender, MouseEventArgs e) { //Nie rob nic jezeli obraz jest jeszcze niewczytany if (source == null) { return; } //Sprawdz format obrazu - sprawdz czy obraz zawiera 3 kanały - RGB if (picture.Image.PixelFormat != PixelFormat.Format24bppRgb) { MessageBox.Show("Nieobsługiwany format pliku!", "Bład", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } //Kopiuj obrazek zrodlowy Bitmap bitmap = (Bitmap)source.Clone(); picture.Image = bitmap; //Pobierz wartosc wszystkich punktow obrazu BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, picture.Width, picture.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); byte[] pixelValues = new byte[Math.Abs(bmpData.Stride) * picture.Height]; System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, pixelValues, 0, pixelValues.Length); //Odczytaj kolor kliknietego punktu na obrazie double hsrc, ssrc, vsrc; RGB2HSV(out hsrc, out ssrc, out vsrc, pixelValues[bmpData.Stride * e.Y + 3 * e.X + 2] / 255.0, pixelValues[bmpData.Stride * e.Y + 3 * e.X + 1] / 255.0, pixelValues[bmpData.Stride * e.Y + 3 * e.X] / 255.0); //Wzynacz tolerencje int tolerance = int.Parse(this.tolerance.Text); double hfrom = (hsrc - (tolerance / 2) + 360) % 360; double hto = (hsrc + (tolerance / 2)) % 360; //Dla kolejnych punktow obrazu for (int i = 0; i < picture.Width * picture.Height; i++) { //Odczytaj wartosc HSV RGB2HSV(out hsrc, out ssrc, out vsrc, pixelValues[3 * i + 2] / 255.0, pixelValues[3 * i + 1] / 255.0, pixelValues[3 * i] / 255.0); //jezeli wartosc koloru jest poza tolerancja to konwertuj ten punkt na odcien szarosci if ((hfrom <= hto && (hsrc < hfrom || hsrc > hto)) || (hfrom > hto && hsrc < hfrom && hsrc > hto)) { //Wartosci kolorow zapisane sa w kolejnosci Blue, Green, Red byte value = (byte)(0.299 * pixelValues[3 * i + 2] + 0.587 * pixelValues[3 * i + 1] + 0.114 * pixelValues[3 * i]); pixelValues[3 * i] = value; pixelValues[3 * i + 1] = value; pixelValues[3 * i + 2] = value; } } //Wczytaj przetworzony obraz System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, bmpData.Scan0, pixelValues.Length); bitmap.UnlockBits(bmpData); picture.Refresh(); } } }