diff options
Diffstat (limited to 'src/png/io_base.hpp')
-rw-r--r-- | src/png/io_base.hpp | 467 |
1 files changed, 467 insertions, 0 deletions
diff --git a/src/png/io_base.hpp b/src/png/io_base.hpp new file mode 100644 index 000000000..3c2d83043 --- /dev/null +++ b/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 <cassert> +#include <cstdio> +#include <cstdarg> +#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 |