liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//
// Copyright 2012 Christian Henning
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#ifndef BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_WRITER_BACKEND_HPP
#define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_WRITER_BACKEND_HPP
 
#include <boost/gil/extension/io/tiff/tags.hpp>
#include <boost/gil/extension/io/tiff/detail/device.hpp>
 
#include <boost/gil/detail/mp11.hpp>
 
namespace boost { namespace gil {
 
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(push)
#pragma warning(disable:4512) //assignment operator could not be generated
#endif
 
///
/// TIFF Writer Backend
///
template< typename Device >
struct writer_backend< Device
                     , tiff_tag
                     >
{
public:
 
    using format_tag_t = tiff_tag;
 
public:
 
    writer_backend( const Device&                       io_dev
                  , const image_write_info< tiff_tag >& info
                  )
    : _io_dev( io_dev )
    , _info( info )
    {}
 
protected:
 
    template< typename View >
    void write_header( const View& view )
    {
        using pixel_t = typename View::value_type;
 
        // get the type of the first channel (heterogeneous pixels might be broken for now!)
        using channel_t = typename channel_traits<typename element_type<pixel_t>::type>::value_type;
                using color_space_t = typename color_space_type<View>::type;
 
        if(! this->_info._photometric_interpretation_user_defined )
        {
            // write photometric interpretion - Warning: This value is rather
            // subjective. The user should better set this value itself. There
            // is no way to decide if a image is PHOTOMETRIC_MINISWHITE or
            // PHOTOMETRIC_MINISBLACK. If the user has not manually set it, then
            // this writer will assume PHOTOMETRIC_MINISBLACK for gray_t images,
            // PHOTOMETRIC_RGB for rgb_t images, and PHOTOMETRIC_SEPARATED (as
            // is conventional) for cmyk_t images.
            this->_info._photometric_interpretation = detail::photometric_interpretation< color_space_t >::value;
        }
 
        // write dimensions
        tiff_image_width::type  width  = (tiff_image_width::type)  view.width();
        tiff_image_height::type height = (tiff_image_height::type) view.height();
 
        this->_io_dev.template set_property< tiff_image_width  >( width  );
        this->_io_dev.template set_property< tiff_image_height >( height );
 
        // write planar configuration
        this->_io_dev.template set_property<tiff_planar_configuration>( this->_info._planar_configuration );
 
        // write samples per pixel
        tiff_samples_per_pixel::type samples_per_pixel = num_channels< pixel_t >::value;
        this->_io_dev.template set_property<tiff_samples_per_pixel>( samples_per_pixel );
 
        if /*constexpr*/ (mp11::mp_contains<color_space_t, alpha_t>::value)
        {
          std:: vector <uint16_t> extra_samples {EXTRASAMPLE_ASSOCALPHA};
          this->_io_dev.template set_property<tiff_extra_samples>( extra_samples );
        }
 
        // write bits per sample
        // @todo: Settings this value usually requires to write for each sample the bit
        // value seperately in case they are different, like rgb556.
        tiff_bits_per_sample::type bits_per_sample = detail::unsigned_integral_num_bits< channel_t >::value;
        this->_io_dev.template set_property<tiff_bits_per_sample>( bits_per_sample );
 
        // write sample format
        tiff_sample_format::type sampl_format = detail::sample_format< channel_t >::value;
        this->_io_dev.template set_property<tiff_sample_format>( sampl_format );
 
        // write photometric format
        this->_io_dev.template set_property<tiff_photometric_interpretation>( this->_info._photometric_interpretation );
 
        // write compression
        this->_io_dev.template set_property<tiff_compression>( this->_info._compression );
 
        // write orientation
        this->_io_dev.template set_property<tiff_orientation>( this->_info._orientation );
 
        // write rows per strip
        this->_io_dev.template set_property<tiff_rows_per_strip>( this->_io_dev.get_default_strip_size() );
 
        // write x, y resolution and units
        this->_io_dev.template set_property<tiff_resolution_unit>( this->_info._resolution_unit );
        this->_io_dev.template set_property<tiff_x_resolution>( this->_info._x_resolution );
        this->_io_dev.template set_property<tiff_y_resolution>( this->_info._y_resolution );
 
        /// Optional and / or non-baseline tags below here
 
        // write ICC colour profile, if it's there
        // http://www.color.org/icc_specs2.xalter
        if ( 0 != this->_info._icc_profile.size())
          this->_io_dev.template set_property<tiff_icc_profile>( this->_info._icc_profile );
    }
 
 
public:
 
    Device _io_dev;
 
    image_write_info< tiff_tag > _info;
};
 
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
#pragma warning(pop)
#endif
 
} // namespace gil
} // namespace boost
 
#endif