11/*
22 * filter_remover.c -- filter to interpolate pixels to cover an area
3- * Copyright (c) 2018-2020 Meltytech, LLC
3+ * Copyright (c) 2018-2025 Meltytech, LLC
44 *
55 * This library is free software; you can redistribute it and/or
66 * modify it under the terms of the GNU Lesser General Public
@@ -73,9 +73,10 @@ static mlt_rect constrain_rect(mlt_rect rect, int max_x, int max_y)
7373
7474typedef struct
7575{
76- uint8_t * chan [4 ]; // pointer to the first value in the channel
76+ void * chan [4 ]; // pointer to the first value in the channel
7777 int rowCount [4 ]; // the number of values in each line (row)
7878 int step [4 ]; // the space between values in each line
79+ int word [4 ]; // the number of bits in a word (8 or 16)
7980 mlt_rect rect [4 ]; // rect the area to be removed
8081} slice_desc ;
8182
@@ -90,31 +91,52 @@ static int remove_spot_channel_proc(int id, int index, int jobs, void *data)
9091 (void ) id ; // unused
9192 (void ) jobs ; // unused
9293 slice_desc * desc = ((slice_desc * ) data );
93- uint8_t * chan = desc -> chan [index ];
9494 int rowCount = desc -> rowCount [index ];
9595 int step = desc -> step [index ];
96+ int word = desc -> word [index ];
9697 mlt_rect rect = desc -> rect [index ];
9798 int yStop = rect .y + rect .h ;
9899 int xStop = rect .x + rect .w ;
99100 int rowSize = rowCount * step ;
100- int y ;
101- for (y = rect .y ; y < yStop ; y ++ ) {
102- uint8_t * xValueL = chan + (y * rowSize ) + (((int ) rect .x - 1 ) * step );
103- uint8_t * xValueR = xValueL + ((int ) rect .w * step );
104- uint8_t * p = chan + (y * rowSize ) + ((int ) rect .x * step );
105- double yRatio = 1.0 - ((y - rect .y ) / rect .h );
106- int x ;
107- for (x = rect .x ; x < xStop ; x ++ ) {
108- uint8_t * yValueT = chan + (((int ) rect .y - 1 ) * rowSize ) + (x * step );
109- uint8_t * yValueB = yValueT + (int ) rect .h * rowSize ;
110- double xRatio = 1.0 - ((x - rect .x ) / rect .w );
111- unsigned int xValueInterp = (* xValueL * xRatio ) + (* xValueR * (1.0 - xRatio ));
112- unsigned int yValueInterp = (* yValueT * yRatio ) + (* yValueB * (1.0 - yRatio ));
113- unsigned int value = (xValueInterp + yValueInterp ) / 2 ;
114- if (value > 255 )
115- value = 255 ;
116- * p = value ;
117- p += step ;
101+ if (word == 8 ) {
102+ uint8_t * chan = desc -> chan [index ];
103+ for (int y = rect .y ; y < yStop ; y ++ ) {
104+ uint8_t * xValueL = chan + (y * rowSize ) + (((int ) rect .x - 1 ) * step );
105+ uint8_t * xValueR = xValueL + ((int ) rect .w * step );
106+ uint8_t * p = chan + (y * rowSize ) + ((int ) rect .x * step );
107+ double yRatio = 1.0 - ((y - rect .y ) / rect .h );
108+ for (int x = rect .x ; x < xStop ; x ++ ) {
109+ uint8_t * yValueT = chan + (((int ) rect .y - 1 ) * rowSize ) + (x * step );
110+ uint8_t * yValueB = yValueT + (int ) rect .h * rowSize ;
111+ double xRatio = 1.0 - ((x - rect .x ) / rect .w );
112+ unsigned int xValueInterp = (* xValueL * xRatio ) + (* xValueR * (1.0 - xRatio ));
113+ unsigned int yValueInterp = (* yValueT * yRatio ) + (* yValueB * (1.0 - yRatio ));
114+ unsigned int value = (xValueInterp + yValueInterp ) / 2 ;
115+ if (value > 255 )
116+ value = 255 ;
117+ * p = value ;
118+ p += step ;
119+ }
120+ }
121+ } else if (word == 16 ) {
122+ uint16_t * chan = desc -> chan [index ];
123+ for (int y = rect .y ; y < yStop ; y ++ ) {
124+ uint16_t * xValueL = chan + (y * rowSize ) + (((int ) rect .x - 1 ) * step );
125+ uint16_t * xValueR = xValueL + ((int ) rect .w * step );
126+ uint16_t * p = chan + (y * rowSize ) + ((int ) rect .x * step );
127+ double yRatio = 1.0 - ((y - rect .y ) / rect .h );
128+ for (int x = rect .x ; x < xStop ; x ++ ) {
129+ uint16_t * yValueT = chan + (((int ) rect .y - 1 ) * rowSize ) + (x * step );
130+ uint16_t * yValueB = yValueT + (int ) rect .h * rowSize ;
131+ double xRatio = 1.0 - ((x - rect .x ) / rect .w );
132+ unsigned int xValueInterp = (* xValueL * xRatio ) + (* xValueR * (1.0 - xRatio ));
133+ unsigned int yValueInterp = (* yValueT * yRatio ) + (* yValueB * (1.0 - yRatio ));
134+ unsigned int value = (xValueInterp + yValueInterp ) / 2 ;
135+ if (value > 65535 )
136+ value = 65535 ;
137+ * p = value ;
138+ p += step ;
139+ }
118140 }
119141 }
120142 return 0 ;
@@ -162,6 +184,7 @@ static int filter_get_image(mlt_frame frame,
162184 case mlt_image_rgb :
163185 case mlt_image_yuv422 :
164186 case mlt_image_yuv420p :
187+ case mlt_image_rgba64 :
165188 // These formats are all supported
166189 break ;
167190 default :
@@ -186,6 +209,7 @@ static int filter_get_image(mlt_frame frame,
186209 desc .chan [i ] = img .planes [0 ] + i ;
187210 desc .rowCount [i ] = img .width ;
188211 desc .step [i ] = 4 ;
212+ desc .word [i ] = 8 ;
189213 desc .rect [i ] = rect ;
190214 }
191215 break ;
@@ -195,6 +219,7 @@ static int filter_get_image(mlt_frame frame,
195219 desc .chan [i ] = img .planes [0 ] + i ;
196220 desc .rowCount [i ] = img .width ;
197221 desc .step [i ] = 4 ;
222+ desc .word [i ] = 8 ;
198223 desc .rect [i ] = rect ;
199224 }
200225 break ;
@@ -204,16 +229,19 @@ static int filter_get_image(mlt_frame frame,
204229 desc .chan [0 ] = img .planes [0 ];
205230 desc .rowCount [0 ] = img .width ;
206231 desc .step [0 ] = 2 ;
232+ desc .word [0 ] = 8 ;
207233 desc .rect [0 ] = rect ;
208234 // U
209235 desc .chan [1 ] = img .planes [0 ] + 1 ;
210236 desc .rowCount [1 ] = img .width / 2 ;
211237 desc .step [1 ] = 4 ;
238+ desc .word [1 ] = 8 ;
212239 desc .rect [1 ] = constrain_rect (scale_rect (rect , 2 , 1 ), img .width / 2 , img .height );
213240 // V
214241 desc .chan [2 ] = img .planes [0 ] + 3 ;
215242 desc .rowCount [2 ] = img .width / 2 ;
216243 desc .step [2 ] = 4 ;
244+ desc .word [2 ] = 8 ;
217245 desc .rect [2 ] = constrain_rect (scale_rect (rect , 2 , 1 ), img .width / 2 , img .height );
218246 break ;
219247 case mlt_image_yuv420p :
@@ -222,28 +250,42 @@ static int filter_get_image(mlt_frame frame,
222250 desc .chan [0 ] = img .planes [0 ];
223251 desc .rowCount [0 ] = img .width ;
224252 desc .step [0 ] = 1 ;
253+ desc .word [0 ] = 8 ;
225254 desc .rect [0 ] = rect ;
226255 // U
227256 desc .chan [1 ] = img .planes [1 ];
228257 desc .rowCount [1 ] = img .width / 2 ;
229258 desc .step [1 ] = 1 ;
259+ desc .word [1 ] = 8 ;
230260 desc .rect [1 ] = constrain_rect (scale_rect (rect , 2 , 2 ), img .width / 2 , img .height / 2 );
231261 // V
232262 desc .chan [2 ] = img .planes [2 ];
233263 desc .rowCount [2 ] = img .width / 2 ;
234264 desc .step [2 ] = 1 ;
265+ desc .word [2 ] = 8 ;
235266 desc .rect [2 ] = constrain_rect (scale_rect (rect , 2 , 2 ), img .width / 2 , img .height / 2 );
236267 break ;
268+ case mlt_image_rgba64 :
269+ jobs = 4 ;
270+ for (i = 0 ; i < 4 ; i ++ ) {
271+ desc .chan [i ] = ((uint16_t * ) img .planes [0 ]) + i ;
272+ desc .rowCount [i ] = img .width ;
273+ desc .step [i ] = 4 ;
274+ desc .word [i ] = 16 ;
275+ desc .rect [i ] = rect ;
276+ }
277+ break ;
237278 default :
238279 return 1 ;
239280 }
240281
241282 uint8_t * alpha = mlt_frame_get_alpha (frame );
242- if (alpha && * format != mlt_image_rgba ) {
283+ if (alpha && * format != mlt_image_rgba && * format != mlt_image_rgba64 ) {
243284 jobs ++ ;
244285 desc .chan [3 ] = alpha ;
245286 desc .rowCount [3 ] = img .width ;
246287 desc .step [3 ] = 1 ;
288+ desc .word [3 ] = 8 ;
247289 desc .rect [3 ] = rect ;
248290 }
249291
0 commit comments