Visualizzazione dei risultati da 1 a 7 su 7
  1. #1
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308

    [C#] Scurire Image di PictureBox

    Un saluto a tutti. Ho scritto questa "cavolata" per scurire di una certa quantità l'image contenuta in una picturebox:

    codice:
            public static void Dark(PictureBox P)
            {
                Color c;
                int R, G, B;
                for (int p = 0; p < P.Width; p++)
                    for (int q = 0; q < P.Height; q++)
                    {
                        c = Form1.bmp.GetPixel(p, q);
                        if (c != Color.Black)
                        {
                            R = c.R;
                            R -= 50;
                            if (R < 0)
                                R = 0;
                            G = c.G;
                            G -= 50;
                            if (G < 0)
                                G = 0;
                            B = c.G;
                            B -= 50;
                            if (B < 0)
                                B = 0;
                            c = Color.FromArgb(R, G, B);
                            Form1.bmp.SetPixel(p, q, c);
                        }
     
                    }
                P.Image = Form1.bmp;
            }
    Vi potete immaginare quanto sia "veloce" questo metodo, soprattutto per immagini di 500x500 pixel o più. Ho provato a cercare nel Framework qualche metodo predefinito già pronto, nelle classi Graphics, Image, Bitmap... ma non ho trovato niente che faccia quello che fa il mio Dark(). Qualche consiglio?
    Grazie.

  2. #2
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308
    Ovviamente c'è un errore....

    codice:
    R = c.R; 
                            R -= 50; 
                            if (R < 0) 
                                R = 0; 
                            G = c.G; 
                            G -= 50; 
                            if (G < 0) 
                                G = 0; 
                            B = c.B; 
                            B -= 50; 
                            if (B < 0) 
                                B = 0;
    Ah dimenticavo: non è che contesto la "velocità" in sè, volendo se occorre applicarlo una volta sola non è tanto scandaloso, il fatto è che devo applicare questo metodo in un timer ogni 10 sec.... e posso avere bitmap di 1400x1400....
    Ultima modifica di escocat; 23-04-2014 a 22:55

  3. #3
    Dai un'occhiata a come sono implementati i filtri descritti in queste pagine; il trucco è cavare fuori i byte dalla bitmap e operare direttamente su quelli invece che chiamare continuamente GetPixel/SetPixel. Si possono migliorare ulteriormente le prestazioni usando i blocchi unsafe (cosa che avevo fatto tanto tempo fa, dovrei ripescare da qualche parte il progetto in questione).
    Amaro C++, il gusto pieno dell'undefined behavior.

  4. #4
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308
    Grazie MItaly!!!! Ho adattato un codice trovato in quelle pagine in questo modo:

    codice:
                // Lock the bitmap's bits.  
                Rectangle rect = new Rectangle(0, 0, Form1.bmp.Width, Form1.bmp.Height);
                System.Drawing.Imaging.BitmapData bmpData =
                    Form1.bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
                    Form1.bmp.PixelFormat);
                // Get the address of the first line.
                IntPtr ptr = bmpData.Scan0;
                // Declare an array to hold the bytes of the bitmap. 
                int bytes  = Math.Abs(bmpData.Stride) * Form1.bmp.Height;
                byte[] rgbValues = new byte[bytes];
                // Copy the RGB values into the array.
                System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
    
                /*
                // Set every third value to 255. A 24bpp bitmap will look red.   
                for (int counter = 2; counter < rgbValues.Length; counter += 3)
                    rgbValues[counter] = 255;
                */
    
                // Set every value to value - 32.    
                for (int counter = 0; counter < rgbValues.Length; counter++)
                {
                    rgbValues[counter] -= 32;
                    if (rgbValues[counter] < 32)
                        rgbValues[counter] = 32;
                }
                // Copy the RGB values back to the bitmap
                System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
                // Unlock the bits.
                Form1.bmp.UnlockBits(bmpData);
                P.Image = Form1.bmp;
    E' molto veloce! A parte qualche brillamento negli istanti iniziali, poi procede benino. Veramente grazie, non mi rimane che studiarlo capirlo e perfezionarlo.

  5. #5
    codice:
                    rgbValues[counter] -= 32;
                    if (rgbValues[counter] < 32)
                        rgbValues[counter] = 32;
    Occhio che byte è senza segno, per cui se è minore di 32 fa wraparound e diventa positivo; probabilmente quello che vuoi fare è:
    codice:
    if (rgbValues[counter] > 32)
        rgbValues[counter] -= 32;
    else
        rgbValues[counter] = 0;
    Amaro C++, il gusto pieno dell'undefined behavior.

  6. #6
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308
    Ah già! Ecco cos'erano quei "brillamenti". Ho corretto, grazie. Ripeto, è estremamente veloce: anche richiamandolo ogni 2-3 secondi non si nota alcun disturbo di continuità. Ciao.

  7. #7
    Amaro C++, il gusto pieno dell'undefined behavior.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.