OSDN Git Service

WinGui:
[handbrake-jp/handbrake-jp-git.git] / win / C# / Controls / PictureSettings.cs
1 using System;\r
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
7 using Handbrake.Presets;\r
8 \r
9 namespace Handbrake.Controls\r
10 {\r
11     public partial class PictureSettings : UserControl\r
12     {\r
13         private readonly CultureInfo Culture = new CultureInfo("en-US", false);\r
14         public event EventHandler PictureSettingsChanged;\r
15 \r
16         private Boolean _preventChangingWidth, _preventChangingHeight, _preventChangingCustom, _preventChangingDisplayWidth;\r
17         private int _presetMaximumWidth, _presetMaximumHeight;\r
18         private double _cachedDar;\r
19         private Title _sourceTitle;\r
20 \r
21         public PictureSettings()\r
22         {\r
23             InitializeComponent();\r
24 \r
25             drp_anamorphic.SelectedIndex = 1;\r
26             drp_modulus.SelectedIndex = 0;\r
27         }\r
28 \r
29         /// <summary>\r
30         /// Gets or sets the source media used by this control.\r
31         /// </summary>\r
32         [Browsable(false)]\r
33         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]\r
34         public Title Source\r
35         {\r
36             private get { return _sourceTitle; }\r
37             set\r
38             {\r
39                 _sourceTitle = value;\r
40                 Enabled = _sourceTitle != null;\r
41 \r
42                 // Set the Aspect Ratio\r
43                 lbl_Aspect.Text = _sourceTitle.AspectRatio.ToString(Culture);\r
44                 lbl_src_res.Text = _sourceTitle.Resolution.Width + " x " + _sourceTitle.Resolution.Height;\r
45 \r
46                 // Set the Recommended Cropping values, but only if a preset doesn't have hard set picture settings.\r
47                 if (CurrentlySelectedPreset != null && CurrentlySelectedPreset.PictureSettings == false)\r
48                 {\r
49                     crop_top.Value = GetCropMod2Clean(_sourceTitle.AutoCropDimensions[0]);\r
50                     crop_bottom.Value = GetCropMod2Clean(_sourceTitle.AutoCropDimensions[1]);\r
51                     crop_left.Value = GetCropMod2Clean(_sourceTitle.AutoCropDimensions[2]);\r
52                     crop_right.Value = GetCropMod2Clean(_sourceTitle.AutoCropDimensions[3]);\r
53                 }\r
54                 else if (CurrentlySelectedPreset == null)\r
55                 {\r
56                     crop_top.Value = GetCropMod2Clean(_sourceTitle.AutoCropDimensions[0]);\r
57                     crop_bottom.Value = GetCropMod2Clean(_sourceTitle.AutoCropDimensions[1]);\r
58                     crop_left.Value = GetCropMod2Clean(_sourceTitle.AutoCropDimensions[2]);\r
59                     crop_right.Value = GetCropMod2Clean(_sourceTitle.AutoCropDimensions[3]);\r
60                 }\r
61                 SetPresetCropWarningLabel(CurrentlySelectedPreset);\r
62 \r
63                 // Set the Resolution Boxes\r
64                 if (drp_anamorphic.SelectedIndex == 0)\r
65                 {\r
66                     if (text_width.Value == 0) // Only update the values if the fields don't already have values.\r
67                         text_width.Value = _sourceTitle.Resolution.Width;\r
68 \r
69                     check_KeepAR.Checked = true; // Forces Resolution to be correct.\r
70                 }\r
71                 else\r
72                 {\r
73                     if (text_width.Value == 0 && text_height.Value == 0)// Only update the values if the fields don't already have values.\r
74                     {\r
75                         text_width.Value = _sourceTitle.Resolution.Width;\r
76                         text_height.Value = _sourceTitle.Resolution.Height - (int)crop_top.Value - (int)crop_bottom.Value;\r
77                     }\r
78 \r
79                     labelDisplaySize.Text = CalculateAnamorphicSizes().Width + "x" + CalculateAnamorphicSizes().Height;\r
80                 }\r
81 \r
82                 //updownDisplayWidth.Value = CalculateAnamorphicSizes().Width;\r
83                 updownParWidth.Value = _sourceTitle.ParVal.Width;\r
84                 updownParHeight.Value = _sourceTitle.ParVal.Height;\r
85                 //_cachedDar = (double)updownDisplayWidth.Value / (double)text_height.Value;\r
86 \r
87 \r
88                 Size croppedDar = CalculateAnamorphicSizes();\r
89                 _cachedDar = (double)croppedDar.Width / croppedDar.Height;\r
90                 updownDisplayWidth.Value = croppedDar.Width;\r
91             }\r
92         }\r
93 \r
94         /// <summary>\r
95         /// Which preset is currently selected by the user.\r
96         /// </summary>\r
97         public Preset CurrentlySelectedPreset { get; set; }\r
98 \r
99         /// <summary>\r
100         /// Gets or sets the maximum allowable size for the encoded resolution. Set a value to\r
101         /// "0" if the maximum does not matter.\r
102         /// </summary>\r
103         [Browsable(false)]\r
104         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]\r
105         public Size PresetMaximumResolution\r
106         {\r
107             get { return new Size(_presetMaximumWidth, _presetMaximumHeight); }\r
108             set\r
109             {\r
110                 _presetMaximumWidth = value.Width;\r
111                 _presetMaximumHeight = value.Height;\r
112 \r
113                 if (value.Width != 0 && value.Height != 0)\r
114                     lbl_max.Text = "Max Width / Height";\r
115                 else if (value.Width != 0)\r
116                     lbl_max.Text = "Max Width";\r
117                 else if (value.Height != 0)\r
118                     lbl_max.Text = "Max Height";\r
119                 else\r
120                     lbl_max.Text = "";\r
121             }\r
122         }\r
123 \r
124         public void SetPresetCropWarningLabel(Preset selectedPreset)\r
125         {\r
126             lbl_presetCropWarning.Visible = true;\r
127             if (selectedPreset != null && selectedPreset.PictureSettings == false)\r
128                 lbl_presetCropWarning.Visible = false;\r
129             else if (selectedPreset == null)\r
130                 lbl_presetCropWarning.Visible = false;\r
131         }\r
132 \r
133         // Picture Controls\r
134         private void text_width_ValueChanged(object sender, EventArgs e)\r
135         {\r
136             if (Properties.Settings.Default.disableResCalc)\r
137                 return;\r
138 \r
139             if (_preventChangingWidth)\r
140                 return;\r
141 \r
142             // Make sure the new value doesn't exceed the maximum\r
143             if (Source != null)\r
144                 if (text_width.Value > Source.Resolution.Width)\r
145                     text_width.Value = Source.Resolution.Width;\r
146 \r
147             switch (drp_anamorphic.SelectedIndex)\r
148             {\r
149                 case 0:\r
150                     if (check_KeepAR.Checked && Source != null)\r
151                     {\r
152                         _preventChangingHeight = true;\r
153 \r
154                         int width = (int)text_width.Value;\r
155 \r
156                         double crop_width = Source.Resolution.Width - (int)crop_left.Value - (int)crop_right.Value;\r
157                         double crop_height = Source.Resolution.Height - (int)crop_top.Value - (int)crop_bottom.Value;\r
158 \r
159                         if (SourceAspect.Width == 0 && SourceAspect.Height == 0)\r
160                             break;\r
161 \r
162                         double newHeight = ((double)width * Source.Resolution.Width * SourceAspect.Height * crop_height) /\r
163                                            (Source.Resolution.Height * SourceAspect.Width * crop_width);\r
164                         text_height.Value = (decimal)GetModulusValue(newHeight);\r
165 \r
166                         _preventChangingHeight = false;\r
167                     }\r
168                     break;\r
169                 case 3:\r
170                     if (check_KeepAR.CheckState == CheckState.Unchecked && Source != null)\r
171                     {\r
172                         if (_preventChangingCustom)\r
173                             break;\r
174 \r
175                         _preventChangingDisplayWidth = true;\r
176                         updownDisplayWidth.Value = text_width.Value * updownParWidth.Value / updownParHeight.Value;\r
177                         _preventChangingDisplayWidth = false;\r
178 \r
179                         labelDisplaySize.Text = Math.Truncate(updownDisplayWidth.Value) + "x" + text_height.Value;\r
180                     }\r
181 \r
182                     if (check_KeepAR.CheckState == CheckState.Checked && Source != null)\r
183                     {\r
184                         updownParWidth.Value = updownDisplayWidth.Value;\r
185                         updownParHeight.Value = text_width.Value;\r
186                     }\r
187                     break;\r
188                 default:\r
189                     labelDisplaySize.Text = CalculateAnamorphicSizes().Width + "x" + CalculateAnamorphicSizes().Height;\r
190                     break;\r
191             }\r
192 \r
193             _preventChangingWidth = false;\r
194         }\r
195         private void text_height_ValueChanged(object sender, EventArgs e)\r
196         {\r
197             if (Properties.Settings.Default.disableResCalc)\r
198                 return;\r
199 \r
200             if (_preventChangingHeight)\r
201                 return;\r
202 \r
203             if (Source != null)\r
204                 if (text_height.Value > Source.Resolution.Height)\r
205                     text_height.Value = Source.Resolution.Height;\r
206 \r
207             switch (drp_anamorphic.SelectedIndex)\r
208             {\r
209                 case 0:\r
210                     if (check_KeepAR.Checked && Source != null)\r
211                     {\r
212                         _preventChangingWidth = true;\r
213 \r
214                         double crop_width = Source.Resolution.Width - (int)crop_left.Value - (int)crop_right.Value;\r
215                         double crop_height = Source.Resolution.Height - (int)crop_top.Value - (int)crop_bottom.Value;\r
216 \r
217                         double new_width = ((double)text_height.Value * Source.Resolution.Height * SourceAspect.Width * crop_width) /\r
218                                             (Source.Resolution.Width * SourceAspect.Height * crop_height);\r
219 \r
220                         text_width.Value = (decimal)GetModulusValue(new_width);\r
221 \r
222                         _preventChangingWidth = false;\r
223                     }\r
224                     break;\r
225                 case 3:\r
226                     labelDisplaySize.Text = Math.Truncate(updownDisplayWidth.Value) + "x" + text_height.Value;\r
227 \r
228                     if (check_KeepAR.CheckState == CheckState.Checked && Source != null)\r
229                     {\r
230                         // - Changes DISPLAY WIDTH to keep DAR\r
231                         // - Changes PIXEL WIDTH to new DISPLAY WIDTH\r
232                         // - Changes PIXEL HEIGHT to STORAGE WIDTH\r
233                         // DAR = DISPLAY WIDTH / DISPLAY HEIGHT (cache after every modification)\r
234 \r
235                         double rawCalculatedDisplayWidth = (double)text_height.Value * _cachedDar;\r
236 \r
237                         _preventChangingDisplayWidth = true; // Start Guards\r
238                         _preventChangingWidth = true;\r
239 \r
240                         updownDisplayWidth.Value = (decimal)rawCalculatedDisplayWidth;\r
241                         updownParWidth.Value = updownDisplayWidth.Value;\r
242                         updownParHeight.Value = text_width.Value;\r
243 \r
244                         _preventChangingWidth = false; // Reset Guards\r
245                         _preventChangingDisplayWidth = false;\r
246                     }\r
247 \r
248                     break;\r
249                 default:\r
250                     labelDisplaySize.Text = CalculateAnamorphicSizes().Width + "x" + CalculateAnamorphicSizes().Height;\r
251                     break;\r
252             }\r
253 \r
254             _preventChangingHeight = false;\r
255         }\r
256         private void check_KeepAR_CheckedChanged(object sender, EventArgs e)\r
257         {\r
258             if (Properties.Settings.Default.disableResCalc)\r
259                 return;\r
260 \r
261             //Force TextWidth to recalc height\r
262             if (check_KeepAR.Checked)\r
263                 text_width_ValueChanged(this, new EventArgs());\r
264 \r
265             // Disable the Custom Anamorphic Par Controls if checked.\r
266             if (drp_anamorphic.SelectedIndex == 3)\r
267             {\r
268                 updownParWidth.Enabled = !check_KeepAR.Checked;\r
269                 updownParHeight.Enabled = !check_KeepAR.Checked;\r
270             }\r
271 \r
272             // Raise the Picture Settings Changed Event\r
273             if (PictureSettingsChanged != null)\r
274                 PictureSettingsChanged(this, new EventArgs());\r
275         }\r
276         private void updownDisplayWidth_ValueChanged(object sender, EventArgs e)\r
277         {\r
278             if (Properties.Settings.Default.disableResCalc)\r
279                 return;\r
280 \r
281             if (_preventChangingDisplayWidth == false && check_KeepAR.CheckState == CheckState.Unchecked)\r
282             {\r
283                 _preventChangingCustom = true;\r
284                 updownParWidth.Value = updownDisplayWidth.Value;\r
285                 updownParHeight.Value = text_width.Value;\r
286                 _preventChangingCustom = false;\r
287             }\r
288 \r
289             if (_preventChangingDisplayWidth == false && check_KeepAR.CheckState == CheckState.Checked)\r
290             {\r
291                 // - Changes HEIGHT to keep DAR\r
292                 // - Changes PIXEL WIDTH to new DISPLAY WIDTH\r
293                 // - Changes PIXEL HEIGHT to STORAGE WIDTH\r
294                 // DAR = DISPLAY WIDTH / DISPLAY HEIGHT (cache after every modification)\r
295 \r
296                 // Calculate new Height Value\r
297                 int modulus;\r
298                 if (!int.TryParse(drp_modulus.SelectedItem.ToString(), out modulus))\r
299                     modulus = 16;\r
300 \r
301                 int rawCalculatedHeight = (int)((int)updownDisplayWidth.Value / _cachedDar);\r
302                 int modulusHeight = rawCalculatedHeight - (rawCalculatedHeight % modulus);\r
303 \r
304                 // Update value\r
305                 _preventChangingHeight = true;\r
306                 text_height.Value = (decimal)modulusHeight;\r
307                 updownParWidth.Value = updownDisplayWidth.Value;\r
308                 updownParHeight.Value = text_width.Value;\r
309                 _preventChangingHeight = false;\r
310             }\r
311 \r
312         }\r
313 \r
314         // Anamorphic Controls\r
315         private void drp_anamorphic_SelectedIndexChanged(object sender, EventArgs e)\r
316         {\r
317             switch (drp_anamorphic.SelectedIndex)\r
318             {\r
319                 case 0:\r
320                     text_width.Enabled = true;\r
321                     text_height.Enabled = true;\r
322                     check_KeepAR.Enabled = true;\r
323 \r
324                     SetCustomAnamorphicOptionsVisible(false);\r
325                     labelStaticDisplaySize.Visible = false;\r
326                     labelDisplaySize.Visible = false;\r
327 \r
328                     // check_KeepAR.Checked = true;\r
329                     drp_modulus.SelectedIndex = 0;\r
330 \r
331                     if (check_KeepAR.Checked)\r
332                         text_width_ValueChanged(this, new EventArgs());\r
333                     // Don't update display size if we're not using anamorphic\r
334                     return;\r
335                 case 1:\r
336                     text_width.Enabled = false;\r
337                     text_height.Enabled = false;\r
338                     check_KeepAR.Enabled = false;\r
339 \r
340                     SetCustomAnamorphicOptionsVisible(false);\r
341                     labelStaticDisplaySize.Visible = true;\r
342                     labelDisplaySize.Visible = true;\r
343                     drp_modulus.SelectedIndex = 0;\r
344 \r
345                     check_KeepAR.Checked = true;\r
346                     break;\r
347                 case 2:\r
348                     text_width.Enabled = true;\r
349                     text_height.Enabled = false;\r
350                     check_KeepAR.Enabled = false;\r
351 \r
352                     SetCustomAnamorphicOptionsVisible(false);\r
353                     labelStaticDisplaySize.Visible = true;\r
354                     labelDisplaySize.Visible = true;\r
355                     drp_modulus.SelectedIndex = 0;\r
356 \r
357                     check_KeepAR.Checked = true;\r
358                     break;\r
359                 case 3:\r
360                     text_width.Enabled = true;\r
361                     text_height.Enabled = true;\r
362                     check_KeepAR.Enabled = true;\r
363 \r
364                     SetCustomAnamorphicOptionsVisible(true);\r
365                     labelStaticDisplaySize.Visible = true;\r
366                     labelDisplaySize.Visible = true;\r
367 \r
368                     check_KeepAR.Checked = true;\r
369                     updownParWidth.Enabled = !check_KeepAR.Checked;\r
370                     updownParHeight.Enabled = !check_KeepAR.Checked;\r
371                     break;\r
372 \r
373             }\r
374 \r
375             labelDisplaySize.Text = CalculateAnamorphicSizes().Width + "x" + CalculateAnamorphicSizes().Height;\r
376 \r
377             if (check_KeepAR.Checked)\r
378                 text_width_ValueChanged(this, new EventArgs());\r
379 \r
380             if (PictureSettingsChanged != null)\r
381                 PictureSettingsChanged(this, new EventArgs());\r
382         }\r
383         private void drp_modulus_SelectedIndexChanged(object sender, EventArgs e)\r
384         {\r
385             _preventChangingWidth = true;\r
386             _preventChangingHeight = true;\r
387 \r
388             text_width.Value = (decimal)GetModulusValue((double)text_width.Value);\r
389             text_height.Value = (decimal)GetModulusValue((double)text_height.Value);\r
390 \r
391             _preventChangingWidth = false;\r
392             _preventChangingHeight = false;\r
393 \r
394             text_width.Increment = int.Parse(drp_modulus.SelectedItem.ToString());\r
395             text_height.Increment = int.Parse(drp_modulus.SelectedItem.ToString());\r
396 \r
397             if (PictureSettingsChanged != null)\r
398                 PictureSettingsChanged(this, new EventArgs());\r
399         }\r
400 \r
401         // Cropping Controls\r
402         private void check_autoCrop_CheckedChanged(object sender, EventArgs e)\r
403         {\r
404             crop_top.Enabled = check_customCrop.Checked;\r
405             crop_bottom.Enabled = check_customCrop.Checked;\r
406             crop_left.Enabled = check_customCrop.Checked;\r
407             crop_right.Enabled = check_customCrop.Checked;\r
408 \r
409             if (Source != null)\r
410             {\r
411                 crop_top.Value = Source.AutoCropDimensions[0];\r
412                 crop_bottom.Value = Source.AutoCropDimensions[1];\r
413                 crop_left.Value = Source.AutoCropDimensions[2];\r
414                 crop_right.Value = Source.AutoCropDimensions[3];\r
415             }\r
416         }\r
417         private void crop_ValueChanged(object sender, EventArgs e)\r
418         {\r
419             text_width_ValueChanged(this, new EventArgs());\r
420         }\r
421 \r
422         // GUI Functions\r
423         private void SetCustomAnamorphicOptionsVisible(bool visible)\r
424         {\r
425             lbl_modulus.Visible = visible;\r
426             lbl_displayWidth.Visible = visible;\r
427             lbl_parWidth.Visible = visible;\r
428             lbl_parHeight.Visible = visible;\r
429 \r
430             drp_modulus.Visible = visible;\r
431             updownDisplayWidth.Visible = visible;\r
432             updownParWidth.Visible = visible;\r
433             updownParHeight.Visible = visible;\r
434         }\r
435 \r
436         // Calculation Functions\r
437         private Size SourceAspect\r
438         {\r
439             get\r
440             {\r
441                 if (Source != null) // display aspect = (width * par_width) / (height * par_height)\r
442                     return new Size((Source.ParVal.Width * Source.Resolution.Width), (Source.ParVal.Height * Source.Resolution.Height));\r
443 \r
444                 return new Size(0, 0); // Fall over to 16:9 and hope for the best\r
445             }\r
446         }\r
447         private Size CalculateAnamorphicSizes()\r
448         {\r
449             if (Source != null)\r
450             {\r
451                 /* Set up some variables to make the math easier to follow. */\r
452                 int cropped_width = Source.Resolution.Width - (int)crop_left.Value - (int)crop_right.Value;\r
453                 int cropped_height = Source.Resolution.Height - (int)crop_top.Value - (int)crop_bottom.Value;\r
454                 double storage_aspect = (double)cropped_width / cropped_height;\r
455 \r
456                 /* Figure out what width the source would display at. */\r
457                 double source_display_width = (double)cropped_width * Source.ParVal.Width / Source.ParVal.Height;\r
458 \r
459                 /*\r
460                      3 different ways of deciding output dimensions:\r
461                       - 1: Strict anamorphic, preserve source dimensions\r
462                       - 2: Loose anamorphic, round to mod16 and preserve storage aspect ratio\r
463                       - 3: Power user anamorphic, specify everything\r
464                   */\r
465                 double width, height;\r
466                 switch (drp_anamorphic.SelectedIndex)\r
467                 {\r
468                     default:\r
469                     case 1:\r
470                         /* Strict anamorphic */\r
471                         double displayWidth = ((double)cropped_width * Source.ParVal.Width / Source.ParVal.Height);\r
472                         displayWidth = Math.Round(displayWidth, 0);\r
473                         Size output = new Size((int)displayWidth, cropped_height);\r
474                         return output;\r
475                     case 2:\r
476                         /* "Loose" anamorphic.\r
477                             - Uses mod16-compliant dimensions,\r
478                             - Allows users to set the width\r
479                         */\r
480                         width = (int)text_width.Value;\r
481                         width = GetModulusValue(width); /* Time to get picture width that divide cleanly.*/\r
482 \r
483                         height = (width / storage_aspect) + 0.5;\r
484                         height = GetModulusValue(height); /* Time to get picture height that divide cleanly.*/\r
485 \r
486                         /* The film AR is the source's display width / cropped source height.\r
487                            The output display width is the output height * film AR.\r
488                            The output PAR is the output display width / output storage width. */\r
489                         double pixel_aspect_width = height * source_display_width / cropped_height;\r
490                         double pixel_aspect_height = width;\r
491 \r
492                         double disWidthLoose = (width * pixel_aspect_width / pixel_aspect_height);\r
493                         if (double.IsNaN(disWidthLoose))\r
494                             disWidthLoose = 0;\r
495                         return new Size((int)disWidthLoose, (int)height);\r
496                     case 3:\r
497 \r
498                         // Get the User Interface Values\r
499                         double UIdisplayWidth;\r
500                         double.TryParse(updownDisplayWidth.Text, out UIdisplayWidth);\r
501 \r
502                         /* Anamorphic 3: Power User Jamboree - Set everything based on specified values */\r
503                         height = GetModulusValue((double)text_height.Value);\r
504 \r
505                         if (check_KeepAR.Checked)\r
506                             return new Size((int)Math.Truncate(UIdisplayWidth), (int)height);\r
507 \r
508                         return new Size((int)Math.Truncate(UIdisplayWidth), (int)height);\r
509                 }\r
510             }\r
511 \r
512             // Return a default value of 0,0 to indicate failure\r
513             return new Size(0, 0);\r
514         }\r
515         private double GetModulusValue(double value)\r
516         {\r
517             int mod = int.Parse(drp_modulus.SelectedItem.ToString());\r
518             double remainder = value % mod;\r
519 \r
520             if (remainder == 0)\r
521                 return value;\r
522 \r
523             return remainder >= ((double)mod / 2) ? value + (mod - remainder) : value - remainder;\r
524         }\r
525         private static int GetCropMod2Clean(int value)\r
526         {\r
527             int remainder = value % 2;\r
528             if (remainder == 0) return value;\r
529             return (value + remainder);\r
530         }\r
531 \r
532         // Hidden UI feature to drop the MaxWidth / Height with the MaxWidth/Height label is double clicked\r
533         private void lbl_max_DoubleClick(object sender, EventArgs e)\r
534         {\r
535             PresetMaximumResolution = new Size(0, 0);\r
536             if (PictureSettingsChanged != null)\r
537                 PictureSettingsChanged(this, new EventArgs());\r
538         }\r
539 \r
540     }\r
541 }