OSDN Git Service

Reverting 3452
[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 (Properties.Settings.Default.disableResCalc)\r
156                 return;\r
157 \r
158             if (preventChangingWidth)\r
159                 return;\r
160 \r
161             // Make sure the new value doesn't exceed the maximum\r
162             if (Source != null)\r
163                 if (text_width.Value > Source.Resolution.Width)\r
164                     text_width.Value = Source.Resolution.Width;\r
165 \r
166             switch (drp_anamorphic.SelectedIndex)\r
167             {\r
168                 case 0:\r
169                     if (check_KeepAR.Checked && Source != null)\r
170                     {\r
171                         preventChangingHeight = true;\r
172 \r
173                         int width = (int)text_width.Value;\r
174 \r
175                         double crop_width = Source.Resolution.Width - (int)crop_left.Value - (int)crop_right.Value;\r
176                         double crop_height = Source.Resolution.Height - (int)crop_top.Value - (int)crop_bottom.Value;\r
177 \r
178                         if (SourceAspect.Width == 0 && SourceAspect.Height == 0)\r
179                             break;\r
180 \r
181                         double newHeight = ((double)width * Source.Resolution.Width * SourceAspect.Height * crop_height) /\r
182                                            (Source.Resolution.Height * SourceAspect.Width * crop_width);\r
183                         text_height.Value = (decimal)GetModulusValue(newHeight);\r
184 \r
185                         preventChangingHeight = false;\r
186                     }\r
187                     break;\r
188                 case 3:\r
189                     if (check_KeepAR.CheckState == CheckState.Unchecked && Source != null)\r
190                     {\r
191                         if (preventChangingCustom)\r
192                             break;\r
193 \r
194                         preventChangingDisplayWidth = true;\r
195                         updownDisplayWidth.Value = text_width.Value * updownParWidth.Value / updownParHeight.Value;\r
196                         preventChangingDisplayWidth = false;\r
197 \r
198                         labelDisplaySize.Text = Math.Truncate(updownDisplayWidth.Value) + "x" + text_height.Value;\r
199                     }\r
200 \r
201                     if (check_KeepAR.CheckState == CheckState.Checked && Source != null)\r
202                     {\r
203                         updownParWidth.Value = updownDisplayWidth.Value;\r
204                         updownParHeight.Value = text_width.Value;\r
205                     }\r
206                     break;\r
207                 default:\r
208                     labelDisplaySize.Text = CalculateAnamorphicSizes().Width + "x" + CalculateAnamorphicSizes().Height;\r
209                     break;\r
210             }\r
211 \r
212             preventChangingWidth = false;\r
213         }\r
214 \r
215         private void TextHeightValueChanged(object sender, EventArgs e)\r
216         {\r
217             if (Properties.Settings.Default.disableResCalc)\r
218                 return;\r
219 \r
220             if (preventChangingHeight)\r
221                 return;\r
222 \r
223             if (Source != null)\r
224                 if (text_height.Value > Source.Resolution.Height)\r
225                     text_height.Value = Source.Resolution.Height;\r
226 \r
227             switch (drp_anamorphic.SelectedIndex)\r
228             {\r
229                 case 0:\r
230                     if (check_KeepAR.Checked && Source != null)\r
231                     {\r
232                         preventChangingWidth = true;\r
233 \r
234                         double crop_width = Source.Resolution.Width - (int)crop_left.Value - (int)crop_right.Value;\r
235                         double crop_height = Source.Resolution.Height - (int)crop_top.Value - (int)crop_bottom.Value;\r
236 \r
237                         double new_width = ((double)text_height.Value * Source.Resolution.Height * SourceAspect.Width *\r
238                                             crop_width) /\r
239                                            (Source.Resolution.Width * SourceAspect.Height * crop_height);\r
240 \r
241                         text_width.Value = (decimal)GetModulusValue(new_width);\r
242 \r
243                         preventChangingWidth = false;\r
244                     }\r
245                     break;\r
246                 case 3:\r
247                     labelDisplaySize.Text = Math.Truncate(updownDisplayWidth.Value) + "x" + text_height.Value;\r
248 \r
249                     if (check_KeepAR.CheckState == CheckState.Checked && Source != null)\r
250                     {\r
251                         // - Changes DISPLAY WIDTH to keep DAR\r
252                         // - Changes PIXEL WIDTH to new DISPLAY WIDTH\r
253                         // - Changes PIXEL HEIGHT to STORAGE WIDTH\r
254                         // DAR = DISPLAY WIDTH / DISPLAY HEIGHT (cache after every modification)\r
255 \r
256                         double rawCalculatedDisplayWidth = (double)text_height.Value * cachedDar;\r
257 \r
258                         preventChangingDisplayWidth = true; // Start Guards\r
259                         preventChangingWidth = true;\r
260 \r
261                         updownDisplayWidth.Value = (decimal)rawCalculatedDisplayWidth;\r
262                         updownParWidth.Value = updownDisplayWidth.Value;\r
263                         updownParHeight.Value = text_width.Value;\r
264 \r
265                         preventChangingWidth = false; // Reset Guards\r
266                         preventChangingDisplayWidth = false;\r
267                     }\r
268 \r
269                     break;\r
270                 default:\r
271                     labelDisplaySize.Text = CalculateAnamorphicSizes().Width + "x" + CalculateAnamorphicSizes().Height;\r
272                     break;\r
273             }\r
274 \r
275             preventChangingHeight = false;\r
276         }\r
277 \r
278         private void CheckKeepArCheckedChanged(object sender, EventArgs e)\r
279         {\r
280             if (Properties.Settings.Default.disableResCalc)\r
281                 return;\r
282 \r
283             // Force TextWidth to recalc height\r
284             if (check_KeepAR.Checked)\r
285                 TextWidthValueChanged(this, new EventArgs());\r
286 \r
287             // Disable the Custom Anamorphic Par Controls if checked.\r
288             if (drp_anamorphic.SelectedIndex == 3)\r
289             {\r
290                 updownParWidth.Enabled = !check_KeepAR.Checked;\r
291                 updownParHeight.Enabled = !check_KeepAR.Checked;\r
292             }\r
293 \r
294             // Raise the Picture Settings Changed Event\r
295             if (PictureSettingsChanged != null)\r
296                 PictureSettingsChanged(this, new EventArgs());\r
297         }\r
298 \r
299         private void UpdownDisplayWidthValueChanged(object sender, EventArgs e)\r
300         {\r
301             if (Properties.Settings.Default.disableResCalc)\r
302                 return;\r
303 \r
304             if (preventChangingDisplayWidth == false && check_KeepAR.CheckState == CheckState.Unchecked)\r
305             {\r
306                 preventChangingCustom = true;\r
307                 updownParWidth.Value = updownDisplayWidth.Value;\r
308                 updownParHeight.Value = text_width.Value;\r
309                 preventChangingCustom = false;\r
310             }\r
311 \r
312             if (preventChangingDisplayWidth == false && check_KeepAR.CheckState == CheckState.Checked)\r
313             {\r
314                 // - Changes HEIGHT to keep DAR\r
315                 // - Changes PIXEL WIDTH to new DISPLAY WIDTH\r
316                 // - Changes PIXEL HEIGHT to STORAGE WIDTH\r
317                 // DAR = DISPLAY WIDTH / DISPLAY HEIGHT (cache after every modification)\r
318 \r
319                 // Calculate new Height Value\r
320                 int modulus;\r
321                 if (!int.TryParse(drp_modulus.SelectedItem.ToString(), out modulus))\r
322                     modulus = 16;\r
323 \r
324                 int rawCalculatedHeight = (int)((int)updownDisplayWidth.Value / cachedDar);\r
325                 int modulusHeight = rawCalculatedHeight - (rawCalculatedHeight % modulus);\r
326 \r
327                 // Update value\r
328                 preventChangingHeight = true;\r
329                 text_height.Value = (decimal)modulusHeight;\r
330                 updownParWidth.Value = updownDisplayWidth.Value;\r
331                 updownParHeight.Value = text_width.Value;\r
332                 preventChangingHeight = false;\r
333             }\r
334         }\r
335 \r
336         // Anamorphic Controls\r
337         private void DrpAnamorphicSelectedIndexChanged(object sender, EventArgs e)\r
338         {\r
339             switch (drp_anamorphic.SelectedIndex)\r
340             {\r
341                 case 0: // None\r
342                     text_width.Enabled = true;\r
343                     text_height.Enabled = true;\r
344                     check_KeepAR.Enabled = true;\r
345 \r
346                     SetCustomAnamorphicOptionsVisible(false);\r
347                     labelStaticDisplaySize.Visible = false;\r
348                     labelDisplaySize.Visible = false;\r
349                     drp_modulus.Visible = true;\r
350                     lbl_modulus.Visible = true;\r
351 \r
352                     // check_KeepAR.Checked = true;\r
353 \r
354                     if (check_KeepAR.Checked)\r
355                         TextWidthValueChanged(this, new EventArgs());\r
356                     // Don't update display size if we're not using anamorphic\r
357                     return;\r
358                 case 1: // Strict\r
359                     text_width.Enabled = false;\r
360                     text_height.Enabled = false;\r
361                     check_KeepAR.Enabled = false;\r
362 \r
363                     SetCustomAnamorphicOptionsVisible(false);\r
364                     labelStaticDisplaySize.Visible = true;\r
365                     labelDisplaySize.Visible = true;\r
366 \r
367                     check_KeepAR.Checked = true;\r
368                     break;\r
369                 case 2: // Loose\r
370                     text_width.Enabled = true;\r
371                     text_height.Enabled = false;\r
372                     check_KeepAR.Enabled = false;\r
373 \r
374                     SetCustomAnamorphicOptionsVisible(false);\r
375                     labelStaticDisplaySize.Visible = true;\r
376                     labelDisplaySize.Visible = true;\r
377                     drp_modulus.Visible = true;\r
378                     lbl_modulus.Visible = true;\r
379 \r
380                     check_KeepAR.Checked = true;\r
381                     break;\r
382                 case 3: // Custom\r
383                     text_width.Enabled = true;\r
384                     text_height.Enabled = true;\r
385                     check_KeepAR.Enabled = true;\r
386 \r
387                     SetCustomAnamorphicOptionsVisible(true);\r
388                     labelStaticDisplaySize.Visible = true;\r
389                     labelDisplaySize.Visible = true;\r
390 \r
391                     check_KeepAR.Checked = true;\r
392                     updownParWidth.Enabled = !check_KeepAR.Checked;\r
393                     updownParHeight.Enabled = !check_KeepAR.Checked;\r
394                     break;\r
395             }\r
396 \r
397             labelDisplaySize.Text = CalculateAnamorphicSizes().Width + "x" + CalculateAnamorphicSizes().Height;\r
398 \r
399             if (check_KeepAR.Checked)\r
400                 TextWidthValueChanged(this, new EventArgs());\r
401 \r
402             if (PictureSettingsChanged != null)\r
403                 PictureSettingsChanged(this, new EventArgs());\r
404         }\r
405 \r
406         private void DrpModulusSelectedIndexChanged(object sender, EventArgs e)\r
407         {\r
408             preventChangingWidth = true;\r
409             preventChangingHeight = true;\r
410 \r
411             text_width.Value = (decimal)GetModulusValue((double)text_width.Value);\r
412             text_height.Value = (decimal)GetModulusValue((double)text_height.Value);\r
413 \r
414             preventChangingWidth = false;\r
415             preventChangingHeight = false;\r
416 \r
417             text_width.Increment = int.Parse(drp_modulus.SelectedItem.ToString());\r
418             text_height.Increment = int.Parse(drp_modulus.SelectedItem.ToString());\r
419 \r
420             if (PictureSettingsChanged != null)\r
421                 PictureSettingsChanged(this, new EventArgs());\r
422         }\r
423 \r
424         // Cropping Controls\r
425         private void CheckAutoCropCheckedChanged(object sender, EventArgs e)\r
426         {\r
427             crop_top.Enabled = check_customCrop.Checked;\r
428             crop_bottom.Enabled = check_customCrop.Checked;\r
429             crop_left.Enabled = check_customCrop.Checked;\r
430             crop_right.Enabled = check_customCrop.Checked;\r
431 \r
432             if (Source != null)\r
433             {\r
434                 crop_top.Value = Source.AutoCropDimensions.Top;\r
435                 crop_bottom.Value = Source.AutoCropDimensions.Bottom;\r
436                 crop_left.Value = Source.AutoCropDimensions.Left;\r
437                 crop_right.Value = Source.AutoCropDimensions.Right;\r
438             }\r
439         }\r
440 \r
441         private void CropValueChanged(object sender, EventArgs e)\r
442         {\r
443             TextWidthValueChanged(this, new EventArgs());\r
444         }\r
445 \r
446         // GUI Functions\r
447         private void SetCustomAnamorphicOptionsVisible(bool visible)\r
448         {\r
449             lbl_modulus.Visible = visible;\r
450             lbl_displayWidth.Visible = visible;\r
451             lbl_parWidth.Visible = visible;\r
452             lbl_parHeight.Visible = visible;\r
453 \r
454             drp_modulus.Visible = visible;\r
455             updownDisplayWidth.Visible = visible;\r
456             updownParWidth.Visible = visible;\r
457             updownParHeight.Visible = visible;\r
458         }\r
459 \r
460         // Calculation Functions\r
461         private Size SourceAspect\r
462         {\r
463             get\r
464             {\r
465                 if (Source != null) // display aspect = (width * par_width) / (height * par_height)\r
466                     return new Size((Source.ParVal.Width * Source.Resolution.Width),\r
467                                     (Source.ParVal.Height * Source.Resolution.Height));\r
468 \r
469                 return new Size(0, 0); // Fall over to 16:9 and hope for the best\r
470             }\r
471         }\r
472 \r
473         private Size CalculateAnamorphicSizes()\r
474         {\r
475             if (Source != null)\r
476             {\r
477                 /* Set up some variables to make the math easier to follow. */\r
478                 int croppedWidth = Source.Resolution.Width - (int)crop_left.Value - (int)crop_right.Value;\r
479                 int croppedHeight = Source.Resolution.Height - (int)crop_top.Value - (int)crop_bottom.Value;\r
480                 double storageAspect = (double)croppedWidth / croppedHeight;\r
481 \r
482                 /* Figure out what width the source would display at. */\r
483                 double sourceDisplayWidth = (double)croppedWidth * Source.ParVal.Width / Source.ParVal.Height;\r
484 \r
485                 /*\r
486                      3 different ways of deciding output dimensions:\r
487                       - 1: Strict anamorphic, preserve source dimensions\r
488                       - 2: Loose anamorphic, round to mod16 and preserve storage aspect ratio\r
489                       - 3: Power user anamorphic, specify everything\r
490                   */\r
491                 double width, height;\r
492                 switch (drp_anamorphic.SelectedIndex)\r
493                 {\r
494                     default:\r
495                     case 1:\r
496                         /* Strict anamorphic */\r
497                         double displayWidth = ((double)croppedWidth * Source.ParVal.Width / Source.ParVal.Height);\r
498                         displayWidth = Math.Round(displayWidth, 0);\r
499                         Size output = new Size((int)displayWidth, croppedHeight);\r
500                         return output;\r
501                     case 2:\r
502                         /* "Loose" anamorphic.\r
503                             - Uses mod16-compliant dimensions,\r
504                             - Allows users to set the width\r
505                         */\r
506                         width = (int)text_width.Value;\r
507                         width = GetModulusValue(width); /* Time to get picture width that divide cleanly.*/\r
508 \r
509                         height = (width / storageAspect) + 0.5;\r
510                         height = GetModulusValue(height); /* Time to get picture height that divide cleanly.*/\r
511 \r
512                         /* The film AR is the source's display width / cropped source height.\r
513                            The output display width is the output height * film AR.\r
514                            The output PAR is the output display width / output storage width. */\r
515                         double pixelAspectWidth = height * sourceDisplayWidth / croppedHeight;\r
516                         double pixelAspectHeight = width;\r
517 \r
518                         double disWidthLoose = (width * pixelAspectWidth / pixelAspectHeight);\r
519                         if (double.IsNaN(disWidthLoose))\r
520                             disWidthLoose = 0;\r
521                         return new Size((int)disWidthLoose, (int)height);\r
522                     case 3:\r
523 \r
524                         // Get the User Interface Values\r
525                         double UIdisplayWidth;\r
526                         double.TryParse(updownDisplayWidth.Text, out UIdisplayWidth);\r
527 \r
528                         /* Anamorphic 3: Power User Jamboree - Set everything based on specified values */\r
529                         height = GetModulusValue((double)text_height.Value);\r
530 \r
531                         if (check_KeepAR.Checked)\r
532                             return new Size((int)Math.Truncate(UIdisplayWidth), (int)height);\r
533 \r
534                         return new Size((int)Math.Truncate(UIdisplayWidth), (int)height);\r
535                 }\r
536             }\r
537 \r
538             // Return a default value of 0,0 to indicate failure\r
539             return new Size(0, 0);\r
540         }\r
541 \r
542         private double GetModulusValue(double value)\r
543         {\r
544             int mod = int.Parse(drp_modulus.SelectedItem.ToString());\r
545             double remainder = value % mod;\r
546 \r
547             if (remainder == 0)\r
548                 return value;\r
549 \r
550             return remainder >= ((double)mod / 2) ? value + (mod - remainder) : value - remainder;\r
551         }\r
552 \r
553         private static int GetCropMod2Clean(int value)\r
554         {\r
555             int remainder = value % 2;\r
556             if (remainder == 0) return value;\r
557             return (value + remainder);\r
558         }\r
559     }\r
560 }