Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 13
  1. #1
    Utente di HTML.it
    Registrato dal
    Dec 2009
    Messaggi
    1,123

    [Java] Scrittura byte su file (.ppm), anomalia nei colori

    Ciao a tutti,

    Ho scritto una sempice classe che permette di salvare immagini in ppm..

    Durante il salvataggio dell'immagine è come se ci fossero i colori invertiti.. La parte dedicata al salvataggio è la seguente:

    codice:
      void saveImage(String name) throws IOException {
    	PrintStream bos = new PrintStream(new FileOutputStream(name+".ppm"));
    	
    	bos.println("P6\n"+"#Immagine generata da ImagePpm\n"+width+" "+height+"\n255\n");
    	
    	bos.write(data);
    	//bos.flush();
    	bos.close();
      }
    Dove data è un array di byte.
    Se utilizzo un ciclo for e nel corpo inserisco bos.println(data[i]); l'immagine si vede bene! Però, vi è un problema in questo caso..il tempo di esecuzione aumenta di 20 volte..

    Dunque mi chiedo..perchè in quel modo, se creo un immagine a croce con i seguenti valori orizzontali 255,0,0 mi trovo la croce blu e non rossa?

    Se volete altri dettagli sono qui..

    Grazie a tutti!!

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: [Java] Scrittura byte su file (.ppm), anomalia nei colori

    Originariamente inviato da Patrick Jane
    Dove data è un array di byte.
    E questo array di byte cosa contiene?
    Perché l'header P6 indica un "Portable pixmap" con encoding "binary".
    E stando a quanto dice Wikipedia su questa famiglia di formati:
    http://en.wikipedia.org/wiki/Netpbm_format

    The P6 binary format of the same image will store each color component of each pixel with one byte (thus three bytes per pixel) in the order red, green, then blue. The file will be smaller but the color information will not be readable by humans.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it
    Registrato dal
    Dec 2009
    Messaggi
    1,123

    Re: Re: [Java] Scrittura byte su file (.ppm), anomalia nei colori

    Originariamente inviato da andbin
    E questo array di byte cosa contiene?
    Perché l'header P6 indica un "Portable pixmap" con encoding "binary".
    E stando a quanto dice Wikipedia su questa famiglia di formati:
    http://en.wikipedia.org/wiki/Netpbm_format

    The P6 binary format of the same image will store each color component of each pixel with one byte (thus three bytes per pixel) in the order red, green, then blue. The file will be smaller but the color information will not be readable by humans.
    Intanto grazie per la risposta! ^^

    Dunque, questo array contiene i pixel. I pixel li aggiungo all'array con quest'altro metodo

    codice:
      void setPixel(int x,int y, int r, int g, int b) {
        if(x >=0 && y>=0 && x<=width && y<=height) {
    	  data[3*(x+y*width)  ] =(byte) r;
    	  data[3*(x+y*width)+1] =(byte) g;
    	  data[3*(x+y*width)+2] =(byte) b;
    	}
      }
    Il fatto è che se setto il rosso a 255 io vedo il colore blu..

    Grazie!

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    E chi invoca setPixel() ? Perché a parte un pochino la "fumosità" di questo metodo, non mi pare di vedere nulla di sbagliato a livello tecnico.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Utente di HTML.it
    Registrato dal
    Dec 2009
    Messaggi
    1,123
    Originariamente inviato da andbin
    E chi invoca setPixel() ? Perché a parte un pochino la "fumosità" di questo metodo, non mi pare di vedere nulla di sbagliato a livello tecnico.
    setPixel() viene invocato da un altra classe che instanzia appunto Ppm.
    codice:
        int w=1024,h=768;
        ImagePpm ppm = new ImagePpm(w,h);
    	
    	for(int i=0; i<w; i++) {
    	  ppm.setPixel(i,h/2,255,0,0);
    	}
    	for(int j=0; j<h; j++) {
          ppm.setPixel(w/2,j,255,0,0);
    	}
    	
    	ppm.saveImage("test");
    ..come dicevo disegna una croce.

    quel metodo è così perchè si occuperò di settare il colore di un pixel in una certa posizione, ed il colore cambierà da pixel a pixel (in sostanza la userò per i frattali).

    Però quella cosa non me la spiego (del colore). Se io uso questo ad esempio:

    codice:
      void saveImage(String name) throws IOException {
    	PrintStream bos = new PrintStream(new FileOutputStream(name+".ppm"));
    	
    	bos.println("P3\n"+"#Immagine generata da ImagePpm\n"+width+" "+height+"\n255\n");
    	
    	for(int i=0; i<data.length; i++) {
    	  bos.println(data[i]);
    	}
    	bos.close();
      }
    il tutto funziona in modo corretto.. però ci mette moltissimo tempo, visto che deve scorrere l'array con un for..

  6. #6
    Utente di HTML.it
    Registrato dal
    Dec 2009
    Messaggi
    1,123
    ..penso d'aver trovato la causa!

    255, è fuori da un byte signed!

    ..ora mi chiedo..come faccio a farglielo considerare un byte unsigned?
    Aritmetica binaria?

    Grazie!^^

  7. #7
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Patrick Jane
    255, è fuori da un byte signed!

    ..ora mi chiedo..come faccio a farglielo considerare un byte unsigned?
    Aritmetica binaria?
    No, non ci siamo ... e qui non centra il "segno".
    Il setPixel riceve dei int. Se passi 255, poi il cast a byte lo fa diventare chiaramente un byte (troncando i 24 bit alti del int) e tecnicamente, come lo gestisce e vede Java, sarebbe un valore -1 (il byte è signed in Java). Ma questo non importa!! Che tu lo veda come 255 (senza segno) o come -1 (con segno), sono sempre comunque 8 bit a 1 (11111111) ed è questo che importa e viene salvato su file.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  8. #8
    Utente di HTML.it
    Registrato dal
    Dec 2009
    Messaggi
    1,123
    Ah ok..

    Secondo te cosa può causare questa sorta di scambio di colori?

    Grazie!^^

  9. #9
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da Patrick Jane
    Secondo te cosa può causare questa sorta di scambio di colori?
    Guarda, così su due piedi non ti so dire, anche perché dovrei vedere bene tutto quello che hai scritto in modo completo (non frammentato come hai postato finora).

    Io ho fatto una mia prova:

    codice:
    import java.io.*;
    
    public class Test {
        public static void main(String[] args) {
            try {
                PPMImage ppmImg = new PPMImage(200, 200);
    
                for (int x = 0; x < 200; x++) {
                    ppmImg.setPixel(x, 0, 255, 0, 0);
                    ppmImg.setPixel(x, 10, 0, 255, 0);
                    ppmImg.setPixel(x, 20, 0, 0, 255);
                }
    
                ppmImg.write(new File("test.ppm"));
            } catch (Exception e) {
                System.err.println(e);
            }
        }
    }
    
    
    class PPMImage {
        private byte[] data;
        private int width;
        private int height;
    
        public PPMImage(int width, int height) {
            data = new byte[width * height * 3];
            this.width = width;
            this.height = height;
        }
    
        public void setPixel(int x, int y, int red, int green, int blue) {
            if (x < 0 || x >= width) {
                throw new IllegalArgumentException("x out of range");
            }
    
            if (y < 0 || y >= height) {
                throw new IllegalArgumentException("y out of range");
            }
    
            int i = (y * width + x) * 3;
            data[i] = (byte) red;
            data[i+1] = (byte) green;
            data[i+2] = (byte) blue;
        }
    
        public void write(File f) throws IOException {
            FileOutputStream fos = new FileOutputStream(f);
    
            String header = "P6\n" +
                            "#Image by PPMImage java class\n" +
                            width + " " + height + "\n" +
                            "255\n";
    
            try {
                fos.write(header.getBytes("US-ASCII"));
                fos.write(data);
            } finally {
                fos.close();
            }
        }
    }
    La immagine la scrive correttamente e la "vedo" perfettamente sia con GIMP che con IrfanView: tutta nera con una riga rossa, poi una verde, poi una blu.

    Nota comunque come ho lanciato una eccezione in setPixel e come ho fatto la scrittura usando solo FileOutputStream e gestendo anche correttamente la chiusura dello stream.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  10. #10
    Utente di HTML.it
    Registrato dal
    Dec 2009
    Messaggi
    1,123
    Scusa il ritardo nella risposta ma avevo lasciato il sorgente su ubuntu.

    Ecco il codice completo

    codice:
    import java.io.*;
    
    import java.util.Arrays;
    
    
    
    class ImagePpm {
    
      private byte data[];
    
      private int width,height;
    
      
    
      ImagePpm(int w, int h) {
    
        width = w;
    
    	height = h;
    
        data = new byte[3+(width*height*3)];
    
    	
    
    	Arrays.fill(data,(byte)0);
    
      }
    
      
    
      void setPixel(int x,int y, int r, int g, int b) {
    
        if(x >=0 && y>=0 && x<=width && y<=height) {
    
    	  data[3*(x+y*width)  ] = (byte)(r&0xff);
    
    	  data[3*(x+y*width)+1] = (byte)(g&0xff);
    
    	  data[3*(x+y*width)+2] = (byte)(b&0xff);
    
    	}
    
      }
    
      
    
      void saveImage(String name) throws IOException {
    
    	PrintStream bos = new PrintStream(new FileOutputStream(name+".ppm"));
    
    	
    
    	bos.println("P6\n"+"#Immagine generata da ImagePpm di RootkitNeo\n"+width+" "+height+"\n255\n");
    
    	
    
    	/*for(int i=0; i<data.length; i++) {
    
    	  bos.println(data[i]);
    
    	}*/
    
    	bos.write(data);
    
    	//bos.flush();
    
    	bos.close();
    
      }
    
    }
    
    
    
    class Ppm {
    
      public static void main(String args[]) throws IOException {
    
        int w=1024,h=768;
    
        ImagePpm ppm = new ImagePpm(w,h);
    
    	
    
    	for(int i=0; i<w; i++) {
    
    	  ppm.setPixel(i,h/2,255,0,0);
    
    	}
    
    	for(int j=0; j<h; j++) {
    
          ppm.setPixel(w/2,j,255,0,0);
    
    	}
    
    	
    
    	ppm.saveImage("test");
    
      }
    
    }

    Ora provo a modificare lo stream sul mio e a guardare bene il tuo source

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.