Log in

View Full Version : Delete Lines in image


Lyris
2nd April 2019, 17:57
I have a master that's been vertically stretched with what looks line nearest neighbor scaling, so roughly every 30th line in the frame is an exact duplicate of the one above or below it.

I know the line numbers we need to get rid of - is there a script or AVISynth function where I can just say

removeline(30)
removeline(60)
removeline(90)

and so on? Thought I'd check before I bust out the crop and stackvertical commands.

Thanks!

StainlessS
2nd April 2019, 18:27
Are you sure that you numbers are correct ?

00 -> 29 = 30 frames
31 -> 59 = 29 frames
61 -> 89 = 29 frames

roughly every 30th line
I guess they are then.

No choice but Crop and Stack.

EDIT:
removeline(30)
removeline(60)
removeline(90)

Every time you RemoveLine(), the higher number lines would change position, unless started at highest line number to remove.

Lyris
2nd April 2019, 18:40
The numbers are correct, yeah - I sat in Photoshop and manually picked them all out.

Good point re the shifting. All right, Crop and stack it is. Thanks!

StainlessS
2nd April 2019, 18:58
Lyris, try this, think it works.


Function RemoveRow(clip c,Int Row) { # Remove Pixel Row from clip:- https://forum.doom9.org/showthread.php?p=1870721#post1870721
c
Assert( 0 <= Row < c.Height,string(Row,"RemoveRow: Invalid Row number(%.0f)"))
Return (Row==0) ? Crop(0,1,0,0)
\ : (Row==Height-1) ? Crop(0,0,0,Row)
\ : StackVertical(Crop(0,0,0,Row),Crop(0,Row+1,0,0))
}

Colorbars.KillAudio.ConvertToYV24

RemoveRow(30)


EDIT: Or maybe more convienient (Avs+ and RT_Stats)

Function RemoveRow(clip c,Int Row) {
c
Assert( 0 <= Row < c.Height,string(Row,"RemoveRow: Invalid Row number(%.0f)"))
Return (Row==0) ? Crop(0,1,0,0)
\ : (Row==Height-1) ? Crop(0,0,0,Row)
\ : StackVertical(Crop(0,0,0,Row),Crop(0,Row+1,0,0))
}

Function ChrIsNul(String S) {return RT_Ord(S)== 0}
Function ChrIsHash(String S) {return RT_Ord(S)==35}
Function ChrIsDigit(String S) {C=RT_Ord(S) return C>=48&&C<=57}
Function ChrEatWhite(String S) {i=1 C=RT_Ord(S,i) While(C==32||C>=8&&C<=13) {i=i+1 C=RT_Ord(S,i)} return i>1?MidStr(S,i):S}
Function ChrEatDigits(String S) {i=1 C=RT_Ord(S,i) While(C>=48&&C<=57) {i=i+1 C=RT_Ord(S,i)} return i>1?MidStr(S,i):S}


Colorbars.KillAudio.ConvertToYV24

ROWCMD="""
120 # Delete Row 120
90
60
30
"""

LINES=RT_TxtQueryLines(ROWCMD)
for(i=0,LINES-1) {
SS=RT_TxtGetLine(ROWCMD,i).ChrEatWhite
if(!SS.ChrIsNul && !SS.ChrIsHash) {
S=SS
if(S.ChrIsDigit) {
RowNum = S.RT_NumberValue
Assert(0 <= RowNum < Height,RT_String("ROWCMD: Error@Line_%d, RowNum(%d) Out Of Frame\n%s",i+1,RowNum,SS))
RT_DebugF("Removing RowNum=%d",RowNum,name="ROWCMD: ")
RemoveRow(RowNum)
S=S.ChrEatDigits.ChrEatWhite
}
Assert(S.ChrIsHash || S.ChrIsNul,RT_String("ROWCMD: Error@Line_%d, *** NON-PARSE ***\n'%s'",i+1,SS))
}
}

return last.Info


EDIT: And for symmetry

Function RemoveColumn(clip c,Int Column) { # Remove Pixel Column from clip:- https://forum.doom9.org/showthread.php?p=1870721#post1870721
c
Assert( 0 <= Column < c.Width,string(Column,"RemoveColumn: Invalid Column number(%.0f)"))
Return (Column==0) ? Crop(1,0,0,0)
\ : (Column==Width-1) ? Crop(0,0,Column,0)
\ : StackHorizontal(Crop(0,0,Column,0),Crop(Column+1,0,0,0))
}

johnmeyer
3rd April 2019, 01:47
Every time you RemoveLine(), the higher number lines would change position, unless started at highest line number to remove.Ah yes, the old "reiterate after removing a member from the set" problem. It can bite you.

Lyris
5th April 2019, 16:28
Function RemoveRow(clip c,Int Row) { # Remove Pixel Row from clip:- https://forum.doom9.org/showthread.php?p=1870721#post1870721
c
Assert( 0 <= Row < c.Height,string(Row,"RemoveRow: Invalid Row number(%.0f)"))
Return (Row==0) ? Crop(0,1,0,0)
\ : (Row==Height-1) ? Crop(0,0,0,Row)
\ : StackVertical(Crop(0,0,0,Row),Crop(0,Row+1,0,0))
}



RemoveRow(30)


That does work! Thanks!
Although, before I saw this, I put a spreadsheet together to do the necessary calculations.
This way is much cleaner and hopefully helps someone else in the future though.

StainlessS
5th April 2019, 16:43
I posted 18 mins after your prev post where you then went offline, so I is sorry bouts dat,.

EDIT: You could always use the single frame/row/column number command processor in future projects, easily modified (ie as given as ROWCMD etc).

EDIT: Below can process commands from first to last line or last to 1st line of ROWCMD. (so can specify in ascending order, but execute in descending order [if required, as in this case])

Function RemoveRow(clip c,Int Row) {
c
Assert( 0 <= Row < c.Height,string(Row,"RemoveRow: Invalid Row number(%.0f)"))
Return (Row==0) ? Crop(0,1,0,0)
\ : (Row==Height-1) ? Crop(0,0,0,Row)
\ : StackVertical(Crop(0,0,0,Row),Crop(0,Row+1,0,0))
}

Function ChrIsNul(String S) {return RT_Ord(S)== 0}
Function ChrIsHash(String S) {return RT_Ord(S)==35}
Function ChrIsDigit(String S) {C=RT_Ord(S) return C>=48&&C<=57}
Function ChrEatWhite(String S) {i=1 C=RT_Ord(S,i) While(C==32||C>=8&&C<=13) {i=i+1 C=RT_Ord(S,i)} return i>1?MidStr(S,i):S}
Function ChrEatDigits(String S) {i=1 C=RT_Ord(S,i) While(C>=48&&C<=57) {i=i+1 C=RT_Ord(S,i)} return i>1?MidStr(S,i):S}


Colorbars.KillAudio.ConvertToYV24

REVERSE=True # If true start at last line in ROWCMD Else at first line

ROWCMD="""
30
60
90
120 # Delete Row 120
"""

###############
LINES=RT_TxtQueryLines(ROWCMD)
LINE_START = (REVERSE) ? LINES-1 : 0
LINE_END = (REVERSE) ? 0 : LINES-1
LINE_STEP = (REVERSE) ? -1 : 1

for(i=LINE_START, LINE_END, LINE_STEP) {
SS=RT_TxtGetLine(ROWCMD,i).ChrEatWhite
if(!SS.ChrIsNul && !SS.ChrIsHash) {
S=SS
if(S.ChrIsDigit) {
RowNum = S.RT_NumberValue
Assert(0 <= RowNum < Height,RT_String("ROWCMD: Error@Line_%d, RowNum(%d) Out Of Frame\n%s",i+1,RowNum,SS))
RT_DebugF("Removing RowNum=%d",RowNum,name="ROWCMD: ")
RemoveRow(RowNum)
S=S.ChrEatDigits.ChrEatWhite
}
Assert(S.ChrIsHash || S.ChrIsNul,RT_String("ROWCMD: Error@Line_%d, *** NON-PARSE ***\n'%s'",i+1,SS))
}
}

return last.Info


EDIT: See new thread here:- https://forum.doom9.org/showthread.php?t=176257