2
Copyright 2013 Larry Gritz and the other authors and contributors.
5
Redistribution and use in source and binary forms, with or without
6
modification, are permitted provided that the following conditions are
8
* Redistributions of source code must retain the above copyright
9
notice, this list of conditions and the following disclaimer.
10
* Redistributions in binary form must reproduce the above copyright
11
notice, this list of conditions and the following disclaimer in the
12
documentation and/or other materials provided with the distribution.
13
* Neither the name of the software's owners nor the names of its
14
contributors may be used to endorse or promote products derived from
15
this software without specific prior written permission.
16
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
(This is the Modified BSD License)
32
#ifndef OPENIMAGEIO_IMAGEBUFALGO_UTIL_H
33
#define OPENIMAGEIO_IMAGEBUFALGO_UTIL_H
35
#include "imagebufalgo.h"
44
namespace ImageBufAlgo {
46
/// Helper template for generalized multithreading for image processing
47
/// functions. Some function/functor f is applied to every pixel the
48
/// region of interest roi, dividing the region into multiple threads if
49
/// threads != 1. Note that threads == 0 indicates that the number of
50
/// threads should be as set by the global OIIO "threads" attribute.
52
/// Most image operations will require additional arguments, including
53
/// additional input and output images or other parameters. The
54
/// parallel_image template can still be used by employing the
55
/// boost::bind (or std::bind, for C++11). For example, suppose you
56
/// have an image operation defined as:
57
/// void my_image_op (ImageBuf &out, const ImageBuf &in,
58
/// float scale, ROI roi);
59
/// Then you can parallelize it as follows:
60
/// ImageBuf R /*result*/, A /*input*/;
61
/// ROI roi = get_roi (R.spec());
62
/// parallel_image (boost::bind(my_image_op,boost::ref(R),
63
/// boost::cref(A),3.14,_1), roi);
67
parallel_image (Func f, ROI roi, int nthreads=0)
69
// Special case: threads <= 0 means to use the "threads" attribute
71
OIIO::getattribute ("threads", nthreads);
73
if (nthreads <= 1 || roi.npixels() < 1000) {
74
// Just one thread, or a small image region: use this thread only
77
// Spawn threads by dividing the region into y bands.
78
boost::thread_group threads;
79
int blocksize = std::max (1, (roi.height() + nthreads - 1) / nthreads);
80
int roi_ybegin = roi.ybegin;
81
int roi_yend = roi.yend;
82
for (int i = 0; i < nthreads; i++) {
83
roi.ybegin = roi_ybegin + i * blocksize;
84
roi.yend = std::min (roi.ybegin + blocksize, roi_yend);
85
if (roi.ybegin >= roi.yend)
86
break; // no more work to dole out
87
threads.add_thread (new boost::thread (f, roi));
95
/// Common preparation for IBA functions: Given an ROI (which may or may not
96
/// be the default ROI::All()), destination image (which may or may not yet
97
/// be allocated), and optional input images, adjust roi if necessary and
98
/// allocate pixels for dst if necessary. If dst is already initialized, it
99
/// will keep its "full" (aka display) window, otherwise its full/display
100
/// window will be set to the union of A's and B's full/display windows. If
101
/// dst is uninitialized and force_spec is not NULL, use *force_spec as
102
/// dst's new spec rather than using A's. Also, if A or B inputs are
103
/// specified but not initialized or broken, it's an error so return false.
104
/// If all is ok, return true. Some additional checks and behaviors may be
105
/// specified by the 'prepflags', which is a bit field defined by
107
bool OIIO_API IBAprep (ROI &roi, ImageBuf *dst,
108
const ImageBuf *A=NULL, const ImageBuf *B=NULL,
109
ImageSpec *force_spec=NULL, int prepflags=0);
113
IBAprep_REQUIRE_ALPHA = 1,
114
IBAprep_REQUIRE_Z = 2,
115
IBAprep_REQUIRE_SAME_NCHANNELS = 4
120
// Macro to call a type-specialzed version func<type>(R,...)
121
#define OIIO_DISPATCH_TYPES(name,func,type,R,...) \
122
switch (type.basetype) { \
123
case TypeDesc::FLOAT : \
124
return func<float> (R, __VA_ARGS__); break; \
125
case TypeDesc::UINT8 : \
126
return func<unsigned char> (R, __VA_ARGS__); break; \
127
case TypeDesc::HALF : \
128
return func<half> (R, __VA_ARGS__); break; \
129
case TypeDesc::UINT16: \
130
return func<unsigned short> (R, __VA_ARGS__); break; \
131
case TypeDesc::INT8 : \
132
return func<char> (R, __VA_ARGS__); break; \
133
case TypeDesc::INT16 : \
134
return func<short> (R, __VA_ARGS__); break; \
135
case TypeDesc::UINT : \
136
return func<unsigned int> (R, __VA_ARGS__); break; \
137
case TypeDesc::INT : \
138
return func<int> (R, __VA_ARGS__); break; \
139
case TypeDesc::DOUBLE: \
140
return func<double> (R, __VA_ARGS__); break; \
142
(R).error ("%s: Unsupported pixel data format '%s'", name, type); \
146
// Helper, do not call from the outside world.
147
#define OIIO_DISPATCH_TYPES2_HELP(name,func,Atype,Btype,R,...) \
148
switch (Btype.basetype) { \
149
case TypeDesc::FLOAT : \
150
return func<Atype,float> (R, __VA_ARGS__); break; \
151
case TypeDesc::UINT8 : \
152
return func<Atype,unsigned char> (R, __VA_ARGS__); break; \
153
case TypeDesc::HALF : \
154
return func<Atype,half> (R, __VA_ARGS__); break; \
155
case TypeDesc::UINT16: \
156
return func<Atype,unsigned short> (R, __VA_ARGS__); break; \
157
case TypeDesc::INT8 : \
158
return func<Atype,char> (R, __VA_ARGS__); break; \
159
case TypeDesc::INT16 : \
160
return func<Atype,short> (R, __VA_ARGS__); break; \
161
case TypeDesc::UINT : \
162
return func<Atype,unsigned int> (R, __VA_ARGS__); break; \
163
case TypeDesc::INT : \
164
return func<Atype,int> (R, __VA_ARGS__); break; \
165
case TypeDesc::DOUBLE : \
166
return func<Atype,double> (R, __VA_ARGS__); break; \
168
(R).error ("%s: Unsupported pixel data format '%s'", name, Btype); \
172
// Macro to call a type-specialzed version func<Atype,Btype>(R,...).
173
#define OIIO_DISPATCH_TYPES2(name,func,Atype,Btype,R,...) \
174
switch (Atype.basetype) { \
175
case TypeDesc::FLOAT : \
176
OIIO_DISPATCH_TYPES2_HELP(name,func,float,Btype,R,__VA_ARGS__); \
177
case TypeDesc::UINT8 : \
178
OIIO_DISPATCH_TYPES2_HELP(name,func,unsigned char,Btype,R,__VA_ARGS__); \
179
case TypeDesc::HALF : \
180
OIIO_DISPATCH_TYPES2_HELP(name,func,half,Btype,R,__VA_ARGS__); \
181
case TypeDesc::UINT16: \
182
OIIO_DISPATCH_TYPES2_HELP(name,func,unsigned short,Btype,R,__VA_ARGS__); \
183
case TypeDesc::INT8: \
184
OIIO_DISPATCH_TYPES2_HELP(name,func,char,Btype,R,__VA_ARGS__); \
185
case TypeDesc::INT16: \
186
OIIO_DISPATCH_TYPES2_HELP(name,func,short,Btype,R,__VA_ARGS__); \
187
case TypeDesc::UINT: \
188
OIIO_DISPATCH_TYPES2_HELP(name,func,unsigned int,Btype,R,__VA_ARGS__); \
189
case TypeDesc::INT: \
190
OIIO_DISPATCH_TYPES2_HELP(name,func,int,Btype,R,__VA_ARGS__); \
191
case TypeDesc::DOUBLE: \
192
OIIO_DISPATCH_TYPES2_HELP(name,func,double,Btype,R,__VA_ARGS__);\
194
(R).error ("%s: Unsupported pixel data format '%s'", name, Atype); \
199
// Macro to call a type-specialzed version func<type>(R,...) for
200
// the most common types, fail for anything else.
201
#define OIIO_DISPATCH_COMMON_TYPES(name,func,type,R,...) \
202
switch (type.basetype) { \
203
case TypeDesc::FLOAT : \
204
return func<float> (R, __VA_ARGS__); break; \
205
case TypeDesc::UINT8 : \
206
return func<unsigned char> (R, __VA_ARGS__); break; \
207
case TypeDesc::HALF : \
208
return func<half> (R, __VA_ARGS__); break; \
209
case TypeDesc::UINT16: \
210
return func<unsigned short> (R, __VA_ARGS__); break; \
212
(R).error ("%s: Unsupported pixel data format '%s'", name, type); \
216
// Helper, do not call from the outside world.
217
#define OIIO_DISPATCH_COMMON_TYPES2_HELP(name,func,Atype,Btype,R,...) \
218
switch (Btype.basetype) { \
219
case TypeDesc::FLOAT : \
220
return func<Atype,float> (R, __VA_ARGS__); break; \
221
case TypeDesc::UINT8 : \
222
return func<Atype,unsigned char> (R, __VA_ARGS__); break; \
223
case TypeDesc::HALF : \
224
return func<Atype,half> (R, __VA_ARGS__); break; \
225
case TypeDesc::UINT16: \
226
return func<Atype,unsigned short> (R, __VA_ARGS__); break; \
228
(R).error ("%s: Unsupported pixel data format '%s'", name, Btype); \
232
// Macro to call a type-specialzed version func<Atype,Btype>(R,...) for
233
// the most common types, fail for anything else.
234
#define OIIO_DISPATCH_COMMON_TYPES2(name,func,Atype,Btype,R,...) \
235
switch (Atype.basetype) { \
236
case TypeDesc::FLOAT : \
237
OIIO_DISPATCH_COMMON_TYPES2_HELP(name,func,float,Btype,R,__VA_ARGS__); \
238
case TypeDesc::UINT8 : \
239
OIIO_DISPATCH_COMMON_TYPES2_HELP(name,func,unsigned char,Btype,R,__VA_ARGS__); \
240
case TypeDesc::HALF : \
241
OIIO_DISPATCH_COMMON_TYPES2_HELP(name,func,half,Btype,R,__VA_ARGS__); \
242
case TypeDesc::UINT16: \
243
OIIO_DISPATCH_COMMON_TYPES2_HELP(name,func,unsigned short,Btype,R,__VA_ARGS__); \
245
(R).error ("%s: Unsupported pixel data format '%s'", name, Atype); \
250
// Helper, do not call from the outside world.
251
#define OIIO_DISPATCH_COMMON_TYPES3_HELP2(name,func,Rtype,Atype,Btype,R,...) \
252
switch (Rtype.basetype) { \
253
case TypeDesc::FLOAT : \
254
return func<float,Atype,Btype> (R, __VA_ARGS__); break; \
255
case TypeDesc::UINT8 : \
256
return func<unsigned char,Atype,Btype> (R, __VA_ARGS__); break; \
257
case TypeDesc::HALF : \
258
return func<half,Atype,Btype> (R, __VA_ARGS__); break; \
259
case TypeDesc::UINT16: \
260
return func<unsigned short,Atype,Btype> (R, __VA_ARGS__); break; \
262
(R).error ("%s: Unsupported pixel data format '%s'", name, Rtype); \
266
// Helper, do not call from the outside world.
267
#define OIIO_DISPATCH_COMMON_TYPES3_HELP(name,func,Rtype,Atype,Btype,R,...) \
268
switch (Btype.basetype) { \
269
case TypeDesc::FLOAT : \
270
OIIO_DISPATCH_COMMON_TYPES3_HELP2(name,func,Rtype,Atype,float,R,__VA_ARGS__); \
271
case TypeDesc::UINT8 : \
272
OIIO_DISPATCH_COMMON_TYPES3_HELP2(name,func,Rtype,Atype,unsigned char,R,__VA_ARGS__); \
273
case TypeDesc::HALF : \
274
OIIO_DISPATCH_COMMON_TYPES3_HELP2(name,func,Rtype,Atype,half,R,__VA_ARGS__); \
275
case TypeDesc::UINT16 : \
276
OIIO_DISPATCH_COMMON_TYPES3_HELP2(name,func,Rtype,Atype,unsigned short,R,__VA_ARGS__); \
278
(R).error ("%s: Unsupported pixel data format '%s'", name, Btype); \
282
// Macro to call a type-specialzed version func<Rtype,Atype,Btype>(R,...)
283
// for the most common types, fail for anything else.
284
#define OIIO_DISPATCH_COMMON_TYPES3(name,func,Rtype,Atype,Btype,R,...) \
285
switch (Atype.basetype) { \
286
case TypeDesc::FLOAT : \
287
OIIO_DISPATCH_COMMON_TYPES3_HELP(name,func,Rtype,float,Btype,R,__VA_ARGS__); \
288
case TypeDesc::UINT8 : \
289
OIIO_DISPATCH_COMMON_TYPES3_HELP(name,func,Rtype,unsigned char,Btype,R,__VA_ARGS__); \
290
case TypeDesc::HALF : \
291
OIIO_DISPATCH_COMMON_TYPES3_HELP(name,func,Rtype,half,Btype,R,__VA_ARGS__); \
292
case TypeDesc::UINT16: \
293
OIIO_DISPATCH_COMMON_TYPES3_HELP(name,func,Rtype,unsigned short,Btype,R,__VA_ARGS__); \
295
(R).error ("%s: Unsupported pixel data format '%s'", name, Atype); \
301
} // end namespace ImageBufAlgo
307
#endif // OPENIMAGEIO_IMAGEBUFALGO_UTIL_H