00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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;
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
00119
00120 size_t get_width() const
00121 {
00122 return m_info.get_width();
00123 }
00124
00125 void set_width(size_t width)
00126 {
00127 m_info.set_width(width);
00128 }
00129
00130 size_t get_height() const
00131 {
00132 return m_info.get_height();
00133 }
00134
00135 void set_height(size_t 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 size_t get_bit_depth() const
00151 {
00152 return m_info.get_bit_depth();
00153 }
00154
00155 void set_bit_depth(size_t 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
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"
00366 " color type");
00367 }
00368 color_info bits;
00369 bits.gray = gray_bits;
00370 bits.alpha = alpha_bits;
00371 png_set_shift(m_png, & bits);
00372 }
00373 #endif // PNG_READ_SHIFT_SUPPORTED || PNG_WRITE_SHIFT_SUPPORTED
00374
00375 #if defined(PNG_READ_INTERLACING_SUPPORTED) \
00376 || defined(PNG_WRITE_INTERLACING_SUPPORTED)
00377 int set_interlace_handling() const
00378 {
00379 TRACE_IO_TRANSFORM("png_set_interlace_handling\n");
00380 return png_set_interlace_handling(m_png);
00381 }
00382 #endif
00383
00384 #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
00385 void set_invert_mono() const
00386 {
00387 TRACE_IO_TRANSFORM("png_set_invert_mono\n");
00388 png_set_invert_mono(m_png);
00389 }
00390 #endif
00391
00392 #if defined(PNG_READ_16_TO_8_SUPPORTED)
00393 void set_strip_16() const
00394 {
00395 TRACE_IO_TRANSFORM("png_set_strip_16\n");
00396 png_set_strip_16(m_png);
00397 }
00398 #endif
00399
00400 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
00401 void set_read_user_transform(png_user_transform_ptr transform_fn)
00402 {
00403 TRACE_IO_TRANSFORM("png_set_read_user_transform_fn\n");
00404 png_set_read_user_transform_fn(m_png, transform_fn);
00405 }
00406 #endif
00407
00408 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) \
00409 || defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
00410 void set_user_transform_info(void* info, int bit_depth, int channels)
00411 {
00412 TRACE_IO_TRANSFORM("png_set_user_transform_info: bit_depth=%d,"
00413 " channels=%d\n", bit_depth, channels);
00414
00415 png_set_user_transform_info(m_png, info, bit_depth, channels);
00416 }
00417 #endif
00418
00419 protected:
00420 void* get_io_ptr() const
00421 {
00422 return png_get_io_ptr(m_png);
00423 }
00424
00425 void set_error(char const* message)
00426 {
00427 assert(message);
00428 m_error = message;
00429 }
00430
00431 void reset_error()
00432 {
00433 m_error.clear();
00434 }
00435
00436
00437
00438
00439
00440
00441
00442
00443 bool is_error() const
00444 {
00445 return !m_error.empty();
00446 }
00447
00448 void raise_error()
00449 {
00450 longjmp(png_jmpbuf(m_png), -1);
00451 }
00452
00453 static void raise_error(png_struct* png, char const* message)
00454 {
00455 io_base* io = static_cast< io_base* >(png_get_error_ptr(png));
00456 io->set_error(message);
00457 io->raise_error();
00458 }
00459
00460 png_struct* m_png;
00461 info m_info;
00462 end_info m_end_info;
00463 std::string m_error;
00464 };
00465
00466 }
00467
00468 #endif // PNGPP_IO_BASE_HPP_INCLUDED