GLX/GteWICFileIO.cpp
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.1 (2016/06/28)
7 
8 // The functions were written based on the example source code
9 // https://dev.w3.org/Amaya/libpng/example.c
10 
12 #include <Graphics/GteTexture2.h>
13 #include <png.h>
14 #include <cstdint>
15 #include <cstdio>
16 #include <string>
17 #include <vector>
18 using namespace gte;
19 
21 {
22  WICFileIOPrivateHelper(char const* name, bool readMode)
23  :
24  fp(fopen(name, (readMode ? "rb" : "wb"))),
25  png_ptr(nullptr),
26  info_ptr(nullptr),
27  isRead(readMode)
28  {
29  }
30 
32  {
33  if (fp)
34  {
35  fclose(fp);
36  }
37 
38  if (png_ptr)
39  {
40  if (isRead)
41  {
42  png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
43  }
44  else
45  {
46  png_destroy_write_struct(&png_ptr, &info_ptr);
47  }
48  }
49  }
50 
51  FILE* fp;
52  png_structp png_ptr;
53  png_infop info_ptr;
54  bool isRead;
55 };
56 
57 std::shared_ptr<Texture2> WICFileIO::Load(std::string const& filename, bool wantMipmaps)
58 {
59  // The destructor for the helper will be called on any return from
60  // this function.
61  WICFileIOPrivateHelper helper(filename.c_str(), true);
62  if (!helper.fp)
63  {
64  return nullptr;
65  }
66 
67  helper.png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
68  if (!helper.png_ptr)
69  {
70  return nullptr;
71  }
72 
73  helper.info_ptr = png_create_info_struct(helper.png_ptr);
74  if (!helper.info_ptr)
75  {
76  return nullptr;
77  }
78 
79  if (setjmp(png_jmpbuf(helper.png_ptr)))
80  {
81  return nullptr;
82  }
83 
84  png_init_io(helper.png_ptr, helper.fp);
85  png_set_sig_bytes(helper.png_ptr, 0);
86 
87  png_read_png(helper.png_ptr, helper.info_ptr, 0, nullptr);
88 
89  png_uint_32 width, height;
90  int bit_depth, color_type, interlace_method, compression_method, filter_method;
91  png_get_IHDR(helper.png_ptr, helper.info_ptr, &width, &height, &bit_depth,
92  &color_type, &interlace_method, &compression_method, &filter_method);
93 
94  if (bit_depth != 8 && bit_depth != 16)
95  {
96  // We support only 8-bit and 16-bit pixel types.
97  return nullptr;
98  }
99 
100  if (color_type & PNG_COLOR_MASK_PALETTE)
101  {
102  // We do not support palettized textures.
103  return nullptr;
104  }
105 
106  if (interlace_method != 0 || filter_method != 0)
107  {
108  // We do not support interlaced data or filtering.
109  return nullptr;
110  }
111 
112  png_bytepp rows = png_get_rows(helper.png_ptr, helper.info_ptr);
113 
114  std::shared_ptr<Texture2> texture;
115  if (bit_depth == 8)
116  {
117  uint8_t const* src = nullptr;
118  uint8_t* trg = nullptr;
119  if (color_type == PNG_COLOR_TYPE_RGBA)
120  {
121  texture = std::make_shared<Texture2>(DF_R8G8B8A8_UNORM, width, height, wantMipmaps);
122  trg = texture->Get<uint8_t>();
123  for (png_uint_32 y = 0; y < height; ++y)
124  {
125  src = reinterpret_cast<uint8_t const*>(rows[y]);
126  for (png_uint_32 x = 0; x < width; ++x)
127  {
128  for (int i = 0; i < 4; ++i)
129  {
130  *trg++ = src[4 * x + i];
131  }
132  }
133  }
134  }
135  else if (color_type == PNG_COLOR_TYPE_RGB)
136  {
137  texture = std::make_shared<Texture2>(DF_R8G8B8A8_UNORM, width, height, wantMipmaps);
138  trg = texture->Get<uint8_t>();
139  for (png_uint_32 y = 0; y < height; ++y)
140  {
141  src = reinterpret_cast<uint8_t const*>(rows[y]);
142  for (png_uint_32 x = 0; x < width; ++x)
143  {
144  for (int i = 0; i < 3; ++i)
145  {
146  *trg++ = src[3 * x + i];
147  }
148  *trg++ = 0xFFu;
149  }
150  }
151  }
152  else if (color_type == PNG_COLOR_TYPE_GRAY)
153  {
154  texture = std::make_shared<Texture2>(DF_R8_UNORM, width, height, wantMipmaps);
155  trg = texture->Get<uint8_t>();
156  for (png_uint_32 y = 0; y < height; ++y)
157  {
158  src = reinterpret_cast<uint8_t const*>(rows[y]);
159  for (png_uint_32 x = 0; x < width; ++x)
160  {
161  *trg++ = src[x];
162  }
163  }
164  }
165  else if (color_type == PNG_COLOR_TYPE_GA)
166  {
167  texture = std::make_shared<Texture2>(DF_R8G8_UNORM, width, height, wantMipmaps);
168  trg = texture->Get<uint8_t>();
169  for (png_uint_32 y = 0; y < height; ++y)
170  {
171  src = reinterpret_cast<uint8_t const*>(rows[y]);
172  for (png_uint_32 x = 0; x < width; ++x)
173  {
174  for (int i = 0; i < 2; ++i)
175  {
176  *trg++ = src[2 * x + i];
177  }
178  }
179  }
180  }
181  }
182  else // bit_depth is 16
183  {
184  uint16_t const* src = nullptr;
185  uint16_t* trg = nullptr;
186  if (color_type == PNG_COLOR_TYPE_RGBA)
187  {
188  texture = std::make_shared<Texture2>(DF_R16G16B16A16_UNORM, width, height, wantMipmaps);
189  trg = texture->Get<uint16_t>();
190  for (png_uint_32 y = 0; y < height; ++y)
191  {
192  src = reinterpret_cast<uint16_t const*>(rows[y]);
193  for (png_uint_32 x = 0; x < width; ++x)
194  {
195  for (int i = 0; i < 4; ++i)
196  {
197  *trg++ = src[4 * x + i];
198  }
199  }
200  }
201  }
202  else if (color_type == PNG_COLOR_TYPE_RGB)
203  {
204  texture = std::make_shared<Texture2>(DF_R8G8B8A8_UNORM, width, height, wantMipmaps);
205  trg = texture->Get<uint16_t>();
206  for (png_uint_32 y = 0; y < height; ++y)
207  {
208  src = reinterpret_cast<uint16_t const*>(rows[y]);
209  for (png_uint_32 x = 0; x < width; ++x)
210  {
211  for (int i = 0; i < 3; ++i)
212  {
213  *trg++ = src[3 * x + i];
214  }
215  *trg++ = 0xFFFFu;
216  }
217  }
218  }
219  else if (color_type == PNG_COLOR_TYPE_GRAY)
220  {
221  texture = std::make_shared<Texture2>(DF_R16_UNORM, width, height, wantMipmaps);
222  trg = texture->Get<uint16_t>();
223  for (png_uint_32 y = 0; y < height; ++y)
224  {
225  src = reinterpret_cast<uint16_t const*>(rows[y]);
226  for (png_uint_32 x = 0; x < width; ++x)
227  {
228  *trg++ = src[x];
229  }
230  }
231  }
232  else if (color_type == PNG_COLOR_TYPE_GA)
233  {
234  texture = std::make_shared<Texture2>(DF_R16G16_UNORM, width, height, wantMipmaps);
235  trg = texture->Get<uint16_t>();
236  for (png_uint_32 y = 0; y < height; ++y)
237  {
238  src = reinterpret_cast<uint16_t const*>(rows[y]);
239  for (png_uint_32 x = 0; x < width; ++x)
240  {
241  for (int i = 0; i < 2; ++i)
242  {
243  *trg++ = src[2 * x + i];
244  }
245  }
246  }
247  }
248  }
249 
250  return texture;
251 }
252 
253 bool WICFileIO::SaveToPNG(std::string const& filename, std::shared_ptr<Texture2> const& texture)
254 {
255  if (!texture)
256  {
257  return false;
258  }
259 
260  int bit_depth = 0;
261  int color_type = 0;
262  png_uint_32 bytes_per_pixel = 0;
263  switch (texture->GetFormat())
264  {
265  case DF_R8G8B8A8_UNORM:
266  {
267  bit_depth = 8;
268  color_type = PNG_COLOR_TYPE_RGBA;
269  bytes_per_pixel = 4;
270  break;
271  }
272  case DF_R8G8_UNORM:
273  bit_depth = 8;
274  color_type = PNG_COLOR_TYPE_GA;
275  bytes_per_pixel = 2;
276  break;
277  case DF_R8_UNORM:
278  bit_depth = 8;
279  color_type = PNG_COLOR_TYPE_GRAY;
280  bytes_per_pixel = 1;
281  break;
283  bit_depth = 16;
284  color_type = PNG_COLOR_TYPE_RGBA;
285  bytes_per_pixel = 8;
286  break;
287  case DF_R16G16_UNORM:
288  bit_depth = 16;
289  color_type = PNG_COLOR_TYPE_GA;
290  bytes_per_pixel = 4;
291  break;
292  case DF_R16_UNORM:
293  bit_depth = 16;
294  color_type = PNG_COLOR_TYPE_GRAY;
295  bytes_per_pixel = 2;
296  break;
297  default: // unsupported format
298  return false;
299  }
300 
301  // The destructor for the helper will be called on any return from
302  // this function after the constructor call.
303  WICFileIOPrivateHelper helper(filename.c_str(), false);
304  if (!helper.fp)
305  {
306  return false;
307  }
308 
309  helper.png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
310  if (!helper.png_ptr)
311  {
312  return false;
313  }
314 
315  helper.info_ptr = png_create_info_struct(helper.png_ptr);
316  if (!helper.info_ptr)
317  {
318  return false;
319  }
320 
321  if (setjmp(png_jmpbuf(helper.png_ptr)))
322  {
323  return false;
324  }
325 
326  png_init_io(helper.png_ptr, helper.fp);
327 
328  png_uint_32 width = texture->GetWidth();
329  png_uint_32 height = texture->GetHeight();
330  int interlace_method = PNG_INTERLACE_NONE;
331  int compression_method = PNG_COMPRESSION_TYPE_BASE;
332  int filter_method = PNG_FILTER_TYPE_BASE;
333 
334  png_set_IHDR(helper.png_ptr, helper.info_ptr, width, height, bit_depth,
335  color_type, interlace_method, compression_method, filter_method);
336 
337  std::vector<uint8_t*> row_pointers(height);
338  uint8_t* texels = texture->Get<uint8_t>();
339  for (png_uint_32 y = 0; y < height; ++y)
340  {
341  row_pointers[y] = texels + y * width * bytes_per_pixel;
342  }
343 
344  png_write_info(helper.png_ptr, helper.info_ptr);
345  png_write_image(helper.png_ptr, row_pointers.data());
346  png_write_end(helper.png_ptr, helper.info_ptr);
347  return true;
348 }
WICFileIOPrivateHelper(char const *name, bool readMode)
GLint GLsizei width
Definition: glcorearb.h:98
GLenum src
Definition: glcorearb.h:1788
GLuint const GLchar * name
Definition: glcorearb.h:781
GLint GLenum GLint x
Definition: glcorearb.h:404
DF_R8_UNORM
Definition: GteDataFormat.h:20
GLsizei const GLchar *const * string
Definition: glcorearb.h:809
GLuint texture
Definition: glcorearb.h:410
DF_R16G16B16A16_UNORM
Definition: GteDataFormat.h:20
GLint GLsizei GLsizei height
Definition: glcorearb.h:98
DF_R8G8B8A8_UNORM
Definition: GteDataFormat.h:20
static std::shared_ptr< Texture2 > Load(std::string const &filename, bool wantMipmaps)
DF_R16G16_UNORM
Definition: GteDataFormat.h:20
static bool SaveToPNG(std::string const &filename, std::shared_ptr< Texture2 > const &texture)
DF_R16_UNORM
Definition: GteDataFormat.h:20
GLint y
Definition: glcorearb.h:98
DF_R8G8_UNORM
Definition: GteDataFormat.h:20


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:02