-1

As a homework assignment we are supposed to read in a .pgm file and then draw a square in by changing the pixel values, and then output the new image. After I go through and change the pixels I print them all to a .txt as a way to check that they actually got added. The part I'm having trouble with is writing the new file. I know it's supposed to be binary so after googling I think I should be using DataOutputStream, but I could be wrong. After I write the file its size is 1.9MB where as the original is only 480KB, so right off the bat I suspect something must be wrong. Any advice or tips for writing to .pgm files would be great!

public static void writeImage(String fileName) throws IOException{
    DataOutputStream writeFile = new DataOutputStream(new FileOutputStream(fileName)); 
     // Write the .pgm header (P5, 800 600, 250) 
    writeFile.writeUTF(type + "\n");
    writeFile.writeUTF(width + "  " + height + "\n");
    writeFile.writeUTF(max + "\n");

    for(int i = 0; i < height; i++){
        for(int j = 0; j < width; j++){
            writeFile.writeByte(img[i][j]); //Write the number
            writeFile.writeUTF(" "); //Add white space
        }
        writeFile.writeUTF(" \n"); //finished one line so drop to next
    }
    writeFile.close();

}

When I try to open the new file i get an error message saying "illegal image format", and the original file opens properly.

John
  • 1,808
  • 7
  • 28
  • 57
  • Did you read the [Java Tutorial on Byte Streams](http://docs.oracle.com/javase/tutorial/essential/io/bytestreams.html)? –  Mar 18 '15 at 15:41
  • @Obicere "we are supposed to read in a .pgm file" The question is if the original file is binary or ASCII. –  Mar 18 '15 at 15:41
  • @Obicere The original file is a .pgm file – John Mar 18 '15 at 15:42
  • @LutzHorn its P5 so that would be a binary file. And reading the Tutorial now, Thanks! – John Mar 18 '15 at 15:43
  • @LutzHorn Im not sure how I could manipulate the values that way – John Mar 18 '15 at 15:59

2 Answers2

0

It can't be right that you use the writeByte method to write a pixel. writeByte will write a single byte even if the argument is of type int. (the eight low-order bits of the argument are written).

You need to read the file format specification carefully and make sure that you are writing out the right number of bytes. A hex editor can help a lot.

lbalazscs
  • 17,474
  • 7
  • 42
  • 50
  • True. I could use writeChar because that writes an int with 2 bytes, and each pixel is either 1 or 2 bytes, correct? Would using writeUTF through it off also, or no because theres allowed multiple white spaces between each? Or am I just completely wrong and dataOutputStream is not the way to go – John Mar 18 '15 at 16:15
  • I don't know the details of this format, but usually one pixel is 4 bytes (red, green, blue, and possibly an alpha channel) – lbalazscs Mar 18 '15 at 17:04
  • @lbalazscs PGM is Portable *Gray* Map. Thus a pixel is always 1 or 2 bytes (2 bytes for 16 bit, or `max > 255`). No R, G, B or A. :-) – Harald K Mar 23 '15 at 11:25
0

I think you are somehow confusing the binary (P5) and ASCII (P2) modes of the PGM format.

The ASCII version has spaces between each pixel and (optional) line feeds, like you have in your code.

For the binary format, you should just write the pixel values (as bytes, as you have max value 250). No spaces or line feeds.

(I don't write the code for you, as this is an assignment, but you are almost there, so I'm sure you'll make it! :-)

PS: Also carefully read the documentation on DataOuputStream.writeUTF(...):

First, two bytes are written to the output stream as if by the writeShort method giving the number of bytes to follow.

Are you sure this is what you want? Keep in mind that the PGM format headers are all ASCII, so there's really no need to use UTF here.

Harald K
  • 26,314
  • 7
  • 65
  • 111