2 using System.ComponentModel;
\r
3 using System.Drawing;
\r
4 using System.Globalization;
\r
5 using System.Windows.Forms;
\r
6 using Handbrake.Parsing;
\r
8 namespace Handbrake.Controls
\r
11 // TODO Custom Anamorphic
\r
12 /* NOT KEEPING DISPLAY ASPECT == [Complete]
\r
14 KEEPING DISPLAY ASPECT RATIO == [TODO]
\r
15 DAR = DISPLAY WIDTH / DISPLAY HEIGHT (cache after every modification)
\r
16 Disable editing: PIXEL WIDTH, PIXEL HEIGHT
\r
17 Changing DISPLAY WIDTH:
\r
18 Changes HEIGHT to keep DAR
\r
19 Changes PIXEL WIDTH to new DISPLAY WIDTH
\r
20 Changes PIXEL HEIGHT to STORAGE WIDTH
\r
22 Changes DISPLAY WIDTH to keep DAR
\r
23 Changes PIXEL WIDTH to new DISPLAY WIDTH
\r
24 Changes PIXEL HEIGHT to STORAGE WIDTH
\r
25 Changing STORAGE_WIDTH:
\r
26 Changes PIXEL WIDTH to DISPLAY WIDTH
\r
27 Changes PIXEL HEIGHT to new STORAGE WIDTH
\r
31 public partial class PictureSettings : UserControl
\r
33 private readonly CultureInfo Culture = new CultureInfo("en-US", false);
\r
34 public event EventHandler PictureSettingsChanged;
\r
36 private Boolean preventChangingWidth, preventChangingHeight, preventChangingCustom, preventChangingDisplayWidth;
\r
37 private int _PresetMaximumWidth, _PresetMaximumHeight;
\r
38 private Title _SourceTitle;
\r
40 public PictureSettings()
\r
42 InitializeComponent();
\r
44 drp_anamorphic.SelectedIndex = 1;
\r
45 drp_modulus.SelectedIndex = 0;
\r
49 /// Gets or sets the source media used by this control.
\r
52 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
\r
55 get { return _SourceTitle; }
\r
58 _SourceTitle = value;
\r
59 Enabled = _SourceTitle != null;
\r
61 // Set the Aspect Ratio
\r
62 lbl_Aspect.Text = _SourceTitle.AspectRatio.ToString(Culture);
\r
63 lbl_src_res.Text = _SourceTitle.Resolution.Width + " x " + _SourceTitle.Resolution.Height;
\r
65 // Set the Recommended Cropping values
\r
66 crop_top.Value = GetCropMod2Clean(_SourceTitle.AutoCropDimensions[0]);
\r
67 crop_bottom.Value = GetCropMod2Clean(_SourceTitle.AutoCropDimensions[1]);
\r
68 crop_left.Value = GetCropMod2Clean(_SourceTitle.AutoCropDimensions[2]);
\r
69 crop_right.Value = GetCropMod2Clean(_SourceTitle.AutoCropDimensions[3]);
\r
71 // Set the Resolution Boxes
\r
72 if (drp_anamorphic.SelectedIndex == 0)
\r
74 if (text_width.Value == 0) // Only update the values if the fields don't already have values.
\r
75 text_width.Value = _SourceTitle.Resolution.Width;
\r
77 check_KeepAR.Checked = true; // Forces Resolution to be correct.
\r
81 text_width.Value = _SourceTitle.Resolution.Width;
\r
82 text_height.Value = _SourceTitle.Resolution.Height - (int)crop_top.Value - (int)crop_bottom.Value;
\r
83 labelDisplaySize.Text = calculateAnamorphicSizes().Width + "x" + calculateAnamorphicSizes().Height;
\r
86 updownDisplayWidth.Value = calculateAnamorphicSizes().Width;
\r
87 updownParWidth.Value = _SourceTitle.ParVal.Width;
\r
88 updownParHeight.Value = _SourceTitle.ParVal.Height;
\r
93 /// Gets or sets the maximum allowable size for the encoded resolution. Set a value to
\r
94 /// "0" if the maximum does not matter.
\r
97 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
\r
98 public Size PresetMaximumResolution
\r
100 get { return new Size(_PresetMaximumWidth, _PresetMaximumHeight); }
\r
103 _PresetMaximumWidth = value.Width;
\r
104 _PresetMaximumHeight = value.Height;
\r
106 if (value.Width != 0 && value.Height != 0)
\r
107 lbl_max.Text = "Max Width / Height";
\r
108 else if (value.Width != 0)
\r
109 lbl_max.Text = "Max Width";
\r
110 else if (value.Height != 0)
\r
111 lbl_max.Text = "Max Height";
\r
117 // Picture Controls
\r
118 private void text_width_ValueChanged(object sender, EventArgs e)
\r
120 if (preventChangingWidth)
\r
123 // Make sure the new value doesn't exceed the maximum
\r
124 if (Source != null)
\r
125 if (text_width.Value > Source.Resolution.Width)
\r
126 text_width.Value = Source.Resolution.Width;
\r
128 switch (drp_anamorphic.SelectedIndex)
\r
131 if (check_KeepAR.Checked && Source != null)
\r
133 preventChangingHeight = true;
\r
135 int width = (int)text_width.Value;
\r
137 double crop_width = Source.Resolution.Width - (double)crop_left.Value - (double)crop_right.Value;
\r
138 double crop_height = Source.Resolution.Height - (double)crop_top.Value - (double)crop_bottom.Value;
\r
139 double newHeight = (width * Source.Resolution.Width * sourceAspect.Height * crop_height) /
\r
140 (Source.Resolution.Height * sourceAspect.Width * crop_width);
\r
141 text_height.Value = (decimal)GetModulusValue(newHeight);
\r
143 preventChangingHeight = false;
\r
147 if (check_KeepAR.CheckState == CheckState.Unchecked && Source != null)
\r
149 if (preventChangingCustom)
\r
152 preventChangingDisplayWidth = true;
\r
153 updownDisplayWidth.Value = text_width.Value * updownParWidth.Value / updownParHeight.Value;
\r
154 preventChangingDisplayWidth = false;
\r
156 labelDisplaySize.Text = Math.Truncate(updownDisplayWidth.Value) + "x" + text_height.Value;
\r
160 labelDisplaySize.Text = calculateAnamorphicSizes().Width + "x" + calculateAnamorphicSizes().Height;
\r
164 preventChangingWidth = false;
\r
166 private void text_height_ValueChanged(object sender, EventArgs e)
\r
168 if (preventChangingHeight)
\r
171 if (Source != null)
\r
172 if (text_height.Value > Source.Resolution.Height)
\r
173 text_height.Value = Source.Resolution.Height;
\r
175 switch (drp_anamorphic.SelectedIndex)
\r
178 if (check_KeepAR.Checked && Source != null)
\r
180 preventChangingWidth = true;
\r
182 double crop_width = Source.Resolution.Width - (double)crop_left.Value - (double)crop_right.Value;
\r
183 double crop_height = Source.Resolution.Height - (double)crop_top.Value - (double)crop_bottom.Value;
\r
185 double new_width = ((double)text_height.Value * Source.Resolution.Height * sourceAspect.Width * crop_width) /
\r
186 (Source.Resolution.Width * sourceAspect.Height * crop_height);
\r
188 text_width.Value = (decimal)GetModulusValue(new_width);
\r
190 preventChangingWidth = false;
\r
194 labelDisplaySize.Text = Math.Truncate(updownDisplayWidth.Value) + "x" + text_height.Value;
\r
197 labelDisplaySize.Text = calculateAnamorphicSizes().Width + "x" + calculateAnamorphicSizes().Height;
\r
201 preventChangingHeight = false;
\r
203 private void check_KeepAR_CheckedChanged(object sender, EventArgs e)
\r
205 //Force TextWidth to recalc height
\r
206 if (check_KeepAR.Checked)
\r
207 text_width_ValueChanged(this, new EventArgs());
\r
209 // Disable the Custom Anamorphic Par Controls if checked.
\r
210 if (drp_anamorphic.SelectedIndex == 3)
\r
212 updownParWidth.Enabled = !check_KeepAR.Checked;
\r
213 updownParHeight.Enabled = !check_KeepAR.Checked;
\r
216 // Raise the Picture Settings Changed Event
\r
217 if (PictureSettingsChanged != null)
\r
218 PictureSettingsChanged(this, new EventArgs());
\r
220 private void updownDisplayWidth_ValueChanged(object sender, EventArgs e)
\r
222 if (preventChangingDisplayWidth == false)
\r
224 preventChangingCustom = true;
\r
225 updownParWidth.Value = updownDisplayWidth.Value;
\r
226 updownParHeight.Value = text_width.Value;
\r
227 preventChangingCustom = false;
\r
231 // Anamorphic Controls
\r
232 private void drp_anamorphic_SelectedIndexChanged(object sender, EventArgs e)
\r
234 switch (drp_anamorphic.SelectedIndex)
\r
237 text_width.Enabled = true;
\r
238 text_height.Enabled = true;
\r
239 check_KeepAR.Enabled = true;
\r
241 setCustomAnamorphicOptionsVisible(false);
\r
242 labelStaticDisplaySize.Visible = false;
\r
243 labelDisplaySize.Visible = false;
\r
245 check_KeepAR.Checked = true;
\r
246 drp_modulus.SelectedIndex = 0;
\r
248 if (check_KeepAR.Checked)
\r
249 text_width_ValueChanged(this, new EventArgs());
\r
250 // Don't update display size if we're not using anamorphic
\r
253 text_width.Enabled = false;
\r
254 text_height.Enabled = false;
\r
255 check_KeepAR.Enabled = false;
\r
257 setCustomAnamorphicOptionsVisible(false);
\r
258 labelStaticDisplaySize.Visible = true;
\r
259 labelDisplaySize.Visible = true;
\r
260 drp_modulus.SelectedIndex = 0;
\r
262 check_KeepAR.Checked = true;
\r
265 text_width.Enabled = true;
\r
266 text_height.Enabled = false;
\r
267 check_KeepAR.Enabled = false;
\r
269 setCustomAnamorphicOptionsVisible(false);
\r
270 labelStaticDisplaySize.Visible = true;
\r
271 labelDisplaySize.Visible = true;
\r
272 drp_modulus.SelectedIndex = 0;
\r
274 check_KeepAR.Checked = true;
\r
277 text_width.Enabled = true;
\r
278 text_height.Enabled = true;
\r
279 check_KeepAR.Enabled = true;
\r
281 setCustomAnamorphicOptionsVisible(true);
\r
282 labelStaticDisplaySize.Visible = true;
\r
283 labelDisplaySize.Visible = true;
\r
285 check_KeepAR.Checked = true;
\r
289 labelDisplaySize.Text = calculateAnamorphicSizes().Width + "x" + calculateAnamorphicSizes().Height;
\r
291 if (check_KeepAR.Checked)
\r
292 text_width_ValueChanged(this, new EventArgs());
\r
294 if (PictureSettingsChanged != null)
\r
295 PictureSettingsChanged(this, new EventArgs());
\r
297 private void drp_modulus_SelectedIndexChanged(object sender, EventArgs e)
\r
299 preventChangingWidth = true;
\r
300 preventChangingHeight = true;
\r
302 text_width.Value = (decimal)GetModulusValue((double)text_width.Value);
\r
303 text_height.Value = (decimal)GetModulusValue((double)text_height.Value);
\r
305 preventChangingWidth = false;
\r
306 preventChangingHeight = false;
\r
308 text_width.Increment = int.Parse(drp_modulus.SelectedItem.ToString());
\r
309 text_height.Increment = int.Parse(drp_modulus.SelectedItem.ToString());
\r
311 if (PictureSettingsChanged != null)
\r
312 PictureSettingsChanged(this, new EventArgs());
\r
315 // Cropping Controls
\r
316 private void check_autoCrop_CheckedChanged(object sender, EventArgs e)
\r
318 crop_top.Enabled = check_customCrop.Checked;
\r
319 crop_bottom.Enabled = check_customCrop.Checked;
\r
320 crop_left.Enabled = check_customCrop.Checked;
\r
321 crop_right.Enabled = check_customCrop.Checked;
\r
323 private void crop_ValueChanged(object sender, EventArgs e)
\r
325 text_width_ValueChanged(this, new EventArgs());
\r
329 private void setCustomAnamorphicOptionsVisible(bool visible)
\r
331 lbl_modulus.Visible = visible;
\r
332 lbl_displayWidth.Visible = visible;
\r
333 lbl_parWidth.Visible = visible;
\r
334 lbl_parHeight.Visible = visible;
\r
336 drp_modulus.Visible = visible;
\r
337 updownDisplayWidth.Visible = visible;
\r
338 updownParWidth.Visible = visible;
\r
339 updownParHeight.Visible = visible;
\r
342 // Calculation Functions
\r
343 private Size sourceAspect
\r
347 if (Source != null)
\r
349 if (Source.AspectRatio == 1.78F)
\r
350 return new Size(16, 9);
\r
351 if (Source.AspectRatio == 1.33F)
\r
352 return new Size(4, 3);
\r
354 return new Size(0, 0);
\r
357 private Size calculateAnamorphicSizes()
\r
359 if (Source != null)
\r
361 /* Set up some variables to make the math easier to follow. */
\r
362 int cropped_width = Source.Resolution.Width - (int)crop_left.Value - (int)crop_right.Value;
\r
363 int cropped_height = Source.Resolution.Height - (int)crop_top.Value - (int)crop_bottom.Value;
\r
364 double storage_aspect = (double)cropped_width / cropped_height;
\r
366 /* Figure out what width the source would display at. */
\r
367 double source_display_width = (double)cropped_width * Source.ParVal.Width / Source.ParVal.Height;
\r
370 3 different ways of deciding output dimensions:
\r
371 - 1: Strict anamorphic, preserve source dimensions
\r
372 - 2: Loose anamorphic, round to mod16 and preserve storage aspect ratio
\r
373 - 3: Power user anamorphic, specify everything
\r
375 double width, height;
\r
376 switch (drp_anamorphic.SelectedIndex)
\r
379 /* Strict anamorphic */
\r
380 double displayWidth = ((double)cropped_width * Source.ParVal.Width / Source.ParVal.Height);
\r
381 displayWidth = Math.Round(displayWidth, 0);
\r
382 Size output = new Size((int)displayWidth, cropped_height);
\r
385 /* "Loose" anamorphic.
\r
386 - Uses mod16-compliant dimensions,
\r
387 - Allows users to set the width
\r
389 width = (int)text_width.Value - (int)crop_left.Value - (int)crop_right.Value;
\r
390 width = GetModulusValue(width); /* Time to get picture width that divide cleanly.*/
\r
392 height = (width / storage_aspect) + 0.5;
\r
393 height = GetModulusValue(height); /* Time to get picture height that divide cleanly.*/
\r
395 /* The film AR is the source's display width / cropped source height.
\r
396 The output display width is the output height * film AR.
\r
397 The output PAR is the output display width / output storage width. */
\r
398 double pixel_aspect_width = height * source_display_width / cropped_height;
\r
399 double pixel_aspect_height = width;
\r
401 double disWidthLoose = (width * pixel_aspect_width / pixel_aspect_height);
\r
402 return new Size((int)disWidthLoose, (int)height);
\r
405 // Get the User Interface Values
\r
406 double UIdisplayWidth;
\r
407 double.TryParse(updownDisplayWidth.Text, out UIdisplayWidth);
\r
409 /* Anamorphic 3: Power User Jamboree - Set everything based on specified values */
\r
410 height = GetModulusValue((double)text_height.Value);
\r
412 if (check_KeepAR.Checked)
\r
413 return new Size((int)Math.Truncate(UIdisplayWidth), (int)height);
\r
415 return new Size((int)Math.Truncate(UIdisplayWidth), (int)height);
\r
419 // Return a default value of 0,0 to indicate failure
\r
420 return new Size(0, 0);
\r
422 private double GetModulusValue(double value)
\r
424 int mod = int.Parse(drp_modulus.SelectedItem.ToString());
\r
425 double remainder = value % mod;
\r
427 if (remainder == 0)
\r
430 return remainder >= ((double)mod / 2) ? value + (mod - remainder) : value - remainder;
\r
432 private static int GetCropMod2Clean(int value)
\r
434 int remainder = value % 2;
\r
435 if (remainder == 0) return value;
\r
436 return (value + remainder);
\r