@@ -140,45 +140,76 @@ static void vertical_sbr_c(void* __restrict dstp_, void* __restrict tempp_, cons
140140 }
141141}
142142
143- template <typename T>
144- static void finalize_plane_c (void * __restrict dstp_, const void * srcp_, const void * pb3_, const void * pb6_, float sstr, float scl, int src_pitch, int dst_pitch, int pb_pitch, int width, int height, int amnt) noexcept
143+ template <typename T, bool eclip >
144+ static void finalize_plane_c (void * __restrict dstp_, const void * srcp_, const void * pb3_, const void * pb6_, float sstr, float scl, int src_pitch, int dst_pitch, int pb_pitch, int clip2_pitch, int width, int height, int amnt) noexcept
145145{
146146 const T* srcp = reinterpret_cast <const T*>(srcp_);
147147 const T* pb3 = reinterpret_cast <const T*>(pb3_);
148148 const T* pb6 = reinterpret_cast <const T*>(pb6_);
149149 T* __restrict dstp = reinterpret_cast <T*>(dstp_);
150150
151- for ( int y = 0 ; y < height; ++y )
151+ if (eclip )
152152 {
153- for (int x = 0 ; x < width ; ++x )
153+ for (int y = 0 ; y < height ; ++y )
154154 {
155- const float d1 = static_cast <float >(srcp[x] - pb3[x]);
156- const int d2 = pb3[x] - pb6[x];
157- const float t = d2 * sstr;
155+ for (int x = 0 ; x < width; ++x)
156+ {
157+ const float d1 = static_cast <float >(srcp[x] - pb3[x]);
158+ const float d2 = static_cast <float >(srcp[x] - pb6[x]);
158159
159- const float da = (std::abs (d1) < std::abs (t )) ? d1 : t ;
160- const float desired = da * scl;
160+ const float da = (std::abs (d1) < std::abs (d2 )) ? d1 : d2 ;
161+ const float desired = da * scl;
161162
162- const int add = static_cast <int >(((d1 * t ) < 0 .0f ) ? desired : da);
163- int df = pb3 [x] + add;
163+ const int add = static_cast <int >(((d1 * d2 ) < 0 .0f ) ? desired : da);
164+ int df = pb6 [x] + add;
164165
165- const int minm = srcp[x] - amnt;
166- const int maxf = srcp[x] + amnt;
166+ const int minm = srcp[x] - amnt;
167+ const int maxf = srcp[x] + amnt;
167168
168- df = std::max (df, minm);
169- dstp[x] = std::min (df, maxf);
169+ df = std::max (df, minm);
170+ dstp[x] = std::min (df, maxf);
171+ }
172+
173+ srcp += src_pitch;
174+ pb3 += pb_pitch;
175+ pb6 += clip2_pitch;
176+ dstp += dst_pitch;
170177 }
178+ }
179+ else
180+ {
181+ for (int y = 0 ; y < height; ++y)
182+ {
183+ for (int x = 0 ; x < width; ++x)
184+ {
185+ const float d1 = static_cast <float >(srcp[x] - pb3[x]);
186+ const int d2 = pb3[x] - pb6[x];
187+ const float t = d2 * sstr;
171188
172- srcp += src_pitch;
173- pb3 += pb_pitch;
174- pb6 += pb_pitch;
175- dstp += dst_pitch;
189+ const float da = (std::abs (d1) < std::abs (t)) ? d1 : t;
190+ const float desired = da * scl;
191+
192+ const int add = static_cast <int >(((d1 * t) < 0 .0f ) ? desired : da);
193+ int df = pb3[x] + add;
194+
195+ const int minm = srcp[x] - amnt;
196+ const int maxf = srcp[x] + amnt;
197+
198+ df = std::max (df, minm);
199+ dstp[x] = std::min (df, maxf);
200+ }
201+
202+ srcp += src_pitch;
203+ pb3 += pb_pitch;
204+ pb6 += pb_pitch;
205+ dstp += dst_pitch;
206+ }
176207 }
177208}
178209
179- template <typename T>
180- Vinverse<T>::Vinverse(PClip child, float sstr, int amnt, int uv, float scl, int opt, VinverseMode mode , IScriptEnvironment* env)
181- : GenericVideoFilter(child), sstr_(sstr), amnt_(amnt), uv_(uv), scl_(scl), opt_(opt), mode_(mode ), blur3_buffer(nullptr ), blur6_buffer(nullptr )
210+ template <typename T, VinverseMode mode, bool eclip >
211+ Vinverse<T, mode, eclip >::Vinverse(PClip child, float sstr, int amnt, int uv, float scl, int opt, PClip clip2 , IScriptEnvironment* env)
212+ : GenericVideoFilter(child), sstr_(sstr), amnt_(amnt), uv_(uv), scl_(scl), opt_(opt), clip2_(clip2 ), blur3_buffer(nullptr ), blur6_buffer(nullptr )
182213{
183214 if (!vi.IsPlanar ())
184215 env->ThrowError (" Vinverse: only planar input is supported!" );
@@ -206,19 +237,28 @@ Vinverse<T>::Vinverse(PClip child, float sstr, int amnt, int uv, float scl, int
206237 if (!sse2 && opt_ == 1 )
207238 env->ThrowError (" Vinverse: opt=1 requires SSE2." );
208239
209- int align = 16 ;
240+ if (eclip)
241+ {
242+ const VideoInfo& vi_ = clip2_->GetVideoInfo ();
243+
244+ if (!vi.IsSameColorspace (vi_))
245+ env->ThrowError (" Vinverse: clip2's colorspace doesn't match." );
246+ if (vi.width != vi_.width || vi.height != vi_.height )
247+ env->ThrowError (" Vinverse: input and clip2 must be the same resolution." );
248+ if (vi.num_frames != vi_.num_frames )
249+ env->ThrowError (" Vinverse: clip2's number of frames doesn't match." );
250+ }
210251
211252 if ((avx512 && opt_ < 0 ) || opt_ == 3 )
212253 {
213254 pb_pitch = (vi.width + 63 ) & ~63 ;
214- align = 64 ;
215255
216256 if (sizeof (T) == 1 )
217257 {
218258 blur3 = vertical_blur3_avx512_8;
219259 blur5 = vertical_blur5_avx512_8;
220260 sbr = vertical_sbr_avx512_8;
221- fin_plane = finalize_plane_avx512_8;
261+ fin_plane = finalize_plane_avx512_8<eclip> ;
222262 }
223263 else
224264 {
@@ -254,20 +294,19 @@ Vinverse<T>::Vinverse(PClip child, float sstr, int amnt, int uv, float scl, int
254294 }
255295 }
256296
257- fin_plane = finalize_plane_avx512_16;
297+ fin_plane = finalize_plane_avx512_16<eclip> ;
258298 }
259299 }
260300 else if ((avx2 && opt_ < 0 ) || opt_ == 2 )
261301 {
262302 pb_pitch = (vi.width + 31 ) & ~31 ;
263- align = 32 ;
264303
265304 if (sizeof (T) == 1 )
266305 {
267306 blur3 = vertical_blur3_avx2_8;
268307 blur5 = vertical_blur5_avx2_8;
269308 sbr = vertical_sbr_avx2_8;
270- fin_plane = finalize_plane_avx2_8;
309+ fin_plane = finalize_plane_avx2_8<eclip> ;
271310 }
272311 else
273312 {
@@ -303,7 +342,7 @@ Vinverse<T>::Vinverse(PClip child, float sstr, int amnt, int uv, float scl, int
303342 }
304343 }
305344
306- fin_plane = finalize_plane_avx2_16;
345+ fin_plane = finalize_plane_avx2_16<eclip> ;
307346 }
308347 }
309348 else if ((sse2 && opt_ < 0 ) || opt_ == 1 )
@@ -315,7 +354,7 @@ Vinverse<T>::Vinverse(PClip child, float sstr, int amnt, int uv, float scl, int
315354 blur3 = vertical_blur3_sse2_8;
316355 blur5 = vertical_blur5_sse2_8;
317356 sbr = vertical_sbr_sse2_8;
318- fin_plane = finalize_plane_sse2_8;
357+ fin_plane = finalize_plane_sse2_8<eclip> ;
319358 }
320359 else
321360 {
@@ -351,7 +390,7 @@ Vinverse<T>::Vinverse(PClip child, float sstr, int amnt, int uv, float scl, int
351390 }
352391 }
353392
354- fin_plane = finalize_plane_sse2_16;
393+ fin_plane = finalize_plane_sse2_16<eclip> ;
355394 }
356395 }
357396 else
@@ -399,32 +438,26 @@ Vinverse<T>::Vinverse(PClip child, float sstr, int amnt, int uv, float scl, int
399438 }
400439 }
401440
402- fin_plane = finalize_plane_c<T>;
441+ fin_plane = finalize_plane_c<T, eclip >;
403442 }
404443
405444 size_t pbuf_size = vi.height * pb_pitch;
406445
407- buffer = reinterpret_cast <T*>( aligned_malloc ( pbuf_size * 2 * sizeof (T), align ));
446+ buffer = std::make_unique<T[]>( pbuf_size * 2 * sizeof (T));
408447
409448 if (buffer == nullptr )
410449 env->ThrowError (" Vinverse: malloc failure!" );
411450
412- blur3_buffer = buffer;
451+ blur3_buffer = buffer. get () ;
413452 blur6_buffer = blur3_buffer + pbuf_size;
414453
415454 v8 = true ;
416455 try { env->CheckVersion (8 ); }
417456 catch (const AvisynthError&) { v8 = false ; }
418457}
419458
420- template <typename T>
421- Vinverse<T>::~Vinverse ()
422- {
423- aligned_free (buffer);
424- }
425-
426- template <typename T>
427- PVideoFrame __stdcall Vinverse<T>::GetFrame(int n, IScriptEnvironment* env)
459+ template <typename T, VinverseMode mode, bool eclip>
460+ PVideoFrame __stdcall Vinverse<T, mode, eclip>::GetFrame(int n, IScriptEnvironment* env)
428461{
429462 PVideoFrame src = child->GetFrame (n, env);
430463 PVideoFrame dst = (v8) ? env->NewVideoFrameP (vi, &src) : env->NewVideoFrame (vi);
@@ -437,23 +470,25 @@ PVideoFrame __stdcall Vinverse<T>::GetFrame(int n, IScriptEnvironment* env)
437470 if (current_plane != PLANAR_Y && (vi.IsY8 () || uv_ == 1 ))
438471 continue ;
439472
473+ const uint8_t * srcp = src->GetReadPtr (current_plane);
474+ const int src_pitch = src->GetPitch (current_plane) / sizeof (T);
475+ const int dst_pitch = dst->GetPitch (current_plane);
476+ const int height = src->GetHeight (current_plane);
477+ const int width = src->GetRowSize (current_plane) / sizeof (T);
478+ uint8_t * dstp = dst->GetWritePtr (current_plane);
479+
440480 if (current_plane != PLANAR_Y && uv_ == 2 )
441481 {
442- env->BitBlt (dst-> GetWritePtr (current_plane), dst-> GetPitch (current_plane), src-> GetReadPtr (current_plane) , src->GetPitch (current_plane), src->GetRowSize (current_plane), src-> GetHeight (current_plane) );
482+ env->BitBlt (dstp, dst_pitch, srcp , src->GetPitch (current_plane), src->GetRowSize (current_plane), height );
443483 continue ;
444484 }
445485
446- const T* srcp = reinterpret_cast <const T*>(src->GetReadPtr (current_plane));
447- const int src_pitch = src->GetPitch (current_plane) / sizeof (T);
448- const int height = src->GetHeight (current_plane);
449- const int width = src->GetRowSize (current_plane) / sizeof (T);
450- T* dstp = reinterpret_cast <T*>(dst->GetWritePtr (current_plane));
451- const int dst_pitch = dst->GetPitch (current_plane) / sizeof (T);
452-
453- if (mode_ == VinverseMode::Vinverse)
486+ if (mode == VinverseMode::Vinverse)
454487 {
455488 blur3 (blur3_buffer, srcp, pb_pitch, src_pitch, width, height);
456- blur5 (blur6_buffer, blur3_buffer, pb_pitch, pb_pitch, width, height);
489+
490+ if (!eclip)
491+ blur5 (blur6_buffer, blur3_buffer, pb_pitch, pb_pitch, width, height);
457492 }
458493 else
459494 {
@@ -464,36 +499,57 @@ PVideoFrame __stdcall Vinverse<T>::GetFrame(int n, IScriptEnvironment* env)
464499 blur3 (blur6_buffer, blur3_buffer, pb_pitch, pb_pitch, width, height);
465500 }
466501
467- fin_plane (dstp, srcp, blur3_buffer, blur6_buffer, sstr_, scl_, src_pitch, dst_pitch, pb_pitch, width, height, amnt_);
502+ if (eclip)
503+ {
504+ PVideoFrame clp2 = clip2_->GetFrame (n, env);
505+
506+ fin_plane (dstp, srcp, blur3_buffer, clp2->GetReadPtr (current_plane), sstr_, scl_, src_pitch,
507+ dst_pitch / sizeof (T), pb_pitch, clp2->GetPitch (current_plane) / sizeof (T), width, height, amnt_);
508+ }
509+ else
510+ fin_plane (dst->GetWritePtr (current_plane), srcp, blur3_buffer, blur6_buffer, sstr_, scl_, src_pitch, dst_pitch / sizeof (T), pb_pitch, 0 , width, height, amnt_);
468511 }
469512
470513 return dst;
471514}
472515
473516AVSValue __cdecl Create_Vinverse (AVSValue args, void *, IScriptEnvironment* env)
474517{
475- enum { CLIP, SSTR, AMNT, UV, SCL, OPT };
518+ enum { CLIP, SSTR, AMNT, UV, SCL, OPT, CLIP2 };
476519
477520 PClip clip = args[CLIP].AsClip ();
521+ PClip clip2 = (args[CLIP2].Defined ()) ? args[CLIP2].AsClip () : nullptr ;
478522
479- switch (clip-> GetVideoInfo (). ComponentSize () )
523+ if (clip2 )
480524 {
481- case 1 : return new Vinverse<uint8_t >(clip, args[SSTR].AsFloatf (2 .7f ), args[AMNT].AsInt (-1 ), args[UV].AsInt (3 ), args[SCL].AsFloatf (0 .25f ), args[OPT].AsInt (-1 ), VinverseMode::Vinverse, env);
482- case 2 : return new Vinverse<uint16_t >(clip, args[SSTR].AsFloatf (2 .7f ), args[AMNT].AsInt (-1 ), args[UV].AsInt (3 ), args[SCL].AsFloatf (0 .25f ), args[OPT].AsInt (-1 ), VinverseMode::Vinverse, env);
483- default : env->ThrowError (" Vinverse: only 8..16-bit input is supported!" );
525+ switch (clip->GetVideoInfo ().ComponentSize ())
526+ {
527+ case 1 : return new Vinverse<uint8_t , VinverseMode::Vinverse, true >(clip, args[SSTR].AsFloatf (2 .7f ), args[AMNT].AsInt (-1 ), args[UV].AsInt (3 ), args[SCL].AsFloatf (0 .25f ), args[OPT].AsInt (-1 ), clip2, env);
528+ case 2 : return new Vinverse<uint16_t , VinverseMode::Vinverse, true >(clip, args[SSTR].AsFloatf (2 .7f ), args[AMNT].AsInt (-1 ), args[UV].AsInt (3 ), args[SCL].AsFloatf (0 .25f ), args[OPT].AsInt (-1 ), clip2, env);
529+ default : env->ThrowError (" Vinverse: only 8..16-bit input is supported!" );
530+ }
531+ }
532+ else
533+ {
534+ switch (clip->GetVideoInfo ().ComponentSize ())
535+ {
536+ case 1 : return new Vinverse<uint8_t , VinverseMode::Vinverse, false >(clip, args[SSTR].AsFloatf (2 .7f ), args[AMNT].AsInt (-1 ), args[UV].AsInt (3 ), args[SCL].AsFloatf (0 .25f ), args[OPT].AsInt (-1 ), clip2, env);
537+ case 2 : return new Vinverse<uint16_t , VinverseMode::Vinverse, false >(clip, args[SSTR].AsFloatf (2 .7f ), args[AMNT].AsInt (-1 ), args[UV].AsInt (3 ), args[SCL].AsFloatf (0 .25f ), args[OPT].AsInt (-1 ), clip2, env);
538+ default : env->ThrowError (" Vinverse: only 8..16-bit input is supported!" );
539+ }
484540 }
485541}
486542
487543AVSValue __cdecl Create_Vinverse2 (AVSValue args, void *, IScriptEnvironment* env)
488544{
489- enum { CLIP, SSTR, AMNT, UV, SCL, OPT };
545+ enum { CLIP, SSTR, AMNT, UV, SCL, OPT, CLIP2 };
490546
491547 PClip clip = args[CLIP].AsClip ();
492548
493549 switch (clip->GetVideoInfo ().ComponentSize ())
494550 {
495- case 1 : return new Vinverse<uint8_t >(clip, args[SSTR].AsFloatf (2 .7f ), args[AMNT].AsInt (-1 ), args[UV].AsInt (3 ), args[SCL].AsFloatf (0 .25f ), args[OPT].AsInt (-1 ), VinverseMode::Vinverse2 , env);
496- case 2 : return new Vinverse<uint16_t >(clip, args[SSTR].AsFloatf (2 .7f ), args[AMNT].AsInt (-1 ), args[UV].AsInt (3 ), args[SCL].AsFloatf (0 .25f ), args[OPT].AsInt (-1 ), VinverseMode::Vinverse2 , env);
551+ case 1 : return new Vinverse<uint8_t , VinverseMode::Vinverse2, false >(clip, args[SSTR].AsFloatf (2 .7f ), args[AMNT].AsInt (-1 ), args[UV].AsInt (3 ), args[SCL].AsFloatf (0 .25f ), args[OPT].AsInt (-1 ), nullptr , env);
552+ case 2 : return new Vinverse<uint16_t , VinverseMode::Vinverse2, false >(clip, args[SSTR].AsFloatf (2 .7f ), args[AMNT].AsInt (-1 ), args[UV].AsInt (3 ), args[SCL].AsFloatf (0 .25f ), args[OPT].AsInt (-1 ), nullptr , env);
497553 default : env->ThrowError (" Vinverse: only 8..16-bit input is supported!" );
498554 }
499555}
@@ -504,7 +560,7 @@ extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit3(IScri
504560{
505561 AVS_linkage = vectors;
506562
507- env->AddFunction (" vinverse" , " c[sstr]f[amnt]i[uv]i[scl]f[opt]i" , Create_Vinverse, 0 );
563+ env->AddFunction (" vinverse" , " c[sstr]f[amnt]i[uv]i[scl]f[opt]i[clip2]c " , Create_Vinverse, 0 );
508564 env->AddFunction (" vinverse2" , " c[sstr]f[amnt]i[uv]i[scl]f[opt]i" , Create_Vinverse2, 0 );
509565 return " Doushimashita?" ;
510566}
0 commit comments