Search code examples
c#imagefilebinarywriter

C# BinaryWriter Save as PFM image file


Trying to write a 32bit float RGB image as a pfm file, but not sure how to interpret this explanation. (http://www.pauldebevec.com/Research/HDR/PFM/)

The format begins with three lines of text specifying the image size and type, and then continues with raw binary image data for the rest of the file. The text header of a .pfm file takes the following form:

[type] [xres] [yres] [byte_order] Each of the three lines of text ends with a 1-byte Unix-style carriage return: 0x0a in hex, not the Windows/DOS CR/LF combination. The "[type]" is one of "PF" for a 3-channel RGB color image, or "Pf" for a monochrome single-channel image. "[xres] [yres]" indicates the x and y resolutions of the image. "[byte_order]" is a number used to indicate the byte order within the file. A positive number (e.g. "1.0") indicates big-endian, with the most significant byte of each 4-byte float first. If the number is negative (e.g. "-1.0") this indicates little-endian, with the least significant byte first. There are no comments in these files. For example:

PF 768 512 -1.0 Indicates an RGB color image, 768 by 512 pixels, with little-endian byte order.

After the final carriage return the file proceeds with a series of three 4-byte IEEE 754 single precision floating point numbers for each pixel, specified in left to right, bottom to top order.

C# My current Code:

        using (var stream = File.Open(path, FileMode.Create))
        {
            using (var writer = new StreamWriter(stream))
            {
                writer.Write("PF");
                writer.Write((byte)0x0a);
                writer.Write(((int)texture.Width).ToString());
                writer.Write((byte)0x20);
                writer.Write(((int)texture.Height).ToString());
                writer.Write((byte)0x0a);
                if (BitConverter.IsLittleEndian)
                {
                    writer.Write("-1.0");
                }
                else
                {
                    writer.Write("1.0");
                }
                writer.Write((byte)0x0a);
                for (int i = 0; i < texture.Length; i++)
                {
                    writer.Write((float)texture[i].R));
                    writer.Write((float)texture[i].G));
                    writer.Write((float)texture[i].B));
                }
            }
        }

Solution

  • Working verison:

        using (var stream = File.Open(path, FileMode.Create))
        {
            using (var writer = new BinaryWriter(stream))
            {
                string str = $"PF\n{(int)texture.Width} {(int)texture.Height}\n-1.0\n";
    
                byte[] bytes = Encoding.ASCII.GetBytes(str);
    
                writer.Write(bytes);
    
                for (int i = 0; i < texture.Length; i++)
                {
                    writer.Write((float)texture[i].R);
                    writer.Write((float)texture[i].G);
                    writer.Write((float)texture[i].B);
                }
            }
        }