title: Decoding and saving image files from base64 C++
body: <p>I'm trying to write a program in c++ that can encode images into base64 and also decode base64 into images. I believe the encoder function is working fine and some websites can take the base64 code I generate and decode it into the image fine, but for some reason once I decode the base64 into a string and then write it to a file and save it as a png it says it can't be opened in an image viewer.</p>
  
  <p>I confirmed that the string that is being written to the new file is exactly the same as the existing file (when opened in a text editor), but for some reason, the new file can't be opened but the existing one can be. I have even tried just making a new file in a text editor, and copying the text from the old file into it, but it still doesn't open in an image viewer.</p>
  
  <p>I believe that both of the encode functions and the base64 decode function all work fine. I think the problem is in the Image Decode function.</p>
  
  <p>Image Encode Function</p>
  
  <pre><code>string base64_encode_image(const string&amp; path) {
      vector&lt;char&gt; temp;
  
      std::ifstream infile;
      infile.open(path, ios::binary);     // Open file in binary mode
      if (infile.is_open()) {
          while (!infile.eof()) {
              char c = (char)infile.get();
              temp.push_back(c);
          }
          infile.close();
      }
      else return "File could not be opened";
      string ret(temp.begin(), temp.end() - 1);
      ret = base64_encode((unsigned const char*)ret.c_str(), ret.size());
  
      return ret;
  }
  </code></pre>
  
  <p>Image Decode Function</p>
  
  <pre><code>void base64_decode_image(const string&amp; input) {
      ofstream outfile;
      outfile.open("test.png", ofstream::out);
  
      string temp = base64_decode(input);
  
      outfile.write(temp.c_str(), temp.size());
      outfile.close();
      cout &lt;&lt; "file saved" &lt;&lt; endl;
  }
  </code></pre>
  
  <p>Encode Function base64</p>
  
  <pre><code>string base64_encode(unsigned const char* input, unsigned const int len) {
      string ret;
      size_t i = 0;
      unsigned char bytes[3];
      unsigned char sextets[4];
  
      while (i &lt;= (len - 3)) {
          bytes[0] = *(input++);
          bytes[1] = *(input++);
          bytes[2] = *(input++);
  
          sextets[0] = (bytes[0] &amp; 0xfc) &gt;&gt; 2;    // Cuts last two bits off of first byte
          sextets[1] = ((bytes[0] &amp; 0x03) &lt;&lt; 4) + ((bytes[1] &amp; 0xf0) &gt;&gt; 4);   // Takes last two bits from first byte and adds it to first 4 bits of 2nd byte
          sextets[2] = ((bytes[1] &amp; 0x0f) &lt;&lt; 2) + ((bytes[2] &amp; 0xc0) &gt;&gt; 6);   // Takes last 4 bits of 2nd byte and adds it to first 2 bits of third byte
          sextets[3] = bytes[2] &amp; 0x3f;   // takes last 6 bits of third byte
  
          for (size_t j = 0; j &lt; 4; ++j) {
              ret += base64_chars[sextets[j]];
          }
  
          i += 3; // increases to go to third byte
      }
  
      if (i != len) {
          size_t k = 0;
          size_t j = len - i; // Find index of last byte
          while (k &lt; j) {     // Sets first bytes
              bytes[k] = *(input++);
              ++k;
          }
  
          while (j &lt; 3) {     // Set last bytes to 0x00
              bytes[j] = '\0';
              ++j;
          }
  
          sextets[0] = (bytes[0] &amp; 0xfc) &gt;&gt; 2;    // Cuts last two bits off of first byte
          sextets[1] = ((bytes[0] &amp; 0x03) &lt;&lt; 4) + ((bytes[1] &amp; 0xf0) &gt;&gt; 4);   // Takes last two bits from first byte and adds it to first 4 bits of 2nd byte
          sextets[2] = ((bytes[1] &amp; 0x0f) &lt;&lt; 2) + ((bytes[2] &amp; 0xc0) &gt;&gt; 6);   // Takes last 4 bits of 2nd byte and adds it to first 2 bits of third byte
          // No last one is needed, because if there were 4, then (i == len) == true
  
          for (j = 0; j &lt; (len - i) + 1; ++j) {   // Gets sextets that include data
              ret += base64_chars[sextets[j]];    // Appends them to string
          }
  
          while ((j++) &lt; 4)   // Appends remaining ='s
              ret += '=';
  
      }
  
      return ret;
  
  }
  </code></pre>
  
  <p>Decode Function base64</p>
  
  <pre><code>string base64_decode(const string&amp; input) {
      string ret;
      size_t i = 0;
      unsigned char bytes[3];
      unsigned char sextets[4];
  
      while (i &lt; input.size() &amp;&amp; input[i] != '=') {
          size_t j = i % 4;   // index per sextet
          if (is_base64(input[i])) sextets[j] = input[i++];       // set sextets with characters from string
          else { cerr &lt;&lt; "Non base64 string included in input (possibly newline)" &lt;&lt; endl; return ""; }
          if (i % 4 == 0) {
              for (j = 0; j &lt; 4; ++j)             // Using j as a seperate index (not the same as it was originally used as, will later be reset)
                  sextets[j] = indexof(base64_chars, strlen(base64_chars), sextets[j]);   // Change value to indicies of b64 characters and not ascii characters
  
              bytes[0] = (sextets[0] &lt;&lt; 2) + ((sextets[1] &amp; 0x30) &gt;&gt; 4);  // Similar bitshifting to before
              bytes[1] = ((sextets[1] &amp; 0x0f) &lt;&lt; 4) + ((sextets[2] &amp; 0x3c) &gt;&gt; 2);
              bytes[2] = ((sextets[2] &amp; 0x03) &lt;&lt; 6) + sextets[3];
  
              for (j = 0; j &lt; 3; ++j)     // Using j seperately again to iterate through bytes and adding them to full string
                  ret += bytes[j];
          }
      }
  
      if (i % 4 != 0) {
          for (size_t j = 0; j &lt; (i % 4); ++j)
              sextets[j] = indexof(base64_chars, strlen(base64_chars), sextets[j]);
  
          bytes[0] = (sextets[0] &lt;&lt; 2) + ((sextets[1] &amp; 0x30) &gt;&gt; 4);  // Similar bitshifting to before
          bytes[1] = ((sextets[1] &amp; 0x0f) &lt;&lt; 4) + ((sextets[2] &amp; 0x3c) &gt;&gt; 2);
          for (size_t j = 0; j &lt; (i % 4) - 1; ++j)
              ret += bytes[j];        // Add final bytes
      }
      return ret;
  }
  </code></pre>
  
  <p>When I try to open the files produced by Image decode function It says that the file format isn't supported, or that it has been corrupted. 
  The base64 produced by the encode function that I'm trying to decode is in this link
  <a href="https://pastebin.com/S5D90Fs8" rel="nofollow noreferrer">https://pastebin.com/S5D90Fs8</a></p>