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