1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright (c) Contributors to the OpenEXR Project.
4 //
5
6 #ifndef INCLUDED_IMAGE_H
7 #define INCLUDED_IMAGE_H
8
9 //----------------------------------------------------------------------------
10 //
11 // Classes for storing OpenEXR images in memory.
12 //
13 //----------------------------------------------------------------------------
14
15 #include <ImfChannelList.h>
16 #include <ImfFrameBuffer.h>
17 #include <ImfArray.h>
18 #include <ImathBox.h>
19 #include <half.h>
20 #include <Iex.h>
21
22 #include <string>
23 #include <map>
24
25 #include "namespaceAlias.h"
26
27 class Image;
28
29
30 class ImageChannel
31 {
32 public:
33
34 friend class Image;
35
36 ImageChannel (Image &image);
37 virtual ~ImageChannel();
38
39 virtual IMF::Slice slice () const = 0;
40
image()41 Image & image () {return _image;}
image()42 const Image & image () const {return _image;}
43 virtual void black() =0;
44 private:
45
46 virtual void resize () = 0;
47
48 Image & _image;
49 };
50
51
52 template <class T>
53 class TypedImageChannel: public ImageChannel
54 {
55 public:
56
57 TypedImageChannel (Image &image, int xSampling, int ySampling);
58
59 virtual ~TypedImageChannel ();
60
61 IMF::PixelType pixelType () const;
62
63 virtual IMF::Slice slice () const;
64
65
66 private:
67
68 virtual void resize ();
69 virtual void black();
70
71 int _xSampling;
72 int _ySampling;
73 IMF::Array2D<T> _pixels;
74 };
75
76
77 typedef TypedImageChannel<half> HalfChannel;
78 typedef TypedImageChannel<float> FloatChannel;
79 typedef TypedImageChannel<unsigned int> UIntChannel;
80
81
82 class Image
83 {
84 public:
85
86 Image ();
87 Image (const IMATH_NAMESPACE::Box2i &dataWindow);
88 ~Image ();
89
90 Image (const Image& other) = delete;
91 Image & operator = (const Image& other) = delete;
92 Image (Image&& other) = delete;
93 Image & operator = (Image&& other) = delete;
94
95 const IMATH_NAMESPACE::Box2i & dataWindow () const;
96 void resize (const IMATH_NAMESPACE::Box2i &dataWindow);
97
98 int width () const;
99 int height () const;
100
101 void addChannel (const std::string &name,
102 const IMF::Channel &channel);
103
104 ImageChannel & channel (const std::string &name);
105 const ImageChannel & channel (const std::string &name) const;
106
107 template <class T>
108 TypedImageChannel<T> & typedChannel (const std::string &name);
109
110 template <class T>
111 const TypedImageChannel<T> & typedChannel (const std::string &name) const;
112
113
114
115 private:
116
117 typedef std::map <std::string, ImageChannel *> ChannelMap;
118
119 IMATH_NAMESPACE::Box2i _dataWindow;
120 ChannelMap _channels;
121 };
122
123
124 //
125 // Implementation of templates and inline functions.
126 //
127
128 template <class T>
TypedImageChannel(Image & image,int xSampling,int ySampling)129 TypedImageChannel<T>::TypedImageChannel
130 (Image &image,
131 int xSampling,
132 int ySampling)
133 :
134 ImageChannel (image),
135 _xSampling (xSampling),
136 _ySampling (ySampling),
137 _pixels (0, 0)
138 {
139 if ( _xSampling < 1 || _ySampling < 1 )
140 throw IEX_NAMESPACE::ArgExc ("Invalid x/y sampling values");
141 resize();
142 }
143
144
145 template <class T>
~TypedImageChannel()146 TypedImageChannel<T>::~TypedImageChannel ()
147 {
148 // empty
149 }
150
151
152 template <>
153 inline IMF::PixelType
pixelType()154 HalfChannel::pixelType () const
155 {
156 return IMF::HALF;
157 }
158
159
160 template <>
161 inline IMF::PixelType
pixelType()162 FloatChannel::pixelType () const
163 {
164 return IMF::FLOAT;
165 }
166
167
168 template <>
169 inline IMF::PixelType
pixelType()170 UIntChannel::pixelType () const
171 {
172 return IMF::UINT;
173 }
174
175
176 template <class T>
177 IMF::Slice
slice()178 TypedImageChannel<T>::slice () const
179 {
180 const IMATH_NAMESPACE::Box2i &dw = image().dataWindow();
181 int w = dw.max.x - dw.min.x + 1;
182
183 return IMF::Slice::Make (
184 pixelType(),
185 &_pixels[0][0],
186 dw,
187 sizeof(T),
188 (w / _xSampling) * sizeof (T),
189 _xSampling,
190 _ySampling);
191 }
192
193
194 template <class T>
195 void
resize()196 TypedImageChannel<T>::resize ()
197 {
198 int width = image().width() / _xSampling;
199 int height = image().height() / _ySampling;
200
201 _pixels.resizeEraseUnsafe (height, width);
202 }
203
204
205 template <class T>
206 void
black()207 TypedImageChannel<T>::black ()
208 {
209 size_t nx = static_cast<size_t>( image().width() ) / static_cast<size_t>( _xSampling );
210 size_t ny = static_cast<size_t>( image().height() ) / static_cast<size_t>( _ySampling );
211 memset(&_pixels[0][0],0,nx*ny*sizeof(T));
212 }
213
214
215 inline const IMATH_NAMESPACE::Box2i &
dataWindow()216 Image::dataWindow () const
217 {
218 return _dataWindow;
219 }
220
221
222 inline int
width()223 Image::width () const
224 {
225 return _dataWindow.max.x - _dataWindow.min.x + 1;
226 }
227
228
229 inline int
height()230 Image::height () const
231 {
232 return _dataWindow.max.y - _dataWindow.min.y + 1;
233 }
234
235
236 template <class T>
237 TypedImageChannel<T> &
typedChannel(const std::string & name)238 Image::typedChannel (const std::string &name)
239 {
240 return dynamic_cast <TypedImageChannel<T>&> (channel (name));
241 }
242
243
244 template <class T>
245 const TypedImageChannel<T> &
typedChannel(const std::string & name)246 Image::typedChannel (const std::string &name) const
247 {
248 return dynamic_cast <const TypedImageChannel<T>&> (channel (name));
249 }
250
251
252 #endif
253