PDA

View Full Version : [Java] Visualizzare un'immagine e poi applicargli un filtro


e-commerce84
23-09-2011, 13:56
Salve ragazzi,
premetto che stò chiedendo 2 cose diverse in questo 3d...la prima domanda è sicuramente più facile e molti di voi mi sapranno rispondere...per quanto riguarda la seconda spero di trovare qualcuno che abbia già avuto modo di mettere mano all'applicazione di filtri su un'immagine tramite Java.

Seguendo questo articolo (a dire il vero per ora solo la primissima parte dell'articolo): http://www.jhlabs.com/ip/blurring.html stò tentando di fare la seguente cosa:

Una classe che contiene il metodo main che:

1) Visualizza un'immagine JPG (prima domanda su come fare)
2) Ne crea un'altra applicando un filtro blurring all'immagine iniziale (seconda domanda)
3) Visualizza o salva da qualche parte l'immagine modificata

Come detto si tratta di 2 domande...una probabilmetne facile (su come far visualizzare in Java un'immagine...credo tramite Swing) ed un'altra più complicata riguardante l'applicazione del filtro di blurring

Premetto che non ho mai lavorato con Swing ed in generale poco con applicazioni desktop (mi sono occupate principalmente di web application e di mobile application...Android)

Cercando di mettere insieme la primissima parte dell'articolo con dell'altro materiale trovato in rete ho scritto questo pezzo di codice:


import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;

import javax.swing.ImageIcon;


public class blur1 {

public static void main(String [ ] args){

float[] matrix = new float[400];

for (int i = 0; i < 400; i++)
matrix[i] = 1.0f/400.0f;


ImageIcon icon = new ImageIcon("/home/andrea/Scrivania/pesce-pagliaccio.jpg");
Image image = icon.getImage();

BufferedImage imageOriginal = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2Original = imageOriginal.createGraphics();
g2Original.drawImage(image, icon.getIconWidth(), icon.getIconHeight(), null);

ImageIcon icon2 = new ImageIcon("/home/andrea/Scrivania/pesce-pagliaccio.jpg");
Image image2 = icon2.getImage();
BufferedImage imageDestination = new BufferedImage(icon2.getIconWidth(), icon2.getIconHeight(), BufferedImage.TYPE_INT_RGB);

BufferedImageOp op = new ConvolveOp( new Kernel(20, 20, matrix), ConvolveOp.EDGE_NO_OP, null );
BufferedImage blurredImage = op.filter(imageOriginal, imageDestination);
}

}


Di fatto per la prima domanda (come far visualizzare un'immagine ad un'applicazione Java?) dovrebbe bastare questo segmento di codice:


ImageIcon icon = new ImageIcon("/home/andrea/Scrivania/pesce-pagliaccio.jpg");
Image image = icon.getImage();

BufferedImage imageOriginal = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2Original = imageOriginal.createGraphics();
g2Original.drawImage(image, icon.getIconWidth(), icon.getIconHeight(), null);


Ma quanto in Eclipse faccio partire il progetto che contiene questo metodo main non viene visualizzato nulla...ne errori nella console ne l'immagine da nessuna parte...come mai? sbaglio qualcosa io?

Per la seconda domanda che è ben più complessa...beh intanto risolviamo questa...poi quella la formulo bene dopo :D

Tnx
Andrea

banryu79
23-09-2011, 15:00
Andiamo con ordine, partiamo con il caricamento e la visualizzazione di un'immagine.
Ci sarebbero diverse opzioni, io te ne dico una.

Per caricare un'immagine (jpg, png, giff e non mi ricordo se/che altro... ) puoi usare javax.imageio.ImageIO
Ad esempio:

File imagePath = new File(strFolderPath, strFileName);
...
Image image = ImageIO.read(file);//could throws IOException
// a ImageIO.read puoi anche passare un InputStream oppure un URL

Avendo per le mani un'Image, puoi istanziare con essa un ImageIcon da usare come icona in un'umilissima JLabel, ad esempio:

...
JLabel picture = new JLabel(new ImageIcon(image));
...

A questo punto schiaffi la label dove ti pare, ad esempio dentro uno scroll pane inserito a sua volta in un pannello o in un frame o dove vuoi te:

JFrame frame = new JFrame("blablabla");
...
JScrollPane picturePane = new JScrollPane(picture);
picturePane.getVerticalScrollBar().setUnitIncrement(18);
picturePane.getHorizontalScrollBar().setUnitIncrement(18);
...
fame.add(picturePane, BorderLayout.CENTER);
...

e-commerce84
23-09-2011, 17:23
Ti ringrazio molto...sei stato molto chiaro, credo di aver afferrato i concetti dei menu con Swing ache se non lo conosco come sistema perchè non l'ho mai usato...

Ma continuo ad avere qualche problema...sostanzialmente non mi dà errori e nella console appaiono anche i messaggi dei vari System.out.println inseriti all'interno del mio codice ma...facendo partire il progetto da Eclipse (RUN AS --> JAVA APPLICATION) non viene visualizzata da nessuna parte l'immagine...come mai?

Questo è il mio codice completo:


package andrea.blur1.classi;

import java.awt.BorderLayout;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.management.ImmutableDescriptor;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;

public class blur1 {

public static void main(String [] args) throws IOException{

String strFolderPath = "/home/andrea/Scrivania/"; // Percorso immagine da aprire
String strFileName = "pesce-pagliaccio.jpg"; // Nome file immagine da aprire

File imagePath = new File(strFolderPath, strFileName);
// Contiene il riferimento al file da aprire
System.out.println("imagePath punta a: " + imagePath);

Image image = ImageIO.read(imagePath); // Mette dentro image l'immagine a cui fà riferimento imagePath
System.out.println("Info immagine: " + image.toString());

JLabel picture = new JLabel(new ImageIcon(image)); // Istanzio un'ImageIcon da image e la uso come icona in una JLabel

JFrame frame = new JFrame("blablabla"); // E' un container
JScrollPane picturePane = new JScrollPane(picture); // E' una view scrollabile che contiene la JLabel che ha l'ImageIcon come icona
System.out.println(picturePane.toString());
// Setta le scrollbar verticale ed orizzontale:
picturePane.getVerticalScrollBar().setUnitIncrement(18);
picturePane.getHorizontalScrollBar().setUnitIncrement(18);

frame.add(picturePane, BorderLayout.CENTER); // Aggiunco il picturPane al frame esterno e gli dico di posizionarlo al centro
System.out.println(frame.getComponentCount());
}

}


Sostanzialmente pare non intopparsi...l'ultimo system.out mi dice che dentro al frame c'è un componente (ed infatti uno ne ho aggiunto...)

ma come mai non si vede da nessuna parte l'immagine? Possibile che dipenda dal fatto che lo lancio in Eclipse? O c'è qualcosa che mi sfugge?

Tnx
Andrea

banryu79
23-09-2011, 17:36
ma come mai non si vede da nessuna parte l'immagine? Possibile che dipenda dal fatto che lo lancio in Eclipse? O c'è qualcosa che mi sfugge?


Questo percorso relativo:

String strFolderPath = "/home/andrea/Scrivania/";

Immagina come viene risolto quando lo lanci da Eclipse piuttosto che da riga di comando. Credo che il problema stia qua :)

e-commerce84
23-09-2011, 18:09
Questo percorso relativo:

String strFolderPath = "/home/andrea/Scrivania/";

Immagina come viene risolto quando lo lanci da Eclipse piuttosto che da riga di comando. Credo che il problema stia qua :)

mmm temo di non capire cosa intendi :-/
che dovrei fare? come gli dovrei passare il percorso?

Tnx
Andrea

DarkDrake88
24-09-2011, 13:10
mmm temo di non capire cosa intendi :-/
che dovrei fare? come gli dovrei passare il percorso?

Tnx
Andrea

da riga di comando dovresti passargli tutto l'indirizzo, quindi /home/blablabla

invece, se fai partire da progetto di eclipse, devi mettere l'indirizzo partendo dalla workpath di eclipse.

e-commerce84
24-09-2011, 16:44
da riga di comando dovresti passargli tutto l'indirizzo, quindi /home/blablabla

invece, se fai partire da progetto di eclipse, devi mettere l'indirizzo partendo dalla workpath di eclipse.

mmm...continua a non funzionare...allora ho fatto la seguente cosa:

tramite Eclipse ho creato una cartella chiamata img allo stesso livello della cartella src

Dentro img ho messo l'immagine: pesce pagliaccio.jpg ed ho cambiato le righe relative all'indirizzo del file nel seguente modo:


String strFolderPath = "/blur1/img/"; // Percorso immagine da aprire
String strFileName = "pesce-pagliaccio.jpg"; // Nome file immagine da aprire


dove blur1 è il nome del progetto ed img è la directory che contienel'immagine...

Il problema ora è che quando lo lancio nella console mi dà il seguente messaggio di errore:


imagePath punta a: /blur1/img/pesce-pagliaccio.jpg
Exception in thread "main" javax.imageio.IIOException: Can't read input file!
at javax.imageio.ImageIO.read(ImageIO.java:1275)
at andrea.blur1.classi.blur1.main(blur1.java:31)


La prima riga che dice imagePath punta a:.... è il risultato della mi System.out.println che gli fà stampare il riferimento nella variabile imagePath e poi si solleva l'eccezione che dice che non riesce a leggere il file di input...

Non ne riesco ad uscire...sono 2 giorni che ci sbatto la capoccia...qualcuno sà aiutarmi?

Tnx
Andrea

DarkDrake88
25-09-2011, 11:25
La cosa mi pare strana. Hai provato invece di una piattaforma posix di farla girare su Win? E cambiare ovviamente il percorso

e-commerce84
25-09-2011, 12:19
La cosa mi pare strana. Hai provato invece di una piattaforma posix di farla girare su Win? E cambiare ovviamente il percorso

In parte temo di essere un deficiente io perchè avevo rinominato il file pesce-pagliaccio.jpg in pescepagliaccio.jpg...però ancora non funziona....ti spiego ho modificato il codice semplicemente aggiungendo un frame.setVisible(true); e questa volta appare la casellina con scritto blablabla (che è la stringa passata nella costruzione del JFrame) nella barra delle applicazioni aperte...ma se ci clicko sopra non succede nulla...non mi si apre nulla...

Ora non tira fuori nessuna eccezione relativa al file pescepagliaccio.jpg quindi penso che il file jpg sia caricato correttamente adesso e che l'indirizzo sia giusto (credo...se no tirerebbe fuori l'eccezionel...giusto?)

Per caso bisogna dirgli di visualizzare qualcos'altro? Mi sai aiutare? sarà una cavolata ma non ho mai messo mano alle Swing e ci stò impazzendo...

Per completezza di posto il mio nuovo codice:


import java.awt.BorderLayout;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.management.ImmutableDescriptor;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;

public class blur1 {

public static void main(String [] args) throws IOException{

String strFolderPath = "/home/andrea/workspace2/blur1/img/"; // Percorso immagine da aprire
String strFileName = "pesce-pagliaccio.jpg"; // Nome file immagine da aprire

File imagePath = new File(strFolderPath, strFileName);
// Contiene il riferimento al file da aprire
System.out.println("imagePath punta a: " + imagePath);

Image image = ImageIO.read(imagePath); // Mette dentro image l'immagine a cui fà riferimento imagePath
System.out.println("Info immagine: " + image.toString());

JLabel picture = new JLabel(new ImageIcon(image)); // Istanzio un'ImageIcon da image e la uso come icona in una JLabel

JFrame frame = new JFrame("blablabla"); // E' un container
frame.setVisible(true);

JScrollPane picturePane = new JScrollPane(picture); // E' una view scrollabile che contiene la JLabel che ha l'ImageIcon come icona
picturePane.setVisible(true);

System.out.println(picturePane.toString());
// Setta le scrollbar verticale ed orizzontale:
picturePane.getVerticalScrollBar().setUnitIncrement(18);
picturePane.getHorizontalScrollBar().setUnitIncrement(18);

frame.getContentPane().add(picturePane, BorderLayout.CENTER); // Aggiunco il picturPane al frame esterno e gli dico di posizionarlo al centro

System.out.println(frame.getComponentCount());
}

}


Grazie mille
Andrea

e-commerce84
25-09-2011, 17:06
Risolto da me...il problema era che senza settare le dimensioni del Jframe con un setSize() non si visualizzava...è obbligatorio o usare il setSize() o il pack() (setta le dimensioni del frame con le dimensioni dell'immagine che esso contiene) altrimenti non si vedrà nulla :)

DarkDrake88
25-09-2011, 19:02
Risolto da me...il problema era che senza settare le dimensioni del Jframe con un setSize() non si visualizzava...è obbligatorio o usare il setSize() o il pack() (setta le dimensioni del frame con le dimensioni dell'immagine che esso contiene) altrimenti non si vedrà nulla :)

Verissimo, non ci avevo fatto caso che mancava proprio il pack(). E' tanto che non traffico con gli swing eheh!
Meglio così :)