From 0f552832da24a826c671bb335884c7e08e29dc48 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Fri, 18 May 2018 18:11:29 +0200 Subject: [PATCH] PNG conversion and parallel execution working. --- xs/src/agg/copying | 65 +++ xs/src/libslic3r/Print.cpp | 58 +-- xs/src/libslic3r/Print.hpp | 2 +- xs/src/libslic3r/Rasterizer/Rasterizer.cpp | 43 +- xs/src/png/COPYING | 25 ++ xs/src/png/color.hpp | 65 +++ xs/src/png/end_info.hpp | 74 ++++ xs/src/png/error.hpp | 118 ++++++ xs/src/png/image_info.hpp | 215 ++++++++++ xs/src/png/info.hpp | 186 ++++++++ xs/src/png/info_base.hpp | 77 ++++ xs/src/png/io_base.hpp | 467 +++++++++++++++++++++ xs/src/png/palette.hpp | 48 +++ xs/src/png/pixel_traits.hpp | 103 +++++ xs/src/png/tRNS.hpp | 48 +++ xs/src/png/types.hpp | 120 ++++++ xs/src/png/writer.hpp | 199 +++++++++ 17 files changed, 1876 insertions(+), 37 deletions(-) create mode 100644 xs/src/agg/copying create mode 100644 xs/src/png/COPYING create mode 100644 xs/src/png/color.hpp create mode 100644 xs/src/png/end_info.hpp create mode 100644 xs/src/png/error.hpp create mode 100644 xs/src/png/image_info.hpp create mode 100644 xs/src/png/info.hpp create mode 100644 xs/src/png/info_base.hpp create mode 100644 xs/src/png/io_base.hpp create mode 100644 xs/src/png/palette.hpp create mode 100644 xs/src/png/pixel_traits.hpp create mode 100644 xs/src/png/tRNS.hpp create mode 100644 xs/src/png/types.hpp create mode 100644 xs/src/png/writer.hpp diff --git a/xs/src/agg/copying b/xs/src/agg/copying new file mode 100644 index 0000000000..b6028e5195 --- /dev/null +++ b/xs/src/agg/copying @@ -0,0 +1,65 @@ +The Anti-Grain Geometry Project +A high quality rendering engine for C++ +http://antigrain.com + +Anti-Grain Geometry has dual licensing model. The Modified BSD +License was first added in version v2.4 just for convenience. +It is a simple, permissive non-copyleft free software license, +compatible with the GNU GPL. It's well proven and recognizable. +See http://www.fsf.org/licensing/licenses/index_html#ModifiedBSD +for details. + +Note that the Modified BSD license DOES NOT restrict your rights +if you choose the Anti-Grain Geometry Public License. + + + + +Anti-Grain Geometry Public License +==================================================== + +Anti-Grain Geometry - Version 2.4 +Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) + +Permission to copy, use, modify, sell and distribute this software +is granted provided this copyright notice appears in all copies. +This software is provided "as is" without express or implied +warranty, and with no claim as to its suitability for any purpose. + + + + + +Modified BSD License +==================================================== +Anti-Grain Geometry - Version 2.4 +Copyright (C) 2002-2005 Maxim Shemanarev (McSeem) + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + 3. The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 7477a97362..5d596f9e6d 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -11,17 +11,17 @@ #include #include + // For png export of the sliced model #include #include -#include -#include -#include -#include +//#include +//#include +//#include +//#include #include "Rasterizer/Rasterizer.hpp" - -#include +#include "tbb/parallel_for.h" namespace Slic3r { @@ -1265,6 +1265,7 @@ public: void finishLayer(unsigned layer); void finishLayer(); void save(const std::string& path); + void saveLayer(unsigned lyr, const std::string& path); }; template<> @@ -1306,13 +1307,15 @@ public: inline void finishLayer(unsigned lyr_id) { assert(lyr_id < layers_rst_.size()); - layers_rst_[lyr_id].first.save(layers_rst_[lyr_id].second); + layers_rst_[lyr_id].first.save(layers_rst_[lyr_id].second, + Raster::Compression::PNG); layers_rst_[lyr_id].first.reset(); } inline void finishLayer() { if(!layers_rst_.empty()) { - layers_rst_.back().first.save(layers_rst_.back().second); + layers_rst_.back().first.save(layers_rst_.back().second, + Raster::Compression::PNG); layers_rst_.back().first.reset(); } } @@ -1320,17 +1323,28 @@ public: inline void save(const std::string& path) { for(unsigned i = 0; i < layers_rst_.size(); i++) { if(layers_rst_[i].second.rdbuf()->in_avail() > 0) { - std::string loc = path + "layer" + std::to_string(i) + ".pgm"; + std::string loc = path + "layer" + std::to_string(i) + ".png"; std::fstream out(loc, std::fstream::out | std::fstream::binary); if(out.good()) { out << layers_rst_[i].second.rdbuf(); } out.close(); - layers_rst_[i].first.reset(); layers_rst_[i].second.str(""); } } } + + void saveLayer(unsigned lyr, const std::string& path) { + unsigned i = lyr; + assert(i < layers_rst_.size()); + std::string loc = path + "layer" + std::to_string(i) + ".png"; + std::fstream out(loc, std::fstream::out | std::fstream::binary); + if(out.good()) { + layers_rst_[i].first.save(out, Raster::Compression::PNG); + } + out.close(); + layers_rst_[i].first.reset(); + } }; //template<> @@ -1408,17 +1422,15 @@ void Print::print_to(std::string dirpath, Args...args) return l1->print_z < l2->print_z; }); - ExPolygons previous_layer_slices; auto print_bb = bounding_box(); FilePrinter printer(std::forward(args)...); printer.layers(layers.size()); -#pragma omp parallel for /*num_threads(8)*/ - for(int layer_id = 0; layer_id < layers.size(); layer_id++) { + auto process_layer = [&layers, &printer, print_bb, dir] (unsigned layer_id) { Layer& l = *(layers[layer_id]); - auto slices = l.slices; + ExPolygonCollection slices = l.slices; using Sl = ExPolygons::value_type; std::sort(slices.expolygons.begin(), slices.expolygons.end(), @@ -1426,14 +1438,7 @@ void Print::print_to(std::string dirpath, Args...args) return a.contains(b.contour.first_point()) ? false : true; }); - ExPolygons current_layer_slices; - - try { - printer.beginLayer(layer_id); - } catch(std::bad_alloc& ) { - printer.save(dir); - printer.beginLayer(layer_id); - } + printer.beginLayer(layer_id); std::for_each(l.object()->_shifted_copies.begin(), l.object()->_shifted_copies.end(), @@ -1447,18 +1452,15 @@ void Print::print_to(std::string dirpath, Args...args) slice.translate(-print_bb.min.x, -print_bb.min.y); printer.drawPolygon(slice, layer_id); - - current_layer_slices.push_back(slice); }); }); printer.finishLayer(layer_id); +// printer.saveLayer(layer_id, dir); - std::cout << "processed layer: " << layer_id << " by thread: " - << omp_get_thread_num() << std::endl; + }; - previous_layer_slices = current_layer_slices; - } + tbb::parallel_for(0, layers.size(), process_layer); printer.save(dir); } diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index fc2cf2b202..2409b6f4fc 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -323,7 +323,7 @@ public: void print_to_png(std::string dirpath) { // Where should this be specified? - print_to_png(dirpath, 2560, 1440, 70.0, 40.0); + print_to_png(dirpath, 1440, 2560, 40.0, 72.0); } private: diff --git a/xs/src/libslic3r/Rasterizer/Rasterizer.cpp b/xs/src/libslic3r/Rasterizer/Rasterizer.cpp index bd27278ed6..5b0719ecfd 100644 --- a/xs/src/libslic3r/Rasterizer/Rasterizer.cpp +++ b/xs/src/libslic3r/Rasterizer/Rasterizer.cpp @@ -1,5 +1,4 @@ #include "Rasterizer.hpp" - #include // For rasterizing @@ -16,7 +15,13 @@ #include // For compression -#include +#ifdef WIN32 +inline char *strerror_r(int errnum, char *buf, size_t buflen) { + strerror_s(buf, buflen, errnum); + return buf; +} +#endif +#include namespace Slic3r { @@ -77,7 +82,7 @@ public: raw_renderer_.clear(ColorBlack); } - inline const TBuffer& buffer() const { return buf_; } + inline TBuffer& buffer() { return buf_; } inline const Raster::Resolution resolution() { return resolution_; } @@ -153,16 +158,38 @@ void Raster::save(std::ostream& stream, Compression comp) { assert(impl_); switch(comp) { - case Compression::PNG: - case Compression::RAW: + case Compression::PNG: { + + png::writer wr(stream); + + wr.set_bit_depth(8); + wr.set_color_type(png::color_type_gray); + wr.set_width(resolution().width_px); + wr.set_height(resolution().height_px); + wr.set_compression_type(png::compression_type_default); + + wr.write_info(); + + auto& b = impl_->buffer(); + auto ptr = reinterpret_cast( b.data() ); + unsigned stride = + sizeof(Impl::TBuffer::value_type) * resolution().width_px; + + for(unsigned r = 0; r < resolution().height_px; r++, ptr+=stride) { + wr.write_row(ptr); + } + + break; + } + case Compression::RAW: { stream << "P5 " << impl_->resolution().width_px << " " << impl_->resolution().height_px << " " << "255 "; + stream.write(reinterpret_cast(impl_->buffer().data()), + impl_->buffer().size()*sizeof(Impl::TBuffer::value_type)); + } } - - stream.write(reinterpret_cast(impl_->buffer().data()), - impl_->buffer().size()*sizeof(Impl::TBuffer::value_type)); } } diff --git a/xs/src/png/COPYING b/xs/src/png/COPYING new file mode 100644 index 0000000000..04889ba11d --- /dev/null +++ b/xs/src/png/COPYING @@ -0,0 +1,25 @@ +Copying png++ is subject to the following license: + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/xs/src/png/color.hpp b/xs/src/png/color.hpp new file mode 100644 index 0000000000..b5ffde2c4e --- /dev/null +++ b/xs/src/png/color.hpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2007,2008 Alex Shulgin + * + * This file is part of png++ the C++ wrapper for libpng. PNG++ is free + * software; the exact copying conditions are as follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PNGPP_COLOR_HPP_INCLUDED +#define PNGPP_COLOR_HPP_INCLUDED + +#include "types.hpp" + +namespace png +{ + + /** + * \brief PNG color struct extension. Adds constructors. + */ + struct color + : png_color + { + explicit color(byte r = 0, byte g = 0, byte b = 0) + { + this->red = r; + this->green = g; + this->blue = b; + } + + /** + * \brief Initializes color with a copy of png_color object. + */ + color(png_color const& other) + { + this->red = other.red; + this->green = other.green; + this->blue = other.blue; + } + }; + +} // namespace png + +#endif // PNGPP_COLOR_HPP_INCLUDED diff --git a/xs/src/png/end_info.hpp b/xs/src/png/end_info.hpp new file mode 100644 index 0000000000..09590596df --- /dev/null +++ b/xs/src/png/end_info.hpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2007,2008 Alex Shulgin + * + * This file is part of png++ the C++ wrapper for libpng. PNG++ is free + * software; the exact copying conditions are as follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PNGPP_END_INFO_HPP_INCLUDED +#define PNGPP_END_INFO_HPP_INCLUDED + +#include "info_base.hpp" + +namespace png +{ + + /** + * \brief Internal class to hold PNG ending %info. + * + * \see info, info_base + */ + class end_info + : public info_base + { + public: + end_info(io_base& io, png_struct* png) + : info_base(io, png) + { + } + + void destroy() + { + assert(m_info); + png_destroy_info_struct(m_png, & m_info); + } + + void read() + { + png_read_end(m_png, m_info); + } + + void write() const + { + png_write_end(m_png, m_info); + } + + // TODO: add methods to read/write text comments etc. + }; + +} // namespace png + +#endif // PNGPP_END_INFO_HPP_INCLUDED diff --git a/xs/src/png/error.hpp b/xs/src/png/error.hpp new file mode 100644 index 0000000000..834cf1b3a9 --- /dev/null +++ b/xs/src/png/error.hpp @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2007,2008 Alex Shulgin + * + * This file is part of png++ the C++ wrapper for libpng. PNG++ is free + * software; the exact copying conditions are as follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PNGPP_ERROR_HPP_INCLUDED +#define PNGPP_ERROR_HPP_INCLUDED + +/* check if we have strerror_s or strerror_r, prefer the former which is C11 std */ +#ifdef __STDC_LIB_EXT1__ +#define __STDC_WANT_LIB_EXT1__ 1 +#include + +#define HAVE_STRERROR_S 1 +#else +#undef HAVE_STRERROR_S +#endif + +#include +#include +#include +#include +#include + +namespace png +{ + + /** + * \brief Exception class to represent runtime errors related to + * png++ operation. + */ + class error + : public std::runtime_error + { + public: + /** + * \param message error description + */ + explicit error(std::string const& message) + : std::runtime_error(message) + { + } + }; + + /** + * \brief Exception class to represent standard library errors + * (generally IO). + * + * \see reader, writer + */ + class std_error + : public std::runtime_error + { + public: + /** + * Constructs an std_error object. The \a message string is + * appended with ": " and the error description as + * returned by \c strerror(\a error). + * + * \param message error description + * \param error error number + */ + explicit std_error(std::string const& message, int errnum = errno) + : std::runtime_error((message + ": ") + thread_safe_strerror(errnum)) + { + } + + protected: + static std::string thread_safe_strerror(int errnum) + { +#define ERRBUF_SIZE 512 + char buf[ERRBUF_SIZE] = { 0 }; + +#ifdef HAVE_STRERROR_S + strerror_s(buf, ERRBUF_SIZE, errnum); + return std::string(buf); +#else +#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE + strerror_r(errnum, buf, ERRBUF_SIZE); + return std::string(buf); +#else + /* GNU variant can return a pointer to static buffer instead of buf */ + return std::string(strerror_r(errnum, buf, ERRBUF_SIZE)); +#endif +#endif + +#undef ERRBUF_SIZE + } + }; + +} // namespace png + +#endif // PNGPP_ERROR_HPP_INCLUDED diff --git a/xs/src/png/image_info.hpp b/xs/src/png/image_info.hpp new file mode 100644 index 0000000000..8407bc18b8 --- /dev/null +++ b/xs/src/png/image_info.hpp @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2007,2008 Alex Shulgin + * + * This file is part of png++ the C++ wrapper for libpng. PNG++ is free + * software; the exact copying conditions are as follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PNGPP_IMAGE_INFO_HPP_INCLUDED +#define PNGPP_IMAGE_INFO_HPP_INCLUDED + +#include "types.hpp" +#include "palette.hpp" +#include "tRNS.hpp" +#include "pixel_traits.hpp" + +namespace png +{ + + /** + * \brief Holds information about PNG image. + * + * \see image, generator, consumer + */ + class image_info + { + public: + /** + * \brief Constructs the image_info object with default values + * for color_type, interlace_type, compression_method and + * filter_type. + */ + image_info() + : m_width(0), + m_height(0), + m_bit_depth(0), + m_color_type(color_type_none), + m_interlace_type(interlace_none), + m_compression_type(compression_type_default), + m_filter_type(filter_type_default), + m_gamma(0.0) + { + } + + uint_32 get_width() const + { + return m_width; + } + + void set_width(uint_32 width) + { + m_width = width; + } + + uint_32 get_height() const + { + return m_height; + } + + void set_height(uint_32 height) + { + m_height = height; + } + + color_type get_color_type() const + { + return m_color_type; + } + + void set_color_type(color_type color_space) + { + m_color_type = color_space; + } + + int get_bit_depth() const + { + return m_bit_depth; + } + + void set_bit_depth(int bit_depth) + { + m_bit_depth = bit_depth; + } + + interlace_type get_interlace_type() const + { + return m_interlace_type; + } + + void set_interlace_type(interlace_type interlace) + { + m_interlace_type = interlace; + } + + compression_type get_compression_type() const + { + return m_compression_type; + } + + void set_compression_type(compression_type compression) + { + m_compression_type = compression; + } + + filter_type get_filter_type() const + { + return m_filter_type; + } + + void set_filter_type(filter_type filter) + { + m_filter_type = filter; + } + + palette const& get_palette() const + { + return m_palette; + } + + palette& get_palette() + { + return m_palette; + } + + void set_palette(palette const& plte) + { + m_palette = plte; + } + + /** + * \brief Removes all entries from the palette. + */ + void drop_palette() + { + m_palette.clear(); + } + + tRNS const& get_tRNS() const + { + return m_tRNS; + } + + tRNS& get_tRNS() + { + return m_tRNS; + } + + void set_tRNS(tRNS const& trns) + { + m_tRNS = trns; + } + + double get_gamma() const + { + return m_gamma; + } + + void set_gamma(double gamma) + { + m_gamma = gamma; + } + + protected: + uint_32 m_width; + uint_32 m_height; + int m_bit_depth; + color_type m_color_type; + interlace_type m_interlace_type; + compression_type m_compression_type; + filter_type m_filter_type; + palette m_palette; + tRNS m_tRNS; + double m_gamma; + }; + + /** + * \brief Returns an image_info object with color_type and + * bit_depth fields setup appropriate for the \c pixel type. + */ + template< typename pixel > + image_info + make_image_info() + { + typedef pixel_traits< pixel > traits; + image_info info; + info.set_color_type(traits::get_color_type()); + info.set_bit_depth(traits::get_bit_depth()); + return info; + } + +} // namespace png + +#endif // PNGPP_IMAGE_INFO_HPP_INCLUDED diff --git a/xs/src/png/info.hpp b/xs/src/png/info.hpp new file mode 100644 index 0000000000..3f3cf09c31 --- /dev/null +++ b/xs/src/png/info.hpp @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2007,2008 Alex Shulgin + * + * This file is part of png++ the C++ wrapper for libpng. PNG++ is free + * software; the exact copying conditions are as follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PNGPP_INFO_HPP_INCLUDED +#define PNGPP_INFO_HPP_INCLUDED + +#include +#include "info_base.hpp" +#include "image_info.hpp" + +namespace png +{ + + /** + * \brief Holds information about PNG image. Adapter class for IO + * image operations. + */ + class info + : public info_base, + public image_info + { + public: + info(io_base& io, png_struct* png) + : info_base(io, png) + { + } + + void read() + { + assert(m_png); + assert(m_info); + + png_read_info(m_png, m_info); + png_get_IHDR(m_png, + m_info, + & m_width, + & m_height, + reinterpret_cast< int* >(& m_bit_depth), + reinterpret_cast< int* >(& m_color_type), + reinterpret_cast< int* >(& m_interlace_type), + reinterpret_cast< int* >(& m_compression_type), + reinterpret_cast< int* >(& m_filter_type)); + + if (png_get_valid(m_png, m_info, chunk_PLTE) == chunk_PLTE) + { + png_color* colors = 0; + int count = 0; + png_get_PLTE(m_png, m_info, & colors, & count); + m_palette.assign(colors, colors + count); + } + +#ifdef PNG_tRNS_SUPPORTED + if (png_get_valid(m_png, m_info, chunk_tRNS) == chunk_tRNS) + { + if (m_color_type == color_type_palette) + { + int count; + byte* values; + if (png_get_tRNS(m_png, m_info, & values, & count, NULL) + != PNG_INFO_tRNS) + { + throw error("png_get_tRNS() failed"); + } + m_tRNS.assign(values, values + count); + } + } +#endif + +#ifdef PNG_gAMA_SUPPORTED + if (png_get_valid(m_png, m_info, chunk_gAMA) == chunk_gAMA) + { +#ifdef PNG_FLOATING_POINT_SUPPORTED + if (png_get_gAMA(m_png, m_info, &m_gamma) != PNG_INFO_gAMA) + { + throw error("png_get_gAMA() failed"); + } +#else + png_fixed_point gamma = 0; + if (png_get_gAMA_fixed(m_png, m_info, &gamma) != PNG_INFO_gAMA) + { + throw error("png_get_gAMA_fixed() failed"); + } + m_gamma = gamma / 100000.0; +#endif + } +#endif + } + + void write() const + { + assert(m_png); + assert(m_info); + + sync_ihdr(); + if (m_color_type == color_type_palette) + { + if (! m_palette.empty()) + { + png_set_PLTE(m_png, m_info, + const_cast< color* >(& m_palette[0]), + (int) m_palette.size()); + } + if (! m_tRNS.empty()) + { +#ifdef PNG_tRNS_SUPPORTED + png_set_tRNS(m_png, m_info, + const_cast< byte* >(& m_tRNS[0]), + m_tRNS.size(), + NULL); +#else + throw error("attempted to write tRNS chunk; recompile with PNG_tRNS_SUPPORTED"); +#endif + } + } + + if (m_gamma > 0) + { +#ifdef PNG_gAMA_SUPPORTED +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_gAMA(m_png, m_info, m_gamma); +#else + png_set_gAMA_fixed(m_png, m_info, + (png_fixed_point)(m_gamma * 100000)); +#endif +#else + throw error("attempted to write gAMA chunk; recompile with PNG_gAMA_SUPPORTED"); +#endif + } + + png_write_info(m_png, m_info); + } + + void update() + { + assert(m_png); + assert(m_info); + + sync_ihdr(); + png_read_update_info(m_png, m_info); + } + + protected: + void sync_ihdr(void) const + { + png_set_IHDR(m_png, + m_info, + m_width, + m_height, + m_bit_depth, + m_color_type, + m_interlace_type, + m_compression_type, + m_filter_type); + } + }; + +} // namespace png + +#endif // PNGPP_INFO_HPP_INCLUDED diff --git a/xs/src/png/info_base.hpp b/xs/src/png/info_base.hpp new file mode 100644 index 0000000000..45e1542963 --- /dev/null +++ b/xs/src/png/info_base.hpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2007,2008 Alex Shulgin + * + * This file is part of png++ the C++ wrapper for libpng. PNG++ is free + * software; the exact copying conditions are as follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PNGPP_INFO_BASE_HPP_INCLUDED +#define PNGPP_INFO_BASE_HPP_INCLUDED + +#include +#include "error.hpp" +#include "types.hpp" + +namespace png +{ + + class io_base; + + /** + * \brief Internal class to hold PNG info or end_info. + */ + class info_base + { + info_base(info_base const&); + info_base& operator=(info_base const&); + + public: + info_base(io_base& io, png_struct* png) + : m_io(io), + m_png(png), + m_info(png_create_info_struct(m_png)) + { + } + + png_info* get_png_info() const + { + return m_info; + } + + png_info** get_png_info_ptr() + { + return & m_info; + } + + protected: + io_base& m_io; + png_struct* m_png; + png_info* m_info; + }; + +} // namespace png + +#endif // PNGPP_INFO_BASE_HPP_INCLUDED diff --git a/xs/src/png/io_base.hpp b/xs/src/png/io_base.hpp new file mode 100644 index 0000000000..3c2d830435 --- /dev/null +++ b/xs/src/png/io_base.hpp @@ -0,0 +1,467 @@ +/* + * Copyright (C) 2007,2008 Alex Shulgin + * + * This file is part of png++ the C++ wrapper for libpng. PNG++ is free + * software; the exact copying conditions are as follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PNGPP_IO_BASE_HPP_INCLUDED +#define PNGPP_IO_BASE_HPP_INCLUDED + +#include +#include +#include +#include "error.hpp" +#include "info.hpp" +#include "end_info.hpp" + +static void +trace_io_transform(char const* fmt, ...) +{ +#ifdef DEBUG_IO_TRANSFORM + va_list va; + va_start(va, fmt); + fprintf(stderr, "TRANSFORM_IO: "); + vfprintf(stderr, fmt, va); + va_end(va); +#endif +} +#define TRACE_IO_TRANSFORM trace_io_transform + +namespace png +{ + + /** + * \brief Base class for PNG reader/writer classes. + * + * \see reader, writer + */ + class io_base + { + io_base(io_base const&); + io_base& operator=(io_base const&); + + public: + explicit io_base(png_struct* png) + : m_png(png), + m_info(*this, m_png), + m_end_info(*this, m_png) + { + } + + ~io_base() + { + assert(! m_png); + assert(! m_info.get_png_info()); + assert(! m_end_info.get_png_info()); + } + + png_struct* get_png_struct() const + { + return m_png; + } + + info& get_info() + { + return m_info; + } + + info const& get_info() const + { + return m_info; + } + + image_info const& get_image_info() const + { + return m_info; + } + + void set_image_info(image_info const& info) + { + static_cast< image_info& >(m_info) = info; // slice it + } + + end_info& get_end_info() + { + return m_end_info; + } + + end_info const& get_end_info() const + { + return m_end_info; + } + + ////////////////////////////////////////////////////////////////////// + // info accessors + // + uint_32 get_width() const + { + return m_info.get_width(); + } + + void set_width(uint_32 width) + { + m_info.set_width(width); + } + + uint_32 get_height() const + { + return m_info.get_height(); + } + + void set_height(uint_32 height) + { + m_info.set_height(height); + } + + color_type get_color_type() const + { + return m_info.get_color_type(); + } + + void set_color_type(color_type color_space) + { + m_info.set_color_type(color_space); + } + + int get_bit_depth() const + { + return m_info.get_bit_depth(); + } + + void set_bit_depth(int bit_depth) + { + m_info.set_bit_depth(bit_depth); + } + + interlace_type get_interlace_type() const + { + return m_info.get_interlace_type(); + } + + void set_interlace_type(interlace_type interlace) + { + m_info.set_interlace_type(interlace); + } + + compression_type get_compression_type() const + { + return m_info.get_compression_type(); + } + + void set_compression_type(compression_type compression) + { + m_info.set_compression_type(compression); + } + + filter_type get_filter_type() const + { + return m_info.get_filter_type(); + } + + void set_filter_type(filter_type filter) + { + m_info.set_filter_type(filter); + } + + ////////////////////////////////////////////////////////////////////// + + bool has_chunk(chunk id) + { + return png_get_valid(m_png, + m_info.get_png_info(), + uint_32(id)) == uint_32(id); + } + +#if defined(PNG_READ_EXPAND_SUPPORTED) + void set_gray_1_2_4_to_8() const + { + TRACE_IO_TRANSFORM("png_set_expand_gray_1_2_4_to_8\n"); + png_set_expand_gray_1_2_4_to_8(m_png); + } + + void set_palette_to_rgb() const + { + TRACE_IO_TRANSFORM("png_set_palette_to_rgb\n"); + png_set_palette_to_rgb(m_png); + } + + void set_tRNS_to_alpha() const + { + TRACE_IO_TRANSFORM("png_set_tRNS_to_alpha\n"); + png_set_tRNS_to_alpha(m_png); + } +#endif // defined(PNG_READ_EXPAND_SUPPORTED) + +#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) + void set_bgr() const + { + TRACE_IO_TRANSFORM("png_set_bgr\n"); + png_set_bgr(m_png); + } +#endif + +#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + void set_gray_to_rgb() const + { + TRACE_IO_TRANSFORM("png_set_gray_to_rgb\n"); + png_set_gray_to_rgb(m_png); + } +#endif + +#ifdef PNG_FLOATING_POINT_SUPPORTED + void set_rgb_to_gray(rgb_to_gray_error_action error_action + = rgb_to_gray_silent, + double red_weight = -1.0, + double green_weight = -1.0) const + { + TRACE_IO_TRANSFORM("png_set_rgb_to_gray: error_action=%d," + " red_weight=%lf, green_weight=%lf\n", + error_action, red_weight, green_weight); + + png_set_rgb_to_gray(m_png, error_action, red_weight, green_weight); + } +#else + void set_rgb_to_gray(rgb_to_gray_error_action error_action + = rgb_to_gray_silent, + fixed_point red_weight = -1, + fixed_point green_weight = -1) const + { + TRACE_IO_TRANSFORM("png_set_rgb_to_gray_fixed: error_action=%d," + " red_weight=%d, green_weight=%d\n", + error_action, red_weight, green_weight); + + png_set_rgb_to_gray_fixed(m_png, error_action, + red_weight, green_weight); + } +#endif // PNG_FLOATING_POINT_SUPPORTED + + ////////////////////////////////////////////////////////////////////// + // alpha channel transformations + // +#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) + void set_strip_alpha() const + { + TRACE_IO_TRANSFORM("png_set_strip_alpha\n"); + png_set_strip_alpha(m_png); + } +#endif + +#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) \ + || defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) + void set_swap_alpha() const + { + TRACE_IO_TRANSFORM("png_set_swap_alpha\n"); + png_set_swap_alpha(m_png); + } +#endif + +#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) \ + || defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) + void set_invert_alpha() const + { + TRACE_IO_TRANSFORM("png_set_invert_alpha\n"); + png_set_invert_alpha(m_png); + } +#endif + +#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) + void set_filler(uint_32 filler, filler_type type) const + { + TRACE_IO_TRANSFORM("png_set_filler: filler=%08x, type=%d\n", + filler, type); + + png_set_filler(m_png, filler, type); + } + +#if !defined(PNG_1_0_X) + void set_add_alpha(uint_32 filler, filler_type type) const + { + TRACE_IO_TRANSFORM("png_set_add_alpha: filler=%08x, type=%d\n", + filler, type); + + png_set_add_alpha(m_png, filler, type); + } +#endif +#endif // PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED + +#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) + void set_swap() const + { + TRACE_IO_TRANSFORM("png_set_swap\n"); + png_set_swap(m_png); + } +#endif + +#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) + void set_packing() const + { + TRACE_IO_TRANSFORM("png_set_packing\n"); + png_set_packing(m_png); + } +#endif + +#if defined(PNG_READ_PACKSWAP_SUPPORTED) \ + || defined(PNG_WRITE_PACKSWAP_SUPPORTED) + void set_packswap() const + { + TRACE_IO_TRANSFORM("png_set_packswap\n"); + png_set_packswap(m_png); + } +#endif + +#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) + void set_shift(byte red_bits, byte green_bits, byte blue_bits, + byte alpha_bits = 0) const + { + TRACE_IO_TRANSFORM("png_set_shift: red_bits=%d, green_bits=%d," + " blue_bits=%d, alpha_bits=%d\n", + red_bits, green_bits, blue_bits, alpha_bits); + + if (get_color_type() != color_type_rgb + || get_color_type() != color_type_rgb_alpha) + { + throw error("set_shift: expected RGB or RGBA color type"); + } + color_info bits; + bits.red = red_bits; + bits.green = green_bits; + bits.blue = blue_bits; + bits.alpha = alpha_bits; + png_set_shift(m_png, & bits); + } + + void set_shift(byte gray_bits, byte alpha_bits = 0) const + { + TRACE_IO_TRANSFORM("png_set_shift: gray_bits=%d, alpha_bits=%d\n", + gray_bits, alpha_bits); + + if (get_color_type() != color_type_gray + || get_color_type() != color_type_gray_alpha) + { + throw error("set_shift: expected Gray or Gray+Alpha color type"); + } + color_info bits; + bits.gray = gray_bits; + bits.alpha = alpha_bits; + png_set_shift(m_png, & bits); + } +#endif // PNG_READ_SHIFT_SUPPORTED || PNG_WRITE_SHIFT_SUPPORTED + +#if defined(PNG_READ_INTERLACING_SUPPORTED) \ + || defined(PNG_WRITE_INTERLACING_SUPPORTED) + int set_interlace_handling() const + { + TRACE_IO_TRANSFORM("png_set_interlace_handling\n"); + return png_set_interlace_handling(m_png); + } +#endif + +#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) + void set_invert_mono() const + { + TRACE_IO_TRANSFORM("png_set_invert_mono\n"); + png_set_invert_mono(m_png); + } +#endif + +#if defined(PNG_READ_16_TO_8_SUPPORTED) + void set_strip_16() const + { + TRACE_IO_TRANSFORM("png_set_strip_16\n"); + png_set_strip_16(m_png); + } +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) + void set_read_user_transform(png_user_transform_ptr transform_fn) + { + TRACE_IO_TRANSFORM("png_set_read_user_transform_fn\n"); + png_set_read_user_transform_fn(m_png, transform_fn); + } +#endif + +#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) \ + || defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) + void set_user_transform_info(void* info, int bit_depth, int channels) + { + TRACE_IO_TRANSFORM("png_set_user_transform_info: bit_depth=%d," + " channels=%d\n", bit_depth, channels); + + png_set_user_transform_info(m_png, info, bit_depth, channels); + } +#endif + + protected: + void* get_io_ptr() const + { + return png_get_io_ptr(m_png); + } + + void set_error(char const* message) + { + assert(message); + m_error = message; + } + + void reset_error() + { + m_error.clear(); + } + +/* + std::string const& get_error() const + { + return m_error; + } +*/ + + bool is_error() const + { + return !m_error.empty(); + } + + void raise_error() + { + longjmp(png_jmpbuf(m_png), -1); + } + + static void raise_error(png_struct* png, char const* message) + { + io_base* io = static_cast< io_base* >(png_get_error_ptr(png)); + io->set_error(message); + io->raise_error(); + } + + png_struct* m_png; + info m_info; + end_info m_end_info; + std::string m_error; + }; + +} // namespace png + +#endif // PNGPP_IO_BASE_HPP_INCLUDED diff --git a/xs/src/png/palette.hpp b/xs/src/png/palette.hpp new file mode 100644 index 0000000000..917f280075 --- /dev/null +++ b/xs/src/png/palette.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2007,2008 Alex Shulgin + * + * This file is part of png++ the C++ wrapper for libpng. PNG++ is free + * software; the exact copying conditions are as follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PNGPP_PALETTE_HPP_INCLUDED +#define PNGPP_PALETTE_HPP_INCLUDED + +#include +#include "color.hpp" + +namespace png +{ + + /** + * \brief The palette type. Currently implemented as \c std::vector + * of png::color. + */ + typedef std::vector< color > palette; + +} // namespace png + +#endif // PNGPP_PALETTE_HPP_INCLUDED diff --git a/xs/src/png/pixel_traits.hpp b/xs/src/png/pixel_traits.hpp new file mode 100644 index 0000000000..8ffdfeedb4 --- /dev/null +++ b/xs/src/png/pixel_traits.hpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2007,2008 Alex Shulgin + * + * This file is part of png++ the C++ wrapper for libpng. PNG++ is free + * software; the exact copying conditions are as follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PNGPP_PIXEL_TRAITS_HPP_INCLUDED +#define PNGPP_PIXEL_TRAITS_HPP_INCLUDED + +#include +#include "types.hpp" + +namespace png +{ + + /** + * \brief Pixel traits class template. + * + * Provides information about pixel color type and components bit depth. + * Not implemented--see specializations. + * + * \see pixel_traits, pixel_traits + */ + template< typename pixel > struct pixel_traits; + + /** + * \brief Basic pixel traits class template. + * + * Provides common implementation for various pixel_traits<> + * specializations. + */ + template< typename pixel, + typename component, + color_type pixel_color_type, + int channels_value = sizeof(pixel) / sizeof(component), + int bit_depth_value = std::numeric_limits< component >::digits > + struct basic_pixel_traits + { + typedef pixel pixel_type; + typedef component component_type; + + static color_type get_color_type() + { + return pixel_color_type; + } + + static const int channels = channels_value; + static int get_channels() + { + return channels; + } + + static const int bit_depth = bit_depth_value; + static int get_bit_depth() + { + return bit_depth; + } + }; + + /** + * \brief Basic pixel traits class template for pixels with alpha + * channel. + */ + template< typename component > + struct basic_alpha_pixel_traits + { + /** + * \brief Returns the default alpha channel filler for full + * opacity. + */ + static component get_alpha_filler() + { + return std::numeric_limits< component >::max(); + } + }; + +} // namespace png + +#endif // PNGPP_PIXEL_TRAITS_HPP_INCLUDED diff --git a/xs/src/png/tRNS.hpp b/xs/src/png/tRNS.hpp new file mode 100644 index 0000000000..ff01816433 --- /dev/null +++ b/xs/src/png/tRNS.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2007,2008 Alex Shulgin + * + * This file is part of png++ the C++ wrapper for libpng. PNG++ is free + * software; the exact copying conditions are as follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PNGPP_TRNS_HPP_INCLUDED +#define PNGPP_TRNS_HPP_INCLUDED + +#include +#include "color.hpp" + +namespace png +{ + + /** + * \brief The palette transparency map type. Currently + * implemented as \c std::vector of png::byte. + */ + typedef std::vector< byte > tRNS; + +} // namespace png + +#endif // PNGPP_TRNS_HPP_INCLUDED diff --git a/xs/src/png/types.hpp b/xs/src/png/types.hpp new file mode 100644 index 0000000000..1538d6bd28 --- /dev/null +++ b/xs/src/png/types.hpp @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2007,2008 Alex Shulgin + * + * This file is part of png++ the C++ wrapper for libpng. PNG++ is free + * software; the exact copying conditions are as follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PNGPP_TYPES_HPP_INCLUDED +#define PNGPP_TYPES_HPP_INCLUDED + +#include + +namespace png +{ + + typedef png_byte byte; + typedef png_uint_16 uint_16; + typedef png_uint_32 uint_32; + typedef png_fixed_point fixed_point; + typedef png_color_8 color_info; + typedef png_color_16 color_info_16; + + enum color_type + { + color_type_none = -1, + color_type_gray = PNG_COLOR_TYPE_GRAY, + color_type_palette = PNG_COLOR_TYPE_PALETTE, + color_type_rgb = PNG_COLOR_TYPE_RGB, + color_type_rgb_alpha = PNG_COLOR_TYPE_RGB_ALPHA, + color_type_gray_alpha = PNG_COLOR_TYPE_GRAY_ALPHA, + color_type_rgba = PNG_COLOR_TYPE_RGBA, + color_type_ga = PNG_COLOR_TYPE_GA + }; + + enum color_mask + { + color_mask_palette = PNG_COLOR_MASK_PALETTE, + color_mask_color = PNG_COLOR_MASK_COLOR, + color_mask_rgb = color_mask_color, + color_mask_alpha = PNG_COLOR_MASK_ALPHA + }; + + enum filler_type + { + filler_before = PNG_FILLER_BEFORE, + filler_after = PNG_FILLER_AFTER + }; + + enum rgb_to_gray_error_action + { + rgb_to_gray_silent = 1, + rgb_to_gray_warning = 2, + rgb_to_gray_error = 3 + }; + + enum interlace_type + { + interlace_none = PNG_INTERLACE_NONE, + interlace_adam7 = PNG_INTERLACE_ADAM7 + }; + + enum compression_type + { + compression_type_base = PNG_COMPRESSION_TYPE_BASE, + compression_type_default = PNG_COMPRESSION_TYPE_DEFAULT + }; + + enum filter_type + { + filter_type_base = PNG_FILTER_TYPE_BASE, + intrapixel_differencing = PNG_INTRAPIXEL_DIFFERENCING, + filter_type_default = PNG_FILTER_TYPE_DEFAULT + }; + + enum chunk + { + chunk_gAMA = PNG_INFO_gAMA, + chunk_sBIT = PNG_INFO_sBIT, + chunk_cHRM = PNG_INFO_cHRM, + chunk_PLTE = PNG_INFO_PLTE, + chunk_tRNS = PNG_INFO_tRNS, + chunk_bKGD = PNG_INFO_bKGD, + chunk_hIST = PNG_INFO_hIST, + chunk_pHYs = PNG_INFO_pHYs, + chunk_oFFs = PNG_INFO_oFFs, + chunk_tIME = PNG_INFO_tIME, + chunk_pCAL = PNG_INFO_pCAL, + chunk_sRGB = PNG_INFO_sRGB, + chunk_iCCP = PNG_INFO_iCCP, + chunk_sPLT = PNG_INFO_sPLT, + chunk_sCAL = PNG_INFO_sCAL, + chunk_IDAT = PNG_INFO_IDAT + }; + +} // namespace png + +#endif // PNGPP_TYPES_HPP_INCLUDED diff --git a/xs/src/png/writer.hpp b/xs/src/png/writer.hpp new file mode 100644 index 0000000000..448dfd50b1 --- /dev/null +++ b/xs/src/png/writer.hpp @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2007,2008 Alex Shulgin + * + * This file is part of png++ the C++ wrapper for libpng. PNG++ is free + * software; the exact copying conditions are as follows: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PNGPP_WRITER_HPP_INCLUDED +#define PNGPP_WRITER_HPP_INCLUDED + +#include +#include "io_base.hpp" + +namespace png +{ + + /** + * \brief PNG writer class template. This is the low-level + * writing interface--use image class or generator class to + * actually write images. + * + * The \c ostream template parameter specifies the type of output + * stream to work with. The \c ostream class should implement the + * minimum of the following interface: + * + * \code + * class my_ostream + * { + * public: + * void write(char const*, size_t); + * void flush(); + * bool good(); + * }; + * \endcode + * + * With the semantics similar to the \c std::ostream. Naturally, + * \c std::ostream fits this requirement and can be used with the + * writer class as is. + * + * \see image, reader, generator, io_base + */ + template< class ostream > + class writer + : public io_base + { + public: + /** + * \brief Constructs a writer prepared to write PNG image into + * a \a stream. + */ + explicit writer(ostream& stream) + : io_base(png_create_write_struct(PNG_LIBPNG_VER_STRING, + static_cast< io_base* >(this), + raise_error, + 0)) + { + png_set_write_fn(m_png, & stream, write_data, flush_data); + } + + ~writer() + { + m_end_info.destroy(); + png_destroy_write_struct(& m_png, m_info.get_png_info_ptr()); + } + + void write_png() const + { + if (setjmp(png_jmpbuf(m_png))) + { + throw error(m_error); + } + png_write_png(m_png, + m_info.get_png_info(), + /* transforms = */ 0, + /* params = */ 0); + } + + /** + * \brief Write info about PNG image. + */ + void write_info() const + { + if (setjmp(png_jmpbuf(m_png))) + { + throw error(m_error); + } + m_info.write(); + } + + /** + * \brief Writes a row of image data at a time. + */ + void write_row(byte* bytes) + { + if (setjmp(png_jmpbuf(m_png))) + { + throw error(m_error); + } + png_write_row(m_png, bytes); + } + + /** + * \brief Reads ending info about PNG image. + */ + void write_end_info() const + { + if (setjmp(png_jmpbuf(m_png))) + { + throw error(m_error); + } + m_end_info.write(); + } + + private: + static void write_data(png_struct* png, byte* data, png_size_t length) + { + io_base* io = static_cast< io_base* >(png_get_error_ptr(png)); + writer* wr = static_cast< writer* >(io); + wr->reset_error(); + ostream* stream = reinterpret_cast< ostream* >(png_get_io_ptr(png)); + try + { + stream->write(reinterpret_cast< char* >(data), length); + if (!stream->good()) + { + wr->set_error("ostream::write() failed"); + } + } + catch (std::exception const& error) + { + wr->set_error(error.what()); + } + catch (...) + { + assert(!"caught something wrong"); + wr->set_error("write_data: caught something wrong"); + } + if (wr->is_error()) + { + wr->raise_error(); + } + } + + static void flush_data(png_struct* png) + { + io_base* io = static_cast< io_base* >(png_get_error_ptr(png)); + writer* wr = static_cast< writer* >(io); + wr->reset_error(); + ostream* stream = reinterpret_cast< ostream* >(png_get_io_ptr(png)); + try + { + stream->flush(); + if (!stream->good()) + { + wr->set_error("ostream::flush() failed"); + } + } + catch (std::exception const& error) + { + wr->set_error(error.what()); + } + catch (...) + { + assert(!"caught something wrong"); + wr->set_error("flush_data: caught something wrong"); + } + if (wr->is_error()) + { + wr->raise_error(); + } + } + }; + +} // namespace png + +#endif // PNGPP_WRITER_HPP_INCLUDED