Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
18th December 2012, 05:37 | #1 | Link |
Registered User
Join Date: Aug 2008
Posts: 233
|
Alternative to the old Unpremultiply() plugin?
Hi all –
I need to unpremultiply some matted RGB32 clips. I am currently using the Unpremultiply() function (ca. 2008) but the results are not always good. It tends to add dark or bright speckles, particularly in near-transparent areas. Does anyone know of a good alternative to this or perhaps some updated/re-tooled version? I have tried using a series of Overlay operations with different modes ... but no luck. Perhaps there is some way with MaskTools or something similar? Thx. Last edited by vampiredom; 18th December 2012 at 06:50. |
18th December 2012, 07:44 | #2 | Link |
Avisynth Developer
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
|
Assuming this source code unpremultiply.cpp
Code:
// Formula is: Cu = Cm / a // Adding alpha/2 rounds instead of truncates the result of integer division // This will cause horrible things to happen to your image if a color value // is ever greater than the alpha value. // This can happen if your source program used some kind of specular highlighting *dstbpix = (srcbpix * 255 + srcapix / 2) / srcapix; *dstgpix = (srcgpix * 255 + srcapix / 2) / srcapix; *dstrpix = (srcrpix * 255 + srcapix / 2) / srcapix; Apply this patch or similar Code:
inline uint8_t uint8clamp(int x) { if (x < 0) return 0; if (x > 255) return 255; return x; } .... *dstbpix = uint8clamp((srcbpix * 255 + srcapix / 2) / srcapix); *dstgpix = uint8clamp((srcgpix * 255 + srcapix / 2) / srcapix); *dstrpix = uint8clamp((srcrpix * 255 + srcapix / 2) / srcapix); |
27th December 2012, 09:10 | #4 | Link |
Avisynth Developer
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
|
Try the attached version.
Also changed to uses a fast 65K lookup table instead of the slow in place idiv's. :Edit: See below for new version Last edited by IanB; 31st December 2012 at 23:55. |
31st December 2012, 21:38 | #6 | Link |
Registered User
Join Date: Aug 2008
Posts: 233
|
Hi --
There is something strange going on: It seems that areas that should be fully opaque turn to black. This can be demonstrated with a simple test: Code:
# This works properly, showing a white rectangle with a gray rectangle a = BlankClip(width=1280, height=720, length=1, color=$808080, pixel_type="RGB32").ResetMask() b = BlankClip(width=640, height=480, length=1, color=$FFFFFF, pixel_type="RGB32").ResetMask() Layer(a, b, x=320, y=120) Code:
# When Unpremultiply() is applied, the inner rectangle turns black a = BlankClip(width=1280, height=720, length=1, color=$808080, pixel_type="RGB32").ResetMask() b = BlankClip(width=640, height=480, length=1, color=$FFFFFF, pixel_type="RGB32").ResetMask().Unpremultiply() Layer(a, b, x=320, y=120) |
31st December 2012, 23:07 | #7 | Link |
Avisynth Developer
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
|
Opps, The bottom row and right column of the lookup table are not being initialised.
Code:
for (int i=0; i< 255; i++) { lookup[i<<8] = i; for (int j=1; j<255; j++) lookup[(i<<8)+j] = uint8clamp((i * 255 + j / 2) / j); } Last edited by IanB; 31st December 2012 at 23:54. |
2nd January 2013, 19:51 | #8 | Link |
Registered User
Join Date: Aug 2008
Posts: 233
|
Ah, much better! I have not tested it thoroughly but it seems to work well on some tests I have tried.
However, it seems to only work correctly when the matte color is black. I wish there were a way (similar to Adobe After Effects, for example) where you could choose the matte color to remove. Photoshop has a similar-but-simplified approach with "Matting > Remove Black Matte" and "Matting > Remove White Matte". Unpremultiply() wreaks havoc on a white-matted clip. |
2nd January 2013, 23:00 | #9 | Link | ||
Avisynth Developer
Join Date: Jan 2003
Location: Melbourne, Australia
Posts: 3,167
|
From our PM exchange
Quote:
Code:
// Formula is: Cu = Cm / a // Adding alpha/2 rounds instead of truncates the result of integer division // This will cause horrible things to happen to your image if a color value // is ever greater than the alpha value. // This can happen if your source program used some kind of specular highlighting *dstbpix = (srcbpix * 255 + srcapix / 2) / srcapix; *dstgpix = (srcgpix * 255 + srcapix / 2) / srcapix; *dstrpix = (srcrpix * 255 + srcapix / 2) / srcapix; As for unpremultiplying based on a [255,255,255] white matte you could try this :- Code:
...source Invert("RGB") # flip rgb channels Unpremultiply() # Orgb = 255 - ( (255 - Irgb) * 255 / Ia ) Invert("RGB") # unflip rgb channels .. Code:
... Ya=ShowAlpha("YV12") # Copy alpha to Y plane Ya3=Interleave(Ya, Ya, Ya) Interleave( ShowRed("YV12"), ShowGreen("YV12"), ShowBlue("YV12") ) # Copy rgb's to Y planes exprstr=mt_polish( "255 - ( ( ( 255 - X ) * 255 + Y / 2 ) / Y )" ) # "255 255 x - 255 * y 2 / + y / -" Mt_LutXY(Ya3, yexpr=exprstr, y=3, u=1, v=1) # do Y, ignore U and V MergeARGB( Ya, SelectEvery(3,0), SelectEvery(3,1), SelectEvery(3,2) ) # Reassemble Y's to ARGB Last edited by IanB; 28th June 2013 at 22:58. Reason: Fix Ya3 bug as per Gavino |
||
28th June 2013, 17:06 | #10 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
But don't you need to replicate the alpha channel three times as well, otherwise the wrong frames will be paired up in the mt_lutxy? I think the Ya in the mt_lutxy call should be Interleave(Ya, Ya, Ya). (unless you are assuming a single frame clip or a static image.) |
|
Tags |
alpha, matte, premultiplied, rgb32, unpremultiply |
Thread Tools | Search this Thread |
Display Modes | |
|
|