diff options
-rw-r--r-- | libhb/common.h | 58 | ||||
-rw-r--r-- | libhb/hb.c | 382 | ||||
-rw-r--r-- | libhb/hb.h | 3 | ||||
-rw-r--r-- | macosx/HBPreviewController.m | 94 | ||||
-rw-r--r-- | macosx/PictureController.m | 635 |
5 files changed, 543 insertions, 629 deletions
diff --git a/libhb/common.h b/libhb/common.h index 236f96895..a5ba78730 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -78,6 +78,9 @@ typedef struct hb_dither_s hb_dither_t; typedef struct hb_mixdown_s hb_mixdown_t; typedef struct hb_encoder_s hb_encoder_t; typedef struct hb_container_s hb_container_t; +typedef struct hb_rational_s hb_rational_t; +typedef struct hb_geometry_s hb_geometry_t; +typedef struct hb_ui_geometry_s hb_ui_geometry_t; typedef struct hb_job_s hb_job_t; typedef struct hb_title_set_s hb_title_set_t; typedef struct hb_title_s hb_title_t; @@ -133,8 +136,9 @@ void hb_reduce( int *x, int *y, int num, int den ); void hb_reduce64( int64_t *x, int64_t *y, int64_t num, int64_t den ); void hb_limit_rational64( int64_t *x, int64_t *y, int64_t num, int64_t den, int64_t limit ); -#define HB_KEEP_WIDTH 0 -#define HB_KEEP_HEIGHT 1 +#define HB_KEEP_WIDTH 0x01 +#define HB_KEEP_HEIGHT 0x02 +#define HB_KEEP_DISPLAY_ASPECT 0x04 void hb_fix_aspect( hb_job_t * job, int keep ); void hb_job_set_encoder_preset (hb_job_t *job, const char *preset); @@ -232,6 +236,34 @@ struct hb_container_s int format; }; +struct hb_rational_s +{ + int num; + int den; +}; + +struct hb_geometry_s +{ + int width; + int height; + hb_rational_t par; +}; + +struct hb_ui_geometry_s +{ + int mode; // Anamorphic mode, see job struct anamorphic + int keep; // Specifies settings that shouldn't be changed + int itu_par; // use dvd dimensions to determine PAR + int modulus; // pixel alignment for loose anamorphic + int crop[4]; // Pixels cropped from source before scaling + int width; // destination storage width + int height; // destination storage height + int maxWidth; // max destination storage width + int maxHeight; // max destination storage height + hb_rational_t par; // Pixel aspect used in custom anamorphic + hb_rational_t dar; // Display aspect used in custom anamorphic +}; + // Update win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_subtitle_config_s.cs when changing this struct struct hb_subtitle_config_s { @@ -379,6 +411,14 @@ struct hb_title_set_s extern int hb_gui_use_hwd_flag; +typedef enum +{ + HB_ANAMORPHIC_NONE, + HB_ANAMORPHIC_STRICT, + HB_ANAMORPHIC_LOOSE, + HB_ANAMORPHIC_CUSTOM +} hb_anamorphic_mode_t; + /****************************************************************************** * hb_job_t: settings to be filled by the UI * Update win/CS/HandBrake.Interop/HandBrakeInterop/HbLib/hb_job_s.cs when changing this struct @@ -422,13 +462,13 @@ struct hb_job_s struct { - int mode; - int itu_par; - int par_width; - int par_height; - int dar_width; // 0 if normal - int dar_height; // 0 if normal - int keep_display_aspect; + hb_anamorphic_mode_t mode; + int itu_par; + int par_width; + int par_height; + int dar_width; // 0 if normal + int dar_height; // 0 if normal + int keep_display_aspect; } anamorphic; int modulus; diff --git a/libhb/hb.c b/libhb/hb.c index 303781cc5..d1e494195 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -913,77 +913,78 @@ int hb_detect_comb( hb_buffer_t * buf, int color_equal, int color_diff, int thre } /** - * Calculates job width and height for anamorphic content, + * Calculates destination width and height for anamorphic content * - * @param job Handle to hb_job_t - * @param output_width Pointer to returned storage width - * @param output_height Pointer to returned storage height - * @param output_par_width Pointer to returned pixel width - * @param output_par_height Pointer to returned pixel height + * Returns calculated geometry + * @param source_geometry - Pointer to source geometry info + * @param ui_geometry - Pointer to requested destination parameters */ -void hb_set_anamorphic_size( hb_job_t * job, - int *output_width, int *output_height, - int *output_par_width, int *output_par_height ) +void hb_set_anamorphic_size2(hb_geometry_t *src_geo, + hb_ui_geometry_t *ui_geo, + hb_geometry_t *result) { + hb_rational_t in_par, out_par; + int keep_display_aspect = !!(ui_geo->keep & HB_KEEP_DISPLAY_ASPECT); + int keep_height = !!(ui_geo->keep & HB_KEEP_HEIGHT); + /* Set up some variables to make the math easier to follow. */ - hb_title_t * title = job->title; - int cropped_width = title->width - job->crop[2] - job->crop[3] ; - int cropped_height = title->height - job->crop[0] - job->crop[1] ; - double storage_aspect = (double)cropped_width / (double)cropped_height; - int mod = job->modulus ? job->modulus : 16; - double aspect = title->aspect; - - int64_t pixel_aspect_width = job->anamorphic.par_width; - int64_t pixel_aspect_height = job->anamorphic.par_height; + int cropped_width = src_geo->width - ui_geo->crop[2] - ui_geo->crop[3]; + int cropped_height = src_geo->height - ui_geo->crop[0] - ui_geo->crop[1]; + double storage_aspect = (double)cropped_width / cropped_height; + int mod = ui_geo->modulus ? EVEN(ui_geo->modulus) : 16; + + // Use 64 bits to avoid overflow till the final hb_reduce() call + hb_reduce(&in_par.num, &in_par.den, ui_geo->par.num, ui_geo->par.den); + int64_t dst_par_num = in_par.num; + int64_t dst_par_den = in_par.den; + + hb_rational_t src_par = src_geo->par; /* If a source was really NTSC or PAL and the user specified ITU PAR values, replace the standard PAR values with the ITU broadcast ones. */ - if( title->width == 720 && job->anamorphic.itu_par ) + if (src_geo->width == 720 && ui_geo->itu_par) { // convert aspect to a scaled integer so we can test for 16:9 & 4:3 // aspect ratios ignoring insignificant differences in the LSBs of // the floating point representation. - int iaspect = aspect * 9.; + int iaspect = src_geo->width * src_par.num * 9. / + (src_geo->height * src_par.den); /* Handle ITU PARs */ - if (title->height == 480) + if (src_geo->height == 480) { /* It's NTSC */ if (iaspect == 16) { /* It's widescreen */ - pixel_aspect_width = 40; - pixel_aspect_height = 33; + dst_par_num = 40; + dst_par_den = 33; } else if (iaspect == 12) { /* It's 4:3 */ - pixel_aspect_width = 10; - pixel_aspect_height = 11; + dst_par_num = 10; + dst_par_den = 11; } } - else if (title->height == 576) + else if (src_geo->height == 576) { /* It's PAL */ - if(iaspect == 16) + if (iaspect == 16) { /* It's widescreen */ - pixel_aspect_width = 16; - pixel_aspect_height = 11; + dst_par_num = 16; + dst_par_den = 11; } else if (iaspect == 12) { /* It's 4:3 */ - pixel_aspect_width = 12; - pixel_aspect_height = 11; + dst_par_num = 12; + dst_par_den = 11; } } } - /* Figure out what width the source would display at. */ - int source_display_width = cropped_width * (double)pixel_aspect_width / - (double)pixel_aspect_height ; - /* 3 different ways of deciding output dimensions: - 1: Strict anamorphic, preserve source dimensions @@ -993,82 +994,135 @@ void hb_set_anamorphic_size( hb_job_t * job, int width, height; int maxWidth, maxHeight; - maxWidth = MULTIPLE_MOD_DOWN( job->maxWidth, mod ); - maxHeight = MULTIPLE_MOD_DOWN( job->maxHeight, mod ); + maxWidth = MULTIPLE_MOD_DOWN(ui_geo->maxWidth, mod); + maxHeight = MULTIPLE_MOD_DOWN(ui_geo->maxHeight, mod); + if (maxWidth && maxWidth < 32) + maxWidth = 32; + if (maxHeight && maxHeight < 32) + maxHeight = 32; - switch( job->anamorphic.mode ) + switch (ui_geo->mode) { - case 1: - /* Strict anamorphic */ - *output_width = MULTIPLE_MOD( cropped_width, 2 ); - *output_height = MULTIPLE_MOD( cropped_height, 2 ); - // adjust the source PAR for new width/height - // new PAR = source PAR * ( old width / new_width ) * ( new_height / old_height ) - pixel_aspect_width = (int64_t)title->pixel_aspect_width * cropped_width * (*output_height); - pixel_aspect_height = (int64_t)title->pixel_aspect_height * (*output_width) * cropped_height; - break; - - case 2: + case HB_ANAMORPHIC_NONE: + { + double par, cropped_sar, dar; + par = (double)src_geo->par.num / src_geo->par.den; + cropped_sar = (double)cropped_width / cropped_height; + dar = par * cropped_sar; + + /* "None" anamorphic. a.k.a. non-anamorphic + * - Uses mod-compliant dimensions, set by user + * - Allows users to set the either width *or* height + */ + if (keep_display_aspect) + { + if (!keep_height) + { + width = ui_geo->width; + height = MULTIPLE_MOD((int)(width / dar), mod); + } + else + { + height = ui_geo->height; + width = MULTIPLE_MOD((int)(height * dar), mod); + } + } + else + { + width = ui_geo->width; + height = ui_geo->height; + } + if (maxWidth && (width > maxWidth)) + { + width = maxWidth; + height = MULTIPLE_MOD((int)(width / dar), mod); + } + if (maxHeight && (height > maxHeight)) + { + height = maxHeight; + width = MULTIPLE_MOD((int)(height * dar), mod); + } + dst_par_num = dst_par_den = 1; + } break; + + default: + case HB_ANAMORPHIC_STRICT: + { + /* "Strict" anamorphic. + * - Uses mod2-compliant dimensions, + * - Forces title - crop dimensions + */ + width = MULTIPLE_MOD(cropped_width, 2); + height = MULTIPLE_MOD(cropped_height, 2); + + /* Adjust the output PAR for new width/height + * Film AR is the source display width / cropped source height. + * Output display width is the output height * film AR. + * Output PAR is the output display width / output storage width. + * + * i.e. + * source_display_width = cropped_width * source PAR + * AR = source_display_width / cropped_height; + * output_display_width = height * AR; + * par = output_display_width / width; + * + * When these terms are reduced, you get the following... + */ + dst_par_num = (int64_t)height * cropped_width * src_par.num; + dst_par_den = (int64_t)width * cropped_height * src_par.den; + } break; + + case HB_ANAMORPHIC_LOOSE: + { /* "Loose" anamorphic. - - Uses mod16-compliant dimensions, - - Allows users to set the width - */ - width = job->width; - // height: Gets set later, ignore user job->height value - - /* Gotta handle bounding dimensions. - If the width is too big, just reset it with no rescaling. - Instead of using the aspect-scaled job height, - we need to see if the job width divided by the storage aspect - is bigger than the max. If so, set it to the max (this is sloppy). - If not, set job height to job width divided by storage aspect. - */ - - /* Time to get picture width that divide cleanly.*/ - width = MULTIPLE_MOD( width, mod); - - if ( maxWidth && (maxWidth < job->width) ) - width = maxWidth; + * - Uses mod-compliant dimensions, set by user + * - Allows users to set the either width *or* height + */ + if (!keep_height) + { + width = MULTIPLE_MOD(ui_geo->width, mod); + height = MULTIPLE_MOD((int)(width / storage_aspect + 0.5), mod); + } + else + { + height = MULTIPLE_MOD(ui_geo->height, mod); + width = MULTIPLE_MOD((int)(height * storage_aspect + 0.5), mod); + } - /* Verify these new dimensions don't violate max height and width settings */ - height = ((double)width / storage_aspect) + 0.5; + if (maxWidth && (maxWidth < width)) + { + width = maxWidth; + height = MULTIPLE_MOD((int)(width / storage_aspect + 0.5), mod); + } - /* Time to get picture height that divide cleanly.*/ - height = MULTIPLE_MOD( height, mod); - - if ( maxHeight && (maxHeight < height) ) + if (maxHeight && (maxHeight < height)) { height = maxHeight; - width = ((double)height * storage_aspect) + 0.5; - width = MULTIPLE_MOD( width, mod); + width = MULTIPLE_MOD((int)(height * storage_aspect + 0.5), mod); } - /* The film AR is the source's display width / cropped source height. - The output display width is the output height * film AR. - The output PAR is the output display width / output storage width. */ - pixel_aspect_width = (int64_t)height * cropped_width * pixel_aspect_width; - pixel_aspect_height = (int64_t)width * cropped_height * pixel_aspect_height; - - /* Pass the results back to the caller */ - *output_width = width; - *output_height = height; - break; - - case 3: + /* Adjust the output PAR for new width/height + See comment in HB_ANAMORPHIC_STRICT */ + dst_par_num = (int64_t)height * cropped_width * src_par.num; + dst_par_den = (int64_t)width * cropped_height * src_par.den; + } break; + + case HB_ANAMORPHIC_CUSTOM: + { /* Anamorphic 3: Power User Jamboree - Set everything based on specified values */ - + /* Use specified storage dimensions */ - storage_aspect = (double)job->width / (double)job->height; - width = job->width; - height = job->height; - + storage_aspect = (double)ui_geo->width / ui_geo->height; + width = ui_geo->width; + height = ui_geo->height; + /* Time to get picture dimensions that divide cleanly.*/ - width = MULTIPLE_MOD( width, mod); - height = MULTIPLE_MOD( height, mod); - + width = MULTIPLE_MOD(width, mod); + height = MULTIPLE_MOD(height, mod); + /* Bind to max dimensions */ - if( maxWidth && width > maxWidth ) + if (maxWidth && width > maxWidth) { width = maxWidth; // If we are keeping the display aspect, then we are going @@ -1079,64 +1133,128 @@ void hb_set_anamorphic_size( hb_job_t * job, // But otherwise, PAR and DAR will change the least // if we stay as close as possible to the requested // storage aspect. - if ( !job->anamorphic.keep_display_aspect ) + if (!keep_display_aspect) { - height = ((double)width / storage_aspect) + 0.5; - height = MULTIPLE_MOD( height, mod); + height = width / storage_aspect + 0.5; + height = MULTIPLE_MOD(height, mod); } } - if( maxHeight && height > maxHeight ) + if (maxHeight && height > maxHeight) { height = maxHeight; // Ditto, see comment above - if ( !job->anamorphic.keep_display_aspect ) + if (!keep_display_aspect) { - width = ((double)height * storage_aspect) + 0.5; - width = MULTIPLE_MOD( width, mod); + width = height * storage_aspect + 0.5; + width = MULTIPLE_MOD(width, mod); } } - - /* That finishes the storage dimensions. On to display. */ - if( job->anamorphic.dar_width && job->anamorphic.dar_height ) + + /* That finishes the storage dimensions. On to display. */ + if (ui_geo->dar.num && ui_geo->dar.den) { /* We need to adjust the PAR to produce this aspect. */ - pixel_aspect_width = (int64_t)height * job->anamorphic.dar_width / job->anamorphic.dar_height; - pixel_aspect_height = width; + dst_par_num = (int64_t)height * ui_geo->dar.num / + ui_geo->dar.den; + dst_par_den = width; } else { - /* If we're doing ana 3 and not specifying a DAR, care needs to be taken. - This indicates a PAR is potentially being set by the interface. But - this is an output PAR, to correct a source, and it should not be assumed - that it properly creates a display aspect ratio when applied to the source, - which could easily be stored in a different resolution. */ - if( job->anamorphic.keep_display_aspect ) + if (keep_display_aspect) { - /* We can ignore the possibility of a PAR change */ - pixel_aspect_width = (int64_t)height * ( (double)source_display_width / (double)cropped_height ); - pixel_aspect_height = width; + /* We can ignore the possibility of a PAR change + * Adjust the output PAR for new width/height + * See comment in HB_ANAMORPHIC_STRICT + */ + dst_par_num = (int64_t)height * cropped_width * + src_par.num; + dst_par_den = (int64_t)width * cropped_height * + src_par.den; } else { - int output_display_width = width * (double)pixel_aspect_width / - (double)pixel_aspect_height; - pixel_aspect_width = output_display_width; - pixel_aspect_height = width; + /* If the dimensions were changed by the modulus + * or by maxWidth/maxHeight, we also change the + * output PAR so that the DAR is unchanged. + * + * PAR is the requested output display width / storage width + * requested output display width is the original + * requested width * original requested PAR + */ + dst_par_num = ui_geo->width * dst_par_num; + dst_par_den = width * dst_par_den; } } - - /* Back to caller */ - *output_width = width; - *output_height = height; - break; + } break; } - + + /* Pass the results back to the caller */ + result->width = width; + result->height = height; + /* While x264 is smart enough to reduce fractions on its own, libavcodec * needs some help with the math, so lose superfluous factors. */ - hb_limit_rational64( &pixel_aspect_width, &pixel_aspect_height, - pixel_aspect_width, pixel_aspect_height, 65535 ); - hb_reduce( output_par_width, output_par_height, - pixel_aspect_width, pixel_aspect_height ); + hb_limit_rational64(&dst_par_num, &dst_par_den, + dst_par_num, dst_par_den, 65535); + + /* If the user is directling updating PAR, don't override his values */ + hb_reduce(&out_par.num, &out_par.den, dst_par_num, dst_par_den); + if (ui_geo->mode == HB_ANAMORPHIC_CUSTOM && !keep_display_aspect && + out_par.num == in_par.num && out_par.den == in_par.den) + { + result->par.num = ui_geo->par.num; + result->par.den = ui_geo->par.den; + } + else + { + hb_reduce(&result->par.num, &result->par.den, dst_par_num, dst_par_den); + } +} + +/** + * Calculates job width and height for anamorphic content, + * + * @param job Handle to hb_job_t + * @param output_width Pointer to returned storage width + * @param output_height Pointer to returned storage height + * @param output_par_width Pointer to returned pixel width + * @param output_par_height Pointer to returned pixel height + */ +void hb_set_anamorphic_size( hb_job_t * job, + int *output_width, int *output_height, + int *output_par_width, int *output_par_height ) +{ + hb_geometry_t result; + hb_geometry_t src; + hb_ui_geometry_t ui_geo; + + src.width = job->title->width; + src.height = job->title->height; + src.par.num = job->title->pixel_aspect_width; + src.par.den = job->title->pixel_aspect_height; + + ui_geo.width = job->width; + ui_geo.height = job->height; + ui_geo.par.num = job->anamorphic.par_width; + ui_geo.par.den = job->anamorphic.par_height; + + ui_geo.modulus = job->modulus; + memcpy(ui_geo.crop, job->crop, sizeof(int[4])); + ui_geo.maxWidth = job->maxWidth; + ui_geo.maxHeight = job->maxHeight; + ui_geo.mode = job->anamorphic.mode; + ui_geo.keep = 0; + if (job->anamorphic.keep_display_aspect) + ui_geo.keep = HB_KEEP_DISPLAY_ASPECT; + ui_geo.itu_par = job->anamorphic.itu_par; + ui_geo.dar.num = job->anamorphic.dar_width; + ui_geo.dar.den = job->anamorphic.dar_height; + + hb_set_anamorphic_size2(&src, &ui_geo, &result); + *output_width = result.width; + *output_height = result.height; + *output_par_width = result.par.num; + *output_par_height = result.par.den; } /** diff --git a/libhb/hb.h b/libhb/hb.h index 6939d8082..e958d68d9 100644 --- a/libhb/hb.h +++ b/libhb/hb.h @@ -72,6 +72,9 @@ hb_buffer_t * hb_read_preview( hb_handle_t * h, int title_idx, int preview ); void hb_get_preview( hb_handle_t *, hb_job_t *, int, uint8_t * ); void hb_set_size( hb_job_t *, double ratio, int pixels ); +void hb_set_anamorphic_size2(hb_geometry_t *src_geo, + hb_ui_geometry_t *ui_geo, + hb_geometry_t *result); void hb_set_anamorphic_size( hb_job_t *, int *output_width, int *output_height, int *output_par_width, int *output_par_height ); diff --git a/macosx/HBPreviewController.m b/macosx/HBPreviewController.m index 9d9d2c6fd..d71f996c3 100644 --- a/macosx/HBPreviewController.m +++ b/macosx/HBPreviewController.m @@ -54,8 +54,9 @@ #endif #define BORDER_SIZE 2.0 -#define MIN_WIDTH 480.0 -#define MIN_HEIGHT 360.0 +// make min width and height of preview window large enough for hud +#define MIN_WIDTH 460.0 +#define MIN_HEIGHT 128.0 #define ANIMATION_DUR 0.2 @@ -356,13 +357,14 @@ typedef enum ViewMode : NSUInteger { */ - (void) resizeWindowForViewSize: (NSSize) viewSize { - // Figure out the deltas for the new frame area NSSize currentSize = [[[self window] contentView] frame].size; - CGFloat deltaX = viewSize.width - currentSize.width; - CGFloat deltaY = viewSize.height - currentSize.height; - - // Now resize the whole panel by those same deltas, but don't exceed the min NSRect frame = [[self window] frame]; + + // Calculate border around content region of the frame + int borderX = frame.size.width - currentSize.width; + int borderY = frame.size.height - currentSize.height; + + // Make sure the frame is smaller than the screen NSSize maxSize = [[[self window] screen] visibleFrame].size; /* if we are not Scale To Screen, put an 10% of visible screen on the window */ @@ -372,40 +374,22 @@ typedef enum ViewMode : NSUInteger { maxSize.height = maxSize.height * 0.90; } - /* Set our min size to the storage size */ - NSSize minSize; - minSize.width = self.title->width / self.backingScaleFactor; - minSize.height = self.title->height / self.backingScaleFactor; + // Set the new frame size + // Add the border to the new frame size so that the content region + // of the frame is large enough to accomodate the preview image + frame.size.width = viewSize.width + borderX; + frame.size.height = viewSize.height + borderY; - frame.size.width += deltaX; - frame.size.height += deltaY; - if( frame.size.width < minSize.width ) - { - frame.size.width = minSize.width; - deltaX = frame.size.width - currentSize.width; - } - if( frame.size.height < minSize.height ) - { - frame.size.height = minSize.height; - //deltaY = frame.size.height - currentSize.height; - } /* compare frame to max size of screen */ - if( frame.size.width > maxSize.width ) { frame.size.width = maxSize.width; } - if( frame.size.height > maxSize.height ) { frame.size.height = maxSize.height; } - // But now the sheet is off-center, so also shift the origin to center it and - // keep the top aligned. - if (frame.size.width != [[self window] frame].size.width) - frame.origin.x -= (deltaX / 2.0); - /* Since upon launch we can open up the preview window if it was open * the last time we quit (and at the size it was) we want to make * sure that upon resize we do not have the window off the screen @@ -414,14 +398,6 @@ typedef enum ViewMode : NSUInteger { */ NSSize screenSize = [[[self window] screen] visibleFrame].size; NSPoint screenOrigin = [[[self window] screen] visibleFrame].origin; - if (screenSize.height < frame.size.height) - { - frame.size.height = screenSize.height; - } - if (screenSize.width < frame.size.width) - { - frame.size.width = screenSize.width; - } /* our origin is off the screen to the left*/ if (frame.origin.x < screenOrigin.x) @@ -643,58 +619,36 @@ typedef enum ViewMode : NSUInteger { NSString *sizeInfoString; /* Set the picture size display fields below the Preview Picture*/ - int output_width, output_height, output_par_width, output_par_height; int display_width; + display_width = title->job->width * title->job->anamorphic.par_width / title->job->anamorphic.par_height; if( title->job->anamorphic.mode == 1 ) // Original PAR Implementation { - output_width = title->width-title->job->crop[2]-title->job->crop[3]; - output_height = title->height-title->job->crop[0]-title->job->crop[1]; - display_width = output_width * title->job->anamorphic.par_width / title->job->anamorphic.par_height; sizeInfoString = [NSString stringWithFormat: @"Source: %dx%d, Output: %dx%d, Anamorphic: %dx%d Strict", - title->width, title->height, output_width, output_height, display_width, output_height]; - - displaySize.width = display_width; - displaySize.height = title->height; - imageScaledSize.width = display_width; - imageScaledSize.height = output_height; + title->width, title->height, title->job->width, title->job->height, display_width, title->job->height]; } else if (title->job->anamorphic.mode == 2) // Loose Anamorphic { - hb_set_anamorphic_size(title->job, &output_width, &output_height, &output_par_width, &output_par_height); - display_width = output_width * output_par_width / output_par_height; sizeInfoString = [NSString stringWithFormat: @"Source: %dx%d, Output: %dx%d, Anamorphic: %dx%d Loose", - title->width, title->height, output_width, output_height, display_width, output_height]; - - displaySize.width = display_width; - displaySize.height = title->height; - imageScaledSize.width = display_width; - imageScaledSize.height = output_height; + title->width, title->height, title->job->width, title->job->height, display_width, title->job->height]; } else if (title->job->anamorphic.mode == 3) // Custom Anamorphic { - hb_set_anamorphic_size(title->job, &output_width, &output_height, &output_par_width, &output_par_height); sizeInfoString = [NSString stringWithFormat: @"Source: %dx%d, Output: %dx%d, Anamorphic: %dx%d Custom", - title->width, title->height, output_width, output_height, title->job->anamorphic.dar_width, title->job->anamorphic.dar_height]; - - displaySize.width = title->job->anamorphic.dar_width + title->job->crop[2] + title->job->crop[3] ; - displaySize.height = title->job->anamorphic.dar_height + title->job->crop[0] + title->job->crop[1]; - imageScaledSize.width = (int)title->job->anamorphic.dar_width; - imageScaledSize.height = (int)title->job->height; + title->width, title->height, title->job->width, title->job->height, display_width, title->job->height]; } else // No Anamorphic { sizeInfoString = [NSString stringWithFormat: - @"Source: %dx%d, Output: %dx%d", title->width, title->height, - title->job->width, title->job->height]; - - displaySize.width = title->width; - displaySize.height = title->height; - imageScaledSize.width = title->job->width; - imageScaledSize.height = title->job->height; + @"Source: %dx%d, Output: %dx%d", + title->width, title->height, title->job->width, title->job->height]; } + displaySize.width = display_width; + displaySize.height = title->job->height; + imageScaledSize.width = display_width; + imageScaledSize.height = title->job->height; if (self.backingScaleFactor != 1.0) { diff --git a/macosx/PictureController.m b/macosx/PictureController.m index 7bf9bf404..2387f689d 100644 --- a/macosx/PictureController.m +++ b/macosx/PictureController.m @@ -46,25 +46,9 @@ IBOutlet NSTextField * fParWidthLabel; IBOutlet NSTextField * fParHeightLabel; - /* for now we setup some values to remember our pars and dars - * from scan - */ - int titleParWidth; - int titleParHeight; - float dar; - IBOutlet NSPopUpButton * fAnamorphicPopUp; IBOutlet NSTextField * fSizeInfoField; - int output_width, output_height, output_par_width, output_par_height; - int display_width; - - /* used to track the previous state of the keep aspect - ratio checkbox when turning anamorphic on, so it can be - returned to the previous state when anamorphic is turned - off */ - BOOL keepAspectRatioPreviousState; - /* Video Filters */ IBOutlet NSBox * fDetelecineBox; IBOutlet NSPopUpButton * fDetelecinePopUp; @@ -208,35 +192,49 @@ fTitle = title; - [fWidthStepper setMaxValue: title->width]; - [fWidthStepper setIntValue: job->width]; - [fWidthField setIntValue: job->width]; - [fHeightStepper setMaxValue: title->height]; - [fHeightStepper setIntValue: job->height]; - [fHeightField setIntValue: job->height]; - [fRatioCheck setState: job->keep_ratio ? NSOnState : NSOffState]; - [fCropTopStepper setMaxValue: title->height/2-2]; - [fCropBottomStepper setMaxValue: title->height/2-2]; - [fCropLeftStepper setMaxValue: title->width/2-2]; - [fCropRightStepper setMaxValue: title->width/2-2]; - [fAnamorphicPopUp selectItemAtIndex: job->anamorphic.mode]; + if (job->anamorphic.mode == HB_ANAMORPHIC_STRICT) + { + [fWidthStepper setEnabled: NO]; + [fHeightStepper setEnabled: NO]; + } + else + { + [fWidthStepper setEnabled: YES]; + [fHeightStepper setEnabled: YES]; + } + if (job->anamorphic.mode == HB_ANAMORPHIC_STRICT || + job->anamorphic.mode == HB_ANAMORPHIC_LOOSE) + { + job->anamorphic.keep_display_aspect = 1; + [fRatioCheck setState: NSOnState]; + [fRatioCheck setEnabled: NO]; + } + else + { + [fRatioCheck setEnabled: YES]; + [fRatioCheck setState: job->anamorphic.keep_display_aspect ? + NSOnState : NSOffState]; + } + [fParWidthField setEnabled: !job->anamorphic.keep_display_aspect]; + [fParHeightField setEnabled: !job->anamorphic.keep_display_aspect]; + [fDisplayWidthField setEnabled: !job->anamorphic.keep_display_aspect]; if (job->modulus) { [fModulusPopUp selectItemWithTitle: [NSString stringWithFormat:@"%d",job->modulus]]; + [fWidthStepper setIncrement: job->modulus]; + [fHeightStepper setIncrement: job->modulus]; } else { [fModulusPopUp selectItemAtIndex: 0]; + [fWidthStepper setIncrement: 16]; + [fHeightStepper setIncrement: 16]; } - - /* We initially set the previous state of keep ar to on */ - keepAspectRatioPreviousState = 1; - if (!self.autoCrop) - { + if (!self.autoCrop) + { [fCropMatrix selectCellAtRow: 1 column:0]; - /* If auto, lets set the crop steppers according to current job->crop values */ [fCropTopStepper setIntValue: job->crop[0]]; [fCropTopField setIntValue: job->crop[0]]; [fCropBottomStepper setIntValue: job->crop[1]]; @@ -245,11 +243,47 @@ [fCropLeftField setIntValue: job->crop[2]]; [fCropRightStepper setIntValue: job->crop[3]]; [fCropRightField setIntValue: job->crop[3]]; - } - else - { + } + else + { [fCropMatrix selectCellAtRow: 0 column:0]; - } + + [fCropTopStepper setEnabled: !self.autoCrop]; + [fCropBottomStepper setEnabled: !self.autoCrop]; + [fCropLeftStepper setEnabled: !self.autoCrop]; + [fCropRightStepper setEnabled: !self.autoCrop]; + + /* If auto, lets set the crop steppers according to + * current fTitle->crop values */ + memcpy( job->crop, fTitle->crop, 4 * sizeof( int ) ); + [fCropTopStepper setIntValue: fTitle->crop[0]]; + [fCropTopField setIntValue: fTitle->crop[0]]; + [fCropBottomStepper setIntValue: fTitle->crop[1]]; + [fCropBottomField setIntValue: fTitle->crop[1]]; + [fCropLeftStepper setIntValue: fTitle->crop[2]]; + [fCropLeftField setIntValue: fTitle->crop[2]]; + [fCropRightStepper setIntValue: fTitle->crop[3]]; + [fCropRightField setIntValue: fTitle->crop[3]]; + } + [fWidthStepper setMaxValue: title->width - job->crop[2] - job->crop[3]]; + [fWidthStepper setIntValue: job->width]; + [fWidthField setIntValue: job->width]; + [fHeightStepper setMaxValue: title->height - job->crop[0] - job->crop[1]]; + [fHeightStepper setIntValue: job->height]; + [fHeightField setIntValue: job->height]; + [fCropTopStepper setMaxValue: title->height/2-2]; + [fCropBottomStepper setMaxValue: title->height/2-2]; + [fCropLeftStepper setMaxValue: title->width/2-2]; + [fCropRightStepper setMaxValue: title->width/2-2]; + + [fParWidthField setIntValue: job->anamorphic.par_width]; + [fParHeightField setIntValue: job->anamorphic.par_height]; + + int display_width; + display_width = job->width * job->anamorphic.par_width / + job->anamorphic.par_height; + [fDisplayWidthField setIntValue: display_width]; + /* Set filters widgets according to the filters struct */ [fDetelecinePopUp selectItemAtIndex:self.detelecine]; @@ -261,9 +295,6 @@ [self deblockSliderChanged: nil]; - titleParWidth = job->anamorphic.par_width; - titleParHeight = job->anamorphic.par_height; - [fPreviewController setTitle:title]; [self FilterSettingsChanged:nil]; @@ -334,8 +365,8 @@ NSSize pictureCropBoxSize = [fPictureCropBox frame].size; NSPoint fPictureCropBoxOrigin = [fPictureCropBox frame].origin; - if ([fAnamorphicPopUp indexOfSelectedItem] == 3) // custom / power user jamboree - { + if ([fAnamorphicPopUp indexOfSelectedItem] == HB_ANAMORPHIC_CUSTOM) + { // custom / power user jamboree pictureSizingBoxSize.width = 350; /* Set visibility of capuj widgets */ @@ -360,13 +391,16 @@ } /* Check to see if we have changed the size from current */ - if (pictureSizingBoxSize.height != [fPictureSizeBox frame].size.height || pictureSizingBoxSize.width != [fPictureSizeBox frame].size.width) + if (pictureSizingBoxSize.height != [fPictureSizeBox frame].size.height || + pictureSizingBoxSize.width != [fPictureSizeBox frame].size.width) { /* Get our delta for the change in picture size box height */ - CGFloat deltaYSizeBoxShift = pictureSizingBoxSize.height - [fPictureSizeBox frame].size.height; + CGFloat deltaYSizeBoxShift = pictureSizingBoxSize.height - + [fPictureSizeBox frame].size.height; fPictureSizeBoxOrigin.y -= deltaYSizeBoxShift; /* Get our delta for the change in picture size box width */ - CGFloat deltaXSizeBoxShift = pictureSizingBoxSize.width - [fPictureSizeBox frame].size.width; + CGFloat deltaXSizeBoxShift = pictureSizingBoxSize.width - + [fPictureSizeBox frame].size.width; //fPictureSizeBoxOrigin.x += deltaXSizeBoxShift; /* set our new Picture size box size */ [fPictureSizeBox setFrameSize:pictureSizingBoxSize]; @@ -582,409 +616,174 @@ return; hb_job_t * job = fTitle->job; + int keep = 0, dar_updated = 0; - /* if we are anything but strict anamorphic */ - if ([fAnamorphicPopUp indexOfSelectedItem] != 1) + if (sender == fAnamorphicPopUp) { - [fModulusLabel setHidden:NO]; - [fModulusPopUp setHidden:NO]; - if (sender == fModulusPopUp) + job->anamorphic.mode = (int)[fAnamorphicPopUp indexOfSelectedItem]; + if (job->anamorphic.mode == HB_ANAMORPHIC_STRICT) { - /* do a dry run with hb_fix aspect to get new modulus */ - job->modulus = [[fModulusPopUp titleOfSelectedItem] intValue]; - job->keep_ratio = 1; - hb_fix_aspect( job, HB_KEEP_WIDTH ); - if( job->height > fTitle->height ) - { - job->height = fTitle->height; - hb_fix_aspect( job, HB_KEEP_HEIGHT ); - } - [fWidthStepper setIntValue: job->width]; - [fWidthField setIntValue: job->width]; - if( [fAnamorphicPopUp indexOfSelectedItem] != 2) // if we are not loose or custom - { - [fHeightStepper setIntValue: job->height]; - [fHeightField setIntValue: job->height]; - } + [fModulusLabel setHidden: YES]; + [fModulusPopUp setHidden: YES]; + [fWidthStepper setEnabled: NO]; + [fHeightStepper setEnabled: NO]; + } + else + { + [fModulusLabel setHidden: NO]; + [fModulusPopUp setHidden: NO]; + [fWidthStepper setEnabled: YES]; + [fHeightStepper setEnabled: YES]; + } + if (job->anamorphic.mode == HB_ANAMORPHIC_STRICT || + job->anamorphic.mode == HB_ANAMORPHIC_LOOSE) + { + job->anamorphic.keep_display_aspect = 1; + [fRatioCheck setState: NSOnState]; + [fRatioCheck setEnabled: NO]; + } + else + { + [fRatioCheck setEnabled: YES]; + [fRatioCheck setState: job->anamorphic.keep_display_aspect ? + NSOnState : NSOffState]; } } - else + else if (sender == fModulusPopUp) { - /* we are strict so hide the mod popup since libhb uses mod 2 for strict anamorphic*/ - [fModulusLabel setHidden:YES]; - [fModulusPopUp setHidden:YES]; + job->modulus = [[fModulusPopUp titleOfSelectedItem] intValue]; + [fWidthStepper setIncrement: job->modulus]; + [fHeightStepper setIncrement: job->modulus]; } - job->modulus = [[fModulusPopUp titleOfSelectedItem] intValue]; - - [fWidthStepper setIncrement: job->modulus]; - [fHeightStepper setIncrement: job->modulus]; - - /* Since custom anamorphic allows for a height setting > fTitle->height - * check to make sure it is returned to fTitle->height for all other modes - */ - [fHeightStepper setMaxValue: fTitle->height]; - - self.autoCrop = ( [fCropMatrix selectedRow] == 0 ); - [fCropTopStepper setEnabled: !self.autoCrop]; - [fCropBottomStepper setEnabled: !self.autoCrop]; - [fCropLeftStepper setEnabled: !self.autoCrop]; - [fCropRightStepper setEnabled: !self.autoCrop]; - - if( self.autoCrop ) + if (sender == fRatioCheck) { - memcpy( job->crop, fTitle->crop, 4 * sizeof( int ) ); + job->anamorphic.keep_display_aspect = [fRatioCheck state] == NSOnState; + [fParWidthField setEnabled: !job->anamorphic.keep_display_aspect]; + [fParHeightField setEnabled: !job->anamorphic.keep_display_aspect]; + [fDisplayWidthField setEnabled: !job->anamorphic.keep_display_aspect]; } - else + + if (sender == fHeightStepper) { - job->crop[0] = [fCropTopStepper intValue]; - job->crop[1] = [fCropBottomStepper intValue]; - job->crop[2] = [fCropLeftStepper intValue]; - job->crop[3] = [fCropRightStepper intValue]; + keep |= HB_KEEP_HEIGHT; + job->height = [fHeightStepper intValue]; } - [fRatioCheck setEnabled: YES]; - - [fParWidthField setEnabled: NO]; - [fParHeightField setEnabled: NO]; - [fDisplayWidthField setEnabled: NO]; - - /* If we are not custom anamorphic, make sure we retain the orginal par */ - if( [fAnamorphicPopUp indexOfSelectedItem] != 3 ) + if (sender == fWidthStepper) { - job->anamorphic.par_width = titleParWidth; - job->anamorphic.par_height = titleParHeight; - [fRatioLabel setHidden: NO]; + keep |= HB_KEEP_WIDTH; + job->width = [fWidthStepper intValue]; } - if( [fAnamorphicPopUp indexOfSelectedItem] > 0 ) - { - if ([fAnamorphicPopUp indexOfSelectedItem] == 1) // strict - { - [fWidthStepper setIntValue: fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]]; - [fWidthField setIntValue: fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]]; - - /* This will show correct anamorphic height values, but - show distorted preview picture ratio */ - [fHeightStepper setIntValue: fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1]]; - [fHeightField setIntValue: fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1]]; - job->width = [fWidthStepper intValue]; - job->height = [fHeightStepper intValue]; - - job->anamorphic.mode = 1; - [fWidthStepper setEnabled: NO]; - [fWidthField setEnabled: NO]; - [fHeightStepper setEnabled: NO]; - [fHeightField setEnabled: NO]; - [fRatioCheck setEnabled: NO]; - } - else if ([fAnamorphicPopUp indexOfSelectedItem] == 2) // Loose anamorphic - { - job->anamorphic.mode = 2; - [fWidthStepper setEnabled: YES]; - [fWidthField setEnabled: YES]; - [fRatioCheck setEnabled: NO]; - [fHeightStepper setEnabled: NO]; - [fHeightField setEnabled: NO]; - /* We set job->width and call hb_set_anamorphic_size in libhb to do a "dry run" to get - * the values to be used by libhb for loose anamorphic - */ - /* if the sender is the anamorphic popup, then we know that loose anamorphic has just - * been turned on, so snap the width to full width for the source. - */ - if (sender == fAnamorphicPopUp) - { - [fWidthStepper setIntValue: fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]]; - [fWidthField setIntValue: fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]]; - } - job->width = [fWidthStepper intValue]; - hb_set_anamorphic_size(job, &output_width, &output_height, &output_par_width, &output_par_height); - [fHeightStepper setIntValue: output_height]; - [fHeightField setIntValue: output_height]; - job->height = [fHeightStepper intValue]; - - } - else if ([fAnamorphicPopUp indexOfSelectedItem] == 3) // custom / power user jamboree - { - job->anamorphic.mode = 3; - - /* Set the status of our custom ana only widgets accordingly */ - [fModulusPopUp setEnabled:YES]; - - [fWidthStepper setEnabled: YES]; - [fWidthField setEnabled: YES]; - - [fHeightStepper setEnabled: YES]; - /* for capuj the storage field is immaterial */ - [fHeightField setEnabled: YES]; - - [fRatioCheck setEnabled: YES]; - if (sender == fRatioCheck) - { - if ([fRatioCheck state] == NSOnState) - { - [fParWidthField setEnabled: NO]; - [fParHeightField setEnabled: NO]; - } - else - { - [fParWidthField setEnabled: YES]; - [fParHeightField setEnabled: YES]; - } - } - - [fParWidthField setEnabled: YES]; - [fParHeightField setEnabled: YES]; - - [fDisplayWidthField setEnabled: YES]; - - - /* If we are coming into custom anamorphic we reset the par to original - * which gives us a way back if things get hosed up. - */ - - if (sender == fAnamorphicPopUp) - { - /* When entering custom anamorphic, we start with keep ar on */ - [fRatioCheck setState: NSOnState]; - /* - KEEPING ASPECT RATIO - Disable editing: PIXEL WIDTH, PIXEL HEIGHT - */ - [fParWidthField setEnabled: NO]; - [fParHeightField setEnabled: NO]; - - job->width = [fWidthStepper intValue]; - job->height = [fHeightStepper intValue]; - - /* make sure our par is set back to original */ - job->anamorphic.par_width = titleParWidth; - job->anamorphic.par_height = titleParHeight; - - [fParWidthField setIntValue: titleParWidth]; - [fParHeightField setIntValue: titleParHeight]; - - /* modify our par dims from our storage dims */ - hb_set_anamorphic_size(job, &output_width, &output_height, &output_par_width, &output_par_height); - float par_display_width = (float)output_width * (float)output_par_width / (float)output_par_height; - - /* go ahead and mod the display dims */ - [fDisplayWidthField setStringValue: [NSString stringWithFormat:@"%.2f", par_display_width]]; - - job->anamorphic.dar_width = [fDisplayWidthField floatValue]; - job->anamorphic.dar_height = (float)[fHeightStepper intValue]; - - /* Set our dar here assuming we are just coming into capuj mode */ - dar = [fDisplayWidthField floatValue] / (float)[fHeightField intValue]; - - } - - /* For capuj we disable these fields if we are keeping the dispay aspect */ - if ([fRatioCheck state] == NSOnState) - { - /* - KEEPING ASPECT RATIO - DAR = DISPLAY WIDTH / DISPLAY HEIGHT (cache after every modification) */ - /*Disable editing: PIXEL WIDTH, PIXEL HEIGHT */ - - [fParWidthField setEnabled: NO]; - [fParHeightField setEnabled: NO]; - - /* Changing DISPLAY WIDTH: */ - if (sender == fDisplayWidthField) - { - job->anamorphic.dar_width = [fDisplayWidthField floatValue]; - /* Changes HEIGHT to keep DAR */ - /* calculate the height to retain the dar */ - int raw_calulated_height = (int)((int)[fDisplayWidthField floatValue] / dar); - /* now use the modulus to go lower if there is a remainder */ - /* Note to me, raw_calulated_height % [[fModulusPopUp titleOfSelectedItem] intValue] - * gives me the remainder we are not mod (whatever our modulus is) subtract that from - * the actual calculated value derived from the dar to round down to the nearest mod value. - * This should be desireable over rounding up to the next mod value - */ - int modulus_height = raw_calulated_height - (raw_calulated_height % [[fModulusPopUp titleOfSelectedItem] intValue]); - if (modulus_height > fTitle->height) - { - [fHeightStepper setMaxValue: modulus_height]; - } - [fHeightStepper setIntValue: modulus_height]; - job->anamorphic.dar_height = (float)[fHeightStepper intValue]; - job->height = [fHeightStepper intValue]; - - /* Changes PIXEL WIDTH to new DISPLAY WIDTH */ - [fParWidthField setIntValue: [fDisplayWidthField intValue]]; - job->anamorphic.par_width = [fParWidthField intValue]; - /* Changes PIXEL HEIGHT to STORAGE WIDTH */ - [fParHeightField setIntValue: [fWidthField intValue]]; - job->anamorphic.par_height = [fParHeightField intValue]; - - } - /* Changing HEIGHT: */ - if (sender == fHeightStepper) - { - job->anamorphic.dar_height = (float)[fHeightStepper intValue]; - job->height = [fHeightStepper intValue]; - - /* Changes DISPLAY WIDTH to keep DAR*/ - [fDisplayWidthField setStringValue: [NSString stringWithFormat: @"%.2f",[fHeightStepper intValue] * dar]]; - job->anamorphic.dar_width = [fDisplayWidthField floatValue]; - /* Changes PIXEL WIDTH to new DISPLAY WIDTH */ - [fParWidthField setIntValue: [fDisplayWidthField intValue]]; - job->anamorphic.par_width = [fParWidthField intValue]; - /* Changes PIXEL HEIGHT to STORAGE WIDTH */ - [fParHeightField setIntValue: [fWidthField intValue]]; - job->anamorphic.par_height = [fParHeightField intValue]; - } - /* Changing STORAGE_WIDTH: */ - if (sender == fWidthStepper) - { - job->width = [fWidthStepper intValue]; - - job->anamorphic.dar_width = [fDisplayWidthField floatValue]; - job->anamorphic.dar_height = [fHeightStepper floatValue]; - - /* Changes PIXEL WIDTH to DISPLAY WIDTH */ - [fParWidthField setIntValue: [fDisplayWidthField intValue]]; - job->anamorphic.par_width = [fParWidthField intValue]; - /* Changes PIXEL HEIGHT to new STORAGE WIDTH */ - [fParHeightField setIntValue: [fWidthStepper intValue]]; - job->anamorphic.par_height = [fParHeightField intValue]; - } - } - else if ([fRatioCheck state] == NSOffState) - { - /* Changing STORAGE_WIDTH: */ - if (sender == fWidthStepper) - { - job->width = [fWidthStepper intValue]; - /* changes DISPLAY WIDTH to STORAGE WIDTH * PIXEL WIDTH / PIXEL HEIGHT */ - [fDisplayWidthField setStringValue: [NSString stringWithFormat: @"%.2f",(float)[fWidthStepper intValue] * [fParWidthField intValue] / [fParHeightField intValue]]]; - job->anamorphic.dar_width = [fDisplayWidthField floatValue]; - } - /* Changing PIXEL dimensions */ - if (sender == fParWidthField || sender == fParHeightField) - { - job->anamorphic.par_width = [fParWidthField intValue]; - job->anamorphic.par_height = [fParHeightField intValue]; - /* changes DISPLAY WIDTH to STORAGE WIDTH * PIXEL WIDTH / PIXEL HEIGHT */ - [fDisplayWidthField setStringValue: [NSString stringWithFormat: @"%.2f",(float)[fWidthStepper intValue] * [fParWidthField intValue] / [fParHeightField intValue]]]; - job->anamorphic.dar_width = [fDisplayWidthField floatValue]; - } - /* Changing DISPLAY WIDTH: */ - if (sender == fDisplayWidthField) - { - job->anamorphic.dar_width = [fDisplayWidthField floatValue]; - job->anamorphic.dar_height = (float)[fHeightStepper intValue]; - /* changes PIXEL WIDTH to DISPLAY WIDTH and PIXEL HEIGHT to STORAGE WIDTH */ - [fParWidthField setIntValue: [fDisplayWidthField intValue]]; - job->anamorphic.par_width = [fParWidthField intValue]; - - [fParHeightField setIntValue: [fWidthField intValue]]; - job->anamorphic.par_height = [fParHeightField intValue]; - hb_set_anamorphic_size(job, &output_width, &output_height, &output_par_width, &output_par_height); - } - /* Changing HEIGHT: */ - if (sender == fHeightStepper) - { - /* just....changes the height.*/ - job->anamorphic.dar_height = [fHeightStepper intValue]; - job->height = [fHeightStepper intValue]; - } - - } - } - - /* if the sender is the Anamorphic checkbox, record the state - of KeepAspect Ratio so it can be reset if Anamorphic is unchecked again */ - if (sender == fAnamorphicPopUp) - { - keepAspectRatioPreviousState = [fRatioCheck state]; - } - if ([fAnamorphicPopUp indexOfSelectedItem] != 3) - { - [fRatioCheck setState:NSOffState]; - } + if (sender == fParWidthField || sender == fParHeightField) + { + job->anamorphic.par_width = [fParWidthField intValue]; + job->anamorphic.par_height = [fParHeightField intValue]; + } + if (sender == fDisplayWidthField) + { + dar_updated = 1; + job->anamorphic.dar_width = [fDisplayWidthField intValue]; + job->anamorphic.dar_height = [fHeightStepper intValue]; } - else - { - job->width = [fWidthStepper intValue]; - job->height = [fHeightStepper intValue]; - job->anamorphic.mode = 0; - [fWidthStepper setEnabled: YES]; - [fWidthField setEnabled: YES]; - [fHeightStepper setEnabled: YES]; - [fHeightField setEnabled: YES]; - [fRatioCheck setEnabled: YES]; - /* if the sender is the Anamorphic checkbox, we return the - keep AR checkbox to its previous state */ - if (sender == fAnamorphicPopUp) - { - [fRatioCheck setState:keepAspectRatioPreviousState]; - } - } - if ([fAnamorphicPopUp indexOfSelectedItem] != 3) + if (sender == fCropMatrix) { - job->keep_ratio = ( [fRatioCheck state] == NSOnState ); - if( job->keep_ratio ) + if (self.autoCrop != ( [fCropMatrix selectedRow] == 0 )) { - if( sender == fWidthStepper || sender == fRatioCheck || - sender == fCropTopStepper || sender == fCropBottomStepper|| - sender == fCropMatrix || sender == nil ) - { - hb_fix_aspect( job, HB_KEEP_WIDTH ); - if( job->height > fTitle->height ) - { - job->height = fTitle->height; - hb_fix_aspect( job, HB_KEEP_HEIGHT ); - } - } - else + self.autoCrop = !self.autoCrop; + if (self.autoCrop) { - hb_fix_aspect( job, HB_KEEP_HEIGHT ); - if( job->width > fTitle->width ) - { - job->width = fTitle->width; - hb_fix_aspect( job, HB_KEEP_WIDTH ); - } + /* If auto, lets set the crop steppers according to + * current fTitle->crop values */ + memcpy( job->crop, fTitle->crop, 4 * sizeof( int ) ); + [fCropTopStepper setIntValue: fTitle->crop[0]]; + [fCropTopField setIntValue: fTitle->crop[0]]; + [fCropBottomStepper setIntValue: fTitle->crop[1]]; + [fCropBottomField setIntValue: fTitle->crop[1]]; + [fCropLeftStepper setIntValue: fTitle->crop[2]]; + [fCropLeftField setIntValue: fTitle->crop[2]]; + [fCropRightStepper setIntValue: fTitle->crop[3]]; + [fCropRightField setIntValue: fTitle->crop[3]]; } - + [fCropTopStepper setEnabled: !self.autoCrop]; + [fCropBottomStepper setEnabled: !self.autoCrop]; + [fCropLeftStepper setEnabled: !self.autoCrop]; + [fCropRightStepper setEnabled: !self.autoCrop]; } } - - // hb_get_preview can't handle sizes that are larger than the original title - if ([fAnamorphicPopUp indexOfSelectedItem] != 3) + if (sender == fCropTopStepper) { - // dimensions - if( job->width > fTitle->width ) - { - job->width = fTitle->width; - } - - if( job->height > fTitle->height ) - { - job->height = fTitle->height; - } + job->crop[0] = [fCropTopStepper intValue]; + [fCropTopField setIntValue: job->crop[0]]; + [fHeightStepper setMaxValue: fTitle->height - job->crop[0] - job->crop[1]]; + } + if (sender == fCropBottomStepper) + { + job->crop[1] = [fCropBottomStepper intValue]; + [fCropBottomField setIntValue: job->crop[1]]; + [fHeightStepper setMaxValue: fTitle->height - job->crop[0] - job->crop[1]]; + } + if (sender == fCropLeftStepper) + { + job->crop[2] = [fCropLeftStepper intValue]; + [fCropLeftField setIntValue: job->crop[2]]; + [fWidthStepper setMaxValue: fTitle->width - job->crop[2] - job->crop[3]]; + } + if (sender == fCropRightStepper) + { + job->crop[3] = [fCropRightStepper intValue]; + [fCropRightField setIntValue: job->crop[3]]; + [fWidthStepper setMaxValue: fTitle->width - job->crop[2] - job->crop[3]]; } - [fWidthStepper setIntValue: job->width]; - [fWidthField setIntValue: job->width]; - if( [fAnamorphicPopUp indexOfSelectedItem] != 2) // if we are not loose or custom + keep |= !!job->anamorphic.keep_display_aspect * HB_KEEP_DISPLAY_ASPECT; + + hb_geometry_t srcGeo, resultGeo; + hb_ui_geometry_t uiGeo; + + srcGeo.width = fTitle->width; + srcGeo.height = fTitle->height; + srcGeo.par.num = fTitle->pixel_aspect_width; + srcGeo.par.den = fTitle->pixel_aspect_height; + + uiGeo.mode = job->anamorphic.mode; + uiGeo.keep = keep; + uiGeo.itu_par = 0; + uiGeo.modulus = job->modulus; + memcpy(uiGeo.crop, job->crop, sizeof(int[4])); + uiGeo.width = job->width; + uiGeo.height = job->height; + uiGeo.maxWidth = fTitle->width - job->crop[2] - job->crop[3]; + uiGeo.maxHeight = fTitle->height - job->crop[0] - job->crop[1]; + uiGeo.par.num = job->anamorphic.par_width; + uiGeo.par.den = job->anamorphic.par_height; + uiGeo.dar.num = 0; + uiGeo.dar.den = 0; + if (job->anamorphic.mode == HB_ANAMORPHIC_CUSTOM && dar_updated) { - [fHeightStepper setIntValue: job->height]; - [fHeightField setIntValue: job->height]; + uiGeo.dar.num = job->anamorphic.dar_width; + uiGeo.dar.den = job->anamorphic.dar_height; } + hb_set_anamorphic_size2(&srcGeo, &uiGeo, &resultGeo); - [fCropTopStepper setIntValue: job->crop[0]]; - [fCropTopField setIntValue: job->crop[0]]; - [fCropBottomStepper setIntValue: job->crop[1]]; - [fCropBottomField setIntValue: job->crop[1]]; - [fCropLeftStepper setIntValue: job->crop[2]]; - [fCropLeftField setIntValue: job->crop[2]]; - [fCropRightStepper setIntValue: job->crop[3]]; - [fCropRightField setIntValue: job->crop[3]]; + job->width = resultGeo.width; + job->height = resultGeo.height; + job->anamorphic.par_width = resultGeo.par.num; + job->anamorphic.par_height = resultGeo.par.den; + + int display_width; + display_width = resultGeo.width * resultGeo.par.num / resultGeo.par.den; + + [fWidthStepper setIntValue: resultGeo.width]; + [fWidthField setIntValue: resultGeo.width]; + [fHeightStepper setIntValue: resultGeo.height]; + [fHeightField setIntValue: resultGeo.height]; + [fParWidthField setIntValue: resultGeo.par.num]; + [fParHeightField setIntValue: resultGeo.par.den]; + [fDisplayWidthField setIntValue: display_width]; /* * Sanity-check here for previews < 16 pixels to avoid crashing |