/// <summary> /// Method todo the transformation. /// It will calculate 2 rectangles. A source and destination rectangle based on the /// current transformation , image width/height and screen width/height /// the returned source rectangle specifies which part of the image/video should be copied /// the returned destination rectangle specifies where the copied part should be presented on screen /// </summary> /// <param name="rSource">rectangle containing the source rectangle of the image/video</param> /// <param name="rDest">rectangle containing the destination rectangle of the image/video</param> public void GetWindow(out Rectangle rSource, out Rectangle rDest) { float fSourceFrameRatio = CalculateFrameAspectRatio(); CropSettings cropSettings = new CropSettings(); GetWindow(fSourceFrameRatio, out rSource, out rDest, cropSettings); }
// used from planescene public void GetWindow(int arVideoWidth, int arVideoHeight, out Rectangle rSource, out Rectangle rDest, CropSettings cropSettings) { float fSourceFrameRatio = (float)arVideoWidth / (float)arVideoHeight; GetWindow(fSourceFrameRatio, out rSource, out rDest, cropSettings); }
/// <summary> /// Finds the bounds an crops accordingly immediatly /// </summary> private void SingleCrop() { // are we viewing video? if (!IsPlaying()) { return; } using (Bitmap frame = GetFrame()) { if (frame == null) { Log.Warn("AutoCropper Failed to get frame (==null), aborting"); return; } Rectangle bounds = new Rectangle(); if (!analyzer.FindBounds(frame, ref bounds)) { return; } CropSettings cropSettings = new CropSettings(); cropSettings.Top = bounds.Top; cropSettings.Bottom = GUIGraphicsContext.VideoSize.Height - (bounds.Bottom + 1); cropSettings.Left = bounds.Left; cropSettings.Right = GUIGraphicsContext.VideoSize.Width - (bounds.Right + 1); RequestCrop(cropSettings); } }
//public ImageLoadSettings Load { get; private set; } //public WebSettings Web { get; private set; } // TODO: Add as many as you need.. public ImageGlobalSettings() { Crop = new CropSettings { Left = 0, Top = 0, Width = 0, Height = 0 }; Fmt = string.Empty; //Load = new ImageLoadSettings(); //Web = new WebSettings(); }
/// <summary> /// Adjusts the source and destination rectangles according to the cropping parameters, maintaining the RATIO between the source and destination /// aspect ratio. /// /// Note: /// Only used for the normal aspect right now, so could as well be coded directly into that zoom mode. /// But maybe it could be useful elsewhere as well and no changes have had to be made to the zoom mode code. /// </summary> /// <param name="rSource"></param> /// <param name="rDest"></param> /// <param name="cropSettings"></param> /* * void AdjustForCropping(ref System.Drawing.Rectangle rSource, ref System.Drawing.Rectangle rDest, CropSettings cropSettings, bool strictKeepAspect) * { * // temp * //return; * float destAspect = rDest.Width / (float)rDest.Height; * float sourceAspect = rSource.Width / (float)rSource.Height; * float croppedSourceAspect = (rSource.Width - cropSettings.Right - cropSettings.Left) / (float)(rSource.Height - cropSettings.Top - cropSettings.Bottom); * float originalAspectChange = destAspect / sourceAspect; * * * //if (( Math.Abs( destAspect - sourceAspect ) < 0.001 )) * // return; * * Log.Debug("AdjustForCropping: rSrc = " + rSource.ToString()); * Log.Debug("AdjustForCropping: rDest = " + rDest.ToString()); * * float newDestAspect = croppedSourceAspect * originalAspectChange; * * Log.Debug("newDestAspect: " + newDestAspect + " destAspect: " + destAspect); * Log.Debug("sourceAspect: " + sourceAspect + " croppedSrcAspect: " + croppedSourceAspect); * * if (newDestAspect > destAspect) * { * Log.Debug("CROPADJUST : DEST NOT WIDE ENOUGH (ie someone cropped top or bottom)"); * // destination needs to be wider * * // width needed to preserve height * float widthNeeded = rDest.Height * newDestAspect; * * if (widthNeeded > ScreenWidth && strictKeepAspect) * { * // decrease height * Log.Info("CROPADJUST : NOT ENOUGH WIDTH, needs " + widthNeeded); * // take all the width we can * rDest.Width = ScreenWidth; * // and reduce height for the rest * rDest.Height = (int)(rDest.Width / newDestAspect); ; * Log.Info("New height : " + rDest.Height); * } * else * { * Log.Info("CROPADJUST : ENOUGH WIDTH"); * rDest.Width = (int)widthNeeded; * } * } * else if (newDestAspect < destAspect) * { * // destination needs to be taller * Log.Info("CROPADJUST : DEST TOO WIDE (ie someone cropped left or right"); * * int heightNeeded = (int)(rDest.Width * newDestAspect); * int heightIncrease = heightNeeded - rDest.Height; * * Log.Info("HeightNeeded = " + heightNeeded); * Log.Info("heightIncrease= " + heightIncrease); * * if (heightNeeded > ScreenHeight && strictKeepAspect) * { * Log.Info("CROPADJUST: NOT ENOUGH HEIGHT, ADJUSTING WIDTH"); * rDest.Height = ScreenHeight; * int newWidth = (int)(newDestAspect * rDest.Height); * rDest.Width = newWidth; * Log.Debug("rDest.Width now " + newWidth); * } * else * { * rDest.Height = heightNeeded; * } * } * * rDest.Y = ScreenHeight / 2 - rDest.Height / 2; * rDest.X = ScreenWidth / 2 - rDest.Width / 2; * * if (rDest.X < 0) Log.Error("Geometry.AdjustForCropping miscalculated, produced NEGATIVE X coordinate!"); * if (rDest.Y < 0) Log.Error("Geometry.AdjustForCropping miscalculated, produced NEGATIVE Y coordinate!"); * * AdjustSourceForCropping(ref rSource, cropSettings); * } */ /// <summary> /// Adjusts only the source rectangle according to the cropping parameters. /// </summary> /// <param name="rSource"></param> /// <param name="cropSettings"></param> private void AdjustSourceForCropping(ref Rectangle rSource, CropSettings cropSettings) { rSource.Y += cropSettings.Top; rSource.Height -= cropSettings.Top; rSource.Height -= cropSettings.Bottom; rSource.X += cropSettings.Left; rSource.Width -= cropSettings.Left; rSource.Width -= cropSettings.Right; }
public CropSettingsInstance(ObjectInstance prototype, CropSettings cropSettings) : this(prototype) { if (cropSettings == null) { throw new ArgumentNullException("cropSettings"); } m_cropSettings = cropSettings; }
/// <summary> /// Implements PlugInBase.Start /// Sets up the autocropper /// and sets GUIGraphicsContext.autoCropper /// to point to this object. /// </summary> public override void Start() { Log.Debug("AutoCropper: Start()"); instance = this; analyzer = new FrameAnalyzer(); // Load settings, if returns false, // none of autocropper modes are allowed // so we dont do anything if (!LoadSettings()) { return; } GUIGraphicsContext.autoCropper = this; lastSettings = new CropSettings(0, 0, 0, 0); int topMemLengthInFrames = (int)(topMemLength / (sampleInterval / 1000.0f)); int bottomMemLengthInFrames = (int)(bottomMemLength / (sampleInterval / 1000.0f)); int leftMemLengthInFrames = (int)(leftMemLength / (sampleInterval / 1000.0f)); int rightMemLengthInFrames = (int)(rightMemLength / (sampleInterval / 1000.0f)); Log.Debug("AutoCropper: Top memory is " + topMemLengthInFrames + " sampleinterval " + sampleInterval + " mem length " + topMemLength); Log.Debug("AutoCropper: Bottom memory is " + bottomMemLengthInFrames + " sampleinterval " + sampleInterval + " mem length " + bottomMemLength); Log.Debug("AutoCropper: Left memory is " + leftMemLengthInFrames + " sampleinterval " + sampleInterval + " mem length " + leftMemLength); Log.Debug("AutoCropper: Right memory is " + rightMemLengthInFrames + " sampleinterval " + sampleInterval + " mem length " + rightMemLength); topCropAvg = new MovingAverage(topMemLengthInFrames, 0); bottomCropAvg = new MovingAverage(bottomMemLengthInFrames, 0); leftCropAvg = new MovingAverage(leftMemLengthInFrames, 0); rightCropAvg = new MovingAverage(rightMemLengthInFrames, 0); // start the thread that will execute the actual cropping Thread t = new Thread(new ThreadStart(instance.Worker)); t.IsBackground = true; t.Priority = ThreadPriority.BelowNormal; t.Name = "AutoCropThread"; t.Start(); // register to handle playback events so we can wake // the above thread when playback starts if (useForMyVideos) { g_Player.PlayBackStarted += OnVideoStarted; } }
public VideoPlayer() { _cropSettings = ServiceRegistration.Get <IGeometryManager>().CropSettings; // EVR is available since Vista OperatingSystem osInfo = Environment.OSVersion; if (osInfo.Version.Major <= 5) { throw new EnvironmentException("This video player can only run on Windows Vista or above"); } PlayerTitle = "VideoPlayer"; }
/// <summary> /// Uses the static cropping system to execute the cropping /// </summary> private void RequestCrop(CropSettings cropSettings) { if (verboseLog) { Log.Debug("AutoCropper: RequestCrop"); } // Send message to planescene with crop GUIMessage msg = new GUIMessage(); msg.Message = GUIMessage.MessageType.GUI_MSG_PLANESCENE_CROP; msg.Object = cropSettings; GUIWindowManager.SendMessage(msg); lastSettings.Bottom = cropSettings.Bottom; lastSettings.Top = cropSettings.Top; lastSettings.Left = cropSettings.Left; lastSettings.Right = cropSettings.Right; }
/// <summary> /// Performs dynamic cropping based on the largest bounding box /// encountered (ie smallest cropping) within the 'memory' of the /// autocropper /// </summary> /// <param name="topCrop">Cropping found in current frame</param> /// <param name="bottomCrop">Cropping found in current frame</param> private void MinDynamicCrop(int topCrop, int bottomCrop, int leftCrop, int rightCrop) { if (firstDynamicCrop) { if (verboseLog) { Log.Debug("First dynamic crop, resetting to top {0}, bottom {1}, left {2}, right {3}", topCrop, bottomCrop, leftCrop, rightCrop); } topCropAvg.Reset(topCrop); bottomCropAvg.Reset(bottomCrop); leftCropAvg.Reset(leftCrop); rightCropAvg.Reset(rightCrop); firstDynamicCrop = false; } else { topCropAvg.Add(topCrop); bottomCropAvg.Add(bottomCrop); leftCropAvg.Add(leftCrop); rightCropAvg.Add(rightCrop); } int topMin = (int)topCropAvg.GetMin(); int bottomMin = (int)bottomCropAvg.GetMin(); int leftMin = (int)leftCropAvg.GetMin(); int rightMin = (int)rightCropAvg.GetMin(); if (verboseLog) { Log.Debug("Current topMin {0}, bottomMin {1}, leftMin {2}, rightMin {3}", topMin, bottomMin, leftMin, rightMin); } if (Math.Abs(topMin - lastSettings.Top) > 2 || Math.Abs(bottomMin - lastSettings.Bottom) > 2 || Math.Abs(leftMin - lastSettings.Left) > 2 || Math.Abs(rightMin - lastSettings.Right) > 2) { CropSettings newSettings = new CropSettings(); newSettings.Top = topMin; newSettings.Bottom = bottomMin; newSettings.Left = leftMin; newSettings.Right = rightMin; RequestCrop(newSettings); } }
/// <summary> /// This method runs in a thread and calls the actual cropping methods /// DynamicCrop and SingleCrop. /// </summary> private void Worker() { while (true) { if (verboseLog) { Log.Debug("AutoCropper: Mode : " + mode + " IsPlaying : " + IsPlaying()); } if (stopWorkerThread) { stopWorkerThread = false; return; } if (mode == Mode.DYNAMIC && IsPlaying()) { // do processing for dynamic cropping and sleep // a short while DynamicCrop(); //Bitmap b = PlaneScene.GetCurrentImage(); Thread.Sleep(sampleInterval); } else if (mode == Mode.MANUAL && IsPlaying()) { // crop once and wait to be woken up again SingleCrop(); workerEvent.WaitOne(); // reset automatically } else if (mode == Mode.OFF && IsPlaying()) { CropSettings noCrop = new CropSettings(0, 0, 0, 0); RequestCrop(noCrop); workerEvent.WaitOne(); } else { if (verboseLog) { Log.Debug("AutoCropper: Worker halting, waiting for worker event"); } ResetDynamic(); workerEvent.WaitOne(); // reset automatically } } }
/// <summary> /// set the oversan of MediaPortal by setting crop parameters /// </summary> private void SetCropMode() { double cropH = fCropH; double cropV = fCropV; if (LastSwitchedAspectRatio > 0.0 && (LastSwitchedGeometry != Geometry.Type.NonLinearStretch)) { if (useMaxCrop) { if (fCropV > (fCropH / LastSwitchedAspectRatio)) { //Adjust horiz crop value to match vertical crop value (without picture distortion) double extraHcropLimit = fWidthH * LastAnamorphFactor * MaxCropLim; cropH = Math.Min(fCropV * LastSwitchedAspectRatio, fCropH + extraHcropLimit); cropV = cropH / LastSwitchedAspectRatio; } else { double extraVcropLimit = fHeightV * MaxCropLim; cropV = Math.Min(fCropH / LastSwitchedAspectRatio, fCropV + extraVcropLimit); cropH = cropV * LastSwitchedAspectRatio; } } else { if (fCropV < (fCropH / LastSwitchedAspectRatio)) { //Adjust horiz crop value to match vertical crop value (without picture distortion) cropH = fCropV * LastSwitchedAspectRatio; } else { cropV = fCropH / LastSwitchedAspectRatio; } } } if (LastAnamorphFactor > 0.0) { //Correction to crop settings for anamorphic video i.e. when pixel aspect ratio != video aspect ratio //Log.Debug("ViewModeSwitcher: SetCropMode() Anamorph factor: {0}", LastAnamorphFactor); cropH /= LastAnamorphFactor; } CropSettings tmpCropSettings = new CropSettings(); tmpCropSettings.Left = (int)cropH; tmpCropSettings.Right = tmpCropSettings.Left; tmpCropSettings.Top = (int)cropV; tmpCropSettings.Bottom = tmpCropSettings.Top; GUIMessage msg = new GUIMessage(); msg.Message = GUIMessage.MessageType.GUI_MSG_PLANESCENE_CROP; msg.Object = tmpCropSettings; GUIWindowManager.SendMessage(msg); if (GUIGraphicsContext.IsFullScreenVideo && currentSettings.ShowSwitchMsg) { GUIMessage guiMsg = new GUIMessage(GUIMessage.MessageType.GUI_MSG_REFRESHRATE_CHANGED, 0, 0, 0, 0, 0, null); guiMsg.Label = "ViewModeSwitcher"; guiMsg.Label2 = ("ViewMode: " + LastSwitchedGeometry + ", AR: " + LastSwitchedAspectRatio + ", BB det: " + (enableLB && !disableLBGlobally) + ", Auto BB: " + useAutoCrop + ", H crop: " + tmpCropSettings.Left + ", V crop: " + tmpCropSettings.Top); guiMsg.Param1 = 3; GUIGraphicsContext.SendMessage(guiMsg); } }
public void GetWindow(int arVideoWidth, int arVideoHeight, out Rectangle rSource, out Rectangle rDest) { CropSettings cropSettings = new CropSettings(); GetWindow(arVideoWidth, arVideoHeight, out rSource, out rDest, cropSettings); }
/// <summary> /// Performs dynamic cropping based on a moving average or the /// cropping the analyzer has produced so far within the memory. /// </summary> /// <param name="topCrop">Cropping found in current frame</param> /// <param name="bottomCrop">Cropping found in current frame</param> private void AvgDynamicCrop(int topCrop, int bottomCrop, int leftCrop, int rightCrop) { CropSettings newSettings = new CropSettings(); newSettings.Top = lastSettings.Top; newSettings.Bottom = lastSettings.Bottom; newSettings.Left = lastSettings.Left; newSettings.Right = lastSettings.Right; bool update = false; // debug //newSettings.Top = topCrop; //newSettings.Bottom = bottomCrop; //RequestCrop(newSettings); //return; // end debug // If the image area has increase immediatly reset to this larger size if (topCrop < lastSettings.Top || firstDynamicCrop) { if (verboseLog) { Log.Debug("Top of image has increased"); } update = true; topCropAvg.Reset(topCrop); newSettings.Top = topCrop; } else { topCropAvg.Add(topCrop); } // If the image area has increase immediatly reset to this larger size if (bottomCrop < lastSettings.Bottom || firstDynamicCrop) { if (verboseLog) { Log.Debug("Bottom of image has increased"); } bottomCropAvg.Reset(bottomCrop); newSettings.Bottom = bottomCrop; update = true; } else { bottomCropAvg.Add(bottomCrop); } // If the image area has increase immediatly reset to this larger size if (leftCrop < lastSettings.Left || firstDynamicCrop) { if (verboseLog) { Log.Debug("Left side of image has increased"); } leftCropAvg.Reset(leftCrop); newSettings.Left = leftCrop; update = true; } else { leftCropAvg.Add(leftCrop); } // If the image area has increase immediatly reset to this larger size if (rightCrop < lastSettings.Right || firstDynamicCrop) { if (verboseLog) { Log.Debug("Right side of image has increased"); } rightCropAvg.Reset(rightCrop); newSettings.Right = rightCrop; update = true; } else { rightCropAvg.Add(rightCrop); } firstDynamicCrop = false; if (verboseLog) { Log.Debug( "Current cropping settings (Top/Bottom Left/Right): This Frames: {0}/{1} {6}/{7}, Avg: {4}/{5} {8}/{9}, Current Crop: {2}/{3} {10}/{11}", topCrop, bottomCrop, lastSettings.Top, lastSettings.Bottom, topCropAvg.Average, bottomCropAvg.Average, leftCrop, rightCrop, leftCropAvg.Average, rightCropAvg.Average, lastSettings.Left, lastSettings.Right); } if (topCropAvg.Average - lastSettings.Top > 4 && Math.Abs(topCropAvg.Average - topCrop) < 2) { newSettings.Top = (int)topCropAvg.Average; update = true; } if (bottomCropAvg.Average - lastSettings.Bottom > 4 && Math.Abs(bottomCropAvg.Average - bottomCrop) < 2) { newSettings.Bottom = (int)bottomCropAvg.Average; update = true; } if (leftCropAvg.Average - lastSettings.Left > 4 && Math.Abs(leftCropAvg.Average - leftCrop) < 2) { newSettings.Left = (int)leftCropAvg.Average; update = true; } if (rightCropAvg.Average - lastSettings.Right > 4 && Math.Abs(rightCropAvg.Average - rightCrop) < 2) { newSettings.Right = (int)rightCropAvg.Average; update = true; } if (update && (newSettings.Top != lastSettings.Top || newSettings.Bottom != lastSettings.Bottom || newSettings.Left != lastSettings.Left || newSettings.Right != lastSettings.Right)) { RequestCrop(newSettings); } }
public void GetWindow(int arVideoWidth, int arVideoHeight, out Rectangle rSource, out Rectangle rDest, out bool bUseNonLinearStretch, CropSettings cropSettings) { GetWindow(arVideoWidth, arVideoHeight, out rSource, out rDest, cropSettings); bUseNonLinearStretch = m_bUseNonLinearStretch; }
/// <summary> /// On Message /// </summary> /// <param name="message"></param> /// <returns></returns> public override bool OnMessage(GUIMessage message) { switch (message.Message) { case GUIMessage.MessageType.GUI_MSG_WINDOW_INIT: { // fetch settings for the current capture card _cropSettings = TvCropManager.CropSettings; GUILabelControl cardLabel = GetControl((int)Controls.CONTROL_CARD_LABEL) as GUILabelControl; cardLabel.Visible = false; foreach (int iCtl in Enum.GetValues(typeof(Controls))) { if (GetControl(iCtl) is GUISpinControl) { GUISpinControl cntl = (GUISpinControl)GetControl(iCtl); cntl.ShowRange = false; } } GUIControl.ClearControl(GetID, (int)Controls.CONTROL_CROP_TOP); for (int i = 0; i <= 200; ++i) { GUIControl.AddItemLabelControl(GetID, (int)Controls.CONTROL_CROP_TOP, i.ToString()); } GUIControl.SelectItemControl(GetID, (int)Controls.CONTROL_CROP_TOP, _cropSettings.Top); GUIControl.ClearControl(GetID, (int)Controls.CONTROL_CROP_BOTTOM); for (int i = 0; i <= 200; ++i) { GUIControl.AddItemLabelControl(GetID, (int)Controls.CONTROL_CROP_BOTTOM, i.ToString()); } GUIControl.SelectItemControl(GetID, (int)Controls.CONTROL_CROP_BOTTOM, _cropSettings.Bottom); GUIControl.ClearControl(GetID, (int)Controls.CONTROL_CROP_LEFT); for (int i = 0; i <= 200; ++i) { GUIControl.AddItemLabelControl(GetID, (int)Controls.CONTROL_CROP_LEFT, i.ToString()); } GUIControl.SelectItemControl(GetID, (int)Controls.CONTROL_CROP_LEFT, _cropSettings.Left); GUIControl.ClearControl(GetID, (int)Controls.CONTROL_CROP_RIGHT); for (int i = 0; i <= 200; ++i) { GUIControl.AddItemLabelControl(GetID, (int)Controls.CONTROL_CROP_RIGHT, i.ToString()); } GUIControl.SelectItemControl(GetID, (int)Controls.CONTROL_CROP_RIGHT, _cropSettings.Right); break; } case GUIMessage.MessageType.GUI_MSG_CLICKED: { int iControl = message.SenderControlId; if (iControl == (int)Controls.CONTROL_EXIT) { Close(); } else if (iControl == (int)Controls.CONTROL_CROP_TOP) { // do not use message.Label, because it's empty for "page up/down", causing exceptions _cropSettings.Top = (GetControl(iControl) as GUISpinControl).Value; } else if (iControl == (int)Controls.CONTROL_CROP_BOTTOM) { _cropSettings.Bottom = (GetControl(iControl) as GUISpinControl).Value; } else if (iControl == (int)Controls.CONTROL_CROP_LEFT) { _cropSettings.Left = (GetControl(iControl) as GUISpinControl).Value; } else if (iControl == (int)Controls.CONTROL_CROP_RIGHT) { _cropSettings.Right = (GetControl(iControl) as GUISpinControl).Value; } // ativate & save settings for the current capture card TvCropManager.CropSettings = _cropSettings; break; } } return(base.OnMessage(message)); }
public void GetWindow(float fSourceFrameRatio, out Rectangle rSource, out Rectangle rDest, CropSettings cropSettings) { float fOutputFrameRatio = fSourceFrameRatio / PixelRatio; // make sure the crop settings are acceptable cropSettings = cropSettings.EnsureSanity(ImageWidth, ImageHeight); int cropW = cropSettings.Left + cropSettings.Right; int cropH = cropSettings.Top + cropSettings.Bottom; // the source image dimensions when taking into // account the crop settings int croppedImageWidth = ImageWidth - cropW; int croppedImageHeight = ImageHeight - cropH; // suggested by ziphnor float fSourcePixelRatio = fSourceFrameRatio / ((float)ImageWidth / (float)ImageHeight); float fCroppedOutputFrameRatio = fSourcePixelRatio * ((float)croppedImageWidth / (float)croppedImageHeight) / PixelRatio; //Log.Debug("croppedImage W/H {0}x{1}", croppedImageWidth, croppedImageHeight); //Log.Debug("fOutputFrameRatio : {0}", fOutputFrameRatio); //Log.Debug("fCroppedOutputFrameRatio : {0}", fCroppedOutputFrameRatio); //Log.Debug("fSourceFrameRatio: {0}", fSourceFrameRatio); //don't use non linear stretch by default m_bUseNonLinearStretch = false; switch (ARType) { case Type.Stretch: { rSource = new Rectangle(cropSettings.Left, cropSettings.Top, croppedImageWidth, croppedImageHeight); rDest = new Rectangle(0, 0, ScreenWidth, ScreenHeight); } break; case Type.Zoom: { // calculate AR compensation (see http://www.iki.fi/znark/video/conversion) // assume that the movie is widescreen first, so use full height float fVertBorder = 0; float fNewHeight = (float)(ScreenHeight); float fNewWidth = fNewHeight * fCroppedOutputFrameRatio; float fHorzBorder = (fNewWidth - (float)ScreenWidth) / 2.0f; float fFactor = fNewWidth / ((float)ImageWidth); fFactor *= PixelRatio; fHorzBorder = fHorzBorder / fFactor; if ((int)fNewWidth < ScreenWidth) { fHorzBorder = 0; fNewWidth = (float)(ScreenWidth); fNewHeight = fNewWidth / fCroppedOutputFrameRatio; fVertBorder = (fNewHeight - (float)ScreenHeight) / 2.0f; fFactor = fNewWidth / ((float)ImageWidth); fFactor *= PixelRatio; fVertBorder = fVertBorder / fFactor; } rSource = new Rectangle((int)fHorzBorder, (int)fVertBorder, (int)((float)ImageWidth - 2.0f * fHorzBorder), (int)((float)ImageHeight - 2.0f * fVertBorder)); rDest = new Rectangle(0, 0, ScreenWidth, ScreenHeight); AdjustSourceForCropping(ref rSource, cropSettings); } break; case Type.Normal: { // maximize the movie width float fNewWidth = (float)ScreenWidth; float fNewHeight = (float)(fNewWidth / fCroppedOutputFrameRatio); if (fNewHeight > ScreenHeight) { fNewHeight = ScreenHeight; fNewWidth = fNewHeight * fCroppedOutputFrameRatio; } // this shouldnt happen, but just make sure that everything still fits onscreen if (fNewWidth > ScreenWidth || fNewHeight > ScreenHeight) { fNewWidth = (float)ImageWidth; fNewWidth = (float)croppedImageWidth; fNewHeight = (float)croppedImageHeight; } // Centre the movie float iPosY = (ScreenHeight - fNewHeight) / 2; float iPosX = (ScreenWidth - fNewWidth) / 2; rSource = new Rectangle(cropSettings.Left, cropSettings.Top, croppedImageWidth, croppedImageHeight); rDest = new Rectangle((int)iPosX, (int)iPosY, (int)(fNewWidth + 0.5f), (int)(fNewHeight + 0.5f)); //AdjustForCropping(ref rSource, ref rDest, cropSettings, true); } break; case Type.Original: { // maximize the movie width float fNewWidth = (float)Math.Min(ImageWidth, ScreenWidth); float fNewHeight = (float)(fNewWidth / fOutputFrameRatio); if (fNewHeight > ScreenHeight) { fNewHeight = Math.Min(ImageHeight, ScreenHeight); fNewWidth = fNewHeight * fOutputFrameRatio; } // this shouldnt happen, but just make sure that everything still fits onscreen if (fNewWidth > ScreenWidth || fNewHeight > ScreenHeight) { Log.Error("Original Zoom Mode: 'this shouldnt happen' {0}x{1}", fNewWidth, fNewHeight); goto case Type.Normal; } // Centre the movie float iPosY = (ScreenHeight - fNewHeight) / 2; float iPosX = (ScreenWidth - fNewWidth) / 2; // The original zoom mode ignores cropping parameters: rSource = new Rectangle(0, 0, ImageWidth, ImageHeight); rDest = new Rectangle((int)iPosX, (int)iPosY, (int)(fNewWidth + 0.5f), (int)(fNewHeight + 0.5f)); } break; case Type.LetterBox43: { // shrink movie 33% vertically float fNewWidth = (float)ScreenWidth; float fNewHeight = (float)(fNewWidth / fOutputFrameRatio); fNewHeight *= (1.0f - 0.33333333333f); if (fNewHeight > ScreenHeight) { fNewHeight = ScreenHeight; fNewHeight *= (1.0f - 0.33333333333f); fNewWidth = fNewHeight * fOutputFrameRatio; } // this shouldnt happen, but just make sure that everything still fits onscreen if (fNewWidth > ScreenWidth || fNewHeight > ScreenHeight) { fNewWidth = (float)ImageWidth; fNewHeight = (float)ImageHeight; } // Centre the movie float iPosY = (ScreenHeight - fNewHeight) / 2; float iPosX = (ScreenWidth - fNewWidth) / 2; rSource = new Rectangle(0, 0, ImageWidth, ImageHeight); rDest = new Rectangle((int)iPosX, (int)iPosY, (int)(fNewWidth + 0.5f), (int)(fNewHeight + 0.5f)); AdjustSourceForCropping(ref rSource, cropSettings); } break; case Type.NonLinearStretch: { // If screen is 16:9 do non-linear stretch, otherwise panscan float fScreenRatio = (float)ScreenWidth / ScreenHeight; fScreenRatio *= PixelRatio; if (fScreenRatio < 1.59) { // pan and scan // assume that the movie is widescreen first, so use full height float fVertBorder = 0; float fNewHeight = (float)(ScreenHeight); float fNewWidth = fNewHeight * fOutputFrameRatio * 1.66666666667f; float fHorzBorder = (fNewWidth - (float)ScreenWidth) / 2.0f; float fFactor = fNewWidth / ((float)ImageWidth); fFactor *= PixelRatio; fHorzBorder = fHorzBorder / fFactor; if ((int)fNewWidth < ScreenWidth) { fHorzBorder = 0; fNewWidth = (float)(ScreenWidth); fNewHeight = fNewWidth / fOutputFrameRatio; fVertBorder = (fNewHeight - (float)ScreenHeight) / 2.0f; fFactor = fNewWidth / ((float)ImageWidth); fFactor *= PixelRatio; fVertBorder = fVertBorder / fFactor; } rSource = new Rectangle((int)fHorzBorder, (int)fVertBorder, (int)((float)ImageWidth - 2.0f * fHorzBorder), (int)((float)ImageHeight - 2.0f * fVertBorder)); rDest = new Rectangle(0, 0, ScreenWidth, ScreenHeight); AdjustSourceForCropping(ref rSource, cropSettings); } else { m_bUseNonLinearStretch = true; //here we just need to remove 8.3% from top/bottom of the image (=Zoom in 9.1%) //The non-linear stretching part will be handled by the VMR9 presenter int newTop = cropSettings.Top + (int)(0.083f * ((float)croppedImageHeight) / 2.0f); int newHeight = (int)(((float)croppedImageHeight) * (1.0f - 0.083f)); //For 16:10 screens the cropping should not be done, which fixes the aspect ratio issue within tolerable accuracy if ((fScreenRatio < 1.61) && (fScreenRatio > 1.59)) { newTop = cropSettings.Top; newHeight = (int)croppedImageHeight; } rSource = new Rectangle(cropSettings.Left, newTop, croppedImageWidth, newHeight); rDest = new Rectangle(0, 0, ScreenWidth, ScreenHeight); } } break; case Type.Zoom14to9: { // fit the image to screen size float fNewWidth = (float)ScreenWidth; float fNewHeight = (float)(fNewWidth / fOutputFrameRatio); if (fNewHeight > ScreenHeight) { fNewHeight = ScreenHeight; fNewWidth = fNewHeight * fOutputFrameRatio; } float iPosX = 0; float iPosY = 0; float fVertBorder = 0; float fHorzBorder = 0; float fFactor = fNewWidth / ((float)ImageWidth); fFactor *= PixelRatio; // increase the image size by 12.5% and crop or pad if needed fNewHeight = fNewHeight * 1.125f; fNewWidth = fNewHeight * fOutputFrameRatio; if ((int)fNewHeight < ScreenHeight) { fHorzBorder = (fNewWidth - (float)ScreenWidth) / 2.0f; fHorzBorder = fHorzBorder / fFactor; iPosY = (ScreenHeight - fNewHeight) / 2; } if ((int)fNewWidth < ScreenWidth) { fVertBorder = (fNewHeight - (float)ScreenHeight) / 2.0f; fVertBorder = fVertBorder / fFactor; iPosX = (ScreenWidth - fNewWidth) / 2; } if ((int)fNewWidth > ScreenWidth && (int)fNewHeight > ScreenHeight) { fHorzBorder = (fNewWidth - (float)ScreenWidth) / 2.0f; fHorzBorder = fHorzBorder / fFactor; fVertBorder = (fNewHeight - (float)ScreenHeight) / 2.0f; fVertBorder = fVertBorder / fFactor; } rSource = new Rectangle((int)fHorzBorder, (int)fVertBorder, (int)((float)ImageWidth - 2.0f * fHorzBorder), (int)((float)ImageHeight - 2.0f * fVertBorder)); rDest = new Rectangle((int)iPosX, (int)iPosY, (int)(fNewWidth - (2.0f * fHorzBorder * fFactor) + 0.5f), (int)(fNewHeight - (2.0f * fVertBorder * fFactor) + 0.5f)); AdjustSourceForCropping(ref rSource, cropSettings); } break; default: { rSource = new Rectangle(0, 0, ImageWidth, ImageHeight); rDest = new Rectangle(0, 0, ScreenWidth, ScreenHeight); } break; } }
public LibRetroPlayer() { _cropSettings = ServiceRegistration.Get <IGeometryManager>().CropSettings; }