• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <gflags/gflags.h>
13 
14 #include "png_helper.h"
15 
abort_(const char * s,...)16 void abort_(const char* s, ...) {
17   va_list args;
18   va_start(args, s);
19   vfprintf(stderr, s, args);
20   fprintf(stderr, "\n");
21   va_end(args);
22   abort();
23 }
24 
write_png_file(const char * file_name,char * pixels,int width,int height)25 void write_png_file(const char* file_name,
26                     char* pixels,
27                     int width,
28                     int height) {
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);  // R
43       pixel[1] = *(p+1);  // G
44       pixel[2] = *(p+2);  // B
45       pixel[3] = *(p+3);  // A
46       p += 4;
47     }
48   }
49 
50   /* create file */
51   FILE* fp = fopen(file_name, "wb");
52   if (!fp)
53     abort_("[write_png_file] File %s could not be opened for writing",
54            file_name);
55   /* initialize stuff */
56   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
57   if (!png_ptr)
58     abort_("[write_png_file] png_create_write_struct failed");
59   info_ptr = png_create_info_struct(png_ptr);
60   if (!info_ptr)
61     abort_("[write_png_file] png_create_info_struct failed");
62   if (setjmp(png_jmpbuf(png_ptr)))
63     abort_("[write_png_file] Error during init_io");
64   png_init_io(png_ptr, fp);
65 
66   /* write header */
67   if (setjmp(png_jmpbuf(png_ptr)))
68     abort_("[write_png_file] Error during writing header");
69   png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type,
70                PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
71                PNG_FILTER_TYPE_BASE);
72   png_write_info(png_ptr, info_ptr);
73 
74   /* write bytes */
75   if (setjmp(png_jmpbuf(png_ptr)))
76     abort_("[write_png_file] Error during writing bytes");
77   png_write_image(png_ptr, row_pointers);
78 
79   /* end write */
80   if (setjmp(png_jmpbuf(png_ptr)))
81     abort_("[write_png_file] Error during end of write");
82   png_write_end(png_ptr, NULL);
83 
84   /* cleanup heap allocation */
85   for (y = 0; y < height; y++)
86     free(row_pointers[y]);
87   free(row_pointers);
88 
89   fclose(fp);
90 
91   // Try to flush saved image to disk such that more data survives a hard crash.
92   system("/bin/sync");
93 }
94