View Full Version : AIUTO Java: passare da una matrice di 0 e 1 a una serie di pixel colorati?!?
Ciao a tutti, la mia è domanda è tanto semplice quanto complessa da realizzare per me, visto che manco so creare una finestra in java (fin'ora ho fatto tutto sempre in dos!)
Allora, al momento possiedo una matrice di 1 e 0 e praticamente dovrei, invece che stamparla su schermo o su file txt, cosa che ho fatto, mandarla in output su una finestra in questo modo: tutti gli uno devono diventare pixel bianchi (o cmq non neri) e tutti gli zero devono essere dei pixel neri...
il max ch son riuscito a fare è scrivere la matrice su file txt, aprire word, sostituire 1 e 0 con pallini bianchi e neri e il tutto esce così
http://img101.imageshack.us/img101/8513/mammamiavl4.th.jpg (http://img101.imageshack.us/my.php?image=mammamiavl4.jpg)
è simile a ciò che devo ottenere, ma a me serve proprio un'immagine creata pixel per pixel bianchi e neri.... e non so assolutamente come fare!!
Help please! :mc:
ma a me serve proprio un'immagine creata pixel per pixel bianchi e neri.... e non so assolutamente come fare!!Ok, prova questo codice:
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
public class ImageTestFrame extends JFrame
{
public ImageTestFrame ()
{
super ("Image Test Frame");
int width = 100;
int height = 100;
int[] pixels = new int [width * height];
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
pixels[y*width+x] = y % 3 == 0 ? 0xFFFF0000 /*rosso*/ : 0xFF00FF00 /*verde*/;
}
}
MemoryImageSource source = new MemoryImageSource (width, height, pixels, 0, width);
Toolkit toolkit = Toolkit.getDefaultToolkit ();
Image img = toolkit.createImage (source);
ImageIcon imgIcon = new ImageIcon (img);
JLabel label = new JLabel (imgIcon);
add (label);
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
pack ();
}
public static void main (String[] args)
{
SwingUtilities.invokeLater (new Runnable ()
{
public void run ()
{
ImageTestFrame f = new ImageTestFrame ();
f.setVisible (true);
}
});
}
}
Tranquillo è facilissimo.
Un'immagine "standard" è un java.awt.image.BufferedImage. BufferedImage ha un costruttore che ti permette di stabilire quanto l'immagine debba essere grande, in pixel.
BufferedImage immagineVuota = new BufferedImage(larghezza, altezza, ...);
Il terzo parametro è un valore costante che specifica il "tipo" di immagine. Il tipo di immagine è il tipo di rappresentazione dei suoi pixel. Ad esempio, il tipo BufferedImage.TYPE_INT_ARGB usa 32 bit per ogni pixel, 4 canali, 8 bit per canale (32-24 per la trasparenza, 24-16 per il componente rosso, 16-8 per il verde e 8-0 per il blu).
Il tipo predetto è eccessivo rispetto alle tue necessità – a te basta un bit per pixel – ma è pienamente compatibile. Proviamo con questo.
BufferedImage immagineVuota = new BufferedImage(larghezza, altezza, BufferedImage.TYPE_INT_ARGB);
Tu hai una matrice di valori, quindi sei in grado di sapere il valore conservato nella riga R e colonna C.
Il che praticamente è tutto quello che ti serve. BufferedImage dispone di un metodo ad-hoc per impostare in scioltezza il valore di un pixel esattamente come se l'immagine fosse una matrice di pixel (a dire il vero è una matrice di pixel :D). Il metodo in questione è:
setRGB(int colonna, int riga, int coloreDelPixel);
Il colore del pixel richiesto dal metodo setRGB è in formato ARGB a 32 bit: la stessa forma di rappresentazione del tipo INT_ARGB su citato. Se l'immagine ha un tipo di pixel diverso da INT_ARGB il colore subisce una conversione prima dell'applicazione all'immagine. Noi abbiamo abbondato, quindi la questione non ci preoccupa.
Dato il BufferedImage immagineVuota, se io volessi "colorare" di bianco il primo pixel in alto a sinistra direi semplicemente:
immagineVuota.setRGB(0, 0, Color.WHITE.getRGB());
Il metodo getRGB() degli oggetti Color restituisce il valore che rappresenta quel dato colore in formato – ancora lui – ARGB a 32 bit. Color.WHITE è il colore bianco. Color.BLACK è nero, Color.BLACK.getRGB() è il valore intero int del nero in formato ARGB 32 bit. Dunque gli enunciati:
immagineVuota.setRGB(0, 0, Color.WHITE.getRGB());
immagineVuota.setRGB(1, 0, Color.BLACK.getRGB());
colorano di bianco il primo pixel in alto a sinistra e di nero il secondo – a partire da sinistra – pixel della prima riga in alto.
Per proiettare un BufferedImage in una finestra ci sono molte vie. Una semplicissima prende l'immagine (per noi immagineVuota), la incapsula in un oggetto di tipo ImageIcon e rifila quell'ImageIcon ad un'etichetta (JLabel). Poi metti l'etichetta in un contenitore (o direttamente nel contenitore principale di una finestra) e infine apri quella finestra sullo schermo.
Esempio condensato:
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;
public class Immagina {
public static void main(String[] args) {
/* questo serve solo per avere una generica "matrice" come
punto di partenza */
Matrice matrice = new Matrice(100, 100);
for(int i = 0; i < matrice.getNumeroRighe(); i++) {
for(int j = 0; j < matrice.getNumeroColonne(); j++) {
matrice.set(i, j, i % 2);
}
}
/* a partire da una matrice di valori... */
int larghezza = matrice.getNumeroColonne();
int altezza = matrice.getNumeroRighe();
int tipo = BufferedImage.TYPE_INT_ARGB;
BufferedImage immagine = new BufferedImage(larghezza, altezza, tipo);
for(int i = 0; i < immagine.getWidth(); i++) {
for(int j = 0; j < immagine.getHeight(); j++) {
int valoreMatrice = matrice.get(j, i); //righe = altezza, colonne = larghezza
/* bianco se il valore è 1, nero se il valore è 0 */
int colorePixel =
valoreMatrice == 1 ? Color.WHITE.getRGB() : Color.BLACK.getRGB();
/* colora di "colorePixel" il pixel della riga i e colonna j */
immagine.setRGB(i, j, colorePixel);
}
}
proiettaImmagine(immagine);
}
private static void proiettaImmagine(final Image immagine) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Icon icona = new ImageIcon(immagine);
JLabel etichetta = new JLabel(icona);
JFrame finestra = new JFrame("Immagina");
finestra.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
finestra.add(etichetta, BorderLayout.CENTER);
finestra.pack();
finestra.setVisible(true);
}
});
}
}
class Matrice {
private int[] dati;
private int numeroRighe, numeroColonne;
public Matrice(int numeroRighe, int numeroColonne) {
dati = new int[numeroRighe * numeroColonne];
this.numeroRighe = numeroRighe;
this.numeroColonne = numeroColonne;
}
public int get(int riga, int colonna) {
return dati[riga * numeroColonne + colonna];
}
public void set(int riga, int colonna, int valore) {
dati[riga * numeroColonne + colonna] = valore;
}
public int getNumeroRighe() {
return numeroRighe;
}
public int getNumeroColonne() {
return numeroColonne;
}
}
beh per fare qualcosa la fa :) ma potresti commentarmelo brevemente così lo capisco e tento di implementarlo nel mio programma? :cry:
grazie mille comunque! ;)
EDIT: mi riferivo alla prima reply, la seconda manco l'avevo vista (post in contemporanea) mo leggo!
beh per fare qualcosa la fa :) ma potresti commentarmelo brevemente così lo capisco e tento di implementarlo nel mio programma? :cry: Guarda ... il mio esempio è molto semplice.
Innanzitutto si usa un array di int, in cui ogni cella contiene il colore di 1 pixel. Sui 32 bit del valore int, il colore è codificato così:
bit 31-24 = alpha (0=trasparente .... 255=opaco)
bit 23-16 = rosso
bit 15-8 = verde
bit 7-0 = blu
Una volta che l'array è stato riempito, si crea un MemoryImageSource, che non è l'immagine ma è il "produttore" della immagine. A quel punto si usa il Toolkit della AWT per creare una Image.
Nel mio esempio ho voluto mettere l'immagine dentro una JLabel, che però si aspetta un ImageIcon, quindi ho dovuto fare un passo in più. In generale basta avere un Image, per esempio se si vuole stampare su un Graphics.
hummm sembra che ci sia riuscito con qualche dritta di PGI-Bis :D
adesso 2 domande veloci che non si sa mai:
1) c'è un modo per zoommare il tutto rendendolo bello pixelloso?
2) ma in java gli exe non esistono vero? se volessi creare na roba eseguibile devo fare un'applet?
cmq grazie siete dei Santi ;)
Exe.
La piattaforma Java funziona come un sistema operativo virtuale. Windows ha gli exe, Linux non ha un'estensione che indica un file come eseguibile, la piattaforma Java ha i "jar eseguibili". Un jar è un archivio zip con estensione jar che contiene i file binari (bytecode) dell'applicazione java, le risorse e compagnia bella, e un file di nome:
META-INF/MANIFEST.MF
Il file META-INF/MANIFEST.MF è un file di testo ASCII che contiene alcuni valori ma, in l'unico necessario ai fini dell'eseguibilità, è il nome pienamente qualificato della classe che dichiara il punto d'entrata dell'applicazione (un metodo tradotto in bytecode la cui firma sia public static void main(String[] args) o public static void main(String... args), insomma il metodo "main").
Pixellosità.
Dunque tu pigli i tuoi file sorgenti e li compili avendo cura che il compilatore generi l'albero di cartelle corrispondenti ai package delle varie classi. Poi metti i file class, con le loro cartelle (se la classe appartiene al package it.bongo avrai una cartella it/ che contiene una cartella bongo/ che contiene il file class, tu zippi la cartella it/) in uno zip, nome a piacimento. Poi metti nello zip una cartella di nome META-INF e dentro a quella cartella piazzi un file di nome MANIFEST.MF che contiene due linee di testo. La prima nella forma:
Main-Class: nomePienamenteQualificatoDellaClasseCheContieneIlMetodoMain
e la seconda la lasci vuota. Se non termina con una linea vuota va tutto a schifìo.
Infine rinomini il file zip affinchè termini estensione jar e ha il tuo eseguibile per la piattaforma Java. In realtà lo stesso zip è pronto per essere eseguito ma il possesso di un'estensione tipica aiuta ad associare l'archivio con il programma che lancia la macchina virtuale Java.
Anzichè fare tutta 'sta manfrina puoi usare il comando "jar" che crea l'archivio zip con estensione jar e tutto quello che gli va dietro. La documentazione del programma "jar" è contenuta nella documentazione standard della piattaforma Java SE.
Pixellosità.
Potresti creare un'immagine grande il doppio e anzichè fare una corrispondenza 1:1 tra i valori della matrice e i valori dei pixel farla 1:2. La cosa dovrebbe corrispondere ad un ingrandimento "nearest neighbor" ma non sono sicurissimo. Se così fosse basterebbe applicare un filtro al tuo BufferedImage. Riporto l'esempio di prima modificato in modo tale da rendere un'immagine ingrandita di 4 volte:
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.*;
import javax.swing.*;
public class Immagina {
public static void main(String[] args) {
/* questo serve solo per avere una generica "matrice" come
punto di partenza */
Matrice matrice = new Matrice(100, 100);
for(int i = 0; i < matrice.getNumeroRighe(); i++) {
for(int j = 0; j < matrice.getNumeroColonne(); j++) {
matrice.set(i, j, i % 2);
}
}
/* a partire da una matrice di valori... */
int larghezza = matrice.getNumeroColonne();
int altezza = matrice.getNumeroRighe();
int tipo = BufferedImage.TYPE_INT_ARGB;
BufferedImage immagine = new BufferedImage(larghezza, altezza, tipo);
for(int i = 0; i < immagine.getWidth(); i++) {
for(int j = 0; j < immagine.getHeight(); j++) {
int valoreMatrice = matrice.get(j, i); //righe = altezza, colonne = larghezza
/* bianco se il valore è 1, nero se il valore è 0 */
int colorePixel =
valoreMatrice == 1 ? Color.WHITE.getRGB() : Color.BLACK.getRGB();
/* colora di "colorePixel" il pixel della riga i e colonna j */
immagine.setRGB(i, j, colorePixel);
}
}
/* anzichè proiettare l'immagine "originale" ne proietto
un'altra, ingrandimento della prima */
BufferedImage ingrandita = ingrandisci(immagine, 4);
proiettaImmagine(ingrandita);
}
private static BufferedImage ingrandisci(BufferedImage originale, float fattoreIngrandimento) {
/* Ingrandimento 4x, orizzontale e verticale */
AffineTransform ingrandimento =
AffineTransform.getScaleInstance(fattoreIngrandimento, fattoreIngrandimento);
/* Crea un trasformatore di BufferedImage che applica la trasformazione
affine "ingrandimento" */
BufferedImageOp op = new AffineTransformOp(ingrandimento, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
/* il "null" significa "crea l'immagine di destinazione" */
BufferedImage risultato = op.filter(originale, null);
return risultato;
}
private static void proiettaImmagine(final Image immagine) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Icon icona = new ImageIcon(immagine);
JLabel etichetta = new JLabel(icona);
/* stavolta infilo l'etichetta in un pannello con delle
barre di scorrimento perchè l'immagine potrebbe essere un po'
troppo grande per lo schermo dell'utente */
JScrollPane contenitoreEtichetta = new JScrollPane(etichetta);
contenitoreEtichetta.setPreferredSize(new Dimension(400, 400));
JFrame finestra = new JFrame("Immagina");
finestra.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
finestra.add(contenitoreEtichetta, BorderLayout.CENTER);
finestra.pack();
finestra.setVisible(true);
}
});
}
}
class Matrice {
private int[] dati;
private int numeroRighe, numeroColonne;
public Matrice(int numeroRighe, int numeroColonne) {
dati = new int[numeroRighe * numeroColonne];
this.numeroRighe = numeroRighe;
this.numeroColonne = numeroColonne;
}
public int get(int riga, int colonna) {
return dati[riga * numeroColonne + colonna];
}
public void set(int riga, int colonna, int valore) {
dati[riga * numeroColonne + colonna] = valore;
}
public int getNumeroRighe() {
return numeroRighe;
}
public int getNumeroColonne() {
return numeroColonne;
}
}
ma perchè far tutto quello sbattimento se c'è il creatore automatico? :confused:
ho provato e lo crea, solo che non so che farci col jar... magari va sul nokiotto :D
con windows non so con cosa aprirlo :rolleyes:
ma perchè far tutto quello sbattimento se c'è il creatore automatico? :confused:
ho provato e lo crea, solo che non so che farci col jar... magari va sul nokiotto :D
con windows non so con cosa aprirlo :rolleyes:
Così, tanto per sapere perchè le cose funzionano.
In windows i jar sono associati all'applicazione javaw.exe che è come java.exe solo che non c'è una "console". Se la tua applicazione è a linea di comando devi lanciare l'applicazione da linea di comando. Se l'applicazione è impacchettata in un jar eseguibile, dal prompt dei comandi:
java -jar NomePacchetto.jar
humm io ce l'ho associato a winrar :D
se provo ad associarlo con javaw me lo apre con quella cacca di ltsa che per ora devo tenere sul pc perchè mi serve... cmq vabè, in pratica su windows si fa prima a farlo partire da dos tramite il solito "java nomeprogramma"
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.