sabato 18 ottobre 2025

C# applicare ad una foto o immagine a colori un effetto olio

 

C# effetto olio


In questo esempio di codice, vedremo come tramite il linguaggio di programmazione C#, in ambiente Windows Application applicheremo un effetto olio ad un’immagine a colori, il tutto come mostrato nella figura precedente.

Tramite le classi presenti nel framework .Net 9, in particolare nello spazio dei nomi System.Drawing, applicheremo tale effetto, senza utilizzare componenti di terze parti.

Nel progetto Windows Application, in alto sopra ad ogni dichiarazione, inseriamo lo spazio dei nomi per la gestione della grafica.

Di seguito il frammento di codice delle suddette operazioni.


C#

using System.Drawing.Imaging;


Si crea una funzione, che effettua un ciclo tra i vari pixel del file immagine, ed applicherà l’effetto olio, in base a parametri che vengono passati alla funzione.

Nella funzione sono riportati i vari commenti a titolo informativo del codice.


C#

public static Bitmap EffettoOlio(Bitmap immagineOriginale, int effettoPennello, int effettoLivelloIntensita)

 {

     if (immagineOriginale == null)

     {

         throw new ArgumentNullException(nameof(immagineOriginale), "L'immagine originale non può essere null.");

     }

     if (effettoPennello < 1)

     {

         throw new ArgumentOutOfRangeException(nameof(effettoPennello), "Il raggio deve essere almeno 1.");

     }

     if (effettoLivelloIntensita < 1)

     {

         throw new ArgumentOutOfRangeException(nameof(effettoLivelloIntensita), "I livelli di intensità devono essere almeno 1.");

     }

 

     Bitmap immagineConEffettoOlio = new Bitmap(immagineOriginale.Width, immagineOriginale.Height);

 

     //Effettua il ciclo su ogni pixel dell'immagine

     for (int y = 0; y < immagineOriginale.Height; y++)

     {

         for (int x = 0; x < immagineOriginale.Width; x++)

         {

             // Array per contare le occorrenze di ogni livello di intensità

             // e per sommare i componenti R, G, B per ogni livello.

             int[] intensityCount = new int[effettoLivelloIntensita];

             int[] avgR = new int[effettoLivelloIntensita];

             int[] avgG = new int[effettoLivelloIntensita];

             int[] avgB = new int[effettoLivelloIntensita];

 

             //Effettua il ciclo sul vicinato (quadrato) definito dal raggio attorno al pixel corrente

             for (int fy = -effettoPennello; fy <= effettoPennello; fy++)

             {

                 for (int fx = -effettoPennello; fx <= effettoPennello; fx++)

                 {

                     int currentX = x + fx;

                     int currentY = y + fy;

 

                     // Controlla che il pixel del vicinato sia all'interno dei bordi dell'immagine

                     if (currentX >= 0 && currentX < immagineOriginale.Width &&

                         currentY >= 0 && currentY < immagineOriginale.Height)

                     {

                         Color pixelColor = immagineOriginale.GetPixel(currentX, currentY);

 

                         // Calcola l'intensità del pixel (media semplice di R, G, B)

                         int intensity = (pixelColor.R + pixelColor.G + pixelColor.B) / 3;

 

                         // Mappa l'intensità a uno dei livelli definiti (quantizzazione)

                         int currentIntensityLevel = (int)Math.Floor((double)intensity * effettoLivelloIntensita / 256);

                         // Assicurati che il livello non superi l'indice massimo

                         if (currentIntensityLevel >= effettoLivelloIntensita) currentIntensityLevel = effettoLivelloIntensita - 1;

 

                         // Incrementa il conteggio per questo livello di intensità

                         intensityCount[currentIntensityLevel]++;

                         // Somma i componenti R, G, B per questo livello

                         avgR[currentIntensityLevel] += pixelColor.R;

                         avgG[currentIntensityLevel] += pixelColor.G;

                         avgB[currentIntensityLevel] += pixelColor.B;

                     }

                 }

             }

 

             // Trova il livello di intensità più dominante (quello con il conteggio più alto)

             int maxCount = 0;

             int dominantIntensityLevel = 0;

             for (int i = 0; i < effettoLivelloIntensita; i++)

             {

                 if (intensityCount[i] > maxCount)

                 {

                     maxCount = intensityCount[i];

                     dominantIntensityLevel = i;

                 }

             }

 

             // Calcola il colore medio per il livello di intensità dominante

             Color newColor;

             if (maxCount > 0)

             {

                 int finalR = avgR[dominantIntensityLevel] / maxCount;

                 int finalG = avgG[dominantIntensityLevel] / maxCount;

                 int finalB = avgB[dominantIntensityLevel] / maxCount;

                 newColor = Color.FromArgb(finalR, finalG, finalB);

             }

             else

             {

                 // Caso di fallback, se per qualche motivo non ci sono pixel nel vicinato (es. immagine 1x1 e raggio grande)

                 newColor = immagineOriginale.GetPixel(x, y);

             }

 

             // Imposta il colore del pixel nell'immagine di output

             immagineConEffettoOlio.SetPixel(x, y, newColor);

         }

     }

 

     return immagineConEffettoOlio;

 }



Infine si riporta il codice da eseguire nell’evento click di un pulsante, per creare l’immagine richiamando la funzione creata in precedenza.



C#

  private void BtnEffettoOlio_Click(object sender, EventArgs e)

  {

 

 

      string immagineOriginale = "C:\\varie\\faro.jpg";

      string immagineNuovaOlio = "C:\\varie\\faroOlio2.jpg";

 

      int effettoPennello = 3; //Imposta la "dimensione del pennello". Valori più grandi = effetto più astratto.

      int effettoLivelloIntensita = 20; // Controlla la quantizzazione del colore. Meno livelli = blocchi di colore più distinti.

 

      try

      {

               

          using (Bitmap originalImage = new Bitmap(immagineOriginale))

          {

                  

              // Applica l'effetto pittura ad olio

              using (Bitmap oilPaintedImage = EffettoOlio(originalImage, effettoPennello, effettoLivelloIntensita))

              {

                  // Salva l'immagine modificata in formato JPEG

                  oilPaintedImage.Save(immagineNuovaOlio, ImageFormat.Jpeg);

                  MessageBox.Show($"Effetto pittura ad olio applicato e salvato in '{immagineNuovaOlio}'");

              }

          }

      }

      catch (System.IO.FileNotFoundException)

      {

          MessageBox.Show($"Errore: Il file '{immagineOriginale}' non è stato trovato. Assicurati che il percorso sia corretto.");

      }

      catch (Exception ex)

      {

          MessageBox.Show($"Si è verificato un errore: {ex.Message}");

      }

  }



Nessun commento: