Log in

View Full Version : Pixel Padding - how?


javlak
7th October 2011, 10:51
Hi.

I am trying to write a window filter, i.e. like a gaussian blur (3x3, 5x5 etc). What I want to do is instead of checking if my window goes "out of bounds", like for instance in the first and last pixels of the picture, is to pad the frame with a mirror of the first and last few rows and columns (OK, I didn't pay much attention at my DSP classes about 20 years ago but I remember that much).

For instance, before the "real" first row will be a copy of that row, and before that a copy of the second "real" row and so on. So I can start processing at (0,0) instead of (1,1). But that would mean that I would have to change vi.width and vi.height but not at the constructor, as this will only be done internally and not affect the output video's dimensions.

Is this possible to do or do I have to write two separate filters, one to do the pixel padding, the other my window function and then crop with an avisynth script?

Thanks in advance.

Gavino
7th October 2011, 14:16
No need to create a separate filter.
In your GetFrame function, simply create a new frame of the appropriate size and after calling child->GetFrame(), copy the corresponding parts of the source frame into it using env->BitBlt().
The remainder of GetFrame() can then treat this new frame as the source for the windowed operation.

SEt
7th October 2011, 14:41
Processing border pixels is a real pain. There are some tricks that can be used here. For example, you don't need to copy first(last) row to negative locations(after the picture) - you can just pass to processing algorithm pointer to previous(next) line the same as pointer to current line.

IanB
8th October 2011, 05:14
BitBlt()'ing a frame is usually an expensive option for dealing with edge pixels. Amortising the cost of the frame blit over the saved filter operations is hardly ever achievable.

As SEt describes being devious with previous_line, current_line and next_line pointers is a very effective way of dealing with extra top and/or bottom pseudo rows.

Similar tricks can be used with extra left and/or right pseudo pixels, but can be clumsy.

There are also a few illicit tricks in Avisynth that can help sometimes by understanding the memory layout of a video frame. There can be between 0 and 15 bytes available for abuse due to alignment regimes.

The use is defined and supported in the case of a MOVDQA being within the bounds as returned by VideoFrame::GetRowSize(PLANAR_[YUV]_ALIGNED)

Further abuse is possible within the bounds described by these functions :-

VideoFrame::GetFrameBuffer() returns a pointer the the associated VideoFrameBuffer.
. VideoFrameBuffer::GetReadPtr() returns a pointer the original malloc'd memory block.
. VideoFrameBuffer::GetDataSize() returns the full size of the original malloc'd memory block.

You may safely read anywhere within the described memory block.

VideoFrame::GetOffset(plane) returns the byte offset into the FrameBuffer that the specified plane begins.

VideoFrame::GetPitch(plane) returns the offset between the start of 2 rows.
VideoFrame::GetRowSize(plane) returns the active length of a row.

As always abuse with care.

javlak
8th October 2011, 09:44
Thank you so much for your help guys, trying to put your words into code right now!