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. Domains: forum.doom9.org / forum.doom9.net / forum.doom9.se |
|
|
#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. |
|
|
|
|
|
#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);
|
|
|
|
|
|
#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. |
|
|
|
|
|
#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) |
|
|
|
|
|
#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. |
|
|
|
|
|
#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. |
|
|
|
|
|
#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 |
||
|
|
|
|
|
#10 | Link | |
|
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,442
|
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 | |
|
|