OSDN Git Service

- Add the accurate rounding flag for software scaling to avoid scaling artifacts...
[handbrake-jp/handbrake-jp-git.git] / macosx / PictureController.mm
1 /* $Id: PictureController.mm,v 1.11 2005/08/01 15:10:44 titer Exp $
2
3    This file is part of the HandBrake source code.
4    Homepage: <http://handbrake.m0k.org/>.
5    It may be used under the terms of the GNU General Public License. */
6
7 #include "PictureController.h"
8
9 static int GetAlignedSize( int size )
10 {
11     int result = 1;
12     while( result < size )
13     {
14         result *= 2;
15     }
16     return result;
17 }
18
19 @implementation PictureController
20
21 - (void) SetHandle: (hb_handle_t *) handle
22 {
23     fHandle = handle;
24
25     fHasQE = CGDisplayUsesOpenGLAcceleration( kCGDirectMainDisplay );
26
27     fBuffer     = NULL;
28     fBufferSize = 0;
29     fTexBuf[0]  = NULL;
30     fTexBuf[1]  = NULL;
31     fTexBufSize = 0;
32
33     [fWidthStepper  setValueWraps: NO];
34     [fWidthStepper  setIncrement: 16];
35     [fWidthStepper  setMinValue: 64];
36     [fHeightStepper setValueWraps: NO];
37     [fHeightStepper setIncrement: 16];
38     [fHeightStepper setMinValue: 64];
39
40     [fCropTopStepper    setIncrement: 2];
41     [fCropTopStepper    setMinValue:  0];
42     [fCropBottomStepper setIncrement: 2];
43     [fCropBottomStepper setMinValue:  0];
44     [fCropLeftStepper   setIncrement: 2];
45     [fCropLeftStepper   setMinValue:  0];
46     [fCropRightStepper  setIncrement: 2];
47     [fCropRightStepper  setMinValue:  0];
48 }
49
50 - (void) SetTitle: (hb_title_t *) title
51 {
52     hb_job_t * job = title->job;
53
54     fTitle = title;
55
56     /* Make sure we have big enough buffers */
57     int newSize;
58     newSize = ( title->width + 2 ) * (title->height + 2 ) * 4;
59     if( fBufferSize < newSize )
60     {
61         fBufferSize = newSize;
62         fBuffer     = (uint8_t *) realloc( fBuffer, fBufferSize );
63     }
64     if( !fHasQE )
65     {
66         newSize = ( GetAlignedSize( title->width + 2 ) *
67             GetAlignedSize( title->height + 2 ) * 4 );
68     }
69     if( fTexBufSize < newSize )
70     {
71         fTexBufSize = newSize;
72         fTexBuf[0]  = (uint8_t *) realloc( fTexBuf[0], fTexBufSize );
73         fTexBuf[1]  = (uint8_t *) realloc( fTexBuf[1], fTexBufSize );
74     }
75
76
77     [fWidthStepper      setMaxValue: title->width];
78     [fWidthStepper      setIntValue: job->width];
79     [fWidthField        setIntValue: job->width];
80     [fHeightStepper     setMaxValue: title->height];
81     [fHeightStepper     setIntValue: job->height];
82     [fHeightField       setIntValue: job->height];
83     [fRatioCheck        setState:    job->keep_ratio ? NSOnState : NSOffState];
84     [fCropTopStepper    setMaxValue: title->height/2-2];
85     [fCropBottomStepper setMaxValue: title->height/2-2];
86     [fCropLeftStepper   setMaxValue: title->width/2-2];
87     [fCropRightStepper  setMaxValue: title->width/2-2];
88     
89         
90         /* we use a popup to show the deinterlace settings */
91         [fDeinterlacePopUp removeAllItems];
92     [fDeinterlacePopUp addItemWithTitle: @"None"];
93     [fDeinterlacePopUp addItemWithTitle: @"Fast"];
94     [fDeinterlacePopUp addItemWithTitle: @"Slow"];
95         [fDeinterlacePopUp addItemWithTitle: @"Slower"];
96         [fDeinterlacePopUp addItemWithTitle: @"Slowest"];
97     
98         /* Set deinterlaces level according to the integer in the main window */
99         [fDeinterlacePopUp selectItemAtIndex: [fDeinterlaceLevelMainWindow intValue]];
100         
101         
102         [fPARCheck  setState:    job->pixel_ratio ? NSOnState : NSOffState];
103         if ([fAutoCropMainWindow  intValue] == 0)
104         {
105         [fCropMatrix  selectCellAtRow: 1 column:0];
106         /* If auto, lets set the crop steppers according to current job->crop values */
107         [fCropTopStepper    setIntValue: job->crop[0]];
108     [fCropTopField      setIntValue: job->crop[0]];
109     [fCropBottomStepper setIntValue: job->crop[1]];
110     [fCropBottomField   setIntValue: job->crop[1]];
111     [fCropLeftStepper   setIntValue: job->crop[2]];
112     [fCropLeftField     setIntValue: job->crop[2]];
113     [fCropRightStepper  setIntValue: job->crop[3]];
114     [fCropRightField    setIntValue: job->crop[3]];
115         }
116         else
117         {
118         [fCropMatrix  selectCellAtRow: 0 column:0];
119         }
120         
121         /* set the detelecine state according to the state in main window */
122         /* if framerate is 23.976 we do not allow detelecine, otherwise, enable and set according to fDetelecineMainWindow outlet */ 
123         if (fTitle->rate_base == 1126125 || [[fVidFrameRatePopUpMainWindow titleOfSelectedItem] isEqualToString: @"23.976 (NTSC Film)"])
124         {
125                 [fDetelecineMainWindow setStringValue: @"No"];
126                 [fDetelecineCheck setEnabled: NO];
127                 [fDetelecineCheck setState: NSOffState];
128                 
129         }
130         else
131         {
132         [fDetelecineCheck setEnabled: YES];
133                 if ([[fDetelecineMainWindow stringValue] isEqualToString: @"Yes"])
134                 {
135                         [fDetelecineCheck setState: NSOnState];
136                 }
137                 else
138                 {
139                         [fDetelecineCheck setState: NSOffState];
140                 }
141                 
142         }
143         
144         /* we use a popup to show the denoise settings */
145         [fDenoisePopUp removeAllItems];
146     [fDenoisePopUp addItemWithTitle: @"None"];
147     [fDenoisePopUp addItemWithTitle: @"Weak"];
148         [fDenoisePopUp addItemWithTitle: @"Medium"];
149     [fDenoisePopUp addItemWithTitle: @"Strong"];
150         /* Set deinterlaces level according to the integer in the main window */
151         [fDenoisePopUp selectItemAtIndex: [fDenoiseMainWindow intValue]];
152         
153     MaxOutputWidth = job->width;
154         MaxOutputHeight = job->height;
155     fPicture = 0;
156     [self SettingsChanged: nil];
157 }
158
159 - (void) Display: (int) anim
160 {
161     hb_get_preview( fHandle, fTitle, fPicture, fBuffer );
162
163     /* Backup previous picture (for effects) */
164     memcpy( fTexBuf[1], fTexBuf[0], fTexBufSize );
165
166     if( fHasQE )
167     {
168         /* Simply copy */
169         memcpy( fTexBuf[0], fBuffer, fTexBufSize );
170     }
171     else
172     {
173         /* Copy line by line */
174         uint8_t * in  = fBuffer;
175         uint8_t * out = fTexBuf[0];
176                 
177         for( int i = fTitle->height + 2; i--; )
178         {
179             memcpy( out, in, 4 * ( fTitle->width + 2 ) );
180             in  += 4 * ( fTitle->width + 2 );
181             out += 4 * GetAlignedSize( fTitle->width + 2 );
182         }
183         
184     }
185
186     if( [fEffectsCheck state] == NSOffState )
187     {
188         anim = HB_ANIMATE_NONE;
189     }
190     else if( [[NSApp currentEvent] modifierFlags] & NSShiftKeyMask )
191     {
192         anim |= HB_ANIMATE_SLOW;
193     }
194
195     [fPictureGLView Display: anim buffer1: fTexBuf[0]
196         buffer2: fTexBuf[1] width: ( fTitle->width + 2 )
197         height: ( fTitle->height + 2 )];
198         
199         /* Set the Output Display below the Preview Picture*/
200         int titlewidth = fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3];
201         int arpwidth = fTitle->job->pixel_aspect_width;
202         int arpheight = fTitle->job->pixel_aspect_height;
203         int displayparwidth = titlewidth * arpwidth / arpheight;
204         int displayparheight = fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1];
205         if (fTitle->job->pixel_ratio == 1)
206         {
207         
208         [fInfoField setStringValue: [NSString stringWithFormat:
209         @"Source: %dx%d, Output: %dx%d, Anamorphic: %dx%d", fTitle->width, fTitle->height,
210         titlewidth, displayparheight, displayparwidth,
211         displayparheight]];
212         
213         
214         }
215         else
216         {
217         [fInfoField setStringValue: [NSString stringWithFormat:
218         @"Source: %dx%d, Output: %dx%d", fTitle->width, fTitle->height,
219         fTitle->job->width, fTitle->job->height]];      
220         }
221
222
223     [fPrevButton setEnabled: ( fPicture > 0 )];
224     [fNextButton setEnabled: ( fPicture < 9 )];
225 }
226
227 - (IBAction) SettingsChanged: (id) sender
228 {
229     hb_job_t * job = fTitle->job;
230     
231         if ([fPARCheck state] == 1 )
232         {
233         [fWidthStepper      setIntValue: MaxOutputWidth];
234         [fWidthField        setIntValue: MaxOutputWidth];
235         
236         /* This will show correct anamorphic height values, but
237         show distorted preview picture ratio */
238         [fHeightStepper      setIntValue: fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1]];
239         [fHeightField        setIntValue: fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1]];
240         
241         /* This will show wrong anamorphic height values, but
242         show proper preview picture ratio */
243         //[fHeightStepper      setIntValue: MaxOutputHeight];
244         //[fHeightField        setIntValue: MaxOutputHeight];
245         [fRatioCheck        setState: 0];
246
247         [fWidthStepper setEnabled: NO];
248         [fWidthField setEnabled: NO];
249         [fHeightStepper setEnabled: NO];
250         [fHeightField setEnabled: NO];
251         [fRatioCheck setEnabled: NO];
252         
253         
254         }
255         else
256         {
257         [fWidthStepper setEnabled: YES];
258         [fWidthField setEnabled: YES];
259         [fHeightStepper setEnabled: YES];
260         [fHeightField setEnabled: YES];
261         [fRatioCheck setEnabled: YES];
262         }
263         
264         
265         
266     job->width       = [fWidthStepper  intValue];
267     job->height      = [fHeightStepper intValue];
268     job->keep_ratio  = ( [fRatioCheck state] == NSOnState );
269         
270         /* multilevel deinterlacing popup */
271         [fDeinterlaceLevelMainWindow setStringValue: [NSString stringWithFormat: @"%d",[fDeinterlacePopUp indexOfSelectedItem]]];
272         if ([fDeinterlacePopUp indexOfSelectedItem] == 0)
273         {
274     job->deinterlace = 0;
275         }
276         else
277         {
278         job->deinterlace = 1;
279         }
280         
281         /* set the detelecine state according to the integer set in the main window field */
282         if ([fDetelecineCheck state] == 1)
283         {
284         [fDetelecineMainWindow setStringValue: @"Yes"];
285         }
286         else
287         {
288         [fDetelecineMainWindow setStringValue: @"No"];
289         }
290         
291         /* new multilevel deinterlacing popup */
292         [fDenoiseMainWindow setStringValue: [NSString stringWithFormat: @"%d",[fDenoisePopUp indexOfSelectedItem]]];
293         job->pixel_ratio = ( [fPARCheck state] == NSOnState );
294
295
296
297     bool autocrop = ( [fCropMatrix selectedRow] == 0 );
298     [fCropTopStepper    setEnabled: !autocrop];
299     [fCropBottomStepper setEnabled: !autocrop];
300     [fCropLeftStepper   setEnabled: !autocrop];
301     [fCropRightStepper  setEnabled: !autocrop];
302         [fAutoCropMainWindow  setStringValue: [NSString stringWithFormat:@"%d",autocrop]];
303     if( autocrop )
304     {
305         memcpy( job->crop, fTitle->crop, 4 * sizeof( int ) );
306     }
307     else
308     {
309         job->crop[0] = [fCropTopStepper    intValue];
310         job->crop[1] = [fCropBottomStepper intValue];
311         job->crop[2] = [fCropLeftStepper   intValue];
312         job->crop[3] = [fCropRightStepper  intValue];
313     }
314
315     if( job->keep_ratio )
316     {
317         if( sender == fWidthStepper || sender == fRatioCheck ||
318             sender == fCropTopStepper || sender == fCropBottomStepper )
319         {
320             hb_fix_aspect( job, HB_KEEP_WIDTH );
321             if( job->height > fTitle->height )
322             {
323                 job->height = fTitle->height;
324                 hb_fix_aspect( job, HB_KEEP_HEIGHT );
325             }
326         }
327         else
328         {
329             hb_fix_aspect( job, HB_KEEP_HEIGHT );
330             if( job->width > fTitle->width )
331             {
332                 job->width = fTitle->width;
333                 hb_fix_aspect( job, HB_KEEP_WIDTH );
334             }
335         }
336     }
337     
338     [fWidthStepper      setIntValue: job->width];
339     [fWidthField        setIntValue: job->width];
340     [fHeightStepper     setIntValue: job->height];
341     [fHeightField       setIntValue: job->height];
342     [fCropTopStepper    setIntValue: job->crop[0]];
343     [fCropTopField      setIntValue: job->crop[0]];
344     [fCropBottomStepper setIntValue: job->crop[1]];
345     [fCropBottomField   setIntValue: job->crop[1]];
346     [fCropLeftStepper   setIntValue: job->crop[2]];
347     [fCropLeftField     setIntValue: job->crop[2]];
348     [fCropRightStepper  setIntValue: job->crop[3]];
349     [fCropRightField    setIntValue: job->crop[3]];
350     /* Sanity Check Here for < 16 px preview to avoid
351        crashing hb_get_preview. In fact, just for kicks
352        lets getting previews at a min limit of 32, since
353        no human can see any meaningful detail below that */
354     if (job->width >= 64 && job->height >= 64)
355     {
356     [self Display: HB_ANIMATE_NONE];
357     }
358
359 }
360
361 - (IBAction) PreviousPicture: (id) sender
362 {   
363     if( fPicture <= 0 )
364     {
365         return;
366     }
367     fPicture--;
368     [self Display: HB_ANIMATE_BACKWARD];
369 }
370
371 - (IBAction) NextPicture: (id) sender
372 {
373     if( fPicture >= 9 )
374     {
375         return;
376     }
377     fPicture++;
378     [self Display: HB_ANIMATE_FORWARD];
379 }
380
381 - (IBAction) ClosePanel: (id) sender
382 {
383
384         [NSApp stopModal];
385 }
386
387 @end