OSDN Git Service

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