source: src/filter/scale0tilt/scale0tilt.c @ a11a00

Revision a11a00, 7.6 KB checked in by Dan Dennedy <dan@…>, 3 years ago (diff)

Fix segfault in scale0tilt on insane widths (ticket:18).

Patch from Burkhard Plaum with indentation fix by me.

  • Property mode set to 100644
Line 
1/* scale0tilt.c
2 * Copyright (C) 2007 Richard Spindler (richard.spindler@gmail.com)
3 * This file is a Frei0r plugin.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#include <math.h>
21#include "frei0r.h"
22#include <gavl/gavl.h>
23#include <stdlib.h>
24#include <string.h>
25
26#define EPSILON 1e-6
27
28typedef struct scale0tilt_instance {
29        double cl, ct, cr, cb;
30        double sx, sy;
31        double tx, ty;
32        int w, h;
33        gavl_video_scaler_t* video_scaler;
34        gavl_video_frame_t* frame_src;
35        gavl_video_frame_t* frame_dst;
36        int do_scale;
37} scale0tilt_instance_t;
38
39void update_scaler( scale0tilt_instance_t* inst )
40{
41        float dst_x, dst_y, dst_w, dst_h;
42        float src_x, src_y, src_w, src_h;
43       
44        inst->do_scale = 1;
45        src_x = inst->w * inst->cl;
46        src_y = inst->h * inst->ct;
47        src_w = inst->w * (1.0 - inst->cl - inst->cr );
48        src_h = inst->h * (1.0 - inst->ct - inst->cb );
49
50        dst_x = inst->w * inst->cl * inst->sx + inst->tx * inst->w;
51        dst_y = inst->h * inst->ct * inst->sy + inst->ty * inst->h;
52        dst_w = inst->w * (1.0 - inst->cl - inst->cr) * inst->sx;
53        dst_h = inst->h * (1.0 - inst->ct - inst->cb) * inst->sy;
54
55        if((dst_w < EPSILON) || (dst_h < EPSILON) ||
56           (src_w < EPSILON) || (src_h < EPSILON)) {
57                inst->do_scale = 0;
58                return;
59        }
60
61        if ( dst_x + dst_w > inst->w ) {
62                src_w = src_w * ( (inst->w-dst_x) / dst_w );
63                dst_w = inst->w - dst_x;
64        }
65        if ( dst_y + dst_h > inst->h ) {
66                src_h = src_h * ( (inst->h-dst_y) / dst_h );
67                dst_h = inst->h - dst_y;
68        }
69        if ( dst_x < 0 ) {
70                src_x = src_x - dst_x * ( src_w / dst_w );
71                src_w = src_w * ( (dst_w+dst_x) / dst_w );
72                dst_w = dst_w + dst_x;
73                dst_x = 0;
74        }
75        if ( dst_y < 0 ) {
76                src_y = src_y - dst_y * ( src_h / dst_h );
77                src_h = src_h * ( (dst_h+dst_y) / dst_h );
78                dst_h = dst_h + dst_y;
79                dst_y = 0;
80        }
81
82        if((dst_w < EPSILON) || (dst_h < EPSILON) ||
83           (src_w < EPSILON) || (src_h < EPSILON)) {
84                inst->do_scale = 0;
85                return;
86        }
87
88        gavl_video_options_t* options = gavl_video_scaler_get_options( inst->video_scaler );
89
90        gavl_video_format_t format_src;
91        gavl_video_format_t format_dst;
92
93        memset(&format_src, 0, sizeof(format_src));
94        memset(&format_dst, 0, sizeof(format_dst));
95
96        format_dst.frame_width  = inst->w;
97        format_dst.frame_height = inst->h;
98        format_dst.image_width  = inst->w;
99        format_dst.image_height = inst->h;
100        format_dst.pixel_width = 1;
101        format_dst.pixel_height = 1;
102        format_dst.pixelformat = GAVL_RGBA_32;
103       
104        format_src.frame_width  = inst->w;
105        format_src.frame_height = inst->h;
106        format_src.image_width  = inst->w;
107        format_src.image_height = inst->h;
108        format_src.pixel_width = 1;
109        format_src.pixel_height = 1;
110        format_src.pixelformat = GAVL_RGBA_32;
111
112        gavl_rectangle_f_t src_rect;
113        gavl_rectangle_i_t dst_rect;
114
115        src_rect.x = src_x;
116        src_rect.y = src_y;
117        src_rect.w = src_w;
118        src_rect.h = src_h;
119
120        dst_rect.x = lroundf(dst_x);
121        dst_rect.y = lroundf(dst_y);
122        dst_rect.w = lroundf(dst_w);
123        dst_rect.h = lroundf(dst_h);
124       
125        gavl_video_options_set_rectangles( options, &src_rect, &dst_rect );
126        gavl_video_scaler_init( inst->video_scaler, &format_src, &format_dst );
127}
128
129int f0r_init()
130{
131  return 1;
132}
133void f0r_deinit()
134{ /* empty */ }
135
136void f0r_get_plugin_info( f0r_plugin_info_t* info )
137{
138        info->name = "Scale0Tilt";
139        info->author = "Richard Spindler";
140        info->plugin_type = F0R_PLUGIN_TYPE_FILTER;
141        info->color_model = F0R_COLOR_MODEL_RGBA8888;
142        info->frei0r_version = FREI0R_MAJOR_VERSION;
143        info->major_version = 0;
144        info->minor_version = 1;
145        info->num_params =  8;
146        info->explanation = "Scales, Tilts and Crops an Image";
147
148}
149void f0r_get_param_info( f0r_param_info_t* info, int param_index )
150{
151        switch ( param_index ) {
152                case 0:
153                        info->name = "Clip left";
154                        info->type = F0R_PARAM_DOUBLE;
155                        info->explanation = "";
156                        break;
157                case 1:
158                        info->name = "Clip right";
159                        info->type = F0R_PARAM_DOUBLE;
160                        info->explanation = "";
161                        break;
162                case 2:
163                        info->name = "Clip top";
164                        info->type = F0R_PARAM_DOUBLE;
165                        info->explanation = "";
166                        break;
167                case 3:
168                        info->name = "Clip bottom";
169                        info->type = F0R_PARAM_DOUBLE;
170                        info->explanation = "";
171                        break;
172                case 4:
173                        info->name = "Scale X";
174                        info->type = F0R_PARAM_DOUBLE;
175                        info->explanation = "";
176                        break;
177                case 5:
178                        info->name = "Scale Y";
179                        info->type = F0R_PARAM_DOUBLE;
180                        info->explanation = "";
181                        break;
182                case 6:
183                        info->name = "Tilt X";
184                        info->type = F0R_PARAM_DOUBLE;
185                        info->explanation = "";
186                        break;
187                case 7:
188                        info->name = "Tilt Y";
189                        info->type = F0R_PARAM_DOUBLE;
190                        info->explanation = "";
191                        break;
192        }
193}
194
195f0r_instance_t f0r_construct(unsigned int width, unsigned int height)
196{
197        scale0tilt_instance_t* inst = calloc(1, sizeof(*inst));
198        inst->w = width;
199        inst->h = height;
200        inst->sx = 1.0;
201        inst->sy = 1.0;
202        inst->video_scaler = gavl_video_scaler_create();
203        inst->frame_src = gavl_video_frame_create( 0 );
204        inst->frame_dst = gavl_video_frame_create( 0 );
205        inst->frame_src->strides[0] = width * 4;
206        inst->frame_dst->strides[0] = width * 4;
207        update_scaler(inst);
208        return (f0r_instance_t)inst;
209}
210void f0r_destruct(f0r_instance_t instance)
211{
212        scale0tilt_instance_t* inst = (scale0tilt_instance_t*)instance;
213        gavl_video_scaler_destroy(inst->video_scaler);
214        gavl_video_frame_null( inst->frame_src );
215        gavl_video_frame_destroy( inst->frame_src );
216        gavl_video_frame_null( inst->frame_dst );
217        gavl_video_frame_destroy( inst->frame_dst );
218        free(instance);
219}
220void f0r_set_param_value(f0r_instance_t instance,
221                         f0r_param_t param, int param_index)
222{
223        scale0tilt_instance_t* inst = (scale0tilt_instance_t*)instance;
224        switch ( param_index ) {
225                case 0:
226                        inst->cl = *((double*)param);
227                        break;
228                case 1:
229                        inst->cr = *((double*)param);
230                        break;
231                case 2:
232                        inst->ct = *((double*)param);
233                        break;
234                case 3:
235                        inst->cb = *((double*)param);
236                        break;
237                case 4:
238                        inst->sx = *((double*)param) * 2.0;
239                        break;
240                case 5:
241                        inst->sy = *((double*)param) * 2.0;
242                        break;
243                case 6:
244                        inst->tx = *((double*)param) * 2.0 - 1.0;
245                        break;
246                case 7:
247                        inst->ty = *((double*)param) * 2.0 - 1.0;
248                        break;
249        }
250        update_scaler( inst );
251}
252void f0r_get_param_value(f0r_instance_t instance,
253                         f0r_param_t param, int param_index)
254{
255        scale0tilt_instance_t* inst = (scale0tilt_instance_t*)instance;
256        switch ( param_index ) {
257                case 0:
258                        *((double*)param) = inst->cl;
259                        break;
260                case 1:
261                        *((double*)param) = inst->cr;
262                        break;
263                case 2:
264                        *((double*)param) = inst->ct;
265                        break;
266                case 3:
267                        *((double*)param) = inst->cb;
268                        break;
269                case 4:
270                        *((double*)param) = inst->sx / 2.0;
271                        break;
272                case 5:
273                        *((double*)param) = inst->sy / 2.0;
274                        break;
275                case 6:
276                        *((double*)param) = (inst->tx + 1.0) / 2.0;
277                        break;
278                case 7:
279                        *((double*)param) = (inst->ty + 1.0) / 2.0;
280                        break;
281        }
282}
283void f0r_update(f0r_instance_t instance, double time,
284                const uint32_t* inframe, uint32_t* outframe)
285{
286        scale0tilt_instance_t* inst = (scale0tilt_instance_t*)instance;
287        inst->frame_src->planes[0] = (uint8_t *)inframe;
288        inst->frame_dst->planes[0] = (uint8_t *)outframe;
289        int len = inst->w * inst->h;
290        int i;
291        for ( i = 0; i < len; i++ ) {
292                outframe[i] = 0;
293        }
294        if(inst->do_scale)
295                gavl_video_scaler_scale( inst->video_scaler, inst->frame_src, inst->frame_dst );
296}
297
Note: See TracBrowser for help on using the repository browser.