OSDN Git Service

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