png++
0.2.9
|
00001 /* 00002 * Copyright (C) 2007,2008 Alex Shulgin 00003 * 00004 * This file is part of png++ the C++ wrapper for libpng. PNG++ is free 00005 * software; the exact copying conditions are as follows: 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions are met: 00009 * 00010 * 1. Redistributions of source code must retain the above copyright notice, 00011 * this list of conditions and the following disclaimer. 00012 * 00013 * 2. Redistributions in binary form must reproduce the above copyright 00014 * notice, this list of conditions and the following disclaimer in the 00015 * documentation and/or other materials provided with the distribution. 00016 * 00017 * 3. The name of the author may not be used to endorse or promote products 00018 * derived from this software without specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00021 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00022 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00023 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00024 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00025 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00026 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00027 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00028 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 */ 00031 #ifndef PNGPP_IO_BASE_HPP_INCLUDED 00032 #define PNGPP_IO_BASE_HPP_INCLUDED 00033 00034 #include <cassert> 00035 #include <cstdio> 00036 #include <cstdarg> 00037 #include "error.hpp" 00038 #include "info.hpp" 00039 #include "end_info.hpp" 00040 00041 static void 00042 trace_io_transform(char const* fmt, ...) 00043 { 00044 #ifdef DEBUG_IO_TRANSFORM 00045 va_list va; 00046 va_start(va, fmt); 00047 fprintf(stderr, "TRANSFORM_IO: "); 00048 vfprintf(stderr, fmt, va); 00049 va_end(va); 00050 #endif 00051 } 00052 #define TRACE_IO_TRANSFORM trace_io_transform 00053 00054 namespace png 00055 { 00056 00062 class io_base 00063 { 00064 io_base(io_base const&); 00065 io_base& operator=(io_base const&); 00066 00067 public: 00068 explicit io_base(png_struct* png) 00069 : m_png(png), 00070 m_info(*this, m_png), 00071 m_end_info(*this, m_png) 00072 { 00073 } 00074 00075 ~io_base() 00076 { 00077 assert(! m_png); 00078 assert(! m_info.get_png_info()); 00079 assert(! m_end_info.get_png_info()); 00080 } 00081 00082 png_struct* get_png_struct() const 00083 { 00084 return m_png; 00085 } 00086 00087 info& get_info() 00088 { 00089 return m_info; 00090 } 00091 00092 info const& get_info() const 00093 { 00094 return m_info; 00095 } 00096 00097 image_info const& get_image_info() const 00098 { 00099 return m_info; 00100 } 00101 00102 void set_image_info(image_info const& info) 00103 { 00104 static_cast< image_info& >(m_info) = info; // slice it 00105 } 00106 00107 end_info& get_end_info() 00108 { 00109 return m_end_info; 00110 } 00111 00112 end_info const& get_end_info() const 00113 { 00114 return m_end_info; 00115 } 00116 00118 // info accessors 00119 // 00120 uint_32 get_width() const 00121 { 00122 return m_info.get_width(); 00123 } 00124 00125 void set_width(uint_32 width) 00126 { 00127 m_info.set_width(width); 00128 } 00129 00130 uint_32 get_height() const 00131 { 00132 return m_info.get_height(); 00133 } 00134 00135 void set_height(uint_32 height) 00136 { 00137 m_info.set_height(height); 00138 } 00139 00140 color_type get_color_type() const 00141 { 00142 return m_info.get_color_type(); 00143 } 00144 00145 void set_color_type(color_type color_space) 00146 { 00147 m_info.set_color_type(color_space); 00148 } 00149 00150 int get_bit_depth() const 00151 { 00152 return m_info.get_bit_depth(); 00153 } 00154 00155 void set_bit_depth(int bit_depth) 00156 { 00157 m_info.set_bit_depth(bit_depth); 00158 } 00159 00160 interlace_type get_interlace_type() const 00161 { 00162 return m_info.get_interlace_type(); 00163 } 00164 00165 void set_interlace_type(interlace_type interlace) 00166 { 00167 m_info.set_interlace_type(interlace); 00168 } 00169 00170 compression_type get_compression_type() const 00171 { 00172 return m_info.get_compression_type(); 00173 } 00174 00175 void set_compression_type(compression_type compression) 00176 { 00177 m_info.set_compression_type(compression); 00178 } 00179 00180 filter_type get_filter_type() const 00181 { 00182 return m_info.get_filter_type(); 00183 } 00184 00185 void set_filter_type(filter_type filter) 00186 { 00187 m_info.set_filter_type(filter); 00188 } 00189 00191 00192 bool has_chunk(chunk id) 00193 { 00194 return png_get_valid(m_png, 00195 m_info.get_png_info(), 00196 uint_32(id)) == uint_32(id); 00197 } 00198 00199 #if defined(PNG_READ_EXPAND_SUPPORTED) 00200 void set_gray_1_2_4_to_8() const 00201 { 00202 TRACE_IO_TRANSFORM("png_set_expand_gray_1_2_4_to_8\n"); 00203 png_set_expand_gray_1_2_4_to_8(m_png); 00204 } 00205 00206 void set_palette_to_rgb() const 00207 { 00208 TRACE_IO_TRANSFORM("png_set_palette_to_rgb\n"); 00209 png_set_palette_to_rgb(m_png); 00210 } 00211 00212 void set_tRNS_to_alpha() const 00213 { 00214 TRACE_IO_TRANSFORM("png_set_tRNS_to_alpha\n"); 00215 png_set_tRNS_to_alpha(m_png); 00216 } 00217 #endif // defined(PNG_READ_EXPAND_SUPPORTED) 00218 00219 #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) 00220 void set_bgr() const 00221 { 00222 TRACE_IO_TRANSFORM("png_set_bgr\n"); 00223 png_set_bgr(m_png); 00224 } 00225 #endif 00226 00227 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) 00228 void set_gray_to_rgb() const 00229 { 00230 TRACE_IO_TRANSFORM("png_set_gray_to_rgb\n"); 00231 png_set_gray_to_rgb(m_png); 00232 } 00233 #endif 00234 00235 #ifdef PNG_FLOATING_POINT_SUPPORTED 00236 void set_rgb_to_gray(rgb_to_gray_error_action error_action 00237 = rgb_to_gray_silent, 00238 double red_weight = -1.0, 00239 double green_weight = -1.0) const 00240 { 00241 TRACE_IO_TRANSFORM("png_set_rgb_to_gray: error_action=%d," 00242 " red_weight=%lf, green_weight=%lf\n", 00243 error_action, red_weight, green_weight); 00244 00245 png_set_rgb_to_gray(m_png, error_action, red_weight, green_weight); 00246 } 00247 #else 00248 void set_rgb_to_gray(rgb_to_gray_error_action error_action 00249 = rgb_to_gray_silent, 00250 fixed_point red_weight = -1, 00251 fixed_point green_weight = -1) const 00252 { 00253 TRACE_IO_TRANSFORM("png_set_rgb_to_gray_fixed: error_action=%d," 00254 " red_weight=%d, green_weight=%d\n", 00255 error_action, red_weight, green_weight); 00256 00257 png_set_rgb_to_gray_fixed(m_png, error_action, 00258 red_weight, green_weight); 00259 } 00260 #endif // PNG_FLOATING_POINT_SUPPORTED 00261 00263 // alpha channel transformations 00264 // 00265 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED) 00266 void set_strip_alpha() const 00267 { 00268 TRACE_IO_TRANSFORM("png_set_strip_alpha\n"); 00269 png_set_strip_alpha(m_png); 00270 } 00271 #endif 00272 00273 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) \ 00274 || defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) 00275 void set_swap_alpha() const 00276 { 00277 TRACE_IO_TRANSFORM("png_set_swap_alpha\n"); 00278 png_set_swap_alpha(m_png); 00279 } 00280 #endif 00281 00282 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) \ 00283 || defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) 00284 void set_invert_alpha() const 00285 { 00286 TRACE_IO_TRANSFORM("png_set_invert_alpha\n"); 00287 png_set_invert_alpha(m_png); 00288 } 00289 #endif 00290 00291 #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) 00292 void set_filler(uint_32 filler, filler_type type) const 00293 { 00294 TRACE_IO_TRANSFORM("png_set_filler: filler=%08x, type=%d\n", 00295 filler, type); 00296 00297 png_set_filler(m_png, filler, type); 00298 } 00299 00300 #if !defined(PNG_1_0_X) 00301 void set_add_alpha(uint_32 filler, filler_type type) const 00302 { 00303 TRACE_IO_TRANSFORM("png_set_add_alpha: filler=%08x, type=%d\n", 00304 filler, type); 00305 00306 png_set_add_alpha(m_png, filler, type); 00307 } 00308 #endif 00309 #endif // PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED 00310 00311 #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) 00312 void set_swap() const 00313 { 00314 TRACE_IO_TRANSFORM("png_set_swap\n"); 00315 png_set_swap(m_png); 00316 } 00317 #endif 00318 00319 #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) 00320 void set_packing() const 00321 { 00322 TRACE_IO_TRANSFORM("png_set_packing\n"); 00323 png_set_packing(m_png); 00324 } 00325 #endif 00326 00327 #if defined(PNG_READ_PACKSWAP_SUPPORTED) \ 00328 || defined(PNG_WRITE_PACKSWAP_SUPPORTED) 00329 void set_packswap() const 00330 { 00331 TRACE_IO_TRANSFORM("png_set_packswap\n"); 00332 png_set_packswap(m_png); 00333 } 00334 #endif 00335 00336 #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) 00337 void set_shift(byte red_bits, byte green_bits, byte blue_bits, 00338 byte alpha_bits = 0) const 00339 { 00340 TRACE_IO_TRANSFORM("png_set_shift: red_bits=%d, green_bits=%d," 00341 " blue_bits=%d, alpha_bits=%d\n", 00342 red_bits, green_bits, blue_bits, alpha_bits); 00343 00344 if (get_color_type() != color_type_rgb 00345 || get_color_type() != color_type_rgb_alpha) 00346 { 00347 throw error("set_shift: expected RGB or RGBA color type"); 00348 } 00349 color_info bits; 00350 bits.red = red_bits; 00351 bits.green = green_bits; 00352 bits.blue = blue_bits; 00353 bits.alpha = alpha_bits; 00354 png_set_shift(m_png, & bits); 00355 } 00356 00357 void set_shift(byte gray_bits, byte alpha_bits = 0) const 00358 { 00359 TRACE_IO_TRANSFORM("png_set_shift: gray_bits=%d, alpha_bits=%d\n", 00360 gray_bits, alpha_bits); 00361 00362 if (get_color_type() != color_type_gray 00363 || get_color_type() != color_type_gray_alpha) 00364 { 00365 throw error("set_shift: expected Gray or Gray+Alpha color type"); 00366 } 00367 color_info bits; 00368 bits.gray = gray_bits; 00369 bits.alpha = alpha_bits; 00370 png_set_shift(m_png, & bits); 00371 } 00372 #endif // PNG_READ_SHIFT_SUPPORTED || PNG_WRITE_SHIFT_SUPPORTED 00373 00374 #if defined(PNG_READ_INTERLACING_SUPPORTED) \ 00375 || defined(PNG_WRITE_INTERLACING_SUPPORTED) 00376 int set_interlace_handling() const 00377 { 00378 TRACE_IO_TRANSFORM("png_set_interlace_handling\n"); 00379 return png_set_interlace_handling(m_png); 00380 } 00381 #endif 00382 00383 #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) 00384 void set_invert_mono() const 00385 { 00386 TRACE_IO_TRANSFORM("png_set_invert_mono\n"); 00387 png_set_invert_mono(m_png); 00388 } 00389 #endif 00390 00391 #if defined(PNG_READ_16_TO_8_SUPPORTED) 00392 void set_strip_16() const 00393 { 00394 TRACE_IO_TRANSFORM("png_set_strip_16\n"); 00395 png_set_strip_16(m_png); 00396 } 00397 #endif 00398 00399 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) 00400 void set_read_user_transform(png_user_transform_ptr transform_fn) 00401 { 00402 TRACE_IO_TRANSFORM("png_set_read_user_transform_fn\n"); 00403 png_set_read_user_transform_fn(m_png, transform_fn); 00404 } 00405 #endif 00406 00407 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) \ 00408 || defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) 00409 void set_user_transform_info(void* info, int bit_depth, int channels) 00410 { 00411 TRACE_IO_TRANSFORM("png_set_user_transform_info: bit_depth=%d," 00412 " channels=%d\n", bit_depth, channels); 00413 00414 png_set_user_transform_info(m_png, info, bit_depth, channels); 00415 } 00416 #endif 00417 00418 protected: 00419 void* get_io_ptr() const 00420 { 00421 return png_get_io_ptr(m_png); 00422 } 00423 00424 void set_error(char const* message) 00425 { 00426 assert(message); 00427 m_error = message; 00428 } 00429 00430 void reset_error() 00431 { 00432 m_error.clear(); 00433 } 00434 00435 /* 00436 std::string const& get_error() const 00437 { 00438 return m_error; 00439 } 00440 */ 00441 00442 bool is_error() const 00443 { 00444 return !m_error.empty(); 00445 } 00446 00447 void raise_error() 00448 { 00449 longjmp(png_jmpbuf(m_png), -1); 00450 } 00451 00452 static void raise_error(png_struct* png, char const* message) 00453 { 00454 io_base* io = static_cast< io_base* >(png_get_error_ptr(png)); 00455 io->set_error(message); 00456 io->raise_error(); 00457 } 00458 00459 png_struct* m_png; 00460 info m_info; 00461 end_info m_end_info; 00462 std::string m_error; 00463 }; 00464 00465 } // namespace png 00466 00467 #endif // PNGPP_IO_BASE_HPP_INCLUDED