Cycles: Remove unneeded include statements
[blender-staging.git] / intern / cycles / util / util_image_impl.h
1 /*
2  * Copyright 2011-2016 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef __UTIL_IMAGE_IMPL_H__
18 #define __UTIL_IMAGE_IMPL_H__
19
20 #include "util/util_algorithm.h"
21 #include "util/util_half.h"
22 #include "util/util_image.h"
23
24 CCL_NAMESPACE_BEGIN
25
26 namespace {
27
28 template<typename T>
29 const T *util_image_read(const vector<T>& pixels,
30                          const size_t width,
31                          const size_t height,
32                          const size_t /*depth*/,
33                          const size_t components,
34                          const size_t x, const size_t y, const size_t z) {
35         const size_t index = ((size_t)z * (width * height) +
36                               (size_t)y * width +
37                               (size_t)x) * components;
38         return &pixels[index];
39 }
40
41 /* Cast input pixel from unknown storage to float. */
42 template<typename T>
43 inline float cast_to_float(T value);
44
45 template<>
46 inline float cast_to_float(float value)
47 {
48         return value;
49 }
50 template<>
51 inline float cast_to_float(uchar value)
52 {
53         return (float)value / 255.0f;
54 }
55 template<>
56 inline float cast_to_float(half value)
57 {
58         return half_to_float(value);
59 }
60
61 /* Cast float value to output pixel type. */
62 template<typename T>
63 inline T cast_from_float(float value);
64
65 template<>
66 inline float cast_from_float(float value)
67 {
68         return value;
69 }
70 template<>
71 inline uchar cast_from_float(float value)
72 {
73         if(value < 0.0f) {
74                 return 0;
75         }
76         else if(value > (1.0f - 0.5f / 255.0f)) {
77                 return 255;
78         }
79         return (uchar)((255.0f * value) + 0.5f);
80 }
81 template<>
82 inline half cast_from_float(float value)
83 {
84         return float_to_half(value);
85 }
86
87 template<typename T>
88 void util_image_downscale_sample(const vector<T>& pixels,
89                                  const size_t width,
90                                  const size_t height,
91                                  const size_t depth,
92                                  const size_t components,
93                                  const size_t kernel_size,
94                                  const float x,
95                                  const float y,
96                                  const float z,
97                                  T *result)
98 {
99         assert(components <= 4);
100         const size_t ix = (size_t)x,
101                      iy = (size_t)y,
102                      iz = (size_t)z;
103         /* TODO(sergey): Support something smarter than box filer. */
104         float accum[4] = {0};
105         size_t count = 0;
106         for(size_t dz = 0; dz < kernel_size; ++dz) {
107                 for(size_t dy = 0; dy < kernel_size; ++dy) {
108                         for(size_t dx = 0; dx < kernel_size; ++dx) {
109                                 const size_t nx = ix + dx,
110                                              ny = iy + dy,
111                                              nz = iz + dz;
112                                 if(nx >= width || ny >= height || nz >= depth) {
113                                         continue;
114                                 }
115                                 const T *pixel = util_image_read(pixels,
116                                                                  width, height, depth,
117                                                                  components,
118                                                                  nx, ny, nz);
119                                 for(size_t k = 0; k < components; ++k) {
120                                         accum[k] += cast_to_float(pixel[k]);
121                                 }
122                                 ++count;
123                         }
124                 }
125         }
126         if(count != 0) {
127                 const float inv_count = 1.0f / (float)count;
128                 for(size_t k = 0; k < components; ++k) {
129                         result[k] = cast_from_float<T>(accum[k] * inv_count);
130                 }
131         }
132         else {
133                 for(size_t k = 0; k < components; ++k) {
134                         result[k] = T(0.0f);
135                 }
136         }
137 }
138
139 template<typename T>
140 void util_image_downscale_pixels(const vector<T>& input_pixels,
141                                  const size_t input_width,
142                                  const size_t input_height,
143                                  const size_t input_depth,
144                                  const size_t components,
145                                  const float inv_scale_factor,
146                                  const size_t output_width,
147                                  const size_t output_height,
148                                  const size_t output_depth,
149                                  vector<T> *output_pixels)
150 {
151         const size_t kernel_size = (size_t)(inv_scale_factor + 0.5f);
152         for(size_t z = 0; z < output_depth; ++z) {
153                 for(size_t y = 0; y < output_height; ++y) {
154                         for(size_t x = 0; x < output_width; ++x) {
155                                 const float input_x = (float)x * inv_scale_factor,
156                                             input_y = (float)y * inv_scale_factor,
157                                             input_z = (float)z * inv_scale_factor;
158                                 const size_t output_index =
159                                         (z * output_width * output_height +
160                                          y * output_width + x) * components;
161                                 util_image_downscale_sample(input_pixels,
162                                                             input_width, input_height, input_depth,
163                                                             components,
164                                                             kernel_size,
165                                                             input_x, input_y, input_z,
166                                                             &output_pixels->at(output_index));
167                         }
168                 }
169         }
170 }
171
172 }  /* namespace */
173
174 template<typename T>
175 void util_image_resize_pixels(const vector<T>& input_pixels,
176                               const size_t input_width,
177                               const size_t input_height,
178                               const size_t input_depth,
179                               const size_t components,
180                               const float scale_factor,
181                               vector<T> *output_pixels,
182                               size_t *output_width,
183                               size_t *output_height,
184                               size_t *output_depth)
185 {
186         /* Early output for case when no scaling is applied. */
187         if(scale_factor == 1.0f) {
188                 *output_width = input_width;
189                 *output_height = input_height;
190                 *output_depth = input_depth;
191                 *output_pixels = input_pixels;
192                 return;
193         }
194         /* First of all, we calculate output image dimensions.
195          * We clamp them to be 1 pixel at least so we do not generate degenerate
196          * image.
197          */
198         *output_width = max((size_t)((float)input_width * scale_factor), (size_t)1);
199         *output_height = max((size_t)((float)input_height * scale_factor), (size_t)1);
200         *output_depth = max((size_t)((float)input_depth * scale_factor), (size_t)1);
201         /* Prepare pixel storage for the result. */
202         const size_t num_output_pixels = ((*output_width) *
203                                           (*output_height) *
204                                           (*output_depth)) * components;
205         output_pixels->resize(num_output_pixels);
206         if(scale_factor < 1.0f) {
207                 const float inv_scale_factor = 1.0f / scale_factor;
208                 util_image_downscale_pixels(input_pixels,
209                                             input_width, input_height, input_depth,
210                                             components,
211                                             inv_scale_factor,
212                                             *output_width, *output_height, *output_depth,
213                                             output_pixels);
214         } else {
215                 /* TODO(sergey): Needs implementation. */
216         }
217 }
218
219 CCL_NAMESPACE_END
220
221 #endif  /* __UTIL_IMAGE_IMPL_H__ */