From: Bradley Sepos Date: Thu, 1 Jun 2017 18:20:10 +0000 (-0400) Subject: mac: Add support for sharpening filters. (#760) X-Git-Tag: 1.1.0~553 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ce086e0db9813a093fcb89cd135d5313fdb8d550;p=handbrake mac: Add support for sharpening filters. (#760) Thanks @galad87 for assistance. --- diff --git a/macosx/English.lproj/HBPictureViewController.xib b/macosx/English.lproj/HBPictureViewController.xib index 1de8a06b8..30305d7ba 100644 --- a/macosx/English.lproj/HBPictureViewController.xib +++ b/macosx/English.lproj/HBPictureViewController.xib @@ -1,9 +1,9 @@ - + - + @@ -85,7 +85,7 @@ Custom allows for manual settings. - + @@ -117,7 +117,7 @@ Custom allows for manual settings. - + @@ -174,7 +174,7 @@ Custom allows for manual settings. - + @@ -231,7 +231,7 @@ Custom allows for manual settings. - + @@ -243,7 +243,7 @@ Custom allows for manual settings. - + @@ -275,12 +275,12 @@ Custom allows for manual settings. - - + + - - + + @@ -291,8 +291,8 @@ Custom allows for manual settings. - - + + @@ -308,8 +308,8 @@ Custom allows for manual settings. - - + + Detelecine removes comb artifacts that are the result of telecine, a process for converting film frame rates to television frame rates. @@ -333,8 +333,8 @@ Custom allows for manual settings. - - + + Custom Detelecine parameters. @@ -356,8 +356,8 @@ Default: skip-left=1:skip-right=1:skip-top=4:skip-bottom=4:plane=0 - - + + @@ -368,8 +368,8 @@ Default: skip-left=1:skip-right=1:skip-top=4:skip-bottom=4:plane=0 - - + + @@ -380,8 +380,8 @@ Default: skip-left=1:skip-right=1:skip-top=4:skip-bottom=4:plane=0 - - + + @@ -392,8 +392,8 @@ Default: skip-left=1:skip-right=1:skip-top=4:skip-bottom=4:plane=0 - - + + @@ -408,8 +408,8 @@ Default: skip-left=1:skip-right=1:skip-top=4:skip-bottom=4:plane=0 - - + + @@ -422,8 +422,8 @@ Default: skip-left=1:skip-right=1:skip-top=4:skip-bottom=4:plane=0 - - + + @@ -434,8 +434,8 @@ Default: skip-left=1:skip-right=1:skip-top=4:skip-bottom=4:plane=0 - - + + Denoise reduces or removes the appearance of noise and grain. This can improve compression efficiency and create higher quality video at smaller file sizes. Overly strong Denoise settings may damage picture quality by discarding detail. @@ -463,8 +463,8 @@ HQDN3D is an adaptive low-pass filter, faster than NLMeans but less effective at - - + + @@ -480,8 +480,8 @@ HQDN3D is an adaptive low-pass filter, faster than NLMeans but less effective at - - + + @@ -504,10 +504,10 @@ HQDN3D is an adaptive low-pass filter, faster than NLMeans but less effective at - - + + - Denoise tune. Further adjusts the Denoise preset to optimize settings for specific scenarios. + Denoise tune. Further adjusts the Denoise preset to optimize settings for specific scenarios. None uses the default preset settings. @@ -521,7 +521,7 @@ Animation is useful for cel animation such as anime and cartoons. Tape is useful for low-detail analog tape sources such as VHS, where Film does not produce a desirable result. -Sprite is useful for 1-/4-/8-/16-bit 2-dimensional games. Sprite is not designed for high definition video. +Sprite is useful for 1-/4-/8-/16-bit 2-dimensional games. Sprite is not designed for high definition video. @@ -541,8 +541,8 @@ Sprite is useful for 1-/4-/8-/16-bit 2-dimensional games. Sprite is not designed - - + + @@ -558,8 +558,8 @@ Sprite is useful for 1-/4-/8-/16-bit 2-dimensional games. Sprite is not designed - - + + Custom Denoise parameters. @@ -584,8 +584,8 @@ HQDN3D default: y-spatial=3:cb-spatial=2:cr-spatial=2:y-temporal=2:cb-temporal=3 - - + + @@ -601,8 +601,8 @@ HQDN3D default: y-spatial=3:cb-spatial=2:cr-spatial=2:y-temporal=2:cb-temporal=3 - - - + + @@ -626,7 +626,7 @@ HQDN3D default: y-spatial=3:cb-spatial=2:cr-spatial=2:y-temporal=2:cb-temporal=3 - + Display width. This is the number of pixels wide your video will appear to be at its native resolution, and is the result of scaling the storage dimensions by the pixel aspect. @@ -648,7 +648,7 @@ HQDN3D default: y-spatial=3:cb-spatial=2:cr-spatial=2:y-temporal=2:cb-temporal=3 - + Display height. This is the number of pixels tall your video will appear to be at its native resolution, and is the result of scaling the storage dimensions by the pixel aspect. @@ -669,7 +669,7 @@ HQDN3D default: y-spatial=3:cb-spatial=2:cr-spatial=2:y-temporal=2:cb-temporal=3 - + Pixel Aspect Ratio defines the shape of the storage pixels, or how to scale anamorphic video to create the correct display aspect and dimensions. Non-anamorphic video (1:1 PAR) is not scaled during playback. @@ -692,7 +692,7 @@ HQDN3D default: y-spatial=3:cb-spatial=2:cr-spatial=2:y-temporal=2:cb-temporal=3 - + @@ -707,7 +707,7 @@ HQDN3D default: y-spatial=3:cb-spatial=2:cr-spatial=2:y-temporal=2:cb-temporal=3 - + @@ -747,7 +747,7 @@ HQDN3D default: y-spatial=3:cb-spatial=2:cr-spatial=2:y-temporal=2:cb-temporal=3 - + Video storage width. This is the number of pixels wide to be encoded. Storage width may differ from display width depending on anamorphic settings. @@ -773,7 +773,7 @@ HQDN3D default: y-spatial=3:cb-spatial=2:cr-spatial=2:y-temporal=2:cb-temporal=3 - + @@ -785,7 +785,7 @@ HQDN3D default: y-spatial=3:cb-spatial=2:cr-spatial=2:y-temporal=2:cb-temporal=3 - + @@ -794,7 +794,7 @@ HQDN3D default: y-spatial=3:cb-spatial=2:cr-spatial=2:y-temporal=2:cb-temporal=3 - + @@ -803,7 +803,7 @@ HQDN3D default: y-spatial=3:cb-spatial=2:cr-spatial=2:y-temporal=2:cb-temporal=3 - + @@ -846,7 +846,7 @@ Custom allows manually setting all parameters. Useful for correcting an incorrec - + @@ -858,7 +858,7 @@ Custom allows manually setting all parameters. Useful for correcting an incorrec - + @@ -870,7 +870,7 @@ Custom allows manually setting all parameters. Useful for correcting an incorrec - + @@ -882,7 +882,7 @@ Custom allows manually setting all parameters. Useful for correcting an incorrec - + @@ -894,7 +894,7 @@ Custom allows manually setting all parameters. Useful for correcting an incorrec - + Video storage height. This is the number of pixels tall to be encoded. Storage height may differ from display height depending on anamorphic settings. @@ -942,7 +942,7 @@ Custom allows manually setting all parameters. Useful for correcting an incorrec - + Pixel Aspect Ratio defines the shape of the storage pixels, or how to scale anamorphic video to create the correct display aspect and dimensions. Non-anamorphic video (1:1 PAR) is not scaled during playback. @@ -963,7 +963,7 @@ Custom allows manually setting all parameters. Useful for correcting an incorrec - + @@ -978,7 +978,7 @@ Custom allows manually setting all parameters. Useful for correcting an incorrec - + @@ -1016,8 +1016,8 @@ Custom allows manually setting all parameters. Useful for correcting an incorrec - - + + @@ -1028,8 +1028,8 @@ Custom allows manually setting all parameters. Useful for correcting an incorrec - - + + @@ -1045,8 +1045,8 @@ Custom allows manually setting all parameters. Useful for correcting an incorrec - - + + Deinterlace removes comb artifacts from the picture. @@ -1073,8 +1073,8 @@ Decomb switches between multiple interpolation algorithms for speed and quality. - - + + Custom Deinterlace parameters. @@ -1099,8 +1099,8 @@ Decomb default: mode=7 - - + + @@ -1116,8 +1116,8 @@ Decomb default: mode=7 - - + + Deinterlace filter preset. @@ -1149,8 +1149,8 @@ Bob attempts to better preserve motion for a slight penalty to perceived resolut - - + + @@ -1174,8 +1174,8 @@ Bob attempts to better preserve motion for a slight penalty to perceived resolut - - - + + @@ -1202,8 +1202,8 @@ Bob attempts to better preserve motion for a slight penalty to perceived resolut - - + + @@ -1219,8 +1219,8 @@ Bob attempts to better preserve motion for a slight penalty to perceived resolut - - + + @@ -1243,8 +1243,8 @@ Bob attempts to better preserve motion for a slight penalty to perceived resolut - - + + Custom Interlace Detection parameters. @@ -1265,6 +1265,183 @@ Default: mode=3:spatial-metric=2:motion-thresh=1:spatial-thresh=1:filter-mode=2: + + + + + + + + + + + + + + + + Sharpening enhances the appearance of detail, especially edges. Overly strong Sharpen settings may damage picture quality and by creating ringing artifacts and enhancing noise, which can reduce compression efficiency. + +Unsharp is a general purpose unsharp masking filter. It sharpens by blurring, then calculating the difference between the blurred picture and the original. + +Lapsharp sharpens by using convolution kernels approximating Laplacian edge filters, often producing higher quality results than unsharp masking. + + + + + + + + + + NSIsNotNil + + + + + HBSharpenTransformer + + + + + + + + + + + + + + + + + + NSNegateBoolean + + + + + + + + + + + + + + + + + + NSNegateBoolean + + + + + HBSharpenPresetTransformer + + + + + + + + + + Sharpen tune. Further adjusts the Sharpen preset to optimize settings for specific scenarios. + +None uses the default preset settings. + +Unsharp can be tuned for Fine, Medium, or Coarse sharpening. Select one based on the output picture resolution and fineness of detail to enhance. + +Lapsharp's Film tune refines settings for use with most live action content. Film uses an isotropic Laplacian kernel to sharpen all edges similarly, and luminance (brightness) information is sharpened more than chrominance (color) information. + +Lapsharp's Grain tune is similar to Film, but uses a slightly larger Laplacian of Gaussian kernel to reduce the effect on noise and grain. Useful for preserving grain and as a general alternative to the Film tune. + +Lapsharp's Animation tune is useful for cel animation such as anime and cartoons. Animation is identical to Film, but overall strength is reduced to avoid creating artifacts. + +Lapsharp's Sprite tune is useful for 1-/4-/8-/16-bit 2-dimensional games. Sprite uses a 4-neighbor Laplacian kernel that enhances vertical and horizontal edges more than diagonal edges. + + + + + + + + + HBSharpenTuneTransformer + + + + + + NSNegateBoolean + + + + + + + + + + + + + + + + NSNegateBoolean + + + + + + + + + Custom Sharpen parameters. + +Unsharp syntax: y-strength=y:y-size=y:cb-strength=c:cb-size=c:cr-strength=c:cr-size=c + +Unsharp default: y-strength=0.25:y-size=7:cb-strength=0.25:cb-size=7 + +Lapsharp syntax: y-strength=y:y-kernel=y:cb-strength=c:cb-kernel=c:cr-strength=c:cr-kernel=c + +Lapsharp default: y-strength=0.2:y-kernel=isolap:cb-strength=0.2:cb-kernel=isolap + + + + + + + + + NSNegateBoolean + + + + + + + + + + + + + + + + + NSNegateBoolean + + + + + diff --git a/macosx/HBFilters+UIAdditions.h b/macosx/HBFilters+UIAdditions.h index 9e70e139d..8664e2aca 100644 --- a/macosx/HBFilters+UIAdditions.h +++ b/macosx/HBFilters+UIAdditions.h @@ -24,6 +24,10 @@ + (NSDictionary *)nlmeansTunesDict; + (NSDictionary *)denoiseTypesDict; ++ (NSDictionary *)sharpenPresetDict; ++ (NSDictionary *)sharpenTunesDict; ++ (NSDictionary *)sharpenTypesDict; + - (BOOL)customDetelecineSelected; @property (nonatomic, readonly) BOOL customCombDetectionSelected; @@ -31,9 +35,9 @@ - (BOOL)deinterlaceEnabled; - (BOOL)customDeinterlaceSelected; -- (BOOL)denoiseEnabled; -- (BOOL)customDenoiseSelected; -- (BOOL)denoiseTunesAvailable; +- (BOOL)sharpenEnabled; +- (BOOL)customSharpenSelected; +- (BOOL)sharpenTunesAvailable; - (NSString *)deblockSummary; @@ -44,9 +48,9 @@ @property (nonatomic, readonly) NSArray *deinterlaceTypes; @property (nonatomic, readonly) NSArray *deinterlacePresets; -@property (nonatomic, readonly) NSArray *denoiseTypes; -@property (nonatomic, readonly) NSArray *denoisePresets; -@property (nonatomic, readonly) NSArray *denoiseTunes; +@property (nonatomic, readonly) NSArray *sharpenTypes; +@property (nonatomic, readonly) NSArray *sharpenPresets; +@property (nonatomic, readonly) NSArray *sharpenTunes; @end @@ -80,6 +84,15 @@ @interface HBDenoiseTransformer : HBGenericDictionaryTransformer @end +@interface HBSharpenPresetTransformer : HBGenericDictionaryTransformer +@end + +@interface HBSharpenTuneTransformer : HBGenericDictionaryTransformer +@end + +@interface HBSharpenTransformer : HBGenericDictionaryTransformer +@end + @interface HBCustomFilterTransformer : NSValueTransformer @end diff --git a/macosx/HBFilters+UIAdditions.m b/macosx/HBFilters+UIAdditions.m index 1ee7cd628..e96a5c6dc 100644 --- a/macosx/HBFilters+UIAdditions.m +++ b/macosx/HBFilters+UIAdditions.m @@ -155,6 +155,42 @@ static NSDictionary * filterParamsToNamesDict(hb_filter_param_t * (f)(int), int @end +@implementation HBSharpenPresetTransformer + +- (instancetype)init +{ + if (self = [super init]) + self.dict = [HBFilters sharpenPresetDict]; + + return self; +} + +@end + +@implementation HBSharpenTuneTransformer + +- (instancetype)init +{ + if (self = [super init]) + self.dict = [HBFilters sharpenTunesDict]; + + return self; +} + +@end + +@implementation HBSharpenTransformer + +- (instancetype)init +{ + if (self = [super init]) + self.dict = [HBFilters sharpenTypesDict]; + + return self; +} + +@end + @implementation HBCustomFilterTransformer + (Class)transformedValueClass @@ -189,6 +225,10 @@ static NSDictionary *denoisePresetDict = nil; static NSDictionary *nlmeansTunesDict = nil; static NSDictionary *denoiseTypesDict = nil; +static NSDictionary *sharpenPresetDict = nil; +static NSDictionary *sharpenTunesDict = nil; +static NSDictionary *sharpenTypesDict = nil; + @implementation HBFilters (UIAdditions) #pragma mark - Valid values @@ -275,6 +315,41 @@ static NSDictionary *denoiseTypesDict = nil; return denoiseTypesDict; } ++ (NSDictionary *)sharpenPresetDict +{ + if (!sharpenPresetDict) + { + sharpenPresetDict = filterParamsToNamesDict(hb_filter_param_get_presets, HB_FILTER_UNSHARP); + } + return sharpenPresetDict; +} + ++ (NSDictionary *)sharpenTunesDict +{ + if (!sharpenTunesDict) + { + NSDictionary *unsharpenTunesDict = filterParamsToNamesDict(hb_filter_param_get_tunes, HB_FILTER_UNSHARP); + NSDictionary *lapsharpTunesDict = filterParamsToNamesDict(hb_filter_param_get_tunes, HB_FILTER_LAPSHARP); + + sharpenTunesDict = [NSMutableDictionary dictionary]; + [sharpenTunesDict setValuesForKeysWithDictionary:unsharpenTunesDict]; + [sharpenTunesDict setValuesForKeysWithDictionary:lapsharpTunesDict]; + + } + return sharpenTunesDict; +} + ++ (NSDictionary *)sharpenTypesDict +{ + if (!sharpenTypesDict) + { + sharpenTypesDict = @{NSLocalizedString(@"Off", nil): @"off", + NSLocalizedString(@"Unsharp", nil): @"unsharp", + NSLocalizedString(@"Lapsharp", nil): @"lapsharp"};; + } + return sharpenTypesDict; +} + - (NSArray *)detelecineSettings { return filterParamsToNamesArray(hb_filter_param_get_presets, HB_FILTER_DETELECINE); @@ -312,6 +387,35 @@ static NSDictionary *denoiseTypesDict = nil; return filterParamsToNamesArray(hb_filter_param_get_tunes, HB_FILTER_NLMEANS); } +- (NSArray *)sharpenTypes +{ + return @[@"Off", @"Unsharp", @"Lapsharp"]; +} + +- (NSArray *)sharpenPresets +{ + if ([self.sharpen isEqualToString:@"unsharp"]) + { + return filterParamsToNamesArray(hb_filter_param_get_presets, HB_FILTER_UNSHARP); + } + else + { + return filterParamsToNamesArray(hb_filter_param_get_presets, HB_FILTER_LAPSHARP); + } +} + +- (NSArray *)sharpenTunes +{ + if ([self.sharpen isEqualToString:@"unsharp"]) + { + return filterParamsToNamesArray(hb_filter_param_get_tunes, HB_FILTER_UNSHARP); + } + else + { + return filterParamsToNamesArray(hb_filter_param_get_tunes, HB_FILTER_LAPSHARP); + } +} + - (BOOL)customDetelecineSelected { return [self.detelecine isEqualToString:@"custom"] ? YES : NO; @@ -332,6 +436,11 @@ static NSDictionary *denoiseTypesDict = nil; return ![self.denoise isEqualToString:@"off"]; } +- (BOOL)sharpenEnabled +{ + return ![self.sharpen isEqualToString:@"off"]; +} + - (BOOL)deinterlaceEnabled { return ![self.deinterlace isEqualToString:@"off"]; @@ -347,6 +456,16 @@ static NSDictionary *denoiseTypesDict = nil; return [self.denoise isEqualToString:@"nlmeans"] && ![self.denoisePreset isEqualToString:@"custom"]; } +- (BOOL)customSharpenSelected +{ + return [self.sharpenPreset isEqualToString:@"custom"] && [self sharpenEnabled]; +} + +- (BOOL)sharpenTunesAvailable +{ + return ([self.sharpen isEqualToString:@"unsharp"] || [self.sharpen isEqualToString:@"lapsharp"]) && ![self.sharpenPreset isEqualToString:@"custom"]; +} + - (NSString *)deblockSummary { if (self.deblock == 0) diff --git a/macosx/HBFilters.h b/macosx/HBFilters.h index e5f7cbb65..775829de1 100644 --- a/macosx/HBFilters.h +++ b/macosx/HBFilters.h @@ -31,6 +31,11 @@ extern NSString * const HBFiltersChangedNotification; @property (nonatomic, readwrite, copy) NSString *denoiseTune; @property (nonatomic, readwrite, copy) NSString *denoiseCustomString; +@property (nonatomic, readwrite, copy) NSString *sharpen; +@property (nonatomic, readwrite, copy) NSString *sharpenPreset; +@property (nonatomic, readwrite, copy) NSString *sharpenTune; +@property (nonatomic, readwrite, copy) NSString *sharpenCustomString; + @property (nonatomic, readwrite) int deblock; @property (nonatomic, readwrite) BOOL grayscale; diff --git a/macosx/HBFilters.m b/macosx/HBFilters.m index 12a943953..e9d562eeb 100644 --- a/macosx/HBFilters.m +++ b/macosx/HBFilters.m @@ -37,6 +37,10 @@ NSString * const HBFiltersChangedNotification = @"HBFiltersChangedNotification"; _denoiseCustomString = @""; _denoisePreset = @"medium"; _denoiseTune = @"none"; + _sharpen = @"off"; + _sharpenCustomString = @""; + _sharpenPreset = @"medium"; + _sharpenTune = @"none"; _notificationsEnabled = YES; } @@ -271,6 +275,111 @@ NSString * const HBFiltersChangedNotification = @"HBFiltersChangedNotification"; [self postChangedNotification]; } +- (void)setSharpen:(NSString *)sharpen +{ + if (![sharpen isEqualToString:_sharpen]) + { + [[self.undo prepareWithInvocationTarget:self] setSharpen:_sharpen]; + } + if (sharpen) + { + _sharpen = [sharpen copy]; + } + else + { + _sharpen = @"off"; + } + + if (!(self.undo.isUndoing || self.undo.isRedoing)) + { + [self validateSharpenPreset]; + [self validateSharpenTune]; + } + [self postChangedNotification]; +} + +- (void)setSharpenPreset:(NSString *)sharpenPreset +{ + if (![sharpenPreset isEqualToString:_sharpenPreset]) + { + [[self.undo prepareWithInvocationTarget:self] setSharpenPreset:_sharpenPreset]; + } + if (sharpenPreset) + { + _sharpenPreset = [sharpenPreset copy]; + } + else + { + _sharpenPreset = @"medium"; + } + + [self postChangedNotification]; +} + +- (void)validateSharpenPreset +{ + int filter_id = HB_FILTER_UNSHARP; + if ([self.sharpen isEqualToString:@"lapsharp"]) + { + filter_id = HB_FILTER_LAPSHARP; + } + + if (hb_validate_filter_preset(filter_id, self.sharpenPreset.UTF8String, NULL, NULL)) + { + _sharpenPreset = @"medium"; + } +} + +- (void)setSharpenTune:(NSString *)sharpenTune +{ + if (![sharpenTune isEqualToString:_sharpenTune]) + { + [[self.undo prepareWithInvocationTarget:self] setSharpenTune:_sharpenTune]; + } + if (sharpenTune) + { + _sharpenTune = [sharpenTune copy]; + } + else + { + _sharpenTune = @"none"; + } + + [self postChangedNotification]; +} + +- (void)validateSharpenTune +{ + int filter_id = HB_FILTER_UNSHARP; + if ([self.sharpen isEqualToString:@"lapsharp"]) + { + filter_id = HB_FILTER_LAPSHARP; + } + + if (hb_validate_filter_preset(filter_id, self.sharpenPreset.UTF8String, self.sharpenTune.UTF8String, NULL)) + { + _sharpenTune = @"none"; + } +} + +- (void)setSharpenCustomString:(NSString *)sharpenCustomString +{ + if (![sharpenCustomString isEqualToString:_sharpenCustomString]) + { + [[self.undo prepareWithInvocationTarget:self] setSharpenCustomString:_sharpenCustomString]; + } + if (sharpenCustomString) + { + _sharpenCustomString = [sharpenCustomString copy]; + } + else + { + _sharpenCustomString = @""; + } + + [self postChangedNotification]; +} + - (void)setDeblock:(int)deblock { if (deblock != _deblock) @@ -317,7 +426,7 @@ NSString * const HBFiltersChangedNotification = @"HBFiltersChangedNotification"; if ([key isEqualToString:@"summary"]) { - retval = [NSSet setWithObjects:@"detelecine", @"detelecineCustomString", @"deinterlace", @"deinterlacePreset", @"deinterlaceCustomString", @"denoise", @"denoisePreset", @"denoiseTune", @"denoiseCustomString", @"deblock", @"grayscale", nil]; + retval = [NSSet setWithObjects:@"detelecine", @"detelecineCustomString", @"deinterlace", @"deinterlacePreset", @"deinterlaceCustomString", @"denoise", @"denoisePreset", @"denoiseTune", @"denoiseCustomString", @"deblock", @"grayscale", @"sharpen", @"sharpenPreset", @"sharpenTune", @"sharpenCustomString", nil]; } else if ([key isEqualToString:@"customDetelecineSelected"]) { @@ -336,6 +445,17 @@ NSString * const HBFiltersChangedNotification = @"HBFiltersChangedNotification"; { retval = [NSSet setWithObject:@"denoise"]; } + else if ([key isEqualToString:@"sharpenTunesAvailable"] || + [key isEqualToString:@"customSharpenSelected"]) + { + retval = [NSSet setWithObjects:@"sharpen", @"sharpenPreset", nil]; + } + else if ([key isEqualToString:@"sharpenEnabled"] || + [key isEqualToString:@"sharpenPresets"] || + [key isEqualToString:@"sharpenTunes"]) + { + retval = [NSSet setWithObject:@"sharpen"]; + } else if ([key isEqualToString:@"deinterlaceEnabled"]) { retval = [NSSet setWithObject:@"deinterlace"]; @@ -381,6 +501,11 @@ NSString * const HBFiltersChangedNotification = @"HBFiltersChangedNotification"; copy->_denoiseTune = [_denoiseTune copy]; copy->_denoiseCustomString = [_denoiseCustomString copy]; + copy->_sharpen = [_sharpen copy]; + copy->_sharpenPreset = [_sharpenPreset copy]; + copy->_sharpenTune = [_sharpenTune copy]; + copy->_sharpenCustomString = [_sharpenCustomString copy]; + copy->_deblock = _deblock; copy->_grayscale = _grayscale; copy->_rotate = _rotate; @@ -416,6 +541,11 @@ NSString * const HBFiltersChangedNotification = @"HBFiltersChangedNotification"; encodeObject(_denoiseTune); encodeObject(_denoiseCustomString); + encodeObject(_sharpen); + encodeObject(_sharpenPreset); + encodeObject(_sharpenTune); + encodeObject(_sharpenCustomString); + encodeInt(_deblock); encodeBool(_grayscale); encodeInt(_rotate); @@ -441,6 +571,11 @@ NSString * const HBFiltersChangedNotification = @"HBFiltersChangedNotification"; decodeObjectOrFail(_denoiseTune, NSString); decodeObjectOrFail(_denoiseCustomString, NSString); + decodeObjectOrFail(_sharpen, NSString); + decodeObjectOrFail(_sharpenPreset, NSString); + decodeObjectOrFail(_sharpenTune, NSString); + decodeObjectOrFail(_sharpenCustomString, NSString); + decodeInt(_deblock); decodeBool(_grayscale); decodeInt(_rotate); @@ -473,6 +608,11 @@ fail: preset[@"PictureDenoiseTune"] = self.denoiseTune; preset[@"PictureDenoiseCustom"] = self.denoiseCustomString; + preset[@"PictureSharpenFilter"] = self.sharpen; + preset[@"PictureSharpenPreset"] = self.sharpenPreset; + preset[@"PictureSharpenTune"] = self.sharpenTune; + preset[@"PictureSharpenCustom"] = self.sharpenCustomString; + preset[@"PictureDeblock"] = @(self.deblock); preset[@"VideoGrayScale"] = @(self.grayscale); preset[@"PictureRotate"] = [NSString stringWithFormat:@"angle=%d:hflip=%d", self.rotate, self.flip]; @@ -505,6 +645,12 @@ fail: self.denoiseCustomString = preset[@"PictureDenoiseCustom"]; + // Sharpen + self.sharpen = preset[@"PictureSharpenFilter"]; + self.sharpenPreset = preset[@"PictureSharpenPreset"]; + self.sharpenTune = preset[@"PictureSharpenTune"]; + self.sharpenCustomString = preset[@"PictureSharpenCustom"]; + self.deblock = [preset[@"PictureDeblock"] intValue]; self.grayscale = [preset[@"VideoGrayScale"] boolValue]; diff --git a/macosx/HBJob+HBJobConversion.m b/macosx/HBJob+HBJobConversion.m index 852603e40..3a28629a9 100644 --- a/macosx/HBJob+HBJobConversion.m +++ b/macosx/HBJob+HBJobConversion.m @@ -489,6 +489,24 @@ self.picture.cropTop, self.picture.cropBottom, self.picture.cropLeft, self.picture.cropRight].UTF8String); + // Sharpen + if (![self.filters.sharpen isEqualToString:@"off"]) + { + int filter_id = HB_FILTER_UNSHARP; + if ([self.filters.sharpen isEqualToString:@"lapsharp"]) + { + filter_id = HB_FILTER_LAPSHARP; + } + + hb_dict_t *filter_dict = hb_generate_filter_settings(filter_id, + self.filters.sharpenPreset.UTF8String, + self.filters.sharpenTune.UTF8String, + self.filters.sharpenCustomString.UTF8String); + filter = hb_filter_init(filter_id); + hb_add_filter_dict(job, filter, filter_dict); + hb_dict_free(&filter_dict); + } + // Add grayscale filter if (self.filters.grayscale) { diff --git a/macosx/HBJob+UIAdditions.m b/macosx/HBJob+UIAdditions.m index de7ac410f..569f1249d 100644 --- a/macosx/HBJob+UIAdditions.m +++ b/macosx/HBJob+UIAdditions.m @@ -316,6 +316,32 @@ static NSDictionary *shortHeightAttr; } + // Sharpen + if (![filters.sharpen isEqualToString:@"off"]) + { + [summary appendFormat:@", Sharpen (%@", [[[HBFilters sharpenTypesDict] allKeysForObject:filters.sharpen] firstObject]]; + if (![filters.sharpenPreset isEqualToString:@"custom"]) + { + [summary appendFormat:@", %@", [[[HBFilters sharpenPresetDict] allKeysForObject:filters.sharpenPreset] firstObject]]; + + if ([filters.sharpen isEqualToString:@"unsharp"]) + { + [summary appendFormat:@", %@", [[[HBFilters sharpenTunesDict] allKeysForObject:filters.sharpenTune] firstObject]]; + } + else if ([filters.sharpen isEqualToString:@"lapsharp"]) + { + [summary appendFormat:@", %@", [[[HBFilters sharpenTunesDict] allKeysForObject:filters.sharpenTune] firstObject]]; + } + } + else + { + [summary appendFormat:@", %@", filters.sharpenCustomString]; + } + + [summary appendString:@")"]; + + } + // Grayscale if (filters.grayscale) { diff --git a/macosx/HandBrakeKitTests/HBJobUndoTests.m b/macosx/HandBrakeKitTests/HBJobUndoTests.m index b0d0be702..ab2e5534f 100644 --- a/macosx/HandBrakeKitTests/HBJobUndoTests.m +++ b/macosx/HandBrakeKitTests/HBJobUndoTests.m @@ -168,6 +168,11 @@ XCTAssertEqualObjects(self.job.filters.denoiseTune, self.modifiedJob.filters.denoiseTune); XCTAssertEqualObjects(self.job.filters.denoiseCustomString, self.modifiedJob.filters.denoiseCustomString); + XCTAssertEqualObjects(self.job.filters.sharpen, self.modifiedJob.filters.sharpen); + XCTAssertEqualObjects(self.job.filters.sharpenPreset, self.modifiedJob.filters.sharpenPreset); + XCTAssertEqualObjects(self.job.filters.sharpenTune, self.modifiedJob.filters.sharpenTune); + XCTAssertEqualObjects(self.job.filters.sharpenCustomString, self.modifiedJob.filters.sharpenCustomString); + XCTAssertEqual(self.job.filters.deblock, self.modifiedJob.filters.deblock); XCTAssertEqual(self.job.filters.grayscale, self.modifiedJob.filters.grayscale); }