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));
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
.