javappm

How to encode RGB values for a P6 ppm?


I'm trying to create a ppm image file using the P6 encoding. I'm using this code to create the file:

private static void writeImage(String image, String outputPath) {
    try (PrintWriter out = new PrintWriter(outputPath + "output.pbm")) {
        out.println(image);
    } catch (FileNotFoundException e) {
        System.out.println(e.getMessage());
    }
}

Now all I need to do is build the text that represents the image in the P6 format. Building the header is easy, but despite experimenting and searching, I can't seem to figure out how to convert the RGB values for each pixel into a string I can add to the file.

My question is this:

How do I take an RGB value (for example(red=255, blue=192, green=0)) and get a String representation that will be correctly recognized in an image in the P6 format?


Solution: Credit to Solomon Slow's comment for helping me figure this out. This is the solution I came up with for those who want details. I now use this function to create and output the file:

private static void writeImage(String header, List<Byte> image, String filepath) {
    try (FileOutputStream out = new FileOutputStream(filepath)) {
        out.write(header.getBytes(StandardCharsets.UTF_8));
        for(byte b:image) {
            out.write(b);
        }
    } catch (IOException e) {
        System.out.println(e.getMessage());
        throw new TerminateProgram();
    }
}

The header I pass in is defined like this in another function:

String header = "P6" + "\n" +
                width + " " +
                height + "\n" +
                "255" + "\n";

Finally, I build a list of byte values using an ArrayList, adding each pixel like so:

List<Byte> image = new ArrayList<>();

// red, green, blue already defined as ints from 0 to 255
image.add((byte)(red));
image.add((byte)(green));
image.add((byte)(blue));

Solution

  • From, http://netpbm.sourceforge.net/doc/ppm.html

    Each pixel is a triplet of red, green, and blue samples, in that order. Each sample is represented in pure binary by either 1 or 2 bytes. The most significant byte is first.

    That means, the ppm file is not a text file. You probably should be using a FileOutputStream instead of a PrintWriter.

    It's going to be a little tricky because Java's byte data type is signed. You'll need to have int values in the range [0..255] for the red, green, and blue levels, and then cast those to byte. Maybe see java unsigned byte to stream

    As for the text header of the file, the approach I would use would be to build a String representation of the header, and then call header.getBytes() to turn it into a byte array that you can write to the FileOutputStream.