title: How to encode PNG to buffer using libpng?
body: <p>I'm currently using the following to write a PNG to a file:</p>
  
  <pre><code>#include &lt;png.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;stdint.h&gt;
  
  /* Pixels in this bitmap structure are stored as BGR. */
  typedef struct _RGBPixel {
      uint8_t blue;
      uint8_t green;
      uint8_t red;
  } RGBPixel;
  
  /* Structure for containing decompressed bitmaps. */
  typedef struct _RGBBitmap {
      RGBPixel *pixels;
      size_t width;
      size_t height;
      size_t bytewidth;
      uint8_t bytes_per_pixel;
  } RGBBitmap;
  
  /* Returns pixel of bitmap at given point. */
  #define RGBPixelAtPoint(image, x, y) \
      *(((image)-&gt;pixels) + (((image)-&gt;bytewidth * (y)) \
                          + ((x) * (image)-&gt;bytes_per_pixel)))
  
  /* Attempts to save PNG to file; returns 0 on success, non-zero on error. */
  int save_png_to_file(RGBBitmap *bitmap, const char *path)
  {
      FILE *fp = fopen(path, "wb");
      png_structp png_ptr = NULL;
      png_infop info_ptr = NULL;
      size_t x, y;
      png_uint_32 bytes_per_row;
      png_byte **row_pointers = NULL;
  
      if (fp == NULL) return -1;
  
      /* Initialize the write struct. */
      png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
      if (png_ptr == NULL) {
          fclose(fp);
          return -1;
      }
  
      /* Initialize the info struct. */
      info_ptr = png_create_info_struct(png_ptr);
      if (info_ptr == NULL) {
          png_destroy_write_struct(&amp;png_ptr, NULL);
          fclose(fp);
          return -1;
      }
  
      /* Set up error handling. */
      if (setjmp(png_jmpbuf(png_ptr))) {
          png_destroy_write_struct(&amp;png_ptr, &amp;info_ptr);
          fclose(fp);
          return -1;
      }
  
      /* Set image attributes. */
      png_set_IHDR(png_ptr,
                   info_ptr,
                   bitmap-&gt;width,
                   bitmap-&gt;height,
                   8,
                   PNG_COLOR_TYPE_RGB,
                   PNG_INTERLACE_NONE,
                   PNG_COMPRESSION_TYPE_DEFAULT,
                   PNG_FILTER_TYPE_DEFAULT);
  
      /* Initialize rows of PNG. */
      bytes_per_row = bitmap-&gt;width * bitmap-&gt;bytes_per_pixel;
      row_pointers = png_malloc(png_ptr, bitmap-&gt;height * sizeof(png_byte *));
      for (y = 0; y &lt; bitmap-&gt;height; ++y) {
          uint8_t *row = png_malloc(png_ptr, sizeof(uint8_t) * bitmap-&gt;bytes_per_pixel);
          row_pointers[y] = (png_byte *)row;
          for (x = 0; x &lt; bitmap-&gt;width; ++x) {
              RGBPixel color = RGBPixelAtPoint(bitmap, x, y);
              *row++ = color.red;
              *row++ = color.green;
              *row++ = color.blue;
          }
      }
  
      /* Actually write the image data. */
      png_init_io(png_ptr, fp);
      png_set_rows(png_ptr, info_ptr, row_pointers);
      png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
  
      /* Cleanup. */
      for (y = 0; y &lt; bitmap-&gt;height; y++) {
          png_free(png_ptr, row_pointers[y]);
      }
      png_free(png_ptr, row_pointers);
  
      /* Finish writing. */
      png_destroy_write_struct(&amp;png_ptr, &amp;info_ptr);
      fclose(fp);
      return 0;
  }
  </code></pre>
  
  <p>How can I write a similar function (in C) to encode a PNG to an in-memory buffer?</p>
  
  <p>The prototype would look something like this:</p>
  
  <pre><code>uint8_t *encode_png_to_buffer(RGBBitmap *source);
  </code></pre>
  
  <p>And it seems that I would probably need to make some use of <code>png_set_write_fn()</code>.</p>
  
  <p>But apart from that I'm not sure how to approach this. Are there any examples of this being done? Surely I'm not the first to need this functionality.</p>