Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Redmi Pad 2 9.7: ampio display, economico e peso contenuto, ma qualche limite nelle prestazioni
Redmi Pad 2 9.7: ampio display, economico e peso contenuto, ma qualche limite nelle prestazioni
Redmi Pad 2 9.7 punta su un display ampio e fluido, una batteria capace di accompagnare l'uso quotidiano senza ansie da ricarica e un prezzo accessibile, a partire da 179,90 euro per la versione con 64 GB di storage. Lo Snapdragon 6s 4G Gen 2 e i 4 GB di RAM della configurazione più diffusa frenano però chi cerca reattività e multitasking spinto: ecco il bilancio dopo due settimane di prova diretta
Peugeot Polygon Concept: ecco il futuro delle utilitarie
Peugeot Polygon Concept: ecco il futuro delle utilitarie
Polygon è la concept car di Peugeot che mostra il futuro delle soluzioni del segmento B: tra design compatti e innovativi affiancati da dimensioni compatte uno scherzo dalla manovrabilità incredibile per le manovre a bassa velocità
Reno16 Pro: il compatto di OPPO punta su fotocamera da 200MP e il nuovo Bubble! La recensione
Reno16 Pro: il compatto di OPPO punta su fotocamera da 200MP e il nuovo Bubble! La recensione
OPPO ha portato in Italia, dal 1° luglio 2026, Reno16 Pro: display AMOLED da 6,32 pollici a 144Hz, tripla fotocamera con sensore principale da 200 megapixel, chip Dimensity 8550 Super e batteria da 6000mAh, al prezzo di lancio di 899 euro. Lo abbiamo provato per due settimane insieme al nuovo accessorio Bubble, per capire se la formula compatta della serie regge ancora di fronte a un listino da 1099 euro
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 12-02-2007, 00:11   #1
ceccoggi
Senior Member
 
Iscritto dal: Sep 2001
Messaggi: 1551
[java] modifica luminosità di un'immagine

Buona sera,
sto sviluppando un programmino dove devo aprire un'immagine e attraverso uno slider modificarne la luminosità...qualcuno mi da qualche dritta?
Non ho appunti dell'uni, e non riesco a trovare niente su internet...spero in un vostro aiuto!!
ceccoggi è offline   Rispondi citando il messaggio o parte di esso
Old 12-02-2007, 13:51   #2
ceccoggi
Senior Member
 
Iscritto dal: Sep 2001
Messaggi: 1551
up
ceccoggi è offline   Rispondi citando il messaggio o parte di esso
Old 12-02-2007, 14:03   #3
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Il primo passo è comprendere l'uso dei filtri java.awt.image per immagini di tipo BufferedImage (quelle che carichi con ImageIO

per intenderci). Data un'immagine di partenza:

BufferedImage source = qualcosa

Applichi il filtro BufferedImageOp con;

BufferedImage dest = op.filter(source, null);

Puoi precalcolare il buffer di destinazione per rendere la cosa più rapida.

Codice:
BufferedImage backBuffer = un immagine delle stesse dimensioni di source
op.filter(source, dest);
source.getGraphics().drawImage(dest, 0, 0, null);
Per aumentare la luminosità puoi usare un filtro RescaleOp o un LookupOp. RescaleOp moltiplica il valore dei canali di ogni

pixel per un fattore definito in costruzione. Se il valore è maggiore di 1.0 il risultato è un'immagine che tende al bianco. Se

il valore è minore di 1.0 il risultato è un'immagine che tende al nero.

BufferedImageOp up = new RescaleOp(1.5f, 0, null); //+ verso il bianco
BufferedImageOp down = new RescaleOp(0.5f, 0, null); //+ verso il nero

LookupOp funziona in modo diverso. Applica ad ogni canale del pixel una tabella di sostituzione dei valori. Ad esempio puoi

stabilire che se un canale di un pixel ha il valore 200 esso diventerà 210.

La sostituzione si basa su un array. L'array ha un componente per ogni possibile valore di un canale del pixel. Se il canale può

variare da 0 a 255 allora l'array avrà 256 componenti. L'indice del componente nell'array corrisponde al valore da cercare. Il

valore del componente dell'array è quello che rimpiazzerà l'originale. Vale a dire che se vuoi cambiare il valore 200 in 7

allora il componente di indice 200 dell'array dovrà avere valore 7. Per chiarire ancora meglio, l'array:

short[] data = new short[255];
data[0] = 33;
data[1] = 1;
data[2] = 2;
data[3] = 3;
...
data[n] = n;

comporta una sostituzione del valore 0 (zero) con il valore 33 e lascia inalterati tutti gli altri. Cioè se un pixel ha il

colore RGB (0, 77, 99) l'applicazione del filtro LookupOp con quei dati di sostituzione lo trasformerà in RGB(33, 77, 99).

Per usare i dati di quell'array devi prima incapsularli in un LookupTable. Ad esempio;

LookupTable table = new ShortLookupTable(0, data);
BufferedImageOp op = new LookupOp(table, null);
op.filter(...

Giusto per non farla lunga più del dovuto, un LookupOp ti consente di aumentare o ridurre la luminosità prevendo l'effetto

slavato. Per controllare la luminosità con uno slider puoi creare la tabella di valori come se stessi disegnando una quadratica

di bezier tra i due estremi (0, 0) e (255, 255). Ad esempio:

Codice:
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;

public class Rescaler implements Runnable, ChangeListener {
	private BufferedImage original;
	private BufferedImage current;
	private JLabel view = new JLabel();
	private JSlider slider = new JSlider(0, 100);

	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Rescaler(args[0]));
	}

	public Rescaler(String fileName) {
		try {
			original = toRGB(ImageIO.read(new File(fileName)));
			current = toRGB(original); //una copia
			updateView();
		} catch(IOException ex) {
			throw new RuntimeException(ex);
		}
		slider.addChangeListener(this);
	}

	public void run() {
		JFrame frame = new JFrame("Rescaler");
		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		frame.add(slider, BorderLayout.NORTH);
		frame.add(view, BorderLayout.CENTER);
		frame.pack();
		frame.setVisible(true);
	}

	/* cattura il movimento dello slider */
	public void stateChanged(ChangeEvent e) {
		if(!slider.getValueIsAdjusting()) {
			float scale = slider.getValue() / 100f;
			short[] data = createTable(scale);
			LookupTable table = new ShortLookupTable(0, data);
			LookupOp op = new LookupOp(table, null);
			filter(op);
		}
	}

	/* filtra l'immagine e aggiorna la vista */
	private void filter(BufferedImageOp op) {
		op.filter(original, current);
		updateView();
	}

	/* aggiorna la vista */
	private void updateView() {
		view.setIcon(new ImageIcon(current));
	}

	/* restituisce un'immagine in formato INT_RGB */
	private BufferedImage toRGB(BufferedImage source) {
		BufferedImage rgb = new BufferedImage(source.getWidth(), source.getHeight(), BufferedImage.TYPE_INT_RGB);
		rgb.getGraphics().drawImage(source, 0, 0, null);
		return rgb;
	}

	/* crea i dati di una tabella di sostituzione che aumenta o
	riduce la luminosità al variare di value (0.0 scura, 1.0 chiara) */
	private short[] createTable(float value) {
		int x = (int)(255 - value * 255);
		int y = 255 - x;
		Point p0 = new Point(0, 0);
		Point p1 = new Point(x, y);
		Point p2 = new Point(255, 255);
		float dt = 1f / 256f;
		short[] data = new short[256];
		for(int i = 0; i < data.length; i++) {
			data[i] = (short)quad(p0, p1, p2, i * dt).y;
		}
		return data;
	}

	/* calcola le coordinate di un punto lungo una quadratica di bezier. */
	private Point quad(Point p0, Point p1, Point p2, double t) {
		double x = qb(p0.x, p1.x, p2.x, t);
		double y = qb(p0.y, p1.y, p2.y, t);
		return new Point((int)Math.round(x), (int)Math.round(y));
	}

	/* fai i conti per quad */
	private double qb(double x0, double x1, double x2, double t) {
		return
			Math.pow(1 - t, 2) * x0 +
			2 * t * (1 - t) * x1 +
			Math.pow(t, 2) * x2;
	}
}
In teoria. In pratica siccome io e la matematica non siamo manco lontani parenti sono sicuro dell'idea ma non della realizzazione .

Per provare, dopo la compilazione,

java Rescaler "percorsoDiUnFileImmagine"
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 12-02-2007, 14:57   #4
ceccoggi
Senior Member
 
Iscritto dal: Sep 2001
Messaggi: 1551
guarda devo davvero ringraziarti x il tuo aiuto dato che sei stata l'unica persona in grado di farmi fare qualcosa di produttivo...purtroppo xò il variare dello slider mi provoca degli effetti strani sull'immagine, che sono un po' diversi dallo schiarimento o scurimento dell'immagine...ho usato il metodo della lookup...sapresti darmi qualche aiutino in +? grazie mille!
ceccoggi è offline   Rispondi citando il messaggio o parte di esso
Old 12-02-2007, 15:48   #5
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Prima di trascinarti con me nel baratro ti mostro la stessa classe ma che usa RescaleOp al posto di LookupOp. E' più semplice e illumina ma in modo diverso.

Codice:
import java.awt.*;
import java.awt.image.*;
import javax.imageio.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;

public class Rescaler implements Runnable, ChangeListener {
	private BufferedImage original;
	private BufferedImage current;
	private JLabel view = new JLabel();
	private JSlider slider = new JSlider(0, 200);

	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Rescaler(args[0]));
	}

	public Rescaler(String fileName) {
		try {
			original = toRGB(ImageIO.read(new File(fileName)));
			current = toRGB(original); //una copia
			updateView();
		} catch(IOException ex) {
			throw new RuntimeException(ex);
		}
		slider.addChangeListener(this);
	}

	public void run() {
		JFrame frame = new JFrame("Rescaler");
		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		frame.add(slider, BorderLayout.NORTH);
		frame.add(view, BorderLayout.CENTER);
		frame.pack();
		frame.setVisible(true);
	}

	public void stateChanged(ChangeEvent e) {
		if(!slider.getValueIsAdjusting()) {
			float scale = slider.getValue() / 100f;
			BufferedImageOp op = new RescaleOp(scale, 0, null);
			filter(op);
		}
	}

	private void filter(BufferedImageOp op) {
		op.filter(original, current);
		updateView();
	}

	private void updateView() {
		view.setIcon(new ImageIcon(current));
	}

	private BufferedImage toRGB(BufferedImage source) {
		BufferedImage rgb = new BufferedImage(source.getWidth(), source.getHeight(), BufferedImage.TYPE_INT_RGB);
		rgb.getGraphics().drawImage(source, 0, 0, null);
		return rgb;
	}
}
Nota che lo slider ora va da zero a 200 e nel metodo valueChange al posto di LookupOp uso un RescaleOp.

Per il LookupOp ho provato con un paio di immagini e mi pare che funzioni. Controlla che la tabella sia correttamente inizializzata. Nel metodo "createTable", all'interno del ciclo for dopo l'assegnamento

data[i] = (short)quad(p0, p1, p2, i * dt).y;

Metti una linea di debug tipo:

System.out.println(i + " becomes " + data[i]);

Quando cambi l'illuminazione ora ti stamperà sulla console la tabella di conversione. Controlla che non ci siano valor negativi o superiori a 255.
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
Old 12-02-2007, 15:49   #6
andbin
Senior Member
 
L'Avatar di andbin
 
Iscritto dal: Nov 2005
Messaggi: 5206
Prova questo programmino che ho appena fatto. Non stare a vedere il "design", prestazioni ecc.... perché l'ho scritto velocemente.

Compila con: javac ImageFilterTestFrame.java
e poi lancia con: java ImageFilterTestFrame file_immagine

Muovi lo slider verso destra (va verso il bianco) e verso sinistra (va verso il nero).

In pratica ho creato un RGBImageFilter che filtra i pixel della immagine. La classe BrightnessFilter va creata passando un valore tra -1 e +1, dove -1 indica tutto nero, +1 indica tutto bianco e 0 è l'immagine originale.

Codice:
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.imageio.*;

public class ImageFilterTestFrame extends JFrame implements ChangeListener
{
    private Image image;
    private JSlider levelSlider;
    private JLabel viewerLabel;
    private JScrollPane labelScrollPane;

    public ImageFilterTestFrame (Image image)
    {
        super ("Image Filter");

        this.image = image;

        setLayout (new BorderLayout ());

        levelSlider = new JSlider (JSlider.HORIZONTAL, -100, +100, 0);
        levelSlider.addChangeListener (this);

        viewerLabel = new JLabel (new ImageIcon (image));
        viewerLabel.setHorizontalAlignment (SwingConstants.CENTER);

        labelScrollPane = new JScrollPane (viewerLabel,
                                           JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                                           JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

        add (levelSlider, BorderLayout.NORTH);
        add (labelScrollPane, BorderLayout.CENTER);

        setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
        setSize (600, 500);
    }


    public void stateChanged (ChangeEvent e)
    {
        float level = levelSlider.getValue () / 100.0f;

        BrightnessFilter bf = new BrightnessFilter (level);

        Image imgNew = createImage (new FilteredImageSource (image.getSource (), bf));

        viewerLabel.setIcon (new ImageIcon (imgNew));
    }

    public static void main (String[] args)
    {
        if (args.length == 1)
        {
            final String filename = args[0];

            SwingUtilities.invokeLater (new Runnable()
            {
                public void run ()
                {
                    try
                    {
                        BufferedImage img = ImageIO.read (new File (filename));

                        ImageFilterTestFrame f = new ImageFilterTestFrame (img);
                        f.setVisible (true);
                    }
                    catch (Exception e)
                    {
                        System.err.println (e);
                    }
                }
            });
        }
    }
}


class BrightnessFilter extends RGBImageFilter
{
    private float brightness;

    public BrightnessFilter (float brightness)
    {
        this.brightness = brightness > 1.0f ? 1.0f : brightness < -1.0f ? -1.0f : brightness;

        canFilterIndexColorModel = true;
    }

    public int filterRGB (int x, int y, int rgb)
    {
        int r = rgb >> 16 & 0xff;
        int g = rgb >> 8 & 0xff;
        int b = rgb >> 0 & 0xff;

        if (brightness < 0.0f)
        {
            r = (int) (r * (brightness + 1.0f));
            g = (int) (g * (brightness + 1.0f));
            b = (int) (b * (brightness + 1.0f));
        }
        else
        {
            r = (int) (r * (1.0f - brightness) + 255.0f * brightness);
            g = (int) (g * (1.0f - brightness) + 255.0f * brightness);
            b = (int) (b * (1.0f - brightness) + 255.0f * brightness);
        }

        return (rgb & 0xff000000) | r << 16 | g << 8 | b << 0;
    }
}
__________________
Andrea, Senior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
Java Versions Cheat Sheet
andbin è offline   Rispondi citando il messaggio o parte di esso
Old 12-02-2007, 16:01   #7
ceccoggi
Senior Member
 
Iscritto dal: Sep 2001
Messaggi: 1551
meglio con il secondo metodo che mi hai dato...mi sei stato davvero utilissimo, grazie davvero!
ceccoggi è offline   Rispondi citando il messaggio o parte di esso
Old 12-02-2007, 18:19   #8
ceccoggi
Senior Member
 
Iscritto dal: Sep 2001
Messaggi: 1551
andbin, appena finisco il programma proverò anche la tua versione, è che mi trovo abbastanza alle strette e entro mezzanotte di domani devo consegnare...grazie cmq

Ora dovrei aggiungere uno slider uguale sia per la saturazione che per il contrasto...qualche aiutino?
ceccoggi è offline   Rispondi citando il messaggio o parte di esso
Old 12-02-2007, 21:32   #9
PGI-Bis
Senior Member
 
L'Avatar di PGI-Bis
 
Iscritto dal: Nov 2004
Città: Tra Verona e Mantova
Messaggi: 4553
Non so se ci sia una formula per aumentare la saturazione di un colore RGB che non comporti la conversione, implicita o esplicita, in HSV. Puoi trasformare i pixel da RGB ad HSV, aumentare la saturazione e trasformare il colore in RGB prima di infilarlo nel buffer proiettato sullo schermo.

Codice:
	public void resat(float pc) {
		int w = original.getWidth();
		int h = original.getHeight();
		float[] hsb = new float[3];
		for(int i = 0, x = 0, y = 0; i < w*h; i++, x = i % w, y = i / w) {
			int argb = original.getRGB(x, y);
			Color.RGBtoHSB((argb >> 16) & 0xff, (argb >> 8) & 0xff, (argb & 0xff), hsb);
			if((hsb[1] *= pc) > 1.0f) {
				hsb[1] = 1.0f;
			}
			argb = (argb << 24) + Color.HSBtoRGB(hsb[0], hsb[1], hsb[2]);
			current.setRGB(x, y, argb);
		}
		updateView();
	}
pc varia da 0 a 2 (slider da 0 a 200).

Per il contrasto... in teoria, molto in teoria, si tratta di calcolare il colore medio dell'immagine e aumentare o ridurre la distanza del colore del pixel da quel colore medio. Una versione potrebbe (e dico potrebbe) essere:

Codice:
	public void adjustContrast(float pc) {
		int w = original.getWidth();
		int h = original.getHeight();
		int[] mid = new int[3];
		//1. Calcola il valore medio di colore dell'immagine
		for(int i = 0, x = 0, y = 0; i < w*h; i++, x = i % w, y = i / w) {
			int argb = original.getRGB(x, y);
			mid[0] += (argb >> 16) & 0xff; //rosso
			mid[1] += (argb >> 8) & 0xff; //verde
			mid[2] += argb & 0xff; //blu
		}
		mid[0] /= w*h;
		mid[1] /= w*h;
		mid[2] /= w*h;
		//2. Sposta i colori + vicini o + lontani dal valore medio
		for(int i = 0, x = 0, y = 0; i < w*h; i++, x = i % w, y = i / w) {
			int argb = original.getRGB(x, y);
			int red = (argb >> 16) & 0xff; //rosso
			int green = (argb >> 8) & 0xff; //verde
			int blue = argb & 0xff; //blu
			int rd = Math.round((red - mid[0]) * pc);
			int rg = Math.round((green - mid[1]) * pc);
			int rb = Math.round((blue - mid[2]) * pc);
			red = clamp(red += rd);
			green = clamp(green += rg);
			blue = clamp(blue += rb);
			argb = (argb << 24) + (red << 16) + (green << 8) + blue;
			current.setRGB(x, y, argb);
		}
		updateView();
	}
Qui pc varia da -1 a 1 (slider da -100 a 100). Credo si possa fare anche con una tabella di sostituzione ma la formula esatta mi è ignota. Prendila con le pinze. Probabilmente quando si aumenta il contrasto si dovrebbe spostare il colore lontano dal pixel medio nella direzione in cui c'è più spazio di manovra. Insomma, non sono proprio sicuro sicuro di 'sta roba
__________________
Uilliam Scecspir ti fa un baffo? Gioffri Cioser era uno straccione? E allora blogga anche tu, in inglese come me!
PGI-Bis è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Redmi Pad 2 9.7: ampio display, economico e peso contenuto, ma qualche limite nelle prestazioni Redmi Pad 2 9.7: ampio display, economico e peso...
Peugeot Polygon Concept: ecco il futuro delle utilitarie Peugeot Polygon Concept: ecco il futuro delle ut...
Reno16 Pro: il compatto di OPPO punta su fotocamera da 200MP e il nuovo Bubble! La recensione Reno16 Pro: il compatto di OPPO punta su fotocam...
 Hisense 55U7SE: tuttofare e accessibile, il MiniLED per film, sport e gioco Hisense 55U7SE: tuttofare e accessibile, il Min...
Kindle Scribe Colorsoft: riduce le cornici e diventa a colori, ma il prezzo è alto Kindle Scribe Colorsoft: riduce le cornici e div...
Così l'AI nasconde sé stessa: nasce Acad...
L'europea Mistral AI sfida tutti: il rob...
La 'casetta in Canadà' di Mark Zu...
Una batteria che dura più di 5000...
Addio smemorati: WhatsApp testa una nuov...
Italia finalmente all'avanguardia con il...
Gratis e scritto con l'IA, il convertito...
Cooler Master V8 ACE 3DHP: disponibile i...
L'IA minaccia migliaia di posti nei call...
Assetto Corsa EVO introduce il foveated ...
Il modello base di NVIDIA Shield TV potr...
Meta sta sviluppando occhiali smart capa...
Ecco degli avviatori batteria auto super...
Fujifilm firma il suo obiettivo pi&ugrav...
Le nuove auto in UE devono accorgersi se...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 13:09.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v