Anti-Grain Geometry Tutorial
writepng.h
1 /*
2  * Copyright (c) 2018 Heng Yuan
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #ifndef TUTORIAL_WRITE_PNG_H
17 #define TUTORIAL_WRITE_PNG_H
18 
19 #include "exception.h"
20 
21 #include <cstdio>
22 #include <png.h> // requires libpng on Linux
23 
24 #include <agg_color_rgba.h>
25 
26 template<class T>
27 int
28 getPngColorType () { throw TutorialException ("Cannot determine color type"); }
29 
30 template<>
31 int
32 getPngColorType<agg::rgba8> () { return PNG_COLOR_TYPE_RGBA; }
33 
43 template<class RendererBaseType>
44 void
45 writePng (const char* fileName, const RendererBaseType& rBase)
46 {
47  FILE* outFile;
48  png_structp pngPtr;
49  png_infop infoPtr;
50 
51  outFile = fopen (fileName, "wb");
52  if (outFile == nullptr)
53  {
54  throw TutorialException ("Unable to write to %s", fileName);
55  }
56 
57  pngPtr = png_create_write_struct (PNG_LIBPNG_VER_STRING,
58  nullptr,
59  nullptr,
60  nullptr);
61  ASSERT(pngPtr != nullptr);
62 
63  infoPtr = png_create_info_struct(pngPtr);
64  ASSERT(infoPtr != nullptr);
65 
66  if (setjmp(png_jmpbuf(pngPtr)))
67  {
68  ASSERT(false);
69  }
70 
71  png_init_io(pngPtr, outFile);
72 
73  int pngColorType = getPngColorType<typename RendererBaseType::color_type> ();
74  const int width = rBase.width ();
75  const int height = rBase.height ();
76  const int valueSize = sizeof(typename RendererBaseType::color_type::value_type);
77 
78  png_set_IHDR(pngPtr,
79  infoPtr,
80  width,
81  height,
82  valueSize * 8,
83  getPngColorType<typename RendererBaseType::color_type> (),
84  PNG_INTERLACE_NONE,
85  PNG_COMPRESSION_TYPE_DEFAULT,
86  PNG_FILTER_TYPE_DEFAULT);
87 
88  png_write_info(pngPtr, infoPtr);
89 
90  png_bytep *rows = new png_bytep[height];
91  for (int y = 0; y < height; ++y)
92  {
93  rows[y] = (png_bytep)rBase.ren ().pix_ptr (0, y);
94  }
95 
96  png_write_image(pngPtr, rows);
97  delete rows;
98 
99  png_write_end(pngPtr, NULL);
100  fclose(outFile);
101  png_destroy_write_struct(&pngPtr, &infoPtr);
102 }
103 
104 #endif // TUTORIAL_WRITE_PNG_H