View Full Version : Cropping & Resizing Implementation
Emp3r0r
11th September 2002, 04:25
I need some help understanding the correct process for resizing a DVD. I've been reading and trying to create a program which does the process as well as GKnot or DVD2AVI_Nic. This has been no easy task and is confusing as hell. Can someone lend a hand and correct me where I'm wrong.
1: start with 720x480
2: need to adjust if Anamorphic material
3: need to crop (smart to keep correct AR)
4: need to resize (smart to keep multiples of 16)
I need help with accomplishing the above. I'd love to send you the binary and source of what I have so far if your willing to help. Here is a screenshot of the program I am working on. http://jvance.com/images/dvd2xcd.png (http://jvance.com/hitme.aspx?url=http://jvance.com/images/dvd2xcd.png)
Should this (http://pub56.ezboard.com/fbsplayerforumfrm2.showMessage?topicID=342.topic) page help me accomplish my goals of proper output?
Do you think the ITU method is important?
Thanks for any help
Latexxx
11th September 2002, 10:37
Maybe http://shh.dvdboard.de/ would help. It has an open-source s/x/xxxxxvcd resizer wich does implement almost any of features needed for anything. It's programmed in delphi and the code is too complicated for me to extract the resizing method from it. If you get anything out from it (mathematical formulas) I would be also interested in to see it.
Check also this: http://www.uwasa.fi/~f76998/video/conversion/index.html
Emp3r0r
11th September 2002, 18:46
Ok, I'm beginning to understand all this PAR and DAR stuff. Once I know how to convert to the correct PAR, the anamorphic thing should be easy. Then I just need to figure out the smart way to crop and resize because my current way is just normal :(
Emp3r0r
11th September 2002, 18:47
BTW: Blight is trying to help me over at his forum
http://forum.inmatrix.com/ikonboard/ikonboard.cgi?s=3d7f719b5064ffff;act=ST;f=5;t=14
Latexxx
11th September 2002, 18:56
If you get something to work would you inform me too?
Emp3r0r
11th September 2002, 19:55
Sure I will, but I'm stumped right now. I wish there was a magic number that I could multiply the height (after crop) by whenever they choose NTSC 16:9 Anamorphic.
Latexxx
12th September 2002, 06:52
I've got the point!
I wrote the following last night: http://www.nic.fi/~lhahne/resize.pdf
If you neede it to be multiple of 16, then you need to crop it vertically after the method descripted there.
Latexxx
13th September 2002, 06:04
Just one thing missing..
Add the following to the second procedure:
xtemp=ar*y
Emp3r0r
15th September 2002, 23:54
where do you get ynew?
Emp3r0r
16th September 2002, 04:31
ok, I have the following information to work with:
(!) = known
(?) = un-known
(!) (?) = flexible
source width : 720 (!)
source height : 480 (!)
source ar : 1.500 (!)
anamorphic 16:9 regular PAR : 1.778 (!)
crop top : 60 (!)
crop bot : 64 (!)
crop left : 2 (!)(?)
crop right : 2 (!)(?)
dimensions after pixel crop
in width : 716 (!)(?)
in height : 356 (!)
in ar : 2.384 (?)
chosen width below
out width : 640 (!)
out height : 272 (?)
our ar : 2.353 (?)
w-mod : 32 (!)
h-mod : 16 (!)
ar error : 1.3%
Why do my formalas not stay consistent with TheWef's formulas.
Latexxx
16th September 2002, 07:43
Originally posted by Emp3r0r
where do you get ynew?
My mistake! ytemp = ynew!
An example:
ytemp=480 - 60 - 64 = 356
xtemp=1,778*480=853
arnew=853/356=2,396
yout=640/2,396=267
Final pixels: x=640, y=267
Emp3r0r
16th September 2002, 18:57
@latexxx: that's almost there, now I must take into account any cropping done on the left and right and also mod restrictions. I'm getting very close. Thanks for your help.
mtrooper
17th September 2002, 12:08
Whoa, this thread is really useful :D (==made my own program for resizing)
Now, what it's bugging me is: how do you use AR error to do GKnot's SmartCrop?
I'll reread all the links that were posed, since I probably missed it somewhere, but if you can post it here it would be great :)
Emp3r0r
17th September 2002, 14:12
I am still working on that but I understand how it works. I just havn't come up with the correct formula yet. Keep us posted if you accomplish anything. Thanks.
Latexxx
17th September 2002, 17:12
I've updated my pdf. Includes horizontal cropping(very experimental(didn't have time to test it)). The addres is : http://www.nic.fi/~lhahne/resize.pdf
mtrooper
17th September 2002, 18:16
@Latexxx:
Would it be enough just to do this: Xtemp2=Xtemp-Cx1-Cx2? At least, it seems that GKnot is doing it like this.
But then again, your formula does take in account resizing, which upper one does not (at least I got that impersion since you are calculating Xar).
And great job :D
Emp3r0r
17th September 2002, 21:35
great work latexxx!!!
new example:
ar=1.7778
x=720 y=480
c1=60 c2=64
cx1=2 cx2=2
xout=640
ytemp=480-64-60=356
xtemp=1.7778 * 480 = 853.334
xar=(2+2)/720 = 0.005555
xtemp2=853.334-(0.005555*853.334)=853.334-4.7407444=848.593255
arnew=848.59325555/356=2.38368892
yout=xout/2.38368892=268.491411
on to the smart cropping, so closest mod 16 number is 272,
so now we know yout and more importantly arout which is = 2.356 now we must crop left and right accordingly to reduce difference between arout and arnew to keep arerror to a minimum
WOO HOO! :D
TheWEF
17th September 2002, 23:21
smartcrop example:
desired horizontal res is 640.
using
inputRES
inputPAR
inputAnamorphicOrNot
outputPAR
outputAnamorphicOrNot
you calculate outputExactRES is (640 x 269.3456768)
e.g. y-mod is 16.
now you have two possibilities to get exact AR:
A) crop off the sides until 640 x 272 is correct.
B) crop off top and bottom until 640 x 256 is correct.
so you just calculate back from the two closest resolutions that are vertically multiples of 16, that's all. then choose the one that needs less crop.
wef.
Emp3r0r
18th September 2002, 05:11
Thanks TheWef for your help. I managed to get resizing to obey mod sizes and now I'm about to tackle the smart cropping you explain above. Does your method A refer to Smart Crop Left-Right and method B refer to a Smart Crop Top-Bottom? Here is a screenshot (http://jvance.com/hitme.aspx?url=http://jvance.com/images/dvd2xcdsmartcrop.png) of a few of my methods (C# code) so far. Thanks again everyone!
Latexxx
18th September 2002, 10:35
2 emp3ror:
Now just waiting for your proggie.........
Emp3r0r
18th September 2002, 16:14
Well, I'm a little discouraged as it seems darkcracker is doing all the things to his AutoDub that I have been looking for. I'm going to go check out AutoDub now... BTW: Right now my tool only creates AVS files but I've other work done for using Besweet to get the audiofile and it's size. So much coding, so little time... Anyone know C# and wanna help?
Emp3r0r
18th September 2002, 16:30
I tried AutoDub and it didn't work for me because my C: drive is a Zip Drive (I know my system is screwy). I did see the program though and it seems nice but not what I was looking for so starting VS.NET up.
mtrooper
18th September 2002, 20:01
Well, here are my formulas for getting SmartCrop, as a result of fun with equations :D:
You need:
xTemp, yTemp, yOrig, xOrig, newAr, cy1, cy2, cx1, cx2, yOutMod16 (yout that is comaptible with mod 16 = the target height for which you want to correct cropping), origAR(either 16:9 or 4:3):
You calculate a and b, which mean:
a=cay1+cay2, where cay is additional cropping for top/bottom
b=cax1+cax2
Formulas:
a=-xTemp*yOutMod16/xOut-cy1-cy2+yOrig
b=-origAR^-1*xOut*yTemp*xOrig/(yOutMod16*yOrig)-cx1-cx2+xOrig
Hope anyone finds them useful.
Emp3r0r
18th September 2002, 21:31
My formula is failing but actually halfway working. I just need to take into account the distance as an absolute value wether it is negative or positive and add pixels based on that until the AR error is no more than 0.001. Here is my UNCORRECTED codepublic void SmartCropLeftRight()
{
//restore original cropping from backup
_Left = __Left;
_Right = __Right;
_Top = __Top;
_Bottom = __Bottom;
bool bLeft = true;
//add alternating left and right
while ((this.InAR - this.OutAR) > 0.001 && ((this.OutAR - this.InAR) < -0.001))
{
if (bLeft) _Left++;
else _Right++;
bLeft = !bLeft;
}
}OK, I didn't get what TheWEF said the first time so I'm going about this wrong. If I'm gettin it, I need to see which height resolution produces the least amount of cropping and then use that one.
@mtrooper: I tried the formula (b) but got b=14400. So I have no idea what is going on in your formula or if I'm feeding it the correct values. Can you give us an example of it's use? Thanks
mtrooper
18th September 2002, 22:08
Um, just noticed that I lefte 2 - signs out...sorry, was careless (I edited my previous post so it contains correct formulas) :(
And an example:
xOrig=720
yOrig=576
cy1=5
cy2=0
cx1=14
cx2=10
inAR=4:3
yTemp=571
xTemp=742 (calculated using Latexxx's formulas)
newAR=1,2995
yOut=493, so yOutMod16=496
outAR=1,2903
ARerror: 0,0092 (useless in our calculations)
a=-742*496/640-5-0+576=-4 (since a<0 we leave it alone)
b=-3/4*640*571*720/(496*576)-14-10+720=5, so: cax1=cax2=b div 2
Emp3r0r
19th September 2002, 17:02
(!) = known
(?) = un-known
(!) (?) = depends on method
Variable Name : Value Status
orgX source width : 720 (!)
orgY source height : 480 (!)
orgAR source ar : 1.500 (!)
PAR anamorphic 16:9 PAR : 1.778 (!)
cY1 crop top : 60 (!)
cY2 crop bot : 64 (!)
cX1 crop left : 2 (!)(?)
cX2 crop right : 2 (!)(?)
crpX in width : 716 (!)(?)
crpY in height : 356 (!)
newAR in ar : 2.384 (?)
outX out width : 640 (!)
outY out height : 272 (?)
outAR our ar : 2.353 (?)
modX w-mod : 16 (!)
modY h-mod : 16 (!)
errAR ar error : -0.03 (?)
Formula's for finding unknown's for a PIXEL CROP
newAR = ((PAR * orgY) - ((PAR * orgY) * ((cX1+cX2)/orgX)))/(orgY-(cY1+cY2))
if (((outX/newAR)%modY) >= (modY/2)) outY = (outX/newAR) + (modY - ((outX/newAR)%modY))
else outY = (outX/newAR) - ((outX/newAR)%modY)
outAR = outX/outY
errAR = outAR - newAR
Formula's for finding unknown's for a SMARTCROP LEFT-RIGHT
Woo Hoo, I've got the code working, once I clean it up I'll post it hereSpecial thanks to the WEF for helping with the smart cropping and Latexxx for the PAR code and everyone else who helped. Without you guy's I would have spent months instead of weeks on this. ;)
TheWEF
20th September 2002, 23:56
please read my first post once more:
you do NOT need to calculate display-AR anywhere in the process. forget it for now, it just confuses you.
i recommend that you define records (or structs in c) for resolution and crop, like:
TRes = record
x:integer;
y:integer;
end;
TCrop = record
t:integer;
b:integer;
l:integer;
r:integer;
end;
and functions to operate on them like
function DoCrop(R:TRes;C:TCrop):TRes;
begin
Result.x:=R.x-C.l-C.r;
Result.y:=R.y-C.t-C.b;
end;
or
function AlignRes(R:TRes;Mod:TRes):TRes;
begin
Result.x:=Round(R.x/Mod.x)*Mod.x;
Result.y:=Round(R.y/Mod.y)*Mod.y;
end;
put as many formulas as possible into such functions, try to write very clean and understandable code.
suddenly everything is obvious as you write it...
wef.
Emp3r0r
11th October 2002, 20:23
Still needs some work but generally working.
using System;
using System.Drawing;
namespace DVD2XCD
{
/// <summary>
/// A Crop data structure.
/// </summary>
public struct Crop
{
/// <summary>
/// Top
/// </summary>
public int T;
/// <summary>
/// Bottom
/// </summary>
public int B;
/// <summary>
/// Left
/// </summary>
public int L;
/// <summary>
/// Right
/// </summary>
public int R;
/// <summary>
/// Holds amount of cropping.
/// </summary>
/// <param name="top">Top cropping</param>
/// <param name="bot">Bottom cropping</param>
/// <param name="lft">Left cropping</param>
/// <param name="rht">Right cropping</param>
public Crop(int top, int bot, int lft, int rht)
{
T = top; B = bot; L = lft; R = rht;
}
}
/// <summary>
/// Different types of crop styles.
/// </summary>
public enum CropType {Pixel, SmartLeftRight, SmartAll};
/// <summary>
/// Summary description for CropObject.
/// TODO: -Sometimes the CropObject returns an extra
/// pixel during SmartCropAll (needs fixing)
/// -Free Aspect ratio handling
/// -Make methods publicly accessable?
/// </summary>
public class CropObject
{
/// <summary>
/// Takes cropping information and then applys that to input resolution
/// and performs calculations to find unknown values.
/// </summary>
public Size sourceRes;
public Size outputRes;
public Size croppedRes;
public Size exactRes;
public Size alignedRes;
public Size modRes; //output restriction
public Crop cropping;
public Crop croppingSmartLR;
public Crop croppingSmartAll;
public double pAR; //anamorphic value
public CropType croptype;
public double iAR; //input AR
public double oAR; //output AR
/// <summary>
/// Constructor which finds unknowns after given knowns.
/// </summary>
/// <param name="src">Source Size</param>
/// <param name="crp">Cropping Amount</param>
/// <param name="par">Pixel Aspect Ratio</param>
/// <param name="mod">Output Size Restrictions</param>
/// <param name="target">Target Resolution</param>
/// <param name="ct">Crop Type</param>
public CropObject(Size src, Crop crp, double par, Size mod, Size target, CropType ct)
{
sourceRes = src;
cropping = crp;
pAR = par;
modRes = mod;
outputRes = target;
croptype = ct;
croppedRes = new Size(this.DoCrop(sourceRes,cropping).Width,this.DoCrop(sourceRes,cropping).Height);
//Calculate width
double w = pAR * sourceRes.Height;
double xar = Convert.ToDouble((cropping.L + cropping.R))/Convert.ToDouble(sourceRes.Width);
w = w - (w * xar); //adjust for left,right cropping
//Calculate height
double h = sourceRes.Height - (cropping.T + cropping.B);
h = Convert.ToDouble(this.DoCrop(sourceRes,cropping).Width) / w * Convert.ToDouble(this.DoCrop(sourceRes, cropping).Height);
//Input AR
iAR = w/h;
//Internal
exactRes = new Size(this.AlignRes(this.Resize(this.ApplyPAR(sourceRes,cropping,pAR),outputRes),modRes).Width,this.Resize(this.ApplyPAR(sourceRes,cropping,pAR),outputRes).Height);
alignedRes = new Size(this.AlignRes(exactRes,modRes).Width, this.AlignRes(exactRes,modRes).Height) ;
outputRes = new Size(alignedRes.Width,alignedRes.Height);
//Only if SmartCropLeft-Right modify height
if (croptype == CropType.SmartLeftRight && exactRes.Height >= alignedRes.Height)
{
outputRes.Height = alignedRes.Height + modRes.Height;
}
//We know output size so now calc Output AR
oAR = Convert.ToDouble(outputRes.Width)/Convert.ToDouble(outputRes.Height);
//--- Smart Cropping Code ---
//For Smart Left-Right find adjustment for left and right side
int adj = Convert.ToInt16(Math.Round((Convert.ToDouble(this.DoCrop(sourceRes,cropping).Width) - h*oAR)));
if (adj < 0) adj = 0;
//make smarter by adding excess to smaller side
int sL = cropping.L + adj/2;
int sR = cropping.R + adj/2;
if (sL < sR) sL += adj%2;
else sR += adj%2;
//set it
this.croppingSmartLR = new Crop(cropping.T, cropping.B, sL, sR);
//For Smart All find adjustment first for top and bottom then left and right
int adjY = Convert.ToInt16(Math.Round((Convert.ToDouble(this.DoCrop(sourceRes,cropping).Height) - w/oAR)));
if (adjY < 0) adjY = 0;
//make smarter
int sT = cropping.T + adjY/2;
int sB = cropping.B + adjY/2;
if (sT < sB) sT += adjY%2;
else sB += adjY%2;
//now left right
adj = Convert.ToInt16(Math.Round((Convert.ToDouble(this.DoCrop(sourceRes,cropping).Width) - (h-Convert.ToDouble(adjY))*oAR)));
if (adj < 0) adj = 0;
//make smarter
sL = cropping.L + adj/2;
sR = cropping.R + adj/2;
if (sL <= sR) sL += adj%2;
else sR += adj%2;
//set it
this.croppingSmartAll = new Crop(sT, sB, sL, sR);
//need to change it to use my static methods
//only if SmartCropping, recalc input AR
if (croptype == CropType.SmartLeftRight)
{
croppedRes = new Size(this.DoCrop(sourceRes,this.croppingSmartLR).Width,this.DoCrop(sourceRes,this.croppingSmartLR).Height);
w = pAR * sourceRes.Height;
xar = Convert.ToDouble((croppingSmartLR.L + croppingSmartLR.R))/Convert.ToDouble(sourceRes.Width);
w = w - (w * xar);
h = sourceRes.Height - (croppingSmartLR.T + croppingSmartLR.B);
iAR = w/h;
}
else if (croptype == CropType.SmartAll)
{
croppedRes = new Size(this.DoCrop(sourceRes,this.croppingSmartAll).Width,this.DoCrop(sourceRes,this.croppingSmartAll).Height);
w = pAR * sourceRes.Height;
xar = Convert.ToDouble((croppingSmartAll.L + croppingSmartAll.R))/Convert.ToDouble(sourceRes.Width);
w = w - (w * xar);
h = sourceRes.Height - (croppingSmartAll.T + croppingSmartAll.B);
iAR = w/h;
}
}
/// <summary>
/// Does cropping based upon values.
/// </summary>
/// <param name="res">Input Size</param>
/// <param name="crop">Crop Data</param>
/// <returns>Output Size</returns>
private Size DoCrop(Size res, Crop crop)
{
return new Size((res.Width - (crop.L + crop.R)),(res.Height - (crop.T + crop.B)));
}
/// <summary>
/// Adjusts for pixel aspect ratio and returns a new size
/// based upon source size and cropping info.
/// Thanks to Latexxx for the formula.
/// </summary>
/// <param name="res">Input Size</param>
/// <param name="crop">Crop Data</param>
/// <param name="par">Pixel Aspect Ratio (for anamorphic)</param>
/// <returns>Output Size</returns>
private Size ApplyPAR(Size res, Crop crop, double par)
{
double w = par * res.Height;
double xar = Convert.ToDouble((crop.L + crop.R))/Convert.ToDouble(res.Width);
w = w - (w * xar);
Size otemp = new Size(Convert.ToInt32(w), res.Height-(crop.T + crop.B));
return otemp;
}
/// <summary>
/// This takes a input resolution and a target resolution and uses the width
/// from the target resolution to calculate the correct height of the target
/// resolution and then returns that.
/// </summary>
/// <param name="res">Input resolution</param>
/// <param name="tar">Target resolution (Width only significant)</param>
/// <returns>New Resolution</returns>
private Size Resize(Size res, Size tar)
{
double xar = Convert.ToDouble(res.Width) / Convert.ToDouble(res.Height);
int height = Convert.ToInt32(Convert.ToDouble(tar.Width) / xar);
return new Size(tar.Width, height);
}
/// <summary>
/// Takes input resolution and modifies to be multiples of the mod resolution
/// (Thanks to TheWEF)
/// </summary>
/// <param name="res">Input Resolution</param>
/// <param name="mod">Mod Resolution</param>
/// <returns>New Resolution</returns>
private Size AlignRes(Size res, Size mod)
{
int width = Convert.ToInt32(Math.Round(Convert.ToDouble(res.Width)/Convert.ToDouble(mod.Width))*Convert.ToDouble(mod.Width));
int height = Convert.ToInt32(Math.Round(Convert.ToDouble(res.Height)/Convert.ToDouble(mod.Height))*Convert.ToDouble(mod.Height));
return new Size( width , height );
}
}
}
Emp3r0r
11th October 2002, 21:23
I didn't realize how sloppy this was. What a mess.
vBulletin® v3.8.11, Copyright ©2000-2024, vBulletin Solutions Inc.