/// <summary> /// Calculates FrameDouble, CropSource, CropAfter and OutputWidth values. /// </summary> /// <param name="force">When false, this call is ignored when AutoCalculateSize is false.</param> private void CalculateSize(bool force) { if (!force && !AutoCalculateSize) return; if (!SourceWidth.HasValue || !SourceHeight.HasValue || OutputHeight > 10000) { OutputWidth = null; return; } // Calculate CropSource and CropAfter values. if (Crop) { // CropSource must be a factor of 4. CropSource = new Rect( CropLeft / 4 * 4, CropTop / 4 * 4, CropRight / 4 * 4, CropBottom / 4 * 4); } else CropSource = new Rect(); FrameDouble = 0; int ScaleFactor = 1; int FrameDoubleX = 0, FrameDoubleY = 0; int ScaleFactorX = 1, ScaleFactorY = 1; // Calculate scale factor based on height while ((SourceHeight - CropSource.Top - CropSource.Bottom) * ScaleFactorY < OutputHeight) { FrameDoubleY += 1; ScaleFactorY *= 2; } // Calculate scale factor based on width while ((SourceWidth - CropSource.Left - CropSource.Right) * ScaleFactorX * SourceAspectRatio < OutputWidth) { FrameDoubleX += 1; ScaleFactorX *= 2; } // Take highest ratio FrameDouble = FrameDoubleX > FrameDoubleY ? FrameDoubleX : FrameDoubleY; ScaleFactor = ScaleFactorX > ScaleFactorY ? ScaleFactorX : ScaleFactorY; if (Crop) { CropAfter = new Rect( (CropLeft - CropSource.Left) * ScaleFactor, (CropTop - CropSource.Top) * ScaleFactor, (CropRight - CropSource.Right) * ScaleFactor, (CropBottom - CropSource.Bottom) * ScaleFactor); } else CropAfter = new Rect(); int CropHeight = ((SourceHeight.Value - CropSource.Top - CropSource.Bottom) * ScaleFactor); int CropWidth = ((SourceWidth.Value - CropSource.Left - CropSource.Right) * ScaleFactor); if (CropAfter.HasValue) { CropHeight = CropHeight - CropAfter.Top - CropAfter.Bottom; CropWidth = CropWidth - CropAfter.Left - CropAfter.Right; } // Make width divisible by 4 without distorting pixels float TotalWidth = (float)CropWidth * SourceAspectRatio / CropHeight * OutputHeight; OutputWidth = (int)Math.Round(TotalWidth / 4) * 4; if (TotalWidth >= OutputWidth.Value) { float WidthAdjust = TotalWidth - OutputWidth.Value; int WidthAdjustInt = (int)Math.Round(WidthAdjust / 2); CropAfter.Left += WidthAdjustInt; CropAfter.Right += WidthAdjustInt; } else { float HeightAdjust = (OutputWidth.Value - TotalWidth) / SourceAspectRatio; int HeightAdjustInt = (int)Math.Round(HeightAdjust / 2); CropAfter.Top += HeightAdjustInt; CropAfter.Bottom += HeightAdjustInt; } }