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." 24 # include <vcl_msvc_warnings.h> 27 #include <vxl_config.h> 30 #define SIG_CHECK_SIZE 4 35 static bool problem(
char const* msg)
37 std::cerr <<
"[vil_png: PROBLEM " <<msg <<
']';
46 problem(
"Initial header fread");
50 if (png_sig_cmp (sig_buf, (png_size_t) 0, (png_size_t)
SIG_CHECK_SIZE) != 0)
67 std::cout<<
"ERROR! vil_png_file_format::make_output_image()\n" 68 <<
"Pixel format should be byte, but is "<<format<<
" instead.\n";
82 static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
84 auto* f = static_cast<vil_stream*>(png_get_io_ptr(png_ptr));
85 f->read(data, length);
88 static void user_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
90 auto* f = static_cast<vil_stream*>(png_get_io_ptr(png_ptr));
91 f->write(data, length);
94 static void user_flush_data(png_structp )
106 static bool jmpbuf_ok =
false;
109 #define png_setjmp_on(ACTION) \ 112 if (setjmp (pngtopnm_jmpbuf_struct.jmpbuf) != 0) {\ 113 problem("png_setjmp_on");\ 117 #define png_setjmp_off() (jmpbuf_ok = false) 128 static void pngtopnm_error_handler (png_structp png_ptr, png_const_charp msg)
130 std::cerr <<
"vil_png: fatal libpng error: " << msg <<
'\n';
134 std::cerr <<
"vil_png: jmpbuf is pretty far from ok. returning\n";
139 auto *jmpbuf_ptr = static_cast<vil_jmpbuf_wrapper*>(png_get_error_ptr(png_ptr));
140 if (jmpbuf_ptr ==
nullptr) {
141 std::cerr <<
"pnmtopng: EXTREMELY fatal error: jmpbuf unrecoverable; terminating.\n";
145 longjmp(jmpbuf_ptr->jmpbuf, 1);
169 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, &pngtopnm_jmpbuf_struct, pngtopnm_error_handler,
nullptr);
171 png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, &pngtopnm_jmpbuf_struct, pngtopnm_error_handler,
nullptr);
174 problem(
"cannot allocate LIBPNG structure");
180 png_destroy_read_struct(&
png_ptr,
nullptr,
nullptr);
181 problem(
"cannot allocate LIBPNG structures");
195 return ok = problem(
"couldn't allocate space for image");
197 unsigned long linesize;
203 if (png_get_color_type(
png_ptr,
info_ptr) == PNG_COLOR_TYPE_GRAY_ALPHA)
214 rows[0] =
new png_byte[linesize * height];
216 return ok = problem(
"couldn't allocate space for image");
219 for (
unsigned int y = 1; y < height; ++y)
238 assert(
rows !=
nullptr);
299 components_(nplanes),
336 return problem(
"Initial header fread");
339 if (png_sig_cmp (sig_buf, (png_size_t) 0, (png_size_t)
SIG_CHECK_SIZE) != 0) {
341 return problem(
"png_sig_cmp");
353 bool is_bool_image =
false;
356 if (color_type == PNG_COLOR_TYPE_PALETTE) {
357 assert( bit_depth <= 8 );
360 if (color_type == PNG_COLOR_TYPE_GRAY) {
362 is_bool_image =
true;
365 else if (bit_depth < 8)
366 png_set_expand_gray_1_2_4_to_8(
p_->
png_ptr);
370 assert( channels == 1 || channels == 3 );
381 #if VXL_LITTLE_ENDIAN 387 png_color_8p sig_bit;
410 else return problem(
"Bad bit depth");
426 png_set_write_fn(
p_->
png_ptr,
vs_, user_write_data, user_flush_data);
430 color_type = PNG_COLOR_TYPE_RGB_ALPHA;
432 color_type = PNG_COLOR_TYPE_RGB;
434 color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
436 color_type = PNG_COLOR_TYPE_GRAY;
439 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
443 #if VXL_LITTLE_ENDIAN 468 if (!rows)
return nullptr;
471 int bytes_per_pixel = (bit_depth *
p_->
channels + 7) / 8;
484 std::memcpy(reinterpret_cast<char*>(chunk->data()), rows[y0], ny * bytes_per_row_dst);
488 else if (bit_depth==16)
492 std::memcpy(reinterpret_cast<char*>(chunk->data()), rows[y0], ny * bytes_per_row_dst);
496 else if (bit_depth ==8)
498 std::memcpy(reinterpret_cast<char*>(chunk->data()), rows[y0], ny * bytes_per_row_dst);
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);
516 else if (bit_depth==16)
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);
526 else if (bit_depth==8)
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);
539 unsigned x0,
unsigned y0)
547 if (!
p_->
ok)
return false;
552 if (!rows)
return false;
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);
568 for (
unsigned y = 0; y < view.
nj(); ++y)
569 for (
unsigned x=0; x < view.
ni(); ++x)
571 rows[y0+y][(x0+x)*2] = view2(x,y,0);
572 rows[y0+y][(x0+x)*2+1] = view2(x,y,1);
577 for (
unsigned y = 0; y < view.
nj(); ++y)
578 for (
unsigned x=0; x < view.
ni(); ++x)
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);
588 for (
unsigned y = 0; y < view.
nj(); ++y)
589 for (
unsigned x=0; x < view.
ni(); ++x)
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);
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);
610 for (
unsigned y = 0; y < view.
nj(); ++y)
611 for (
unsigned x=0; x < view.
ni(); ++x)
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);
619 for (
unsigned y = 0; y < view.
nj(); ++y)
620 for (
unsigned x=0; x < view.
ni(); ++x)
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);
630 for (
unsigned y = 0; y < view.
nj(); ++y)
631 for (
unsigned x=0; x < view.
ni(); ++x)
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);
Stream interface for VIL image loaders.
An abstract base class of smart pointers to actual image data in memory.
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.
unsigned nplanes() const override
Dimensions: planes x width x height x components.
bool get_property(char const *tag, void *prop=nullptr) const override
Extra property information.
vil_png_image(vil_stream *is)
virtual void seek(vil_streampos position)=0
Goto file pointer.
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.
#define vil_property_quantisation_depth
The quantisation depth of pixel components.
unsigned ni() const
Width.
Stream interface for VIL image loaders.
#define png_setjmp_on(ACTION)
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.
Generic image implementation for PNG files.
vil_png_structures(bool reading)
char const * vil_png_format_tag
void ref()
up/down the reference count.
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 vil_exception_warning(T exception)
Throw an exception indicating a potential problem.
~vil_png_image() override
char const * file_format() const override
Return a string describing the file format.