vil_png.cxx
Go to the documentation of this file.
1 // This is core/vil/file_formats/vil_png.cxx
2 //:
3 // \file
4 // http://www.libpng.org/pub/png/libpng.html
5 
6 #include <cstring>
7 #include <iostream>
8 #include <algorithm>
9 #include <cstdlib>
10 #include "vil_png.h"
11 
12 #include <cassert>
13 
14 #include <vil/vil_stream.h>
15 #include <vil/vil_image_view.h>
16 #include <vil/vil_property.h>
17 #include <vil/vil_exception.h>
18 
19 #include <png.h>
20 #if (PNG_LIBPNG_VER_MAJOR == 0)
21 extern "You need a later libpng. You should rerun CMake, after setting VXL_FORCE_V3P_PNG to ON."
22 #endif
23 #ifdef _MSC_VER
24 # include <vcl_msvc_warnings.h>
25 #endif
26 
27 #include <vxl_config.h>
28 
29 // Constants
30 #define SIG_CHECK_SIZE 4
31 
32 char const* vil_png_format_tag = "png";
33 
34 // Functions
35 static bool problem(char const* msg)
36 {
37  std::cerr << "[vil_png: PROBLEM " <<msg << ']';
38  return false;
39 }
40 
42 {
43  // Attempt to read header
44  png_byte sig_buf [SIG_CHECK_SIZE];
45  if (is->read(sig_buf, SIG_CHECK_SIZE) != SIG_CHECK_SIZE) {
46  problem("Initial header fread");
47  return nullptr;
48  }
49 
50  if (png_sig_cmp (sig_buf, (png_size_t) 0, (png_size_t) SIG_CHECK_SIZE) != 0)
51  return nullptr;
52 
53  return new vil_png_image(is);
54 }
55 
57  unsigned nx,
58  unsigned ny,
59  unsigned nplanes,
60  enum vil_pixel_format format)
61 {
62  if (format != VIL_PIXEL_FORMAT_BYTE &&
63  format != VIL_PIXEL_FORMAT_UINT_16)
64  // FIXME || format != VIL_PIXEL_FORMAT_BOOL
65 
66  {
67  std::cout<<"ERROR! vil_png_file_format::make_output_image()\n"
68  <<"Pixel format should be byte, but is "<<format<<" instead.\n";
69  return nullptr;
70  }
71 
72  return new vil_png_image(vs, nx, ny, nplanes, format);
73 }
74 
75 char const* vil_png_file_format::tag() const
76 {
77  return vil_png_format_tag;
78 }
79 
80 /////////////////////////////////////////////////////////////////////////////
81 
82 static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
83 {
84  auto* f = static_cast<vil_stream*>(png_get_io_ptr(png_ptr));
85  f->read(data, length);
86 }
87 
88 static void user_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
89 {
90  auto* f = static_cast<vil_stream*>(png_get_io_ptr(png_ptr));
91  f->write(data, length);
92 }
93 
94 static void user_flush_data(png_structp /*png_ptr*/)
95 {
96  // IOFile* f = (IOFile*)png_get_io_ptr(png_ptr);
97  // urk. how to flush?
98 }
99 
101 {
102  jmp_buf jmpbuf;
103 };
104 
105 static vil_jmpbuf_wrapper pngtopnm_jmpbuf_struct;
106 static bool jmpbuf_ok = false;
107 
108 // Must be a macro - setjmp needs its stack frame to live
109 #define png_setjmp_on(ACTION) \
110  do {\
111  jmpbuf_ok = true;\
112  if (setjmp (pngtopnm_jmpbuf_struct.jmpbuf) != 0) {\
113  problem("png_setjmp_on");\
114  ACTION;\
115  }\
116  } while (false);
117 #define png_setjmp_off() (jmpbuf_ok = false)
118 
119 // this function, aside from the extra step of retrieving the "error
120 // pointer" (below) and the fact that it exists within the application
121 // rather than within libpng, is essentially identical to libpng's
122 // default error handler. The second point is critical: since both
123 // setjmp() and longjmp() are called from the same code, they are
124 // guaranteed to have compatible notions of how big a jmp_buf is,
125 // regardless of whether _BSD_SOURCE or anything else has (or has not)
126 // been defined.
127 //
128 static void pngtopnm_error_handler (png_structp png_ptr, png_const_charp msg)
129 {
130  std::cerr << "vil_png: fatal libpng error: " << msg << '\n';
131 
132  if (!jmpbuf_ok) {
133  // Someone called the error handler when the setjmp was wrong
134  std::cerr << "vil_png: jmpbuf is pretty far from ok. returning\n";
135  // std::abort();
136  return;
137  }
138 
139  auto *jmpbuf_ptr = static_cast<vil_jmpbuf_wrapper*>(png_get_error_ptr(png_ptr));
140  if (jmpbuf_ptr == nullptr) { // we are completely hosed now
141  std::cerr << "pnmtopng: EXTREMELY fatal error: jmpbuf unrecoverable; terminating.\n";
142  std::exit(99);
143  }
144 
145  longjmp(jmpbuf_ptr->jmpbuf, 1);
146 }
147 
149 {
150  bool reading_;
151  png_struct *png_ptr;
152  png_info *info_ptr;
153  png_byte **rows;
154  int channels;
155  bool ok;
156 
157  vil_png_structures(bool reading)
158  {
159  reading_ = reading;
160  png_ptr = nullptr;
161  info_ptr = nullptr;
162  rows = nullptr;
163  channels = 0;
164  ok = false;
165 
166  png_setjmp_on(return);
167 
168  if (reading)
169  png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, &pngtopnm_jmpbuf_struct, pngtopnm_error_handler, nullptr);
170  else
171  png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, &pngtopnm_jmpbuf_struct, pngtopnm_error_handler, nullptr);
172 
173  if (!png_ptr) {
174  problem("cannot allocate LIBPNG structure");
175  return;
176  }
177 
178  info_ptr = png_create_info_struct (png_ptr);
179  if (!info_ptr) {
180  png_destroy_read_struct(&png_ptr, nullptr, nullptr);
181  problem("cannot allocate LIBPNG structures");
182  return;
183  }
184 
185  ok = true;
186 
187  // Now jmpbuf is broken, hope noone calls png....
188  png_setjmp_off();
189  }
190 
191  bool alloc_image()
192  {
193  rows = new png_byte* [png_get_image_height(png_ptr, info_ptr)];
194  if (rows == nullptr)
195  return ok = problem("couldn't allocate space for image");
196 
197  unsigned long linesize;
198  if (png_get_bit_depth(png_ptr, info_ptr) == 16)
199  linesize = 2 * png_get_image_width(png_ptr, info_ptr);
200  else
201  linesize = png_get_image_width(png_ptr, info_ptr);
202 
203  if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_GRAY_ALPHA)
204  linesize *= 2;
205  else
206  if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGB)
207  linesize *= 3;
208  else
209  if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGB_ALPHA)
210  linesize *= 4;
211 
212  unsigned int height = png_get_image_height(png_ptr,info_ptr);
213  // Alloc the whole thing at once
214  rows[0] = new png_byte[linesize * height];
215  if (!rows[0])
216  return ok = problem("couldn't allocate space for image");
217 
218  // Re-point rows.
219  for (unsigned int y = 1; y < height; ++y)
220  rows[y] = rows[0] + y * linesize;
221 
222  return true;
223  }
224 
225  png_byte** get_rows()
226  {
227  if (reading_) {
228  if (!rows) {
229  if (alloc_image()) {
230  png_setjmp_on(return nullptr);
231  png_read_image (png_ptr, rows);
232  png_read_end (png_ptr, info_ptr);
233  png_setjmp_off();
234  }
235  }
236  }
237  else {
238  assert(rows != nullptr);
239  }
240 
241  return rows;
242  }
243 
245  {
246  png_setjmp_on(goto del);
247  if (reading_) {
248  // Reading - just delete
249  png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp)nullptr);
250  }
251  else {
252  // Writing - save the rows
253  png_write_image(png_ptr, rows);
254  png_write_end(png_ptr, info_ptr);
255 
256  png_destroy_write_struct (&png_ptr, &info_ptr);
257  }
258  png_setjmp_off();
259 
260  del:
261  if (rows) {
262  delete [] rows[0];
263  delete [] rows;
264  }
265  }
266 };
267 
268 
269 /////////////////////////////////////////////////////////////////////////////
270 
272 : vs_(is),
273  p_(new vil_png_structures(true))
274 {
275  vs_->ref();
276  read_header();
277 }
278 
279 bool vil_png_image::get_property(char const *key, void * value) const
280 {
281  if (std::strcmp(vil_property_quantisation_depth, key)==0)
282  {
283  if (value)
284  *static_cast<unsigned int*>(value) = bits_per_component_;
285  return true;
286  }
287 
288  return false;
289 }
290 
292  unsigned nx,
293  unsigned ny,
294  unsigned nplanes,
295  enum vil_pixel_format format)
296 : vs_(s),
297  width_(nx),
298  height_(ny),
299  components_(nplanes),
300  format_(format),
301  p_(new vil_png_structures(false))
302 {
303  if (format == VIL_PIXEL_FORMAT_BOOL) bits_per_component_ = 1;
305 
306  vs_->ref();
307  write_header();
308  assert(format == VIL_PIXEL_FORMAT_BYTE ||
309  format == VIL_PIXEL_FORMAT_UINT_16);
310  // FIXME || format == VIL_PIXEL_FORMAT_BOOL
311 }
312 
314 {
315  delete p_;
316  vs_->unref();
317 }
318 
319 
320 char const* vil_png_image::file_format() const
321 {
322  return vil_png_format_tag;
323 }
324 
326 {
327  if (!p_->ok)
328  return false;
329 
330  png_setjmp_on(return false);
331 
332  vs_->seek(0L);
333  png_byte sig_buf [SIG_CHECK_SIZE];
334  if (vs_->read(sig_buf, SIG_CHECK_SIZE) != SIG_CHECK_SIZE) {
335  png_setjmp_off();
336  return problem("Initial header fread");
337  }
338 
339  if (png_sig_cmp (sig_buf, (png_size_t) 0, (png_size_t) SIG_CHECK_SIZE) != 0) {
340  png_setjmp_off();
341  return problem("png_sig_cmp");
342  }
343 
344  //
345  // First read info
346  png_set_read_fn(p_->png_ptr, vs_, user_read_data);
347  png_set_sig_bytes (p_->png_ptr, SIG_CHECK_SIZE);
348  png_read_info (p_->png_ptr, p_->info_ptr);
349 
350 
351  png_byte const color_type = png_get_color_type(p_->png_ptr, p_->info_ptr);
352  png_byte const bit_depth = png_get_bit_depth(p_->png_ptr, p_->info_ptr); // valid values are 1, 2, 4, 8, or 16
353  bool is_bool_image = false;
354 
355 #if 1
356  if (color_type == PNG_COLOR_TYPE_PALETTE) {
357  assert( bit_depth <= 8 ); // valid bit depth 1, 2, 4, 8
358  png_set_palette_to_rgb(p_->png_ptr);
359  }
360  if (color_type == PNG_COLOR_TYPE_GRAY) {
361  if (bit_depth==1) { //treat 1-bit image as bool image
362  is_bool_image = true;
363  png_set_packing(p_->png_ptr); // This code expands pixels per byte without changing the values of the pixels"
364  }
365  else if (bit_depth < 8) // treat these images as 8-bit greyscale image
366  png_set_expand_gray_1_2_4_to_8(p_->png_ptr);
367  }
368  if (png_get_valid(p_->png_ptr, p_->info_ptr, PNG_INFO_tRNS)) {
369  int channels = png_get_channels(p_->png_ptr, p_->info_ptr);
370  assert( channels == 1 || channels == 3 );
371  png_set_tRNS_to_alpha(p_->png_ptr);
372  }
373 #else
374  // According to manual:
375  // "This code expands ... per byte without changing the values of the pixels"
376  // But this is not desired if it has palette
377  if (png_get_bit_depth(p_->png_ptr, p_->info_ptr) < 8)
378  png_set_packing (p_->png_ptr);
379 #endif
380 
381 #if VXL_LITTLE_ENDIAN
382  // PNG stores data MSB
383  if ( png_get_bit_depth(p_->png_ptr, p_->info_ptr) > 8 )
384  png_set_swap(p_->png_ptr);
385 #endif
386 
387  png_color_8p sig_bit;
388  if (png_get_valid(p_->png_ptr, p_->info_ptr, PNG_INFO_sBIT) && png_get_sBIT(p_->png_ptr, p_->info_ptr, &sig_bit)) {
389  png_set_shift(p_->png_ptr, sig_bit);
390  }
391 
392  //
393  // Update the info after putting in all these transforms
394  // From this point on, the info reflects not the raw image,
395  // but the image after transform and to be read.
396  png_read_update_info(p_->png_ptr, p_->info_ptr);
397 
398  this->width_ = png_get_image_width(p_->png_ptr, p_->info_ptr);
399  this->height_ = png_get_image_height(p_->png_ptr, p_->info_ptr);
400  this->components_ = p_->channels = png_get_channels(p_->png_ptr, p_->info_ptr);
401  this->bits_per_component_ = png_get_bit_depth(p_->png_ptr, p_->info_ptr);
402 
403  // Set bits_per_component_ back to 1 for bool image
404  if (is_bool_image)
405  this->bits_per_component_ = 1;
406 
410  else return problem("Bad bit depth");
411 
412  // if (p->info_ptr->valid & PNG_INFO_bKGD) problem("LAZY AWF! PNG_INFO_bKGD");
413  png_setjmp_off();
414  return true;
415 }
416 
418 {
419  if (!p_->ok)
420  return false;
421 
422  png_setjmp_on( return false );
423 
424  vs_->seek(0L);
425 
426  png_set_write_fn(p_->png_ptr, vs_, user_write_data, user_flush_data);
427 
428  int color_type;
429  if (components_ == 4)
430  color_type = PNG_COLOR_TYPE_RGB_ALPHA;
431  else if (components_ == 3)
432  color_type = PNG_COLOR_TYPE_RGB;
433  else if (components_ == 2)
434  color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
435  else
436  color_type = PNG_COLOR_TYPE_GRAY;
437 
438  png_set_IHDR(p_->png_ptr, p_->info_ptr, width_, height_, bits_per_component_, color_type,
439  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
440 
441  png_write_info(p_->png_ptr, p_->info_ptr);
442 
443 #if VXL_LITTLE_ENDIAN
444  // PNG stores data MSB
445  if ( bits_per_component_ > 8 )
446  png_set_swap(p_->png_ptr);
447 #endif
448 
449  // Make memory image
451  p_->alloc_image();
452 
453  png_setjmp_off();
454 
455  return true;
456 }
457 
459  unsigned nx,
460  unsigned y0,
461  unsigned ny) const
462 {
463  if (!p_->ok)
464  return nullptr;
465 
466  // PNG lib wants everything in memory - the first get_rows reads the whole image.
467  png_byte** rows = p_->get_rows();
468  if (!rows) return nullptr;
469 
470  int bit_depth = bits_per_component_; // value can be 1, 8, or 16
471  int bytes_per_pixel = (bit_depth * p_->channels + 7) / 8;
472  int bytes_per_row_dst = nx*nplanes() * vil_pixel_format_sizeof_components(format_);
473 
474  vil_memory_chunk_sptr chunk = new vil_memory_chunk(ny*bytes_per_row_dst, format_);
475 
476  if (nx == png_get_image_width(p_->png_ptr, p_->info_ptr))
477  {
478  assert(x0 == 0);
479 
480  if (bit_depth==1)
481  {
483 
484  std::memcpy(reinterpret_cast<char*>(chunk->data()), rows[y0], ny * bytes_per_row_dst);
485  return new vil_image_view<bool>(chunk, reinterpret_cast<bool*>(chunk->data()),
486  nx, ny, nplanes(), nplanes(), nplanes()*nx, 1);
487  }
488  else if (bit_depth==16)
489  {
491 
492  std::memcpy(reinterpret_cast<char*>(chunk->data()), rows[y0], ny * bytes_per_row_dst);
493  return new vil_image_view<vxl_uint_16>(chunk, reinterpret_cast<vxl_uint_16*>(chunk->data()),
494  nx, ny, nplanes(), nplanes(), nplanes()*nx, 1);
495  }
496  else if (bit_depth ==8)
497  {
498  std::memcpy(reinterpret_cast<char*>(chunk->data()), rows[y0], ny * bytes_per_row_dst);
499  return new vil_image_view<vxl_byte>(chunk, reinterpret_cast<vxl_byte*>(chunk->data()),
500  nx, ny, nplanes(), nplanes(), nplanes()*nx, 1);
501  }
502  else return nullptr;
503  }
504  else // not whole row
505  {
506  if (bit_depth==1)
507  {
509 
510  auto* dst = reinterpret_cast<png_byte*>(chunk->data());
511  for (unsigned y = 0; y < ny; ++y, dst += bytes_per_row_dst)
512  std::memcpy(dst, &rows[y0+y][x0*bytes_per_pixel], nx*bytes_per_pixel);
513  return new vil_image_view<bool>(chunk, reinterpret_cast<bool*>(chunk->data()),
514  nx, ny, nplanes(), nplanes(), nplanes()*nx, 1);
515  }
516  else if (bit_depth==16)
517  {
519 
520  auto* dst = reinterpret_cast<png_byte*>(chunk->data());
521  for (unsigned y = 0; y < ny; ++y, dst += bytes_per_row_dst)
522  std::memcpy(dst, &rows[y0+y][x0*bytes_per_pixel], nx*bytes_per_pixel);
523  return new vil_image_view<vxl_uint_16>(chunk, reinterpret_cast<vxl_uint_16*>(chunk->data()),
524  nx, ny, nplanes(), nplanes(), nplanes()*nx, 1);
525  }
526  else if (bit_depth==8)
527  {
528  auto* dst = reinterpret_cast<png_byte*>(chunk->data());
529  for (unsigned y = 0; y < ny; ++y, dst += bytes_per_row_dst)
530  std::memcpy(dst, &rows[y0+y][x0*bytes_per_pixel], nx*bytes_per_pixel);
531  return new vil_image_view<vxl_byte>(chunk, reinterpret_cast<vxl_byte*>(chunk->data()),
532  nx, ny, nplanes(), nplanes(), nplanes()*nx, 1);
533  }
534  else return nullptr;
535  }
536 }
537 
539  unsigned x0, unsigned y0)
540 {
541  if (!view_fits(view, x0, y0))
542  {
543  vil_exception_warning(vil_exception_out_of_bounds("vil_png_image::put_view"));
544  return false;
545  }
546 
547  if (!p_->ok) return false;
548 
549  // PNG lib wants everything in memory - the writing isn't done till this image is deleted.
550 
551  png_byte** rows = p_->get_rows();
552  if (!rows) return false;
553 
554  // int bytes_per_pixel = bit_depth * p_->channels / 8;
555  // int bytes_per_row_dst = view.ni()*bytes_per_pixel;
556  if (bits_per_component_ == 8)
557  {
558  if (view.pixel_format() != VIL_PIXEL_FORMAT_BYTE) return false;
559  const auto &view2 = static_cast<const vil_image_view<vxl_byte>&>(view);
560  if (nplanes()==1)
561  {
562  for (unsigned y = 0; y < view.nj(); ++y)
563  for (unsigned x=0; x < view.ni(); ++x)
564  rows[y0+y][x0+x] = view2(x,y);
565  }
566  else if (nplanes()==2)
567  {
568  for (unsigned y = 0; y < view.nj(); ++y)
569  for (unsigned x=0; x < view.ni(); ++x)
570  {
571  rows[y0+y][(x0+x)*2] = view2(x,y,0);
572  rows[y0+y][(x0+x)*2+1] = view2(x,y,1);
573  }
574  }
575  else if (nplanes()==3)
576  {
577  for (unsigned y = 0; y < view.nj(); ++y)
578  for (unsigned x=0; x < view.ni(); ++x)
579  {
580  rows[y0+y][(x0+x)*3] = view2(x,y,0);
581  rows[y0+y][(x0+x)*3+1] = view2(x,y,1);
582  rows[y0+y][(x0+x)*3+2] = view2(x,y,2);
583  }
584  }
585  else
586  {
587  assert(nplanes() == 4);
588  for (unsigned y = 0; y < view.nj(); ++y)
589  for (unsigned x=0; x < view.ni(); ++x)
590  {
591  rows[y0+y][(x0+x)*4] = view2(x,y,0);
592  rows[y0+y][(x0+x)*4+1] = view2(x,y,1);
593  rows[y0+y][(x0+x)*4+2] = view2(x,y,2);
594  rows[y0+y][(x0+x)*4+3] = view2(x,y,3);
595  }
596  }
597  }
598  else if (bits_per_component_ == 16)
599  {
600  if (view.pixel_format() != VIL_PIXEL_FORMAT_UINT_16) return false;
601  const auto &view2 = static_cast<const vil_image_view<vxl_uint_16>&>(view);
602  if (nplanes()==1)
603  {
604  for (unsigned y = 0; y < view.nj(); ++y)
605  for (unsigned x=0; x < view.ni(); ++x)
606  *reinterpret_cast<vxl_uint_16*>(&rows[y0+y][(x0+x)*2]) = view2(x,y);
607  }
608  else if (nplanes() == 2)
609  {
610  for (unsigned y = 0; y < view.nj(); ++y)
611  for (unsigned x=0; x < view.ni(); ++x)
612  {
613  *reinterpret_cast<vxl_uint_16*>(&rows[y0+y][(x0+x)*4]) = view2(x,y,0);
614  *reinterpret_cast<vxl_uint_16*>(&rows[y0+y][(x0+x)*4+2]) = view2(x,y,1);
615  }
616  }
617  else if (nplanes() == 3)
618  {
619  for (unsigned y = 0; y < view.nj(); ++y)
620  for (unsigned x=0; x < view.ni(); ++x)
621  {
622  *reinterpret_cast<vxl_uint_16*>(&rows[y0+y][(x0+x)*6]) = view2(x,y,0);
623  *reinterpret_cast<vxl_uint_16*>(&rows[y0+y][(x0+x)*6+2]) = view2(x,y,1);
624  *reinterpret_cast<vxl_uint_16*>(&rows[y0+y][(x0+x)*6+4]) = view2(x,y,2);
625  }
626  }
627  else
628  {
629  assert(nplanes() == 4);
630  for (unsigned y = 0; y < view.nj(); ++y)
631  for (unsigned x=0; x < view.ni(); ++x)
632  {
633  *reinterpret_cast<vxl_uint_16*>(&rows[y0+y][(x0+x)*8]) = view2(x,y,0);
634  *reinterpret_cast<vxl_uint_16*>(&rows[y0+y][(x0+x)*8+2]) = view2(x,y,1);
635  *reinterpret_cast<vxl_uint_16*>(&rows[y0+y][(x0+x)*8+4]) = view2(x,y,2);
636  *reinterpret_cast<vxl_uint_16*>(&rows[y0+y][(x0+x)*8+6]) = view2(x,y,3);
637  }
638  }
639  }
640  // FIXME else if (bit_depth=1)
641  else return false;
642 
643  return true;
644 }
vil_image_resource_sptr make_input_image(vil_stream *vs) override
Attempt to make a generic_image which will read from vil_stream vs.
Definition: vil_png.cxx:41
Stream interface for VIL image loaders.
An abstract base class of smart pointers to actual image data in memory.
vil_pixel_format
Describes the type of the concrete data.
virtual bool view_fits(const vil_image_view_base &im, unsigned i0, unsigned j0)
Check that a view will fit into the data at the given offset.
png_struct * png_ptr
Definition: vil_png.cxx:151
unsigned nplanes() const override
Dimensions: planes x width x height x components.
Definition: vil_png.h:57
vil_stream * vs_
Definition: vil_png.h:36
bool get_property(char const *tag, void *prop=nullptr) const override
Extra property information.
Definition: vil_png.cxx:279
int bits_per_component_
Definition: vil_png.h:40
png_byte ** get_rows()
Definition: vil_png.cxx:225
vil_png_image(vil_stream *is)
Definition: vil_png.cxx:271
bool write_header()
Definition: vil_png.cxx:417
int components_
Definition: vil_png.h:39
virtual void seek(vil_streampos position)=0
Goto file pointer.
int height_
Definition: vil_png.h:38
int width_
Definition: vil_png.h:37
png_byte ** rows
Definition: vil_png.cxx:153
virtual vil_streampos read(void *buf, vil_streampos n)=0
Read n bytes into buf. Returns number of bytes read.
Exceptions thrown by vil, and a mechanism for turning them off.
bool put_view(const vil_image_view_base &im, unsigned i0, unsigned j0) override
Put the data in this view back into the image source.
Definition: vil_png.cxx:538
unsigned vil_pixel_format_sizeof_components(enum vil_pixel_format f)
Return the number of bytes used by each component of pixel format f.
#define vil_property_quantisation_depth
The quantisation depth of pixel components.
Definition: vil_property.h:67
vil_png_structures * p_
Definition: vil_png.h:47
unsigned ni() const
Width.
Stream interface for VIL image loaders.
Definition: vil_stream.h:21
#define png_setjmp_on(ACTION)
Definition: vil_png.cxx:109
unsigned nj() const
Height.
virtual enum vil_pixel_format pixel_format() const =0
Return a description of the concrete data pixel type.
Indicates that some reference was made to pixels beyond the bounds of an image.
Definition: vil_exception.h:81
Generic image implementation for PNG files.
Definition: vil_png.h:34
bool read_header()
Definition: vil_png.cxx:325
#define png_setjmp_off()
Definition: vil_png.cxx:117
vil_png_structures(bool reading)
Definition: vil_png.cxx:157
char const * vil_png_format_tag
Definition: vil_png.cxx:32
void ref()
up/down the reference count.
Definition: vil_stream.h:45
vil_image_view_base_sptr get_copy_view() const
Create a read/write view of a copy of all the data.
A base class reference-counting view of some image data.
There is no class or function called vil_property.
Ref. counted block of data on the heap.
void unref()
Definition: vil_stream.cxx:31
vil_image_resource_sptr make_output_image(vil_stream *vs, unsigned nx, unsigned ny, unsigned nplanes, enum vil_pixel_format) override
Make a "generic_image" on which put_section may be applied.
Definition: vil_png.cxx:56
png_info * info_ptr
Definition: vil_png.cxx:152
void vil_exception_warning(T exception)
Throw an exception indicating a potential problem.
Definition: vil_exception.h:37
vil_pixel_format format_
Definition: vil_png.h:41
char const * tag() const override
Return a character string which uniquely identifies this format.
Definition: vil_png.cxx:75
#define SIG_CHECK_SIZE
Definition: vil_png.cxx:30
~vil_png_image() override
Definition: vil_png.cxx:313
char const * file_format() const override
Return a string describing the file format.
Definition: vil_png.cxx:320