title: How can I manually read PNG files in C++?
body: <h2>Portable Network Graphics Overview</h2>
  
  <p>The general layout of any given PNG file looks like this:</p>
  
  <p><strong>File Header</strong>: An 8-byte signature.</p>
  
  <p><img src="https://i.stack.imgur.com/XXxBi.png" alt=""></p>
  
  <p><strong>Chunks</strong>: Chunks of data ranging from image properties to the actual image itself.</p>
  
  <hr>
  
  <h2>The Problem</h2>
  
  <p>I want to read PNG files in C++ without using any external libraries. I want to do this to gain a deeper understanding of both PNG format and the C++ programming language.</p>
  
  <p>I started off using <code>fstream</code> to read images byte-by-byte, but I can't get past the header of any PNG file. I try using <code>read( char*, int )</code> to put the bytes into <code>char</code> arrays, but <code>read</code> fails on every byte after the header.</p>
  
  <p>As seen above, I think my program always gets caught up on the end-of-file <code>1A</code> byte. I'm developing on Windows 7 for Windows 7 and Linux machines.</p>
  
  <hr>
  
  <h2>Some of My (Old) Code</h2>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;fstream&gt;
  #include &lt;cstring&gt;
  #include &lt;cstddef&gt;
  
  const char* INPUT_FILENAME = "image.png";
  
  int main()
  {
    std::ifstream file;
    size_t size = 0;
  
    std::cout &lt;&lt; "Attempting to open " &lt;&lt; INPUT_FILENAME &lt;&lt; std::endl;
  
    file.open( INPUT_FILENAME, std::ios::in | std::ios::binary | std::ios::ate );
    char* data = 0;
  
    file.seekg( 0, std::ios::end );
    size = file.tellg();
    std::cout &lt;&lt; "File size: " &lt;&lt; size &lt;&lt; std::endl;
    file.seekg( 0, std::ios::beg );
  
    data = new char[ size - 8 + 1 ];
    file.seekg( 8 ); // skip the header
    file.read( data, size );
    data[ size ] = '\0';
    std::cout &lt;&lt; "Data size: " &lt;&lt; std::strlen( data ) &lt;&lt; std::endl;
  }
  </code></pre>
  
  <p>The output is always similar to this:</p>
  
  <pre><code>Attempting to open image.png
  File size: 1768222
  Data size: 0
  </code></pre>
  
  <p>The file size is correct, but data size is clearly incorrect. Note that I try to skip the header (avoid the end-of-file character) and also account for this when declaring the size of <code>char* data</code>.</p>
  
  <p>Here are some data size values when I modify the <code>file.seekg( ... );</code> line accordingly:</p>
  
  <pre><code>file.seekg( n );             data size
  ----------------             ---------
  0                            8
  1                            7
  2                            6
  ...                          ...
  8                            0
  9                            0
  10                           0
  </code></pre>
  
  <hr>
  
  <h2>Some of My New Code</h2>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;fstream&gt;
  #include &lt;cstring&gt;
  #include &lt;cstddef&gt;
  
  const char* INPUT_FILENAME = "image.png";
  
  int main()
  {
    std::ifstream file;
    size_t size = 0;
  
    std::cout &lt;&lt; "Attempting to open " &lt;&lt; INPUT_FILENAME &lt;&lt; std::endl;
  
    file.open( INPUT_FILENAME, std::ios::in | std::ios::binary | std::ios::ate );
    char* data = 0;
  
    file.seekg( 0, std::ios::end );
    size = file.tellg();
    std::cout &lt;&lt; "File size: " &lt;&lt; size &lt;&lt; std::endl;
    file.seekg( 0, std::ios::beg );
  
    data = new char[ size - 8 + 1 ];
    file.seekg( 8 ); // skip the header
    file.read( data, size );
    data[ size ] = '\0';
    std::cout &lt;&lt; "Data size: " &lt;&lt; ((unsigned long long)file.tellg() - 8) &lt;&lt; std::endl;
  }
  </code></pre>
  
  <p>I essentially just modified the <code>Data size:</code> line. A thing to note is the output of the <code>Data size:</code> line is always really close to the maximum value of whatever <code>type</code> I cast <code>file.tellg()</code> to.</p>