Log in

View Full Version : Trying to crop YV12 source


Avisynth_challenged
19th October 2008, 03:41
Hello all,

I've been trying to trim letterbox borders from a 720x480 progressive YV12 Huffyuv AVI (encoded w/ ffdshow). The problem is that the image falls into an area where I can't trim directly. Ideally I'd use:

crop = source.crop(0,79,-0,-101)
return crop

but I get the error "Crop: YV12 images can only be cropped by even numbers (top)."

My next idea was to do this:

crop = source.addborders(0,1,0,1).crop(0,80,-0,-102)
return crop

This opened without error, and "addborders" did resize the source to 720x482 as expected... but instead of adding one line to the top and one line to the bottom, it added two lines to the bottom. The source image was not shifted down by 1 line as I was expecting. So I still can't crop the borders because their edges still fall on odd numbered lines.

Avisynth is so amazing, and I have used it to do what seemed impossible in processing digital video... so I'm surprised that this simple task can't be done in a straightforward fashion. Or maybe it's a PEBKAC error, so I thought I'd ping on the Doom9 experts before I try anything else. :thanks:

JoeShrubbery
19th October 2008, 03:49
Push comes to shove, you can always ConvertToRGB32()

Sagekilla
19th October 2008, 05:33
Figured out the problem. It turns out since you're working in YV12, AddBorders() will only pad if you use a mod2 padding in either direction: AddBorders(0,1,0,1) does nothing.


s = ColorBars(720,300)
bd = s.AddBorders(0,79,0,101).ConvertToYV12()
s = s.ConvertToYV12()

a = bd.Spline16Resize(720,300,0,79,0,-101)
b = bd.AddBorders(0,1,0,1).Crop(0,80,0,-102)

Interleave(s,a,b)


Try using Spline16Resize(720,300,0,79,0,-101). It shouldn't do any resizing at all, but only do the cropping.

IanB
19th October 2008, 07:34
@Sagekilla,

Yes, it won't resize the luma plane but will resample the chroma planes across the needed 1 pixel.

Avisynth_challenged
19th October 2008, 08:12
Thanks for the responses. So my cropping problem is due to the source being YV12. Peviously the source was in YUY2 (which can be cropped by odd numbers on the top and bottom), but was converted to YV12 in order to use a chroma derainbowing script.

I should also add that I'm planning on doing the following operations on the derainbowed YV12 source (but I'm not sure yet in what order, suggestions on that would be most appreciated):

1. cropping (720x480 -> 720x300),
2. antialiasing,
3. sharpening,
4. upscaling (720x300 -> 720x380),
(Question: could 3 & 4 be combined into a single step using LimitedSharpen?)
5. addborders(0,50,0,50)

As you can probably guess, my goal is to produce an avi suitable for encoding anamorphic 16:9 MPEG2 for NTSC DVD.

I suppose that I have two choices at this point...

(1). Go back a step in my project and crop my YUY2 source before converting to YV12 then derainbowing.
(2). Continue working with the derainbowed YV12 source, but, in the 5-step workflow described above, skip over the initial cropping step and, instead, crop the image during the upscaling step.

So that's a rough sketch of where I'm at. Thanks to all for reading and especially for responding :)

Jeroi
16th August 2013, 11:29
Just to answer this thread altho it is old because I had similar issues:

Instead of Crop(left,top,-right,-bottom) and then resize function because crop does not support YV12 if any of left, top, right or bottom are an odd number, so use:

Lanczos4Resize(720, 576, left, top, -right, -bottom)

This will work with YV12 and no need to convert to rgb32. The filter will crop and then use target resolution to resize the image. I also suggest that you use this line as last filter on your skript, otherways interlacing will be blend at resize time and make deinterlacing poorer image.

Still tho I hope that someone would update crop() to support YV12 odd lines also.

Groucho2004
16th August 2013, 11:43
crop does not support YV12
What are you smoking?

IanB
16th August 2013, 23:08
Crop does not support YV12 if any of left, top, right or bottom are an odd number.

Groucho2004
16th August 2013, 23:58
Crop does not support YV12 if any of left, top, right or bottom are an odd number.
Of course. Yet that condition was left out of the previous post.

Gavino
17th August 2013, 00:59
Crop does not support YV12 if any of left, top, right or bottom are an odd number.
That's true, but it's a rather back-to-front way of putting it.
To me, it seems clearer to say that Crop does not support left, right, top or bottom being an odd number when the input is YV12 (and that's more or less what the error message says if you try to do it).

gyth
17th August 2013, 02:20
What about something like this?
s = ColorBars(720,300)
bd = s.AddBorders(0,79,0,101).ConvertToYV12()
s = s.ConvertToYV12()

a = bd.Spline16Resize(720,300,0,79,0,-101)
l = bd.converttoy8.crop(0,79,0,-101).ConvertToYV12()
c1 = bd.Crop(0,80,0,-102).Spline16Resize(720,300,0,-1,0,299)
b1 = mergeChroma(l,c1)
c2 = bd.Crop(0,80,0,-102).Spline16Resize(720,300,0,-.5,0,299.5)
b2 = mergeChroma(l,c2)

Interleave(s,a,b2) #.crop(0,180,0,0)
Why doesn't b1 work?

StainlessS
17th August 2013, 02:56
In my humble opinion, it is not eg crop that does not support YV12, it that YV12 does not support
cropping in the middle of chroma samples.
Two half persons, rarely perform as well as a single whole person (No matter how clean the cut).

TheFluff
19th August 2013, 14:52
In my humble opinion, it is not eg crop that does not support YV12, it that YV12 does not support
cropping in the middle of chroma samples.
Two half persons, rarely perform as well as a single whole person (No matter how clean the cut).

There's nothing that stops you from cropping an YV12 image in the middle of a chroma sample, you just have to decide what to do with the leftover "half" sample in a consistent way. Avisynth (and a lot of other software) avoids this decision by not letting you do that, but that doesn't mean there's some divine decree that states that Thou Shalt Not Create Odd-Dimensioned YV12 Images. If you want to handle it, you can, it's just easier not to.

As Avery Lee wrote back in 2004:
I've been trying for some time to get YV12 support working perfectly, but at this point it looks like a wash. The problem is that different drivers and applications are inconsistent about how they treat or format odd-width and odd-height YV12 images. Some support it by truncating the chroma planes (dumb). Some do that and have unused space betweeen the Cr and Cb planes (weird). Many simply crash (very dumb). And a few simply don't support it (lame but pragmatic). YVU9 tends to be even more broken. Arrrgh.

Now, if people had sense, they would have handled this the way that MPEG and JPEG do, and simply require that the bitmap always be padded to the nearest even boundaries and that the extra pixels be ignored on decoding. Unfortunately, no one seems to have bothered to ever define the YV12 format properly in this regard, and thus we have massive confusion.

StainlessS
19th August 2013, 16:35
I stand corrected - perhaps two half persons do frequently perform as well as a whole person. :)

bxyhxyh
25th August 2013, 09:57
According to this thread (http://forum.doom9.org/showthread.php?t=164737), this will work without loss(?) on Avisynth 2.6, if source is YV12.

ConvertToYV24(chromaresample = "point")
MergeChroma(PointResize(width, height, 0, 1))
Crop(0, 79, 0, -101)
ConverttoYV12(chromaresample = "point")

Gavino
25th August 2013, 12:59
According to this thread (http://forum.doom9.org/showthread.php?t=164737), this will work without loss(?) on Avisynth 2.6, if source is YV12.
It 'works' to the extent of not producing an error message, but it introduces a chroma shift, since it retains the original chroma pixels without resampling.

For cropping at odd boundaries, chroma resampling is required, since the chroma sampling positions are different from the original. This can be done using a resizer (eg as in post #6), or by conversion to and from YV24 with chromaresample defaulted or set to something other than "point".

The 'lossless' aspect in the other thread only applies when you remove the Crop() from the script.