OSDN Git Service

WinGui:
[handbrake-jp/handbrake-jp-git.git] / win / C# / Controls / PictureSettings.cs
1 using System;\r
2 using System.ComponentModel;\r
3 using System.Drawing;\r
4 using System.Windows.Forms;\r
5 using Handbrake.Parsing;\r
6 \r
7 namespace Handbrake.Controls\r
8 {\r
9     public partial class PictureSettings : UserControl\r
10     {\r
11         private bool _preventChangingWidth, _preventChangingHeight;\r
12         private int _maxWidth, _maxHeight, _lastEncodeWidth, _lastEncodeHeight;\r
13         private double _anamorphicRatio, _displayRatio;\r
14         private Title _title;\r
15         private double storageAspect;\r
16         public event EventHandler PictureSettingsChanged;\r
17 \r
18         public PictureSettings()\r
19         {\r
20             InitializeComponent();\r
21 \r
22             drp_anamorphic.SelectedIndex = 1;\r
23             drp_modulus.SelectedIndex = 0;\r
24         }\r
25 \r
26         /// <summary>\r
27         /// Gets or sets the source media used by this control.\r
28         /// </summary>\r
29         [Browsable(false)]\r
30         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]\r
31         public Title Source\r
32         {\r
33             get { return _title; }\r
34             set\r
35             {\r
36                 _title = value;\r
37                 _displayRatio = ((double)_title.Resolution.Width * _title.ParVal.Width / _title.ParVal.Height) / _title.Resolution.Height;\r
38 \r
39                 Enabled = _title != null;\r
40 \r
41                 MaximumWidth = _title.Resolution.Width;\r
42                 MaximumHeight = _title.Resolution.Height;\r
43 \r
44                 updownParWidth.Value = _title.ParVal.Width;\r
45                 updownParHeight.Value = _title.ParVal.Height;\r
46 \r
47                 // Set the source resolution\r
48                 lbl_src_res.Text = Source.Resolution.Width + " x " + Source.Resolution.Height;\r
49 \r
50                 // Set ratios\r
51                 _anamorphicRatio = (double)Source.Resolution.Width / Source.Resolution.Height;\r
52 \r
53                 // Set the encode width and height\r
54                 EncodeWidth = _title.Resolution.Width;\r
55                 EncodeHeight = _title.Resolution.Height;\r
56 \r
57                 _lastEncodeWidth = _title.Resolution.Width;\r
58                 _lastEncodeHeight = _title.Resolution.Height;\r
59 \r
60                 // Set cropping\r
61                 CroppingValues = _title.AutoCropDimensions;\r
62 \r
63                 lbl_Aspect.Text = _title.AspectRatio.ToString();\r
64 \r
65                 UpdateAnamorphicValue();\r
66             }\r
67         }\r
68 \r
69         /// <summary>\r
70         /// Gets or sets the resolution of the displayed video.\r
71         /// </summary>\r
72         public Size DisplayResolution { get; set; }\r
73 \r
74         public int EncodeWidth { get { return (int)text_width.Value; } set { text_width.Value = value; } }\r
75 \r
76         public int EncodeHeight { get { return (int)text_height.Value; } set { text_height.Value = value; } }\r
77 \r
78         public int[] CroppingValues\r
79         {\r
80             get\r
81             {\r
82                 return new int[4]\r
83                 {\r
84                     (int)crop_top.Value,\r
85                     (int)crop_bottom.Value,\r
86                     (int)crop_left.Value,\r
87                     (int)crop_right.Value\r
88                 };\r
89             }\r
90             set\r
91             {\r
92                 if (value.Length != 4)\r
93                 {\r
94                     throw new ArgumentException("The cropping values given must have a length of 4.");\r
95                 }\r
96 \r
97                 crop_top.Value = value[0];\r
98                 crop_bottom.Value = value[1];\r
99                 crop_left.Value = value[2];\r
100                 crop_right.Value = value[3];\r
101             }\r
102         }\r
103 \r
104         /// <summary>\r
105         /// Gets or sets the maximum allowable width of the encoded video.\r
106         /// </summary>\r
107         public int MaximumWidth\r
108         {\r
109             get { return _maxWidth; }\r
110             set\r
111             {\r
112                 _maxWidth = value > 0 ? value : (Source != null ? Source.Resolution.Width : 2560);\r
113             }\r
114         }\r
115 \r
116         /// <summary>\r
117         /// Gets or sets the maximum allowable height of the encoded video.\r
118         /// </summary>\r
119         public int MaximumHeight\r
120         {\r
121             get { return _maxHeight; }\r
122             set\r
123             {\r
124                 _maxHeight = value > 0 ? value : (Source != null ? Source.Resolution.Height : 2560);\r
125             }\r
126         }      \r
127 \r
128         public void setMax()\r
129         {\r
130 \r
131         }\r
132 \r
133         /// <summary>\r
134         /// Updates the anamorphic value shown as the display width.\r
135         /// </summary>\r
136         private void UpdateAnamorphicValue()\r
137         {\r
138             if (_title == null || _title.ParVal.IsEmpty)\r
139                 return;\r
140 \r
141             // Set globally useful values\r
142             double width;\r
143             double par;\r
144 \r
145             switch (drp_anamorphic.SelectedIndex)\r
146             {\r
147                 case 2:\r
148                     int actualWidth = (int)text_width.Value - (int)crop_left.Value - (int)crop_right.Value;\r
149                     int source_display_width = Source.Resolution.Width * Source.ParVal.Width / Source.ParVal.Height;\r
150                     int source_cropped_height = Source.Resolution.Height - (int)crop_top.Value - (int)crop_bottom.Value;\r
151                     par = ((double) text_height.Value*source_display_width/source_cropped_height)/actualWidth;\r
152                     width = (actualWidth * par);\r
153                     width = Math.Truncate(width);\r
154                     break;\r
155                 default:\r
156                     {\r
157                         if (drp_anamorphic.SelectedIndex == 1) // Strict\r
158                             par = (double)Source.ParVal.Width / Source.ParVal.Height;\r
159                         else // Custom\r
160                             par = (double)updownParWidth.Value / (double)updownParHeight.Value;\r
161 \r
162                         // Store the latest DAR\r
163                         double rawWidth = (double)text_width.Value * par;\r
164                         _displayRatio = rawWidth / (double)text_height.Value;\r
165 \r
166                         width = (int)Math.Round(rawWidth);\r
167                         break;\r
168                     }\r
169             }\r
170 \r
171             labelDisplaySize.Text = width + " x " + text_height.Value;\r
172 \r
173             updownDisplayWidth.Value = (decimal)width;\r
174             updownParWidth.Value = (decimal)width;\r
175             updownParHeight.Value = text_width.Value;\r
176         }\r
177 \r
178         /// <summary>\r
179         /// Sets the visibility of the advanced anamorphic options.\r
180         /// </summary>\r
181         /// <param name="value">Whether or not the options should be visible.</param>\r
182         private void SetCustomAnamorphicOptionsVisible(bool visible)\r
183         {\r
184             lbl_modulus.Visible = visible;\r
185             lbl_displayWidth.Visible = visible;\r
186             lbl_parWidth.Visible = visible;\r
187             lbl_parHeight.Visible = visible;\r
188 \r
189             drp_modulus.Visible = visible;\r
190             updownDisplayWidth.Visible = visible;\r
191             updownParWidth.Visible = visible;\r
192             updownParHeight.Visible = visible;\r
193         }\r
194 \r
195         /// <summary>\r
196         /// Gets the normalized value from one given by the user that is divisible by the number\r
197         /// set in <see cref="_modulus"/>.\r
198         /// </summary>\r
199         /// <param name="value">The value to normalize</param>\r
200         /// <returns>A number that is divisible by <see cref="_modulus"/>.</returns>\r
201         /// <remarks>\r
202         /// The way that some video codecs, such as x264, compress video is by creating "macroblocks" \r
203         /// that are seperated into defined squares, often 16x16 pixels. Because of this, if the width \r
204         /// and height of the encoded video are not each divisible by the modulus defined, video quality\r
205         /// will suffer. This method takes the supplied value and normalizes it to the nearest mutliple\r
206         /// of <see cref="_modulus"/>.\r
207         /// </remarks>\r
208         private int GetModulusValue(int value)\r
209         {\r
210             int mod = int.Parse(drp_modulus.SelectedItem.ToString());\r
211             int remainder = value % mod;\r
212 \r
213             if (remainder == 0)\r
214                 return value;\r
215 \r
216             return remainder >= mod / 2 ? value + (mod - remainder) : value - remainder;\r
217         }\r
218 \r
219         private void ApplyStrictAnamorphic()\r
220         {\r
221             if (_anamorphicRatio == 0)\r
222                 return;\r
223 \r
224             _preventChangingWidth = true;\r
225             _preventChangingHeight = true;\r
226 \r
227             text_width.Value = _title.Resolution.Width;\r
228             text_height.Value = _title.Resolution.Height;\r
229 \r
230             _preventChangingWidth = false;\r
231             _preventChangingHeight = false;\r
232         }\r
233 \r
234         /// <summary>\r
235         /// Loosely anamorphs encode width and height values.\r
236         /// </summary>\r
237         private void ApplyLooseAnamorphic()\r
238         {\r
239             // Prevents DivideByZeroExceptions\r
240             if (_anamorphicRatio == 0)\r
241                 return;\r
242 \r
243             int actualWidth = (int)text_width.Value - (int)crop_left.Value - (int)crop_right.Value;\r
244             int source_cropped_height = Source.Resolution.Height - (int)crop_top.Value - (int)crop_bottom.Value;\r
245 \r
246             if (storageAspect == 0)\r
247                 storageAspect = (double)actualWidth / source_cropped_height;\r
248             double hcalc = (actualWidth / storageAspect) + 0.5;\r
249             double newHeight = GetModulusValue((int)hcalc);\r
250 \r
251             text_width.Value = GetModulusValue((int)text_width.Value);\r
252             text_height.Value = (decimal)newHeight;\r
253 \r
254             UpdateAnamorphicValue();\r
255         }\r
256 \r
257         /// <summary>\r
258         /// Anamorphs encode width and height based on the custom options specified.\r
259         /// </summary>\r
260         private void ApplyCustomAnamorphic(Control ctrlUpdated)\r
261         {\r
262             // Make sure the PAR values are set correctly\r
263             if (updownParWidth.Value == 0)\r
264                 updownParWidth.Value = Source.ParVal.Width;\r
265             if (updownParHeight.Value == 0)\r
266                 updownParHeight.Value = Source.ParVal.Height;\r
267 \r
268             // Set various values\r
269             int parWidth = (int)updownParWidth.Value;\r
270             int parHeight = (int)updownParHeight.Value;\r
271 \r
272             if (!check_KeepAR.Checked)\r
273             {\r
274                 switch (ctrlUpdated.Name)\r
275                 {\r
276                     case "text_width":\r
277                     case "updownParWidth":\r
278                     case "updownParHeight":\r
279                         updownDisplayWidth.Value = Math.Round(text_width.Value * parWidth / parHeight);\r
280                         break;\r
281                     case "updownDisplayWidth":\r
282                         updownParWidth.Value = updownDisplayWidth.Value;\r
283                         updownParHeight.Value = text_width.Value;\r
284                         break;\r
285                 }\r
286             }\r
287             else\r
288             {\r
289                 switch (ctrlUpdated.Name)\r
290                 {\r
291                     case "updownDisplayWidth":\r
292                         _preventChangingHeight = true;\r
293 \r
294                         text_height.Value = GetModulusValue((int)((double)updownDisplayWidth.Value / _displayRatio));\r
295 \r
296                         _preventChangingHeight = false;\r
297                         goto case "text_width";\r
298                     case "text_height":\r
299                         updownDisplayWidth.Value = GetModulusValue((int)((double)text_width.Value * _anamorphicRatio * _displayRatio));\r
300                         goto case "text_width";\r
301                     case "text_width":\r
302                         updownParWidth.Value = updownDisplayWidth.Value;\r
303                         updownParHeight.Value = text_width.Value;\r
304                         break;\r
305                 }\r
306             }\r
307         }\r
308 \r
309 \r
310 \r
311         private void text_width_ValueChanged(object sender, EventArgs e)\r
312         {\r
313             if (_preventChangingWidth)\r
314                 return;\r
315 \r
316             _preventChangingWidth = true;\r
317 \r
318             if (text_width.Value > MaximumWidth)\r
319             {\r
320                 text_width.Value = MaximumWidth;\r
321             }\r
322 \r
323             switch (drp_anamorphic.SelectedIndex)\r
324             {\r
325                 case 0:\r
326                     if (check_KeepAR.Checked)\r
327                     {\r
328                         _preventChangingHeight = true;\r
329 \r
330                         decimal newHeight = text_width.Value / (decimal)_anamorphicRatio;\r
331                         text_height.Value = newHeight > MaximumHeight ? MaximumHeight : newHeight;\r
332 \r
333                         _preventChangingHeight = false;\r
334                     }\r
335                     break;\r
336                 case 1:\r
337                     ApplyStrictAnamorphic();\r
338                     break;\r
339                 case 2:\r
340                     ApplyLooseAnamorphic();\r
341                     break;\r
342                 case 3:\r
343                     ApplyCustomAnamorphic((Control)sender);\r
344                     break;\r
345             }\r
346 \r
347             _preventChangingWidth = false;\r
348         }\r
349 \r
350         private void text_height_ValueChanged(object sender, EventArgs e)\r
351         {\r
352             if (_preventChangingHeight)\r
353                 return;\r
354 \r
355             _preventChangingHeight = true;\r
356 \r
357             if (text_height.Value > MaximumHeight)\r
358             {\r
359                 text_height.Value = MaximumHeight;\r
360             }\r
361 \r
362             switch (drp_anamorphic.SelectedIndex)\r
363             {\r
364                 case 0:\r
365                     if (check_KeepAR.Checked)\r
366                     {\r
367                         _preventChangingWidth = true;\r
368 \r
369                         decimal newWidth = text_height.Value * (decimal)_anamorphicRatio;\r
370                         text_width.Value = newWidth > MaximumWidth ? MaximumWidth : newWidth;\r
371 \r
372                         _preventChangingWidth = false;\r
373                     }\r
374                     break;\r
375                 case 3:\r
376                     ApplyCustomAnamorphic((Control)sender);\r
377                     break;\r
378             }\r
379 \r
380             _preventChangingHeight = false;\r
381         }\r
382 \r
383         private void drp_anamorphic_SelectedIndexChanged(object sender, EventArgs e)\r
384         {\r
385             switch (drp_anamorphic.SelectedIndex)\r
386             {\r
387                 case 0:\r
388                     text_width.Enabled = true;\r
389                     text_height.Enabled = true;\r
390                     check_KeepAR.Enabled = true;\r
391 \r
392                     SetCustomAnamorphicOptionsVisible(false);\r
393                     labelStaticDisplaySize.Visible = false;\r
394                     labelDisplaySize.Visible = false;\r
395 \r
396                     check_KeepAR.Checked = true;\r
397                     break;\r
398                 case 1:\r
399                     text_width.Enabled = false;\r
400                     text_height.Enabled = false;\r
401                     check_KeepAR.Enabled = false;\r
402 \r
403                     SetCustomAnamorphicOptionsVisible(false);\r
404                     labelStaticDisplaySize.Visible = true;\r
405                     labelDisplaySize.Visible = true;\r
406 \r
407                     check_KeepAR.Checked = true;\r
408                     break;\r
409                 case 2:\r
410                     text_width.Enabled = true;\r
411                     text_height.Enabled = false;\r
412                     check_KeepAR.Enabled = false;\r
413 \r
414                     SetCustomAnamorphicOptionsVisible(false);\r
415                     labelStaticDisplaySize.Visible = true;\r
416                     labelDisplaySize.Visible = true;\r
417 \r
418                     check_KeepAR.Checked = true;\r
419                     break;\r
420                 case 3:\r
421                     text_width.Enabled = true;\r
422                     text_height.Enabled = true;\r
423                     check_KeepAR.Enabled = true;\r
424 \r
425                     SetCustomAnamorphicOptionsVisible(true);\r
426                     labelStaticDisplaySize.Visible = true;\r
427                     labelDisplaySize.Visible = true;\r
428 \r
429                     check_KeepAR.Checked = true;\r
430                     break;\r
431             }\r
432 \r
433             UpdateAnamorphicValue();\r
434         }\r
435 \r
436         private void check_KeepAR_CheckedChanged(object sender, EventArgs e)\r
437         {\r
438             if (drp_anamorphic.SelectedIndex != 3)\r
439             {\r
440                 if (check_KeepAR.Checked)\r
441                 {\r
442                     text_width_ValueChanged(this, new EventArgs());\r
443                 }\r
444             }\r
445             else\r
446             {\r
447                 updownParWidth.Enabled = !check_KeepAR.Checked;\r
448                 updownParHeight.Enabled = !check_KeepAR.Checked;\r
449             }\r
450         }\r
451 \r
452         private void crop_ValueChanged(object sender, EventArgs e)\r
453         {\r
454             text_width_ValueChanged(this, new EventArgs());\r
455         }\r
456 \r
457         private void check_autoCrop_CheckedChanged(object sender, EventArgs e)\r
458         {\r
459             crop_top.Enabled = check_customCrop.Checked;\r
460             crop_bottom.Enabled = check_customCrop.Checked;\r
461             crop_left.Enabled = check_customCrop.Checked;\r
462             crop_right.Enabled = check_customCrop.Checked;\r
463         }\r
464 \r
465         private void drp_modulus_SelectedIndexChanged(object sender, EventArgs e)\r
466         {\r
467             text_width.Increment = int.Parse(drp_modulus.SelectedItem.ToString());\r
468             text_height.Increment = int.Parse(drp_modulus.SelectedItem.ToString());\r
469         }\r
470     }\r
471 }\r