algorytm.org

Implementacja w C#

Baza Wiedzy
wersja offline serwisu przeznaczona na urządzenia z systemem Android
Darowizny
darowiznaWspomóż rozwój serwisu
Nagłówki RSS
Artykuły
Implementacje
Komentarze
Forum
Bookmarki






Sonda
Implementacji w jakim języku programowania poszukujesz?

Akcent kolorystyczny - Implementacja w C#
Ocena użytkownikóww: *****  / 0
SłabyŚwietny
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();
        }
    }
}
Dodaj komentarz