Création d'une image PPM à écrire dans un fichier Java


Je travaille donc sur un programme en java qui crée une image rectangulaire (voir le lien ci-dessous) en tant qu'image ppm qui serait ensuite écrite dans un fichier ppm. Création et écriture de l'image dans le fichier que je reçois. Cependant, j'ai du mal à créer l'image dynamiquement de telle sorte qu'elle fonctionne pour n'importe quelle largeur et hauteur spécifiées. D'après ma compréhension, un fichier p3 ppm suit simplement le format suivant pour une image 4x4.

P3
4 4
15
 0  0  0    0  0  0    0  0  0   15  0 15
 0  0  0    0 15  7    0  0  0    0  0  0
 0  0  0    0  0  0    0 15  7    0  0  0
15  0 15    0  0  0    0  0  0    0  0  0

Où les trois premiers nombres sont les en-têtes et le reste sont simplement les valeurs rvb de chaque pixel. Mais j'ai du mal à comprendre comment je peux créer la matrice ci-dessus pour l'image ci-dessous et pour toutes les dimensions spécifiées car elle n'inclut pas de couleurs unies en ligne droite?

Image à créer:

entrez la description de l'image ici

J'ai pensé que je pouvais créer une arraylist qui contient un tableau de valeurs rvb de sorte que chaque index de la liste soit un ensemble rvb suivi du prochain ensemble rvb à droite. Cependant, je suis tout à fait confus sur ce que les valeurs rvb serait. Voici ce que j'ai:

   public static void createImage(int width, int height){
        pic = new ArrayList();
        int[] rgb = new int[3];

        for(int i = 0; i <= width; i++){
            for(int j = 0; i <= height; j++){
                rgb[0] = 255-j;   //random values as im not sure what they should be or how to calculate them            
                rgb[1] = 0+j; 
                rgb[1] = 0+j; 
                pic.add(rgb);
            } 
        }   
    }

Merci d'avance.


EDITÉ: : Code mis à jour J'ai réussi à résoudre la plupart des problèmes, cependant, l'image produite ne correspond pas à celui affiché ci-dessus. Avec ce code. J'obtiens l'image suivante:

entrez la description de l'image ici

 package ppm;

    import java.awt.Color;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.util.ArrayList;


    public class PPM {

    private BufferedImage img;
    private static final String imageDir = "Image/rect.ppm";
    private final static String filename = "assignment1_q1.ppm";

    private static byte bytes[]=null;      // bytes which make up binary PPM image
    private static double doubles[] = null;
    private static int height = 0;
    private static int width = 0;
    private static ArrayList pic;
    private static String matrix="";

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException {
        createImage(200, 200);
        writeImage(filename);
    }


    public static void createImage(int width, int height){
        pic = new ArrayList();
        int[] rgb = new int[3];
        matrix +="P3\n" + width + "\n" + height + "\n255\n";
        for(int i = 0; i <= height; i++){
            for(int j = 0; j <= width; j++){ 
                Color c = getColor(width, height, j, i);
                //System.out.println(c);
                if(c==Color.red){
                      rgb[0] = (int) (255*factor(width, height, j, i));
                      rgb[1] = 0;
                      rgb[2] = 0;
                }else if(c==Color.green){
                      rgb[0] = 0;
                      rgb[1] = (int) (255*factor(width, height, j, i));
                      rgb[2] = 0;
                }else if(c==Color.blue){
                      rgb[0] = 0;
                      rgb[1] = 0;
                      rgb[2] = (int) (255*factor(width, height, j, i));
                }else if(c== Color.white){
                      rgb[0] = (int) (255*factor(width, height, j, i));
                      rgb[1] = (int) (255*factor(width, height, j, i));
                      rgb[2] = (int) (255*factor(width, height, j, i));
                }
                matrix += ""+ rgb[0] + " " + rgb[1] + " " + rgb[2] + "  " ;
                //System.out.println(""+ rgb[0] + " " + rgb[1] + " " + rgb[2] + "  ");
                //pic.add(rgb);
            } 
            matrix += "\n";
        }   
    }

    public static Color getColor(int width, int height, int a, int b){
        double d1 = ((double) width / height) * a;
        double d2 = (((double) -width / height) * a + height);

        if(d1 > b && d2 > b) return Color.green;
        if(d1 > b && d2 < b) return Color.blue;
        if(d1 < b && d2 > b) return Color.red;
        return Color.white;
    }

    public static double  factor(int width, int height, int a, int b){
        double factorX = (double) Math.min(a, width - a) / width * 2;
        double factorY = (double) Math.min(b, height - b) / height * 2;

        //System.out.println(Math.min(factorX, factorY));

        return Math.min(factorX, factorY);
    }

    public static void writeImage(String fn) throws FileNotFoundException, IOException {

        //if (pic != null) {

               FileOutputStream fos = new FileOutputStream(fn);
                fos.write(new String(matrix).getBytes());

                //fos.write(data.length);
                //System.out.println(data.length);
                fos.close();
       // }
    }
}
Author: Paul, 2017-02-01

1 answers

Vous pouvez utiliser Des fonctions linéaires pour modéliser les diagonales dans l'image. Gardez cependant à l'esprit que dans les coordonnées (0, 0) se trouvent dans le coin supérieur gauche de l'image!

Disons que vous voulez créer une image avec les dimensions width et height, la diagonale du haut à gauche vers le bas à droite croiserait les points (0, 0) et (width, height):

y = ax + t

0      = a *     0 + t    => t = 0
height = a * width + 0    => a = height / width

d1(x) = (height / width) * x

Maintenant, nous pouvons calculer la fonction pour la deuxième diagonale. Cette diagonale passe par les points (0, height) et (width, 0), donc:

y = ax + t

height = a *     0 + t      => t = height
0      = a * width + height => a = -(height/width)

d2(x) = -(height/width) * x + height

À partir de cela, nous pouvons déterminer si un certain point de l'image se trouve en dessous ou au-dessus d'une diagonale. Comme exemple pour le point (a, b):

  • if d1(a) > b: (a, b) se trouve au-dessus de la première diagonale (de gauche à droite), elle doit donc être bleue ou verte. Sinon, il doit être rouge ou blanc

  • if d2(a) > b: (a, b) se trouve au-dessus de la deuxième diagonale, elle doit donc être rouge ou verte. Sinon il doit être blanc ou bleu

En appliquant les deux relations, il est facile de déterminer à laquelle des quatre couleurs appartient un certain point:

Color getColor(int width, int height, int a, int b){
    double d1 = ((double) height / width) * a;
    double d2 = ((double) -height / width) * a + height;

    if(d1 > b && d2 > b) return greenColor;
    if(d1 > b && d2 < b) return blueColor;
    if(d1 < b && d2 > b) return redColor;
    return whiteColor;
}

Maintenant, il y a une dernière chose que nous devons prendre en compte: l'image s'assombrit vers ses frontières.

Une version plus foncée d'une couleur peut être créée en multipliant chaque canal par un facteur. Plus le facteur est faible, plus la couleur résultante est foncée. Par souci de simplicité je suppose que le changement de luminosité est linéaire par rapport à la centre de l'image.

Puisque la luminosité change indépendamment le long de deux axes, nous devons modéliser cela en calculant la variation le long des deux axes et en utilisant le maximum.

Le changement de luminosité en fonction de la distance du centre peut être modélisé en utilisant la distance à la bordure la plus proche de l'image par rapport à la distance au centre (seulement sur un axe):

deltaX = min(a, width - a) / (width / 2)
deltaY = min(b, height - b) / (height / 2)

Nous pouvons donc obtenir le facteur pour multiplier chaque canal de couleur de cette façon:

double factor(int width, int height, int a, int b){
     double factorX = (double) Math.min(a, width - a) / width * 2;
     double factorY = (double) Math.min(b, height - b) / height * 2;

     return Math.min(factorX, factorY);
}
 0
Author: Paul, 2017-02-02 18:29:13