Beispiel #1
0
        /// <summary>
        /// calculates the ideal mod vertical resolution that matches the desired horizontal resolution
        /// </summary>
        /// <param name="readerHeight">height of the source</param>
        /// <param name="readerWidth">width of the source</param>
        /// <param name="customDAR">custom display aspect ratio to be taken into account for resizing</param>
        /// <param name="cropping">the crop values for the source</param>
        /// <param name="horizontalResolution">the desired horizontal resolution of the output</param>
        /// <param name="signalAR">whether or not we're going to signal the aspect ratio (influences the resizing)</param>
        /// <param name="sarX">horizontal pixel aspect ratio (used when signalAR = true)</param>
        /// <param name="sarY">vertical pixel aspect ratio (used when signalAR = true)</param>
        /// <param name="mod">the MOD value</param>
        /// <returns>the suggested horizontal resolution</returns>
        public static int SuggestVerticalResolution(double readerHeight, double readerWidth, Dar inputDAR, CropValues cropping, int horizontalResolution,
                                                    bool signalAR, out Dar?dar, int mod, decimal acceptableAspectErrorPercent)
        {
            int scriptVerticalResolution;

            decimal fractionOfWidth            = ((decimal)readerWidth - (decimal)cropping.left - (decimal)cropping.right) / (decimal)readerWidth;
            decimal sourceHorizontalResolution = (decimal)readerHeight * inputDAR.AR * fractionOfWidth;
            decimal sourceVerticalResolution   = (decimal)readerHeight - (decimal)cropping.top - (decimal)cropping.bottom;
            decimal resizedVerticalResolution  = (decimal)horizontalResolution / (sourceHorizontalResolution / sourceVerticalResolution);

            if (signalAR)
            {
                decimal inputWidthOnHeight = ((decimal)readerWidth - (decimal)cropping.left - (decimal)cropping.right) /
                                             ((decimal)readerHeight - (decimal)cropping.top - (decimal)cropping.bottom);
                decimal realAspectRatio = getAspectRatio(inputDAR.AR, sourceHorizontalResolution / sourceVerticalResolution, acceptableAspectErrorPercent); // the aspect ratio of the video
                resizedVerticalResolution = (decimal)horizontalResolution / inputWidthOnHeight;                                                             // Scale vertical resolution appropriately
                scriptVerticalResolution  = ((int)Math.Round(resizedVerticalResolution / (decimal)mod) * mod);

                if (inputDAR.AR != realAspectRatio)
                {
                    int     parX     = 0;
                    int     parY     = 0;
                    int     iLimit   = 101;
                    decimal distance = 999999;
                    if (acceptableAspectErrorPercent == 0)
                    {
                        iLimit = 100001;
                    }
                    for (int i = 1; i < iLimit; i++)
                    {
                        // We create a fraction with integers, and then convert back to a decimal, and see how big the rounding error is
                        decimal fractionApproximation   = (decimal)Math.Round(realAspectRatio * ((decimal)i)) / (decimal)i;
                        decimal approximationDifference = Math.Abs(realAspectRatio - fractionApproximation);
                        if (approximationDifference < distance)
                        {
                            distance = approximationDifference;
                            parY     = i;
                            parX     = (int)Math.Round(realAspectRatio * ((decimal)parY));
                        }
                    }
                    Debug.Assert(parX > 0 && parY > 0);
                    dar = new Dar((ulong)parX, (ulong)parY);
                }
                else
                {
                    dar = inputDAR;
                }
            }
            else
            {
                scriptVerticalResolution = ((int)Math.Round(resizedVerticalResolution / (decimal)mod)) * mod;
                dar = null;
            }

            return(scriptVerticalResolution);
        }
Beispiel #2
0
        /// <summary>
        /// if enabled, each change of the horizontal resolution triggers this method
        /// it calculates the ideal mod 16 vertical resolution that matches the desired horizontal resolution
        /// </summary>
        /// <param name="readerHeight">height of the source</param>
        /// <param name="readerWidth">width of the source</param>
        /// <param name="customDAR">custom display aspect ratio to be taken into account for resizing</param>
        /// <param name="cropping">the crop values for the source</param>
        /// <param name="horizontalResolution">the desired horizontal resolution of the output</param>
        /// <param name="signalAR">whether or not we're going to signal the aspect ratio (influences the resizing)</param>
        /// <param name="sarX">horizontal pixel aspect ratio (used when signalAR = true)</param>
        /// <param name="sarY">vertical pixel aspect ratio (used when signalAR = true)</param>
        /// <returns>the suggested horizontal resolution</returns>
        public static int suggestResolution(double readerHeight, double readerWidth, double customDAR, CropValues cropping, int horizontalResolution,
                                            bool signalAR, int acceptableAspectError, out Dar?dar)
        {
            double fractionOfWidth    = (readerWidth - (double)cropping.left - (double)cropping.right) / readerWidth;
            double inputWidthOnHeight = (readerWidth - (double)cropping.left - (double)cropping.right) /
                                        (readerHeight - (double)cropping.top - (double)cropping.bottom);
            double sourceHorizontalResolution = readerHeight * customDAR * fractionOfWidth;
            double sourceVerticalResolution   = readerHeight - (double)cropping.top - (double)cropping.bottom;
            double realAspectRatio            = sourceHorizontalResolution / sourceVerticalResolution; // the real aspect ratio of the video

            realAspectRatio = getAspectRatio(realAspectRatio, acceptableAspectError);                  // Constrains DAR to a set of limited possibilities
            double resizedVerticalResolution = (double)horizontalResolution / realAspectRatio;

            int scriptVerticalResolution = ((int)Math.Round(resizedVerticalResolution / 16.0)) * 16;

            if (signalAR)
            {
                resizedVerticalResolution = (double)horizontalResolution / inputWidthOnHeight; // Scale vertical resolution appropriately
                scriptVerticalResolution  = ((int)Math.Round(resizedVerticalResolution / 16.0) * 16);

                int    parX     = 0;
                int    parY     = 0;
                double distance = 999999;
                for (int i = 1; i < 101; i++)
                {
                    // We create a fraction with integers, and then convert back to a double, and see how big the rounding error is
                    double fractionApproximation   = (double)Math.Round(realAspectRatio * ((double)i)) / (double)i;
                    double approximationDifference = Math.Abs(realAspectRatio - fractionApproximation);
                    if (approximationDifference < distance)
                    {
                        distance = approximationDifference;
                        parY     = i;
                        parX     = (int)Math.Round(realAspectRatio * ((double)parY));
                    }
                }
                //sarX = (int)Math.Round(realAspectRatio * resizedVerticalResolution);
                //sarY = (int)Math.Round(horizontalResolution);
                Debug.Assert(parX > 0 && parY > 0);
                dar = new Dar((ulong)parX, (ulong)parY);

                return(scriptVerticalResolution);
            }
            else
            {
                dar = null;
                return(scriptVerticalResolution);
            }
        }
Beispiel #3
0
        /// <summary>
        /// calculates the DAR value based upon the video information
        /// </summary>
        /// <param name="width">width of the video</param>
        /// <param name="height">height of the video</param>
        /// <param name="dar">display aspect ratio </param>
        /// <param name="par">pixel aspect ratio </param>
        /// <param name="darString">display aspect ratio string - e.g. 16:9 or 4:3</param>
        /// <returns>the DAR value</returns>
        public static Dar GetDAR(int width, int height, string darValue, decimal?par, string darString)
        {
            if (!String.IsNullOrEmpty(darString) && width == 720 && (height == 576 || height == 480))
            {
                Dar newDar = Dar.A1x1;
                if (!MainForm.Instance.Settings.UseITUValues)
                {
                    if (darString.Equals("16:9"))
                    {
                        newDar = Dar.STATIC16x9;
                    }
                    else if (darString.Equals("4:3"))
                    {
                        newDar = Dar.STATIC4x3;
                    }
                }
                else if (height == 576)
                {
                    if (darString.Equals("16:9"))
                    {
                        newDar = Dar.ITU16x9PAL;
                    }
                    else if (darString.Equals("4:3"))
                    {
                        newDar = Dar.ITU4x3PAL;
                    }
                }
                else
                {
                    if (darString.Equals("16:9"))
                    {
                        newDar = Dar.ITU16x9NTSC;
                    }
                    else if (darString.Equals("4:3"))
                    {
                        newDar = Dar.ITU4x3NTSC;
                    }
                }
                if (!newDar.Equals(Dar.A1x1))
                {
                    return(newDar);
                }
            }

            if (par == null || par <= 0)
            {
                par = 1;
            }

            decimal?dar = easyParseDecimal(darValue);

            if (dar != null && dar > 0)
            {
                decimal correctDar = (decimal)width * (decimal)par / height;
                if (Math.Abs(Math.Round(correctDar, 3) - Math.Round((decimal)dar, 3)) <= 0.001M)
                {
                    return(new Dar((ulong)(Math.Round(width * (decimal)par)), (ulong)height));
                }
                else
                {
                    return(new Dar((decimal)dar));
                }
            }

            if (darValue.Contains(":"))
            {
                return(new Dar(ulong.Parse(darValue.Split(':')[0]), ulong.Parse(darValue.Split(':')[1])));
            }
            else
            {
                return(new Dar((ulong)width, (ulong)height));
            }
        }
Beispiel #4
0
        /// <summary>
        /// gets the desired resolution based on input settings
        /// </summary>
        /// <param name="sourceWidth">the complete width of the input file without cropping</param>
        /// <param name="sourceHeight">the complete height of the input file without cropping</param>
        /// <param name="inputDAR">the input DAR value</param>
        /// <param name="cropValues">the crop values</param>
        /// <param name="cropEnabled">true if crop values must be used</param>
        /// <param name="mod">the mod value used for the final resize values</param>
        /// <param name="resizeEnabled">true if resize can be used</param>
        /// <param name="upsizingEnabled">true if upsizing can be used</param>
        /// <param name="signalAR">whether or not ar signalling is to be used for the output
        /// (depending on this parameter, resizing changes to match the source AR)</param>
        /// <param name="suggestHeight">true if height should be calculated</param>
        /// <param name="acceptableAspectErrorPercent">acceptable aspect error if signalAR is true</param>
        /// <param name="xTargetDevice">x264 Target Device - may limit the output resolution</param>
        /// <param name="fps">the frames per second of the source</param>
        /// <param name="outputWidth">the calculated output width</param>
        /// <param name="outputHeight">the calculated output height</param>
        /// <param name="paddingValues">the padding values</param>
        /// <param name="outputDar">the output DAR value</param>
        /// <param name="_log">the log item</param>
        public static void GetResolution(int sourceWidth, int sourceHeight, Dar inputDar,
                                         ref CropValues cropValues, bool cropEnabled, int mod, ref bool resizeEnabled, bool upsizingAllowed,
                                         bool signalAR, bool suggestHeight, decimal acceptableAspectErrorPercent,
                                         x264Device xTargetDevice, Double fps, ref int outputWidth, ref int outputHeight,
                                         out CropValues paddingValues, out Dar?outputDar, LogItem _log)
        {
            paddingValues = new CropValues();

            getResolution(sourceWidth, sourceHeight, inputDar,
                          cropValues, cropEnabled, mod, resizeEnabled, upsizingAllowed,
                          signalAR, suggestHeight, acceptableAspectErrorPercent,
                          ref outputWidth, ref outputHeight,
                          out outputDar, _log);

            bool settingsChanged;

            if (isResolutionDeviceCompliant(xTargetDevice, outputWidth, outputHeight, out settingsChanged, ref resizeEnabled, ref cropEnabled, _log) == true)
            {
                if (!cropEnabled)
                {
                    cropValues = new CropValues();
                }
                return;
            }

            if (settingsChanged)
            {
                getResolution(sourceWidth, sourceHeight, inputDar,
                              cropValues, cropEnabled, mod, resizeEnabled, upsizingAllowed,
                              signalAR, suggestHeight, acceptableAspectErrorPercent,
                              ref outputWidth, ref outputHeight,
                              out outputDar, _log);

                // check if the resolution is now compliant
                if (isResolutionDeviceCompliant(xTargetDevice, outputWidth, outputHeight, out settingsChanged, ref resizeEnabled, ref cropEnabled, null) == true)
                {
                    if (!cropEnabled)
                    {
                        cropValues = new CropValues();
                    }
                    return;
                }
            }
            if (!cropEnabled)
            {
                cropValues = new CropValues();
            }

            // adjust horizontal resolution if width or height are too large
            int outputHeightIncludingPadding = 0;
            int outputWidthIncludingPadding  = 0;

            if (xTargetDevice.BluRay)
            {
                if (outputWidth >= 1920)
                {
                    outputWidth = 1920;
                    outputHeightIncludingPadding = 1080;
                }
                else if (outputWidth >= 1280)
                {
                    outputWidth = 1280;
                    outputHeightIncludingPadding = 720;
                }
                else
                {
                    outputWidth = 720;
                    if (fps == 25)
                    {
                        outputHeightIncludingPadding = 576;
                    }
                    else
                    {
                        outputHeightIncludingPadding = 480;
                    }
                }
                outputWidthIncludingPadding = outputWidth;
                if (_log != null)
                {
                    _log.LogEvent("Force resolution of " + outputWidth + "x" + outputHeightIncludingPadding + " as required for " + xTargetDevice.Name);
                }
            }
            else if (xTargetDevice.Width > 0 && outputWidth > xTargetDevice.Width)
            {
                outputWidth = xTargetDevice.Width;
                _log.LogEvent("Set resolution width to " + outputWidth + " as required for " + xTargetDevice.Name);
            }

            // adjust cropped vertical resolution
            getResolution(sourceWidth, sourceHeight, inputDar,
                          cropValues, cropEnabled, mod, resizeEnabled, upsizingAllowed,
                          signalAR, suggestHeight, acceptableAspectErrorPercent,
                          ref outputWidth, ref outputHeight,
                          out outputDar, _log);
            while ((xTargetDevice.Height > 0 && outputHeight > xTargetDevice.Height) || (xTargetDevice.BluRay && outputHeight > outputHeightIncludingPadding))
            {
                outputWidth -= mod;
                getResolution(sourceWidth, sourceHeight, inputDar,
                              cropValues, cropEnabled, mod, resizeEnabled, upsizingAllowed,
                              signalAR, suggestHeight, acceptableAspectErrorPercent,
                              ref outputWidth, ref outputHeight,
                              out outputDar, _log);
            }

            paddingValues.left   = Convert.ToInt32(Math.Floor((outputWidthIncludingPadding - outputWidth) / 2.0));
            paddingValues.right  = Convert.ToInt32(Math.Ceiling((outputWidthIncludingPadding - outputWidth) / 2.0));
            paddingValues.bottom = Convert.ToInt32(Math.Floor((outputHeightIncludingPadding - outputHeight) / 2.0));
            paddingValues.top    = Convert.ToInt32(Math.Ceiling((outputHeightIncludingPadding - outputHeight) / 2.0));

            outputWidth  = outputWidthIncludingPadding;
            outputHeight = outputHeightIncludingPadding;

            if (!cropEnabled)
            {
                cropValues = new CropValues();
            }
        }
Beispiel #5
0
        /// <summary>
        /// gets the desired resolution based on input settings
        /// </summary>
        /// <param name="sourceWidth">the complete width of the input file without cropping</param>
        /// <param name="sourceHeight">the complete height of the input file without cropping</param>
        /// <param name="inputDAR">the input DAR value</param>
        /// <param name="cropping">the crop values</param>
        /// <param name="mod">the mod value used for the final resize values</param>
        /// <param name="resizeEnabled">true if resize can be used</param>
        /// <param name="upsizingEnabled">true if upsizing can be used</param>
        /// <param name="signalAR">whether or not ar signalling is to be used for the output
        /// (depending on this parameter, resizing changes to match the source AR)</param>
        /// <param name="suggestHeight">true if height should be calculated</param>
        /// <param name="acceptableAspectErrorPercent">acceptable aspect error if signalAR is true</param>
        /// <param name="outputWidth">the calculated output width</param>
        /// <param name="outputHeight">the calculated output height</param>
        /// <param name="outputDar">the output DAR value</param>
        /// <param name="_log">the log item</param>
        private static void getResolution(int sourceWidth, int sourceHeight, Dar inputDar,
                                          CropValues cropValues, bool cropEnabled, int mod, bool resizeEnabled,
                                          bool upsizingAllowed, bool signalAR, bool suggestHeight,
                                          decimal acceptableAspectErrorPercent, ref int outputWidth,
                                          ref int outputHeight, out Dar?outputDar, LogItem _log)
        {
            outputDar = null;

            CropValues cropping = new CropValues();

            if (cropEnabled)
            {
                cropping = cropValues.Clone();
            }

            // remove upsizing if not allowed
            if (!upsizingAllowed && sourceWidth - cropping.left - cropping.right < outputWidth)
            {
                outputWidth = sourceWidth - cropping.left - cropping.right;
                if (_log != null)
                {
                    _log.LogEvent("Lowering output width resolution to " + outputWidth + " to avoid upsizing");
                }
            }

            // correct hres if not mod compliant
            if (outputWidth % mod != 0)
            {
                int diff = outputWidth % mod;
                if (outputWidth - diff > 0)
                {
                    outputWidth -= diff;
                }
                else
                {
                    outputWidth = mod;
                }
            }

            if (suggestHeight)
            {
                int scriptVerticalResolution = Resolution.SuggestVerticalResolution(sourceHeight, sourceWidth, inputDar, cropping,
                                                                                    outputWidth, signalAR, out outputDar, mod, acceptableAspectErrorPercent);

                int iMaximum = 9999;
                if (!upsizingAllowed)
                {
                    iMaximum = sourceHeight - cropping.top - cropping.bottom;
                }

                // Reduce horizontal resolution until a fit is found
                while (scriptVerticalResolution > iMaximum && outputWidth > mod)
                {
                    outputWidth -= mod;
                    scriptVerticalResolution = Resolution.SuggestVerticalResolution(sourceHeight, sourceWidth, inputDar, cropping,
                                                                                    outputWidth, signalAR, out outputDar, mod, acceptableAspectErrorPercent);
                }
                outputHeight = scriptVerticalResolution;
            }
            else if (!resizeEnabled)
            {
                outputHeight = sourceHeight - cropping.top - cropping.bottom;
            }
        }