Cycles: Code cleanup, spaces around keywords
[blender-staging.git] / intern / cycles / blender / blender_camera.cpp
1 /*
2  * Copyright 2011-2013 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 #include "camera.h"
18 #include "scene.h"
19
20 #include "blender_sync.h"
21 #include "blender_util.h"
22
23 #include "util_logging.h"
24
25 CCL_NAMESPACE_BEGIN
26
27 /* Blender Camera Intermediate: we first convert both the offline and 3d view
28  * render camera to this, and from there convert to our native camera format. */
29
30 struct BlenderCamera {
31         float nearclip;
32         float farclip;
33
34         CameraType type;
35         float ortho_scale;
36
37         float lens;
38         float shuttertime;
39
40         float aperturesize;
41         uint apertureblades;
42         float aperturerotation;
43         float focaldistance;
44
45         float2 shift;
46         float2 offset;
47         float zoom;
48
49         float2 pixelaspect;
50
51         float aperture_ratio;
52
53         PanoramaType panorama_type;
54         float fisheye_fov;
55         float fisheye_lens;
56         float latitude_min;
57         float latitude_max;
58         float longitude_min;
59         float longitude_max;
60
61         enum { AUTO, HORIZONTAL, VERTICAL } sensor_fit;
62         float sensor_width;
63         float sensor_height;
64
65         int full_width;
66         int full_height;
67
68         BoundBox2D border;
69         BoundBox2D pano_viewplane;
70         BoundBox2D viewport_camera_border;
71
72         Transform matrix;
73 };
74
75 static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings b_render)
76 {
77         memset(bcam, 0, sizeof(BlenderCamera));
78
79         bcam->type = CAMERA_PERSPECTIVE;
80         bcam->zoom = 1.0f;
81         bcam->pixelaspect = make_float2(1.0f, 1.0f);
82         bcam->sensor_width = 32.0f;
83         bcam->sensor_height = 18.0f;
84         bcam->sensor_fit = BlenderCamera::AUTO;
85         bcam->shuttertime = 1.0f;
86         bcam->border.right = 1.0f;
87         bcam->border.top = 1.0f;
88         bcam->pano_viewplane.right = 1.0f;
89         bcam->pano_viewplane.top = 1.0f;
90         bcam->viewport_camera_border.right = 1.0f;
91         bcam->viewport_camera_border.top = 1.0f;
92
93         /* render resolution */
94         bcam->full_width = render_resolution_x(b_render);
95         bcam->full_height = render_resolution_y(b_render);
96 }
97
98 static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera)
99 {
100         BL::Object b_dof_object = b_camera.dof_object();
101
102         if(!b_dof_object)
103                 return b_camera.dof_distance();
104         
105         /* for dof object, return distance along camera Z direction */
106         Transform obmat = transform_clear_scale(get_transform(b_ob.matrix_world()));
107         Transform dofmat = get_transform(b_dof_object.matrix_world());
108         Transform mat = transform_inverse(obmat) * dofmat;
109
110         return fabsf(transform_get_column(&mat, 3).z);
111 }
112
113 static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob, bool skip_panorama = false)
114 {
115         BL::ID b_ob_data = b_ob.data();
116
117         if(b_ob_data.is_a(&RNA_Camera)) {
118                 BL::Camera b_camera(b_ob_data);
119                 PointerRNA ccamera = RNA_pointer_get(&b_camera.ptr, "cycles");
120
121                 bcam->nearclip = b_camera.clip_start();
122                 bcam->farclip = b_camera.clip_end();
123
124                 switch(b_camera.type())
125                 {
126                         case BL::Camera::type_ORTHO:
127                                 bcam->type = CAMERA_ORTHOGRAPHIC;
128                                 break;
129                         case BL::Camera::type_PANO:
130                                 if(!skip_panorama)
131                                         bcam->type = CAMERA_PANORAMA;
132                                 else
133                                         bcam->type = CAMERA_PERSPECTIVE;
134                                 break;
135                         case BL::Camera::type_PERSP:
136                         default:
137                                 bcam->type = CAMERA_PERSPECTIVE;
138                                 break;
139                 }       
140
141                 switch(RNA_enum_get(&ccamera, "panorama_type"))
142                 {
143                         case 1:
144                                 bcam->panorama_type = PANORAMA_FISHEYE_EQUIDISTANT;
145                                 break;
146                         case 2:
147                                 bcam->panorama_type = PANORAMA_FISHEYE_EQUISOLID;
148                                 break;
149                         case 0:
150                         default:
151                                 bcam->panorama_type = PANORAMA_EQUIRECTANGULAR;
152                                 break;
153                 }       
154
155                 bcam->fisheye_fov = RNA_float_get(&ccamera, "fisheye_fov");
156                 bcam->fisheye_lens = RNA_float_get(&ccamera, "fisheye_lens");
157                 bcam->latitude_min = RNA_float_get(&ccamera, "latitude_min");
158                 bcam->latitude_max = RNA_float_get(&ccamera, "latitude_max");
159                 bcam->longitude_min = RNA_float_get(&ccamera, "longitude_min");
160                 bcam->longitude_max = RNA_float_get(&ccamera, "longitude_max");
161
162                 bcam->ortho_scale = b_camera.ortho_scale();
163
164                 bcam->lens = b_camera.lens();
165
166                 /* allow f/stop number to change aperture_size but still
167                  * give manual control over aperture radius */
168                 int aperture_type = RNA_enum_get(&ccamera, "aperture_type");
169
170                 if(aperture_type == 1) {
171                         float fstop = RNA_float_get(&ccamera, "aperture_fstop");
172                         fstop = max(fstop, 1e-5f);
173
174                         if(bcam->type == CAMERA_ORTHOGRAPHIC)
175                                 bcam->aperturesize = 1.0f/(2.0f*fstop);
176                         else
177                                 bcam->aperturesize = (bcam->lens*1e-3f)/(2.0f*fstop);
178                 }
179                 else
180                         bcam->aperturesize = RNA_float_get(&ccamera, "aperture_size");
181
182                 bcam->apertureblades = RNA_int_get(&ccamera, "aperture_blades");
183                 bcam->aperturerotation = RNA_float_get(&ccamera, "aperture_rotation");
184                 bcam->focaldistance = blender_camera_focal_distance(b_ob, b_camera);
185                 bcam->aperture_ratio = RNA_float_get(&ccamera, "aperture_ratio");
186
187                 bcam->shift.x = b_camera.shift_x();
188                 bcam->shift.y = b_camera.shift_y();
189
190                 bcam->sensor_width = b_camera.sensor_width();
191                 bcam->sensor_height = b_camera.sensor_height();
192
193                 if(b_camera.sensor_fit() == BL::Camera::sensor_fit_AUTO)
194                         bcam->sensor_fit = BlenderCamera::AUTO;
195                 else if(b_camera.sensor_fit() == BL::Camera::sensor_fit_HORIZONTAL)
196                         bcam->sensor_fit = BlenderCamera::HORIZONTAL;
197                 else
198                         bcam->sensor_fit = BlenderCamera::VERTICAL;
199         }
200         else {
201                 /* from lamp not implemented yet */
202         }
203 }
204
205 static Transform blender_camera_matrix(const Transform& tfm, CameraType type)
206 {
207         Transform result;
208
209         if(type == CAMERA_PANORAMA) {
210                 /* make it so environment camera needs to be pointed in the direction
211                  * of the positive x-axis to match an environment texture, this way
212                  * it is looking at the center of the texture */
213                 result = tfm *
214                         make_transform( 0.0f, -1.0f, 0.0f, 0.0f,
215                                         0.0f,  0.0f, 1.0f, 0.0f,
216                                        -1.0f,  0.0f, 0.0f, 0.0f,
217                                         0.0f,  0.0f, 0.0f, 1.0f);
218         }
219         else {
220                 /* note the blender camera points along the negative z-axis */
221                 result = tfm * transform_scale(1.0f, 1.0f, -1.0f);
222         }
223
224         return transform_clear_scale(result);
225 }
226
227 static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height,
228         BoundBox2D *viewplane, float *aspectratio, float *sensor_size)
229 {
230         /* dimensions */
231         float xratio = (float)width*bcam->pixelaspect.x;
232         float yratio = (float)height*bcam->pixelaspect.y;
233
234         /* compute x/y aspect and ratio */
235         float xaspect, yaspect;
236         bool horizontal_fit;
237
238         /* sensor fitting */
239         if(bcam->sensor_fit == BlenderCamera::AUTO) {
240                 horizontal_fit = (xratio > yratio);
241                 *sensor_size = bcam->sensor_width;
242         }
243         else if(bcam->sensor_fit == BlenderCamera::HORIZONTAL) {
244                 horizontal_fit = true;
245                 *sensor_size = bcam->sensor_width;
246         }
247         else {
248                 horizontal_fit = false;
249                 *sensor_size = bcam->sensor_height;
250         }
251
252         if(horizontal_fit) {
253                 *aspectratio = xratio/yratio;
254                 xaspect = *aspectratio;
255                 yaspect = 1.0f;
256         }
257         else {
258                 *aspectratio = yratio/xratio;
259                 xaspect = 1.0f;
260                 yaspect = *aspectratio;
261         }
262
263         /* modify aspect for orthographic scale */
264         if(bcam->type == CAMERA_ORTHOGRAPHIC) {
265                 xaspect = xaspect*bcam->ortho_scale/(*aspectratio*2.0f);
266                 yaspect = yaspect*bcam->ortho_scale/(*aspectratio*2.0f);
267                 *aspectratio = bcam->ortho_scale/2.0f;
268         }
269
270         if(bcam->type == CAMERA_PANORAMA) {
271                 /* set viewplane */
272                 *viewplane = bcam->pano_viewplane;
273         }
274         else {
275                 /* set viewplane */
276                 viewplane->left = -xaspect;
277                 viewplane->right = xaspect;
278                 viewplane->bottom = -yaspect;
279                 viewplane->top = yaspect;
280
281                 /* zoom for 3d camera view */
282                 *viewplane = (*viewplane) * bcam->zoom;
283
284                 /* modify viewplane with camera shift and 3d camera view offset */
285                 float dx = 2.0f*(*aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f);
286                 float dy = 2.0f*(*aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f);
287
288                 viewplane->left += dx;
289                 viewplane->right += dx;
290                 viewplane->bottom += dy;
291                 viewplane->top += dy;
292         }
293 }
294
295 static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int height)
296 {
297         /* copy camera to compare later */
298         Camera prevcam = *cam;
299         float aspectratio, sensor_size;
300
301         /* viewplane */
302         blender_camera_viewplane(bcam, width, height,
303                 &cam->viewplane, &aspectratio, &sensor_size);
304
305         /* panorama sensor */
306         if(bcam->type == CAMERA_PANORAMA && bcam->panorama_type == PANORAMA_FISHEYE_EQUISOLID) {
307                 float fit_xratio = (float)bcam->full_width*bcam->pixelaspect.x;
308                 float fit_yratio = (float)bcam->full_height*bcam->pixelaspect.y;
309                 bool horizontal_fit;
310                 float sensor_size;
311
312                 if(bcam->sensor_fit == BlenderCamera::AUTO) {
313                         horizontal_fit = (fit_xratio > fit_yratio);
314                         sensor_size = bcam->sensor_width;
315                 }
316                 else if(bcam->sensor_fit == BlenderCamera::HORIZONTAL) {
317                         horizontal_fit = true;
318                         sensor_size = bcam->sensor_width;
319                 }
320                 else { /* vertical */
321                         horizontal_fit = false;
322                         sensor_size = bcam->sensor_height;
323                 }
324
325                 if(horizontal_fit) {
326                         cam->sensorwidth = sensor_size;
327                         cam->sensorheight = sensor_size * fit_yratio / fit_xratio;
328                 }
329                 else {
330                         cam->sensorwidth = sensor_size * fit_xratio / fit_yratio;
331                         cam->sensorheight = sensor_size;
332                 }
333         }
334
335         /* clipping distances */
336         cam->nearclip = bcam->nearclip;
337         cam->farclip = bcam->farclip;
338
339         /* type */
340         cam->type = bcam->type;
341
342         /* panorama */
343         cam->panorama_type = bcam->panorama_type;
344         cam->fisheye_fov = bcam->fisheye_fov;
345         cam->fisheye_lens = bcam->fisheye_lens;
346         cam->latitude_min = bcam->latitude_min;
347         cam->latitude_max = bcam->latitude_max;
348
349         cam->longitude_min = bcam->longitude_min;
350         cam->longitude_max = bcam->longitude_max;
351
352         /* anamorphic lens bokeh */
353         cam->aperture_ratio = bcam->aperture_ratio;
354
355         /* perspective */
356         cam->fov = 2.0f * atanf((0.5f * sensor_size) / bcam->lens / aspectratio);
357         cam->focaldistance = bcam->focaldistance;
358         cam->aperturesize = bcam->aperturesize;
359         cam->blades = bcam->apertureblades;
360         cam->bladesrotation = bcam->aperturerotation;
361
362         /* transform */
363         cam->matrix = blender_camera_matrix(bcam->matrix, bcam->type);
364         cam->motion.pre = cam->matrix;
365         cam->motion.post = cam->matrix;
366         cam->use_motion = false;
367         cam->shuttertime = bcam->shuttertime;
368
369         /* border */
370         cam->border = bcam->border;
371         cam->viewport_camera_border = bcam->viewport_camera_border;
372
373         /* set update flag */
374         if(cam->modified(prevcam))
375                 cam->tag_update();
376 }
377
378 /* Sync Render Camera */
379
380 void BlenderSync::sync_camera(BL::RenderSettings b_render, BL::Object b_override, int width, int height)
381 {
382         BlenderCamera bcam;
383         blender_camera_init(&bcam, b_render);
384
385         /* pixel aspect */
386         bcam.pixelaspect.x = b_render.pixel_aspect_x();
387         bcam.pixelaspect.y = b_render.pixel_aspect_y();
388         bcam.shuttertime = b_render.motion_blur_shutter();
389
390         /* border */
391         if(b_render.use_border()) {
392                 bcam.border.left = b_render.border_min_x();
393                 bcam.border.right = b_render.border_max_x();
394                 bcam.border.bottom = b_render.border_min_y();
395                 bcam.border.top = b_render.border_max_y();
396         }
397
398         /* camera object */
399         BL::Object b_ob = b_scene.camera();
400
401         if(b_override)
402                 b_ob = b_override;
403
404         if(b_ob) {
405                 blender_camera_from_object(&bcam, b_ob);
406                 bcam.matrix = get_transform(b_ob.matrix_world());
407         }
408
409         /* sync */
410         Camera *cam = scene->camera;
411         blender_camera_sync(cam, &bcam, width, height);
412 }
413
414 void BlenderSync::sync_camera_motion(BL::Object b_ob, float motion_time)
415 {
416         Camera *cam = scene->camera;
417
418         Transform tfm = get_transform(b_ob.matrix_world());
419         tfm = blender_camera_matrix(tfm, cam->type);
420
421         if(tfm != cam->matrix) {
422                 VLOG(1) << "Camera " << b_ob.name() << " motion detected.";
423                 if(motion_time == -1.0f) {
424                         cam->motion.pre = tfm;
425                         cam->use_motion = true;
426                 }
427                 else if(motion_time == 1.0f) {
428                         cam->motion.post = tfm;
429                         cam->use_motion = true;
430                 }
431         }
432 }
433
434 /* Sync 3D View Camera */
435
436 static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d,
437         BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box);
438
439 static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height, bool skip_panorama = false)
440 {
441         /* 3d view parameters */
442         bcam->nearclip = b_v3d.clip_start();
443         bcam->farclip = b_v3d.clip_end();
444         bcam->lens = b_v3d.lens();
445         bcam->shuttertime = b_scene.render().motion_blur_shutter();
446
447         if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA) {
448                 /* camera view */
449                 BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera();
450
451                 if(b_ob) {
452                         blender_camera_from_object(bcam, b_ob, skip_panorama);
453
454                         if(!skip_panorama && bcam->type == CAMERA_PANORAMA) {
455                                 /* in panorama camera view, we map viewplane to camera border */
456                                 BoundBox2D view_box, cam_box;
457
458                                 blender_camera_view_subset(b_scene.render(), b_scene, b_ob, b_v3d, b_rv3d, width, height,
459                                         &view_box, &cam_box);
460
461                                 bcam->pano_viewplane = view_box.make_relative_to(cam_box);
462                         }
463                         else {
464                                 /* magic zoom formula */
465                                 bcam->zoom = (float)b_rv3d.view_camera_zoom();
466                                 bcam->zoom = (1.41421f + bcam->zoom/50.0f);
467                                 bcam->zoom *= bcam->zoom;
468                                 bcam->zoom = 2.0f/bcam->zoom;
469
470                                 /* offset */
471                                 bcam->offset = get_float2(b_rv3d.view_camera_offset());
472                         }
473                 }
474         }
475         else if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_ORTHO) {
476                 /* orthographic view */
477                 bcam->farclip *= 0.5f;
478                 bcam->nearclip = -bcam->farclip;
479
480                 float sensor_size;
481                 if(bcam->sensor_fit == BlenderCamera::VERTICAL)
482                         sensor_size = bcam->sensor_height;
483                 else
484                         sensor_size = bcam->sensor_width;
485
486                 bcam->type = CAMERA_ORTHOGRAPHIC;
487                 bcam->ortho_scale = b_rv3d.view_distance() * sensor_size / b_v3d.lens();
488         }
489
490         bcam->zoom *= 2.0f;
491
492         /* 3d view transform */
493         bcam->matrix = transform_inverse(get_transform(b_rv3d.view_matrix()));
494 }
495
496 static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d,
497         BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box)
498 {
499         BoundBox2D cam, view;
500         float view_aspect, cam_aspect, sensor_size;
501
502         /* get viewport viewplane */
503         BlenderCamera view_bcam;
504         blender_camera_init(&view_bcam, b_render);
505         blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height, true);
506
507         blender_camera_viewplane(&view_bcam, width, height,
508                 &view, &view_aspect, &sensor_size);
509
510         /* get camera viewplane */
511         BlenderCamera cam_bcam;
512         blender_camera_init(&cam_bcam, b_render);
513         blender_camera_from_object(&cam_bcam, b_ob, true);
514
515         blender_camera_viewplane(&cam_bcam, cam_bcam.full_width, cam_bcam.full_height,
516                 &cam, &cam_aspect, &sensor_size);
517         
518         /* return */
519         *view_box = view * (1.0f/view_aspect);
520         *cam_box = cam * (1.0f/cam_aspect);
521 }
522
523 static void blender_camera_border_subset(BL::RenderSettings b_render,
524                                          BL::Scene b_scene,
525                                          BL::SpaceView3D b_v3d,
526                                          BL::RegionView3D b_rv3d,
527                                          BL::Object b_ob,
528                                          int width, int height,
529                                          const BoundBox2D &border,
530                                          BoundBox2D *result)
531 {
532         /* Determine camera viewport subset. */
533         BoundBox2D view_box, cam_box;
534         blender_camera_view_subset(b_render, b_scene, b_ob, b_v3d, b_rv3d, width, height,
535                                    &view_box, &cam_box);
536
537         /* Determine viewport subset matching given border. */
538         cam_box = cam_box.make_relative_to(view_box);
539         *result = cam_box.subset(border);
540 }
541
542 static void blender_camera_border(BlenderCamera *bcam, BL::RenderSettings b_render, BL::Scene b_scene, BL::SpaceView3D b_v3d,
543         BL::RegionView3D b_rv3d, int width, int height)
544 {
545         bool is_camera_view;
546
547         /* camera view? */
548         is_camera_view = b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA;
549
550         if(!is_camera_view) {
551                 /* for non-camera view check whether render border is enabled for viewport
552                  * and if so use border from 3d viewport
553                  * assume viewport has got correctly clamped border already
554                  */
555                 if(b_v3d.use_render_border()) {
556                         bcam->border.left = b_v3d.render_border_min_x();
557                         bcam->border.right = b_v3d.render_border_max_x();
558                         bcam->border.bottom = b_v3d.render_border_min_y();
559                         bcam->border.top = b_v3d.render_border_max_y();
560                 }
561                 return;
562         }
563
564         BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera();
565
566         if(!b_ob)
567                 return;
568
569         /* Determine camera border inside the viewport. */
570         BoundBox2D full_border;
571         blender_camera_border_subset(b_render,
572                                      b_scene,
573                                      b_v3d,
574                                      b_rv3d,
575                                      b_ob,
576                                      width, height,
577                                      full_border,
578                                      &bcam->viewport_camera_border);
579
580         if(!b_render.use_border()) {
581                 return;
582         }
583
584         bcam->border.left = b_render.border_min_x();
585         bcam->border.right = b_render.border_max_x();
586         bcam->border.bottom = b_render.border_min_y();
587         bcam->border.top = b_render.border_max_y();
588
589         /* Determine viewport subset matching camera border. */
590         blender_camera_border_subset(b_render,
591                                      b_scene,
592                                      b_v3d,
593                                      b_rv3d,
594                                      b_ob,
595                                      width, height,
596                                      bcam->border,
597                                      &bcam->border);
598         bcam->border.clamp();
599 }
600
601 void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height)
602 {
603         BlenderCamera bcam;
604         blender_camera_init(&bcam, b_scene.render());
605         blender_camera_from_view(&bcam, b_scene, b_v3d, b_rv3d, width, height);
606         blender_camera_border(&bcam, b_scene.render(), b_scene, b_v3d, b_rv3d, width, height);
607
608         blender_camera_sync(scene->camera, &bcam, width, height);
609 }
610
611 BufferParams BlenderSync::get_buffer_params(BL::RenderSettings b_render, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, Camera *cam, int width, int height)
612 {
613         BufferParams params;
614         bool use_border = false;
615
616         params.full_width = width;
617         params.full_height = height;
618
619         if(b_v3d && b_rv3d && b_rv3d.view_perspective() != BL::RegionView3D::view_perspective_CAMERA)
620                 use_border = b_v3d.use_render_border();
621         else
622                 use_border = b_render.use_border();
623
624         if(use_border) {
625                 /* border render */
626                 /* the viewport may offset the border outside the view */
627                 BoundBox2D border = cam->border.clamp();
628                 params.full_x = (int)(border.left * (float)width);
629                 params.full_y = (int)(border.bottom * (float)height);
630                 params.width = (int)(border.right * (float)width) - params.full_x;
631                 params.height = (int)(border.top * (float)height) - params.full_y;
632
633                 /* survive in case border goes out of view or becomes too small */
634                 params.width = max(params.width, 1);
635                 params.height = max(params.height, 1);
636         }
637         else {
638                 params.width = width;
639                 params.height = height;
640         }
641
642         return params;
643 }
644
645 CCL_NAMESPACE_END
646