Home | History | Annotate | Download | only in src
      1 // Copyright 2002-2010 Guillaume Cottenceau.
      2 // This software may be freely redistributed under the terms of
      3 // the X11 license.
      4 //
      5 // Function write_png_file taken slightly modified from
      6 // http://zarb.org/~gc/html/libpng.html
      7 
      8 #include <png.h>
      9 #include <stdarg.h>
     10 #include <stdio.h>
     11 
     12 #include <base/files/file_util.h>
     13 #include <base/memory/scoped_ptr.h>
     14 #include <gflags/gflags.h>
     15 
     16 #include "png_helper.h"
     17 
     18 void abort_(const char * s, ...) {
     19   va_list args;
     20   va_start(args, s);
     21   vfprintf(stderr, s, args);
     22   fprintf(stderr, "\n");
     23   va_end(args);
     24   abort();
     25 }
     26 
     27 void write_png_file(const char* file_name, char* pixels, int width, int height)
     28 {
     29   int         x, y;
     30   png_bytep  *row_pointers;
     31   png_structp png_ptr;
     32   png_infop   info_ptr;
     33   png_byte    bit_depth = 8;  // 8 bits per channel RGBA
     34   png_byte    color_type = 6; // RGBA
     35 
     36   row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
     37   char *p = pixels;
     38   for (y=height-1; y>=0; y--) {
     39     row_pointers[y] = (png_byte*) malloc(4*width);
     40     for (x=0; x<width; x++) {
     41       png_byte* pixel = &(row_pointers[y][x*4]);
     42       pixel[0] = *p; p++; // R
     43       pixel[1] = *p; p++; // G
     44       pixel[2] = *p; p++; // B
     45       pixel[3] = *p; p++; // A
     46     }
     47   }
     48 
     49   /* create file */
     50   FILE *fp = fopen(file_name, "wb");
     51   if (!fp)
     52     abort_("[write_png_file] File %s could not be opened for writing",
     53            file_name);
     54   /* initialize stuff */
     55   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
     56   if (!png_ptr)
     57     abort_("[write_png_file] png_create_write_struct failed");
     58   info_ptr = png_create_info_struct(png_ptr);
     59   if (!info_ptr)
     60     abort_("[write_png_file] png_create_info_struct failed");
     61   if (setjmp(png_jmpbuf(png_ptr)))
     62     abort_("[write_png_file] Error during init_io");
     63   png_init_io(png_ptr, fp);
     64 
     65   /* write header */
     66   if (setjmp(png_jmpbuf(png_ptr)))
     67     abort_("[write_png_file] Error during writing header");
     68   png_set_IHDR(png_ptr, info_ptr, width, height,
     69                bit_depth, color_type, PNG_INTERLACE_NONE,
     70                PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
     71   png_write_info(png_ptr, info_ptr);
     72 
     73   /* write bytes */
     74   if (setjmp(png_jmpbuf(png_ptr)))
     75     abort_("[write_png_file] Error during writing bytes");
     76   png_write_image(png_ptr, row_pointers);
     77 
     78   /* end write */
     79   if (setjmp(png_jmpbuf(png_ptr)))
     80     abort_("[write_png_file] Error during end of write");
     81   png_write_end(png_ptr, NULL);
     82 
     83   /* cleanup heap allocation */
     84   for (y=0; y<height; y++)
     85     free(row_pointers[y]);
     86   free(row_pointers);
     87 
     88   fclose(fp);
     89 
     90   // Try to flush saved image to disk such that more data survives a hard crash.
     91   system("/bin/sync");
     92 }
     93