mirror of https://github.com/SixLabors/ImageSharp
committed by
GitHub
308 changed files with 5741 additions and 3746 deletions
@ -1,373 +1,436 @@ |
|||
############################################################################### |
|||
# EditorConfig is awesome: http://EditorConfig.org |
|||
############################################################################### |
|||
# Version: 1.6.2 (Using https://semver.org/) |
|||
# Updated: 2020-11-02 |
|||
# See https://github.com/RehanSaeed/EditorConfig/releases for release notes. |
|||
# See https://github.com/RehanSaeed/EditorConfig for updates to this file. |
|||
# See http://EditorConfig.org for more information about .editorconfig files. |
|||
|
|||
############################################################################### |
|||
# Top-most EditorConfig file |
|||
############################################################################### |
|||
########################################## |
|||
# Common Settings |
|||
########################################## |
|||
|
|||
# This file is the top-most EditorConfig file |
|||
root = true |
|||
|
|||
############################################################################### |
|||
# Set default behavior to: |
|||
# a UTF-8 encoding, |
|||
# Unix-style line endings, |
|||
# a newline ending the file, |
|||
# 4 space indentation, and |
|||
# trimming of trailing whitespace |
|||
############################################################################### |
|||
# All Files |
|||
[*] |
|||
charset = utf-8 |
|||
end_of_line = lf |
|||
insert_final_newline = true |
|||
indent_style = space |
|||
indent_size = 4 |
|||
end_of_line = lf |
|||
insert_final_newline = true |
|||
trim_trailing_whitespace = true |
|||
|
|||
############################################################################### |
|||
# Set file behavior to: |
|||
# 2 space indentation |
|||
############################################################################### |
|||
[*.{cmd,config,csproj,json,props,ps1,resx,sh,targets}] |
|||
indent_size = 2 |
|||
########################################## |
|||
# File Extension Settings |
|||
########################################## |
|||
|
|||
############################################################################### |
|||
# Set file behavior to: |
|||
# Windows-style line endings, and |
|||
# tabular indentation |
|||
############################################################################### |
|||
# Visual Studio Solution Files |
|||
[*.sln] |
|||
indent_style = tab |
|||
|
|||
# Visual Studio XML Project Files |
|||
[*.{csproj,vbproj,vcxproj.filters,proj,projitems,shproj}] |
|||
indent_size = 2 |
|||
|
|||
# T4 Templates Files |
|||
[*.{tt,ttinclude}] |
|||
end_of_line = crlf |
|||
|
|||
# XML Configuration Files |
|||
[*.{xml,config,props,targets,nuspec,resx,ruleset,vsixmanifest,vsct}] |
|||
indent_size = 2 |
|||
|
|||
# JSON Files |
|||
[*.{json,json5,webmanifest}] |
|||
indent_size = 2 |
|||
|
|||
# YAML Files |
|||
[*.{yml,yaml}] |
|||
indent_size = 2 |
|||
|
|||
# Markdown Files |
|||
[*.md] |
|||
trim_trailing_whitespace = false |
|||
|
|||
# Web Files |
|||
[*.{htm,html,js,jsm,ts,tsx,css,sass,scss,less,svg,vue}] |
|||
indent_size = 2 |
|||
|
|||
# Batch Files |
|||
[*.{cmd,bat}] |
|||
end_of_line = crlf |
|||
|
|||
# Makefiles |
|||
[Makefile] |
|||
indent_style = tab |
|||
|
|||
############################################################################### |
|||
# Set dotnet naming rules to: |
|||
# suggest async members be pascal case suffixed with Async |
|||
# suggest const declarations be pascal case |
|||
# suggest interfaces be pascal case prefixed with I |
|||
# suggest parameters be camel case |
|||
# suggest private and internal static fields be camel case |
|||
# suggest private and internal fields be camel case |
|||
# suggest public and protected declarations be pascal case |
|||
# suggest static readonly declarations be pascal case |
|||
# suggest type parameters be prefixed with T |
|||
############################################################################### |
|||
[*.cs] |
|||
dotnet_naming_rule.async_members_should_be_pascal_case_suffixed_with_async.severity = suggestion |
|||
dotnet_naming_rule.async_members_should_be_pascal_case_suffixed_with_async.style = pascal_case_suffixed_with_async |
|||
dotnet_naming_rule.async_members_should_be_pascal_case_suffixed_with_async.symbols = async_members |
|||
|
|||
dotnet_naming_rule.const_declarations_should_be_pascal_case.severity = suggestion |
|||
dotnet_naming_rule.const_declarations_should_be_pascal_case.style = pascal_case |
|||
dotnet_naming_rule.const_declarations_should_be_pascal_case.symbols = const_declarations |
|||
|
|||
dotnet_naming_rule.interfaces_should_be_pascal_case_prefixed_with_i.severity = suggestion |
|||
dotnet_naming_rule.interfaces_should_be_pascal_case_prefixed_with_i.style = pascal_case_prefixed_with_i |
|||
dotnet_naming_rule.interfaces_should_be_pascal_case_prefixed_with_i.symbols = interfaces |
|||
|
|||
dotnet_naming_rule.parameters_should_be_camel_case.severity = suggestion |
|||
dotnet_naming_rule.parameters_should_be_camel_case.style = camel_case |
|||
dotnet_naming_rule.parameters_should_be_camel_case.symbols = parameters |
|||
|
|||
dotnet_naming_rule.private_and_internal_static_fields_should_be_camel_case.severity = suggestion |
|||
dotnet_naming_rule.private_and_internal_static_fields_should_be_camel_case.style = camel_case |
|||
dotnet_naming_rule.private_and_internal_static_fields_should_be_camel_case.symbols = private_and_internal_static_fields |
|||
|
|||
dotnet_naming_rule.private_and_internal_fields_should_be_camel_case.severity = suggestion |
|||
dotnet_naming_rule.private_and_internal_fields_should_be_camel_case.style = camel_case |
|||
dotnet_naming_rule.private_and_internal_fields_should_be_camel_case.symbols = private_and_internal_fields |
|||
|
|||
dotnet_naming_rule.public_and_protected_declarations_should_be_pascal_case.severity = suggestion |
|||
dotnet_naming_rule.public_and_protected_declarations_should_be_pascal_case.style = pascal_case |
|||
dotnet_naming_rule.public_and_protected_declarations_should_be_pascal_case.symbols = public_and_protected_declarations |
|||
dotnet_naming_symbols.public_and_protected_declarations.applicable_kinds = method, field, event, property |
|||
|
|||
dotnet_naming_rule.static_readonly_declarations_should_be_pascal_case.severity = suggestion |
|||
dotnet_naming_rule.static_readonly_declarations_should_be_pascal_case.style = pascal_case |
|||
dotnet_naming_rule.static_readonly_declarations_should_be_pascal_case.symbols = static_readonly_declarations |
|||
|
|||
dotnet_naming_rule.type_parameters_should_be_pascal_case_prefixed_with_t.severity = suggestion |
|||
dotnet_naming_rule.type_parameters_should_be_pascal_case_prefixed_with_t.style = pascal_case_prefixed_with_t |
|||
dotnet_naming_rule.type_parameters_should_be_pascal_case_prefixed_with_t.symbols = type_parameters |
|||
|
|||
############################################################################### |
|||
# Set dotnet naming styles to define: |
|||
# camel case |
|||
# pascal case |
|||
# pascal case suffixed with Async |
|||
# pascal case prefixed with I |
|||
# pascal case prefixed with T |
|||
############################################################################### |
|||
[*.cs] |
|||
dotnet_naming_style.camel_case.capitalization = camel_case |
|||
|
|||
dotnet_naming_style.pascal_case.capitalization = pascal_case |
|||
|
|||
dotnet_naming_style.pascal_case_suffixed_with_async.capitalization = pascal_case |
|||
dotnet_naming_style.pascal_case_suffixed_with_async.required_suffix = Async |
|||
|
|||
dotnet_naming_style.pascal_case_prefixed_with_i.capitalization = pascal_case |
|||
dotnet_naming_style.pascal_case_prefixed_with_i.required_prefix = I |
|||
|
|||
dotnet_naming_style.pascal_case_prefixed_with_t.capitalization = pascal_case |
|||
dotnet_naming_style.pascal_case_prefixed_with_t.required_prefix = T |
|||
|
|||
############################################################################### |
|||
# Set dotnet naming symbols to: |
|||
# async members |
|||
# const declarations |
|||
# interfaces |
|||
# private and internal fields |
|||
# private and internal static fields |
|||
# public and protected declarations |
|||
# static readonly declarations |
|||
# type parameters |
|||
############################################################################### |
|||
[*.cs] |
|||
dotnet_naming_symbols.async_members.required_modifiers = async |
|||
|
|||
dotnet_naming_symbols.const_declarations.required_modifiers = const |
|||
|
|||
dotnet_naming_symbols.interfaces.applicable_kinds = interface |
|||
|
|||
dotnet_naming_symbols.parameters.applicable_kinds = parameter |
|||
|
|||
dotnet_naming_symbols.private_and_internal_fields.applicable_accessibilities = private, internal |
|||
dotnet_naming_symbols.private_and_internal_fields.applicable_kinds = field |
|||
|
|||
dotnet_naming_symbols.private_and_internal_static_fields.applicable_accessibilities = private, internal |
|||
dotnet_naming_symbols.private_and_internal_static_fields.applicable_kinds = field |
|||
dotnet_naming_symbols.private_and_internal_static_fields.required_modifiers = static |
|||
|
|||
dotnet_naming_symbols.public_and_protected_declarations.applicable_accessibilities = public, protected |
|||
|
|||
dotnet_naming_symbols.static_readonly_declarations.required_modifiers = static, readonly |
|||
|
|||
dotnet_naming_symbols.type_parameters.applicable_kinds = type_parameter |
|||
|
|||
############################################################################### |
|||
# Set dotnet sort options to: |
|||
# do not separate import directives into groups, and |
|||
# sort system directives first |
|||
############################################################################### |
|||
[*.cs] |
|||
dotnet_separate_import_directive_groups = false |
|||
dotnet_sort_system_directives_first = true |
|||
########################################## |
|||
# File Header (Uncomment to support file headers) |
|||
# https://docs.microsoft.com/visualstudio/ide/reference/add-file-header |
|||
########################################## |
|||
|
|||
############################################################################### |
|||
# Set dotnet style options to: |
|||
# suggest null-coalescing expressions, |
|||
# suggest collection-initializers, |
|||
# suggest explicit tuple names, |
|||
# suggest null-propogation |
|||
# suggest object-initializers, |
|||
# generate parentheses in arithmetic binary operators for clarity, |
|||
# generate parentheses in other binary operators for clarity, |
|||
# don't generate parentheses in other operators if unnecessary, |
|||
# generate parentheses in relational binary operators for clarity, |
|||
# warn when not using predefined-types for locals, parameters, and members, |
|||
# generate predefined-types of type names for member access, |
|||
# generate auto properties, |
|||
# suggest compound assignment, |
|||
# generate conditional expression over assignment, |
|||
# generate conditional expression over return, |
|||
# suggest inferred anonymous types, |
|||
# suggest inferred tuple names, |
|||
# suggest 'is null' checks over '== null', |
|||
# don't generate 'this.' and 'Me.' for events, |
|||
# warn when not using 'this.' and 'Me.' for fields, |
|||
# warn when not using 'this.' and 'Me.' for methods, |
|||
# warn when not using 'this.' and 'Me.' for properties, |
|||
# suggest readonly fields, and |
|||
# generate accessibility modifiers for non interface members |
|||
############################################################################### |
|||
[*.cs] |
|||
dotnet_style_coalesce_expression = true:suggestion |
|||
dotnet_style_collection_initializer = true:suggestion |
|||
dotnet_style_explicit_tuple_names = true:suggestion |
|||
dotnet_style_null_propagation = true:suggestion |
|||
dotnet_style_object_initializer = true:suggestion |
|||
|
|||
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent |
|||
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent |
|||
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent |
|||
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent |
|||
# [*.{cs,csx,cake,vb,vbx,tt,ttinclude}] |
|||
file_header_template = Copyright (c) Six Labors.\nLicensed under the Apache License, Version 2.0. |
|||
|
|||
dotnet_style_predefined_type_for_locals_parameters_members = true:warning |
|||
dotnet_style_predefined_type_for_member_access = true:silent |
|||
# SA1636: File header copyright text should match |
|||
# Justification: .editorconfig supports file headers. If this is changed to a value other than "none", a stylecop.json file will need to added to the project. |
|||
# dotnet_diagnostic.SA1636.severity = none |
|||
|
|||
dotnet_style_prefer_auto_properties = true:silent |
|||
dotnet_style_prefer_compound_assignment = true:suggestion |
|||
dotnet_style_prefer_conditional_expression_over_assignment = true:silent |
|||
dotnet_style_prefer_conditional_expression_over_return = true:silent |
|||
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion |
|||
dotnet_style_prefer_inferred_tuple_names = true:suggestion |
|||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion |
|||
########################################## |
|||
# .NET Language Conventions |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions |
|||
########################################## |
|||
|
|||
dotnet_style_qualification_for_event = false:silent |
|||
# .NET Code Style Settings |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#net-code-style-settings |
|||
[*.{cs,csx,cake,vb,vbx}] |
|||
# "this." and "Me." qualifiers |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#this-and-me |
|||
dotnet_style_qualification_for_field = true:warning |
|||
dotnet_style_qualification_for_method = true:warning |
|||
dotnet_style_qualification_for_property = true:warning |
|||
|
|||
dotnet_style_readonly_field = true:suggestion |
|||
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent |
|||
|
|||
############################################################################### |
|||
# Set dotnet style options to: |
|||
# suggest removing all unused parameters |
|||
############################################################################### |
|||
[*.cs] |
|||
dotnet_code_quality_unused_parameters = all:suggestion |
|||
|
|||
############################################################################### |
|||
# Set csharp indent options to: |
|||
# indent block contents, |
|||
# not indent braces, |
|||
# indent case contents, |
|||
# not indent case contents when block, |
|||
# indent labels one less than the current, and |
|||
# indent switch labels |
|||
############################################################################### |
|||
[*.cs] |
|||
csharp_indent_block_contents = true |
|||
csharp_indent_braces = false |
|||
csharp_indent_case_contents = true |
|||
csharp_indent_case_contents_when_block = false |
|||
csharp_indent_labels = one_less_than_current |
|||
csharp_indent_switch_labels = true |
|||
|
|||
############################################################################### |
|||
# Set csharp new-line options to: |
|||
# insert a new-line before "catch", |
|||
# insert a new-line before "else", |
|||
# insert a new-line before "finally", |
|||
# insert a new-line before members in anonymous-types, |
|||
# insert a new-line before members in object-initializers, and |
|||
# insert a new-line before all open braces |
|||
############################################################################### |
|||
[*.cs] |
|||
csharp_new_line_before_catch = true |
|||
dotnet_style_qualification_for_method = true:warning |
|||
dotnet_style_qualification_for_event = true:warning |
|||
# Language keywords instead of framework type names for type references |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#language-keywords |
|||
dotnet_style_predefined_type_for_locals_parameters_members = true:warning |
|||
dotnet_style_predefined_type_for_member_access = true:warning |
|||
# Modifier preferences |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#normalize-modifiers |
|||
dotnet_style_require_accessibility_modifiers = always:warning |
|||
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:warning |
|||
visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:warning |
|||
dotnet_style_readonly_field = true:warning |
|||
# Parentheses preferences |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parentheses-preferences |
|||
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning |
|||
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning |
|||
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning |
|||
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion |
|||
# Expression-level preferences |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences |
|||
dotnet_style_object_initializer = true:warning |
|||
dotnet_style_collection_initializer = true:warning |
|||
dotnet_style_explicit_tuple_names = true:warning |
|||
dotnet_style_prefer_inferred_tuple_names = true:warning |
|||
dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning |
|||
dotnet_style_prefer_auto_properties = true:warning |
|||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning |
|||
dotnet_style_prefer_conditional_expression_over_assignment = false:suggestion |
|||
dotnet_style_prefer_conditional_expression_over_return = false:suggestion |
|||
dotnet_style_prefer_compound_assignment = true:warning |
|||
# Null-checking preferences |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#null-checking-preferences |
|||
dotnet_style_coalesce_expression = true:warning |
|||
dotnet_style_null_propagation = true:warning |
|||
# Parameter preferences |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parameter-preferences |
|||
dotnet_code_quality_unused_parameters = all:warning |
|||
# More style options (Undocumented) |
|||
# https://github.com/MicrosoftDocs/visualstudio-docs/issues/3641 |
|||
dotnet_style_operator_placement_when_wrapping = end_of_line |
|||
# https://github.com/dotnet/roslyn/pull/40070 |
|||
dotnet_style_prefer_simplified_interpolation = true:warning |
|||
|
|||
# C# Code Style Settings |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-code-style-settings |
|||
[*.{cs,csx,cake}] |
|||
# Implicit and explicit types |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#implicit-and-explicit-types |
|||
csharp_style_var_for_built_in_types = never |
|||
csharp_style_var_when_type_is_apparent = true:warning |
|||
csharp_style_var_elsewhere = false:warning |
|||
# Expression-bodied members |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-bodied-members |
|||
csharp_style_expression_bodied_methods = true:warning |
|||
csharp_style_expression_bodied_constructors = true:warning |
|||
csharp_style_expression_bodied_operators = true:warning |
|||
csharp_style_expression_bodied_properties = true:warning |
|||
csharp_style_expression_bodied_indexers = true:warning |
|||
csharp_style_expression_bodied_accessors = true:warning |
|||
csharp_style_expression_bodied_lambdas = true:warning |
|||
csharp_style_expression_bodied_local_functions = true:warning |
|||
# Pattern matching |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#pattern-matching |
|||
csharp_style_pattern_matching_over_is_with_cast_check = true:warning |
|||
csharp_style_pattern_matching_over_as_with_null_check = true:warning |
|||
# Inlined variable declarations |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#inlined-variable-declarations |
|||
csharp_style_inlined_variable_declaration = true:warning |
|||
# Expression-level preferences |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences |
|||
csharp_prefer_simple_default_expression = true:warning |
|||
# "Null" checking preferences |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-null-checking-preferences |
|||
csharp_style_throw_expression = true:warning |
|||
csharp_style_conditional_delegate_call = true:warning |
|||
# Code block preferences |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#code-block-preferences |
|||
csharp_prefer_braces = true:warning |
|||
# Unused value preferences |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#unused-value-preferences |
|||
csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion |
|||
csharp_style_unused_value_assignment_preference = discard_variable:suggestion |
|||
# Index and range preferences |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#index-and-range-preferences |
|||
csharp_style_prefer_index_operator = true:warning |
|||
csharp_style_prefer_range_operator = true:warning |
|||
# Miscellaneous preferences |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#miscellaneous-preferences |
|||
csharp_style_deconstructed_variable_declaration = true:warning |
|||
csharp_style_pattern_local_over_anonymous_function = true:warning |
|||
csharp_using_directive_placement = outside_namespace:warning |
|||
csharp_prefer_static_local_function = true:warning |
|||
csharp_prefer_simple_using_statement = true:suggestion |
|||
|
|||
########################################## |
|||
# .NET Formatting Conventions |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-code-style-settings-reference#formatting-conventions |
|||
########################################## |
|||
|
|||
# Organize usings |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#organize-using-directives |
|||
dotnet_sort_system_directives_first = true |
|||
# Newline options |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#new-line-options |
|||
csharp_new_line_before_open_brace = all |
|||
csharp_new_line_before_else = true |
|||
csharp_new_line_before_catch = true |
|||
csharp_new_line_before_finally = true |
|||
|
|||
csharp_new_line_before_members_in_anonymous_types = true |
|||
csharp_new_line_before_members_in_object_initializers = true |
|||
|
|||
csharp_new_line_before_open_brace = all |
|||
|
|||
############################################################################### |
|||
# Set csharp preserve options to: |
|||
# preserve single-line blocks, and |
|||
# preserve single-line statements |
|||
############################################################################### |
|||
[*.cs] |
|||
csharp_preserve_single_line_blocks = true |
|||
csharp_preserve_single_line_statements = true |
|||
|
|||
############################################################################### |
|||
# Set csharp space options to: |
|||
# remove any space after a cast, |
|||
# add a space after the colon in an inheritance clause, |
|||
# add a space after a comma, |
|||
# remove any space after a dot, |
|||
# add a space after keywords in control flow statements, |
|||
# add a space after a semicolon in a "for" statement, |
|||
# add a space before and after binary operators, |
|||
# remove space around declaration statements, |
|||
# add a space before the colon in an inheritance clause, |
|||
# remove any space before a comma, |
|||
# remove any space before a dot, |
|||
# remove any space before an open square-bracket, |
|||
# remove any space before a semicolon in a "for" statement, |
|||
# remove any space between empty square-brackets, |
|||
# remove any space between a method call's empty parameter list parenthesis, |
|||
# remove any space between a method call's name and its opening parenthesis, |
|||
# remove any space between a method call's parameter list parenthesis, |
|||
# remove any space between a method declaration's empty parameter list parenthesis, |
|||
# remove any space between a method declaration's name and its openening parenthesis, |
|||
# remove any space between a method declaration's parameter list parenthesis, |
|||
# remove any space between parentheses, and |
|||
# remove any space between square brackets |
|||
############################################################################### |
|||
[*.cs] |
|||
csharp_new_line_before_members_in_anonymous_types = true |
|||
csharp_new_line_between_query_expression_clauses = true |
|||
# Indentation options |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#indentation-options |
|||
csharp_indent_case_contents = true |
|||
csharp_indent_switch_labels = true |
|||
csharp_indent_labels = no_change |
|||
csharp_indent_block_contents = true |
|||
csharp_indent_braces = false |
|||
csharp_indent_case_contents_when_block = false |
|||
# Spacing options |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#spacing-options |
|||
csharp_space_after_cast = false |
|||
csharp_space_after_colon_in_inheritance_clause = true |
|||
csharp_space_after_comma = true |
|||
csharp_space_after_dot = false |
|||
csharp_space_after_keywords_in_control_flow_statements = true |
|||
csharp_space_after_semicolon_in_for_statement = true |
|||
|
|||
csharp_space_around_binary_operators = before_and_after |
|||
csharp_space_around_declaration_statements = do_not_ignore |
|||
|
|||
csharp_space_between_parentheses = false |
|||
csharp_space_before_colon_in_inheritance_clause = true |
|||
csharp_space_after_colon_in_inheritance_clause = true |
|||
csharp_space_around_binary_operators = before_and_after |
|||
csharp_space_between_method_declaration_parameter_list_parentheses = false |
|||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false |
|||
csharp_space_between_method_declaration_name_and_open_parenthesis = false |
|||
csharp_space_between_method_call_parameter_list_parentheses = false |
|||
csharp_space_between_method_call_empty_parameter_list_parentheses = false |
|||
csharp_space_between_method_call_name_and_opening_parenthesis = false |
|||
csharp_space_after_comma = true |
|||
csharp_space_before_comma = false |
|||
csharp_space_after_dot = false |
|||
csharp_space_before_dot = false |
|||
csharp_space_before_open_square_brackets = false |
|||
csharp_space_after_semicolon_in_for_statement = true |
|||
csharp_space_before_semicolon_in_for_statement = false |
|||
|
|||
csharp_space_around_declaration_statements = false |
|||
csharp_space_before_open_square_brackets = false |
|||
csharp_space_between_empty_square_brackets = false |
|||
csharp_space_between_method_call_empty_parameter_list_parentheses = false |
|||
csharp_space_between_method_call_name_and_opening_parenthesis = false |
|||
csharp_space_between_method_call_parameter_list_parentheses = false |
|||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false |
|||
csharp_space_between_method_declaration_name_and_open_parenthesis = false |
|||
csharp_space_between_method_declaration_parameter_list_parentheses = false |
|||
csharp_space_between_parentheses = false |
|||
csharp_space_between_square_brackets = false |
|||
# Wrapping options |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#wrap-options |
|||
csharp_preserve_single_line_statements = false |
|||
csharp_preserve_single_line_blocks = true |
|||
|
|||
############################################################################### |
|||
# Set csharp style options to: |
|||
# generate braces, |
|||
# suggest simple default expressions, |
|||
# generate a preferred modifier order, |
|||
# suggest conditional delegate calls, |
|||
# suggest deconstructed variable declarations, |
|||
# generate expression-bodied accessors, |
|||
# generate expression-bodied constructors, |
|||
# generate expression-bodied indexers, |
|||
# generate expression-bodied lambdas, |
|||
# generate expression-bodied methods, |
|||
# generate expression-bodied operators, |
|||
# generate expression-bodied properties, |
|||
# suggest inlined variable declarations, |
|||
# suggest local over anonymous functions, |
|||
# suggest pattern-matching over "as" with "null" check, |
|||
# suggest pattern-matching over "is" with "cast" check, |
|||
# suggest throw expressions, |
|||
# generate a discard variable for unused value expression statements, |
|||
# suggest a discard variable for unused assignments, |
|||
# warn when using var for built-in types, |
|||
# warn when using var when the type is not apparent, and |
|||
# warn when not using var when the type is apparent |
|||
# warn when using simplified "using" declaration |
|||
############################################################################### |
|||
[*.cs] |
|||
csharp_prefer_braces = true:silent |
|||
csharp_prefer_simple_default_expression = true:suggestion |
|||
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:silent |
|||
|
|||
csharp_style_conditional_delegate_call = true:suggestion |
|||
csharp_style_deconstructed_variable_declaration = true:suggestion |
|||
|
|||
csharp_style_expression_bodied_accessors = true:silent |
|||
csharp_style_expression_bodied_constructors = true:silent |
|||
csharp_style_expression_bodied_indexers = true:silent |
|||
csharp_style_expression_bodied_lambdas = true:silent |
|||
csharp_style_expression_bodied_methods = true:silent |
|||
csharp_style_expression_bodied_operators = true:silent |
|||
csharp_style_expression_bodied_properties = true:silent |
|||
|
|||
csharp_style_inlined_variable_declaration = true:suggestion |
|||
|
|||
csharp_style_pattern_local_over_anonymous_function = true:suggestion |
|||
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion |
|||
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion |
|||
|
|||
csharp_style_throw_expression = true:suggestion |
|||
|
|||
csharp_style_unused_value_expression_statement_preference = discard_variable:silent |
|||
csharp_style_unused_value_assignment_preference = discard_variable:suggestion |
|||
|
|||
csharp_style_var_for_built_in_types = never |
|||
csharp_style_var_when_type_is_apparent = true:warning |
|||
csharp_style_var_elsewhere = false:warning |
|||
########################################## |
|||
# .NET Naming Conventions |
|||
# https://docs.microsoft.com/visualstudio/ide/editorconfig-naming-conventions |
|||
########################################## |
|||
|
|||
[*.{cs,csx,cake,vb,vbx}] |
|||
|
|||
########################################## |
|||
# Styles |
|||
########################################## |
|||
|
|||
# camel_case_style - Define the camelCase style |
|||
dotnet_naming_style.camel_case_style.capitalization = camel_case |
|||
# pascal_case_style - Define the PascalCase style |
|||
dotnet_naming_style.pascal_case_style.capitalization = pascal_case |
|||
# first_upper_style - The first character must start with an upper-case character |
|||
dotnet_naming_style.first_upper_style.capitalization = first_word_upper |
|||
# prefix_interface_with_i_style - Interfaces must be PascalCase and the first character of an interface must be an 'I' |
|||
dotnet_naming_style.prefix_interface_with_i_style.capitalization = pascal_case |
|||
dotnet_naming_style.prefix_interface_with_i_style.required_prefix = I |
|||
# prefix_type_parameters_with_t_style - Generic Type Parameters must be PascalCase and the first character must be a 'T' |
|||
dotnet_naming_style.prefix_type_parameters_with_t_style.capitalization = pascal_case |
|||
dotnet_naming_style.prefix_type_parameters_with_t_style.required_prefix = T |
|||
# disallowed_style - Anything that has this style applied is marked as disallowed |
|||
dotnet_naming_style.disallowed_style.capitalization = pascal_case |
|||
dotnet_naming_style.disallowed_style.required_prefix = ____RULE_VIOLATION____ |
|||
dotnet_naming_style.disallowed_style.required_suffix = ____RULE_VIOLATION____ |
|||
# internal_error_style - This style should never occur... if it does, it indicates a bug in file or in the parser using the file |
|||
dotnet_naming_style.internal_error_style.capitalization = pascal_case |
|||
dotnet_naming_style.internal_error_style.required_prefix = ____INTERNAL_ERROR____ |
|||
dotnet_naming_style.internal_error_style.required_suffix = ____INTERNAL_ERROR____ |
|||
|
|||
########################################## |
|||
# .NET Design Guideline Field Naming Rules |
|||
# Naming rules for fields follow the .NET Framework design guidelines |
|||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/index |
|||
########################################## |
|||
|
|||
# All public/protected/protected_internal constant fields must be PascalCase |
|||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/field |
|||
dotnet_naming_symbols.public_protected_constant_fields_group.applicable_accessibilities = public, protected, protected_internal |
|||
dotnet_naming_symbols.public_protected_constant_fields_group.required_modifiers = const |
|||
dotnet_naming_symbols.public_protected_constant_fields_group.applicable_kinds = field |
|||
dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.symbols = public_protected_constant_fields_group |
|||
dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.style = pascal_case_style |
|||
dotnet_naming_rule.public_protected_constant_fields_must_be_pascal_case_rule.severity = warning |
|||
|
|||
# All public/protected/protected_internal static readonly fields must be PascalCase |
|||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/field |
|||
dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_accessibilities = public, protected, protected_internal |
|||
dotnet_naming_symbols.public_protected_static_readonly_fields_group.required_modifiers = static, readonly |
|||
dotnet_naming_symbols.public_protected_static_readonly_fields_group.applicable_kinds = field |
|||
dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.symbols = public_protected_static_readonly_fields_group |
|||
dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style |
|||
dotnet_naming_rule.public_protected_static_readonly_fields_must_be_pascal_case_rule.severity = warning |
|||
|
|||
# No other public/protected/protected_internal fields are allowed |
|||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/field |
|||
dotnet_naming_symbols.other_public_protected_fields_group.applicable_accessibilities = public, protected, protected_internal |
|||
dotnet_naming_symbols.other_public_protected_fields_group.applicable_kinds = field |
|||
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.symbols = other_public_protected_fields_group |
|||
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.style = disallowed_style |
|||
dotnet_naming_rule.other_public_protected_fields_disallowed_rule.severity = error |
|||
|
|||
########################################## |
|||
# StyleCop Field Naming Rules |
|||
# Naming rules for fields follow the StyleCop analyzers |
|||
# This does not override any rules using disallowed_style above |
|||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers |
|||
########################################## |
|||
|
|||
# All constant fields must be PascalCase |
|||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1303.md |
|||
dotnet_naming_symbols.stylecop_constant_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private |
|||
dotnet_naming_symbols.stylecop_constant_fields_group.required_modifiers = const |
|||
dotnet_naming_symbols.stylecop_constant_fields_group.applicable_kinds = field |
|||
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.symbols = stylecop_constant_fields_group |
|||
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.style = pascal_case_style |
|||
dotnet_naming_rule.stylecop_constant_fields_must_be_pascal_case_rule.severity = warning |
|||
|
|||
# All static readonly fields must be PascalCase |
|||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1311.md |
|||
dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected, private |
|||
dotnet_naming_symbols.stylecop_static_readonly_fields_group.required_modifiers = static, readonly |
|||
dotnet_naming_symbols.stylecop_static_readonly_fields_group.applicable_kinds = field |
|||
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.symbols = stylecop_static_readonly_fields_group |
|||
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.style = pascal_case_style |
|||
dotnet_naming_rule.stylecop_static_readonly_fields_must_be_pascal_case_rule.severity = warning |
|||
|
|||
# No non-private instance fields are allowed |
|||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1401.md |
|||
dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_accessibilities = public, internal, protected_internal, protected, private_protected |
|||
dotnet_naming_symbols.stylecop_fields_must_be_private_group.applicable_kinds = field |
|||
dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.symbols = stylecop_fields_must_be_private_group |
|||
dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.style = disallowed_style |
|||
dotnet_naming_rule.stylecop_instance_fields_must_be_private_rule.severity = error |
|||
|
|||
# Private fields must be camelCase |
|||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1306.md |
|||
dotnet_naming_symbols.stylecop_private_fields_group.applicable_accessibilities = private |
|||
dotnet_naming_symbols.stylecop_private_fields_group.applicable_kinds = field |
|||
dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.symbols = stylecop_private_fields_group |
|||
dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.style = camel_case_style |
|||
dotnet_naming_rule.stylecop_private_fields_must_be_camel_case_rule.severity = warning |
|||
|
|||
# Local variables must be camelCase |
|||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1312.md |
|||
dotnet_naming_symbols.stylecop_local_fields_group.applicable_accessibilities = local |
|||
dotnet_naming_symbols.stylecop_local_fields_group.applicable_kinds = local |
|||
dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.symbols = stylecop_local_fields_group |
|||
dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.style = camel_case_style |
|||
dotnet_naming_rule.stylecop_local_fields_must_be_camel_case_rule.severity = silent |
|||
|
|||
# This rule should never fire. However, it's included for at least two purposes: |
|||
# First, it helps to understand, reason about, and root-case certain types of issues, such as bugs in .editorconfig parsers. |
|||
# Second, it helps to raise immediate awareness if a new field type is added (as occurred recently in C#). |
|||
dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_accessibilities = * |
|||
dotnet_naming_symbols.sanity_check_uncovered_field_case_group.applicable_kinds = field |
|||
dotnet_naming_rule.sanity_check_uncovered_field_case_rule.symbols = sanity_check_uncovered_field_case_group |
|||
dotnet_naming_rule.sanity_check_uncovered_field_case_rule.style = internal_error_style |
|||
dotnet_naming_rule.sanity_check_uncovered_field_case_rule.severity = error |
|||
|
|||
|
|||
########################################## |
|||
# Other Naming Rules |
|||
########################################## |
|||
|
|||
# All of the following must be PascalCase: |
|||
# - Namespaces |
|||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-namespaces |
|||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md |
|||
# - Classes and Enumerations |
|||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces |
|||
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1300.md |
|||
# - Delegates |
|||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces#names-of-common-types |
|||
# - Constructors, Properties, Events, Methods |
|||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-type-members |
|||
dotnet_naming_symbols.element_group.applicable_kinds = namespace, class, enum, struct, delegate, event, method, property |
|||
dotnet_naming_rule.element_rule.symbols = element_group |
|||
dotnet_naming_rule.element_rule.style = pascal_case_style |
|||
dotnet_naming_rule.element_rule.severity = warning |
|||
|
|||
# Interfaces use PascalCase and are prefixed with uppercase 'I' |
|||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces |
|||
dotnet_naming_symbols.interface_group.applicable_kinds = interface |
|||
dotnet_naming_rule.interface_rule.symbols = interface_group |
|||
dotnet_naming_rule.interface_rule.style = prefix_interface_with_i_style |
|||
dotnet_naming_rule.interface_rule.severity = warning |
|||
|
|||
# Generics Type Parameters use PascalCase and are prefixed with uppercase 'T' |
|||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces |
|||
dotnet_naming_symbols.type_parameter_group.applicable_kinds = type_parameter |
|||
dotnet_naming_rule.type_parameter_rule.symbols = type_parameter_group |
|||
dotnet_naming_rule.type_parameter_rule.style = prefix_type_parameters_with_t_style |
|||
dotnet_naming_rule.type_parameter_rule.severity = warning |
|||
|
|||
# Function parameters use camelCase |
|||
# https://docs.microsoft.com/dotnet/standard/design-guidelines/naming-parameters |
|||
dotnet_naming_symbols.parameters_group.applicable_kinds = parameter |
|||
dotnet_naming_rule.parameters_rule.symbols = parameters_group |
|||
dotnet_naming_rule.parameters_rule.style = camel_case_style |
|||
dotnet_naming_rule.parameters_rule.severity = warning |
|||
|
|||
########################################## |
|||
# License |
|||
########################################## |
|||
# The following applies as to the .editorconfig file ONLY, and is |
|||
# included below for reference, per the requirements of the license |
|||
# corresponding to this .editorconfig file. |
|||
# See: https://github.com/RehanSaeed/EditorConfig |
|||
# |
|||
# MIT License |
|||
# |
|||
# Copyright (c) 2017-2019 Muhammad Rehan Saeed |
|||
# Copyright (c) 2019 Henry Gabryjelski |
|||
# |
|||
# Permission is hereby granted, free of charge, to any |
|||
# person obtaining a copy of this software and associated |
|||
# documentation files (the "Software"), to deal in the |
|||
# Software without restriction, including without limitation |
|||
# the rights to use, copy, modify, merge, publish, distribute, |
|||
# sublicense, and/or sell copies of the Software, and to permit |
|||
# persons to whom the Software is furnished to do so, subject |
|||
# to the following conditions: |
|||
# |
|||
# The above copyright notice and this permission notice shall be |
|||
# included in all copies or substantial portions of the Software. |
|||
# |
|||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
|||
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
|||
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|||
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
|||
# OTHER DEALINGS IN THE SOFTWARE. |
|||
########################################## |
|||
|
|||
@ -1 +1 @@ |
|||
Subproject commit b0d4cd98647996265a668e852574d901b27f22d6 |
|||
Subproject commit 3ad6e96a5f900fecd134f0dbba937cb97c7fb94f |
|||
@ -1,140 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp |
|||
{ |
|||
/// <summary>
|
|||
/// Extension methods for classes that implement <see cref="IComparable{T}"/>.
|
|||
/// </summary>
|
|||
internal static class ComparableExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Restricts a <see cref="byte"/> to be within a specified range.
|
|||
/// </summary>
|
|||
/// <param name="value">The value to clamp.</param>
|
|||
/// <param name="min">The minimum value. If value is less than min, min will be returned.</param>
|
|||
/// <param name="max">The maximum value. If value is greater than max, max will be returned.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="byte"/> representing the clamped value.
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static byte Clamp(this byte value, byte min, byte max) |
|||
{ |
|||
// Order is important here as someone might set min to higher than max.
|
|||
if (value >= max) |
|||
{ |
|||
return max; |
|||
} |
|||
|
|||
if (value <= min) |
|||
{ |
|||
return min; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Restricts a <see cref="uint"/> to be within a specified range.
|
|||
/// </summary>
|
|||
/// <param name="value">The The value to clamp.</param>
|
|||
/// <param name="min">The minimum value. If value is less than min, min will be returned.</param>
|
|||
/// <param name="max">The maximum value. If value is greater than max, max will be returned.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="int"/> representing the clamped value.
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static uint Clamp(this uint value, uint min, uint max) |
|||
{ |
|||
if (value >= max) |
|||
{ |
|||
return max; |
|||
} |
|||
|
|||
if (value <= min) |
|||
{ |
|||
return min; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Restricts a <see cref="int"/> to be within a specified range.
|
|||
/// </summary>
|
|||
/// <param name="value">The The value to clamp.</param>
|
|||
/// <param name="min">The minimum value. If value is less than min, min will be returned.</param>
|
|||
/// <param name="max">The maximum value. If value is greater than max, max will be returned.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="int"/> representing the clamped value.
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static int Clamp(this int value, int min, int max) |
|||
{ |
|||
if (value >= max) |
|||
{ |
|||
return max; |
|||
} |
|||
|
|||
if (value <= min) |
|||
{ |
|||
return min; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Restricts a <see cref="float"/> to be within a specified range.
|
|||
/// </summary>
|
|||
/// <param name="value">The The value to clamp.</param>
|
|||
/// <param name="min">The minimum value. If value is less than min, min will be returned.</param>
|
|||
/// <param name="max">The maximum value. If value is greater than max, max will be returned.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/> representing the clamped value.
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float Clamp(this float value, float min, float max) |
|||
{ |
|||
if (value >= max) |
|||
{ |
|||
return max; |
|||
} |
|||
|
|||
if (value <= min) |
|||
{ |
|||
return min; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Restricts a <see cref="double"/> to be within a specified range.
|
|||
/// </summary>
|
|||
/// <param name="value">The The value to clamp.</param>
|
|||
/// <param name="min">The minimum value. If value is less than min, min will be returned.</param>
|
|||
/// <param name="max">The maximum value. If value is greater than max, max will be returned.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="double"/> representing the clamped value.
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static double Clamp(this double value, double min, double max) |
|||
{ |
|||
if (value >= max) |
|||
{ |
|||
return max; |
|||
} |
|||
|
|||
if (value <= min) |
|||
{ |
|||
return min; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,177 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp |
|||
{ |
|||
/// <summary>
|
|||
/// Provides optimized static methods for common mathematical functions specific
|
|||
/// to color processing.
|
|||
/// </summary>
|
|||
internal static class ColorNumerics |
|||
{ |
|||
/// <summary>
|
|||
/// Vector for converting pixel to gray value as specified by
|
|||
/// ITU-R Recommendation BT.709.
|
|||
/// </summary>
|
|||
private static readonly Vector4 Bt709 = new Vector4(.2126f, .7152f, .0722f, 0.0f); |
|||
|
|||
/// <summary>
|
|||
/// Convert a pixel value to grayscale using ITU-R Recommendation BT.709.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector to get the luminance from.</param>
|
|||
/// <param name="luminanceLevels">
|
|||
/// The number of luminance levels (256 for 8 bit, 65536 for 16 bit grayscale images).
|
|||
/// </param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static int GetBT709Luminance(ref Vector4 vector, int luminanceLevels) |
|||
=> (int)MathF.Round(Vector4.Dot(vector, Bt709) * (luminanceLevels - 1)); |
|||
|
|||
/// <summary>
|
|||
/// Gets the luminance from the rgb components using the formula
|
|||
/// as specified by ITU-R Recommendation BT.709.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component.</param>
|
|||
/// <param name="g">The green component.</param>
|
|||
/// <param name="b">The blue component.</param>
|
|||
/// <returns>The <see cref="byte"/>.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static byte Get8BitBT709Luminance(byte r, byte g, byte b) |
|||
=> (byte)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F); |
|||
|
|||
/// <summary>
|
|||
/// Gets the luminance from the rgb components using the formula as
|
|||
/// specified by ITU-R Recommendation BT.709.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component.</param>
|
|||
/// <param name="g">The green component.</param>
|
|||
/// <param name="b">The blue component.</param>
|
|||
/// <returns>The <see cref="ushort"/>.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static ushort Get16BitBT709Luminance(ushort r, ushort g, ushort b) |
|||
=> (ushort)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F); |
|||
|
|||
/// <summary>
|
|||
/// Gets the luminance from the rgb components using the formula as specified
|
|||
/// by ITU-R Recommendation BT.709.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component.</param>
|
|||
/// <param name="g">The green component.</param>
|
|||
/// <param name="b">The blue component.</param>
|
|||
/// <returns>The <see cref="ushort"/>.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static ushort Get16BitBT709Luminance(float r, float g, float b) |
|||
=> (ushort)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F); |
|||
|
|||
/// <summary>
|
|||
/// Scales a value from a 16 bit <see cref="ushort"/> to an
|
|||
/// 8 bit <see cref="byte"/> equivalent.
|
|||
/// </summary>
|
|||
/// <param name="component">The 8 bit component value.</param>
|
|||
/// <returns>The <see cref="byte"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static byte DownScaleFrom16BitTo8Bit(ushort component) |
|||
{ |
|||
// To scale to 8 bits From a 16-bit value V the required value (from the PNG specification) is:
|
|||
//
|
|||
// (V * 255) / 65535
|
|||
//
|
|||
// This reduces to round(V / 257), or floor((V + 128.5)/257)
|
|||
//
|
|||
// Represent V as the two byte value vhi.vlo. Make a guess that the
|
|||
// result is the top byte of V, vhi, then the correction to this value
|
|||
// is:
|
|||
//
|
|||
// error = floor(((V-vhi.vhi) + 128.5) / 257)
|
|||
// = floor(((vlo-vhi) + 128.5) / 257)
|
|||
//
|
|||
// This can be approximated using integer arithmetic (and a signed
|
|||
// shift):
|
|||
//
|
|||
// error = (vlo-vhi+128) >> 8;
|
|||
//
|
|||
// The approximate differs from the exact answer only when (vlo-vhi) is
|
|||
// 128; it then gives a correction of +1 when the exact correction is
|
|||
// 0. This gives 128 errors. The exact answer (correct for all 16-bit
|
|||
// input values) is:
|
|||
//
|
|||
// error = (vlo-vhi+128)*65535 >> 24;
|
|||
//
|
|||
// An alternative arithmetic calculation which also gives no errors is:
|
|||
//
|
|||
// (V * 255 + 32895) >> 16
|
|||
return (byte)(((component * 255) + 32895) >> 16); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Scales a value from an 8 bit <see cref="byte"/> to
|
|||
/// an 16 bit <see cref="ushort"/> equivalent.
|
|||
/// </summary>
|
|||
/// <param name="component">The 8 bit component value.</param>
|
|||
/// <returns>The <see cref="ushort"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static ushort UpscaleFrom8BitTo16Bit(byte component) |
|||
=> (ushort)(component * 257); |
|||
|
|||
/// <summary>
|
|||
/// Returns how many bits are required to store the specified number of colors.
|
|||
/// Performs a Log2() on the value.
|
|||
/// </summary>
|
|||
/// <param name="colors">The number of colors.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="int"/>
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static int GetBitsNeededForColorDepth(int colors) |
|||
=> Math.Max(1, (int)Math.Ceiling(Math.Log(colors, 2))); |
|||
|
|||
/// <summary>
|
|||
/// Returns how many colors will be created by the specified number of bits.
|
|||
/// </summary>
|
|||
/// <param name="bitDepth">The bit depth.</param>
|
|||
/// <returns>The <see cref="int"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static int GetColorCountForBitDepth(int bitDepth) |
|||
=> 1 << bitDepth; |
|||
|
|||
/// <summary>
|
|||
/// Transforms a vector by the given color matrix.
|
|||
/// </summary>
|
|||
/// <param name="vector">The source vector.</param>
|
|||
/// <param name="matrix">The transformation color matrix.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Transform(ref Vector4 vector, ref ColorMatrix matrix) |
|||
{ |
|||
float x = vector.X; |
|||
float y = vector.Y; |
|||
float z = vector.Z; |
|||
float w = vector.W; |
|||
|
|||
vector.X = (x * matrix.M11) + (y * matrix.M21) + (z * matrix.M31) + (w * matrix.M41) + matrix.M51; |
|||
vector.Y = (x * matrix.M12) + (y * matrix.M22) + (z * matrix.M32) + (w * matrix.M42) + matrix.M52; |
|||
vector.Z = (x * matrix.M13) + (y * matrix.M23) + (z * matrix.M33) + (w * matrix.M43) + matrix.M53; |
|||
vector.W = (x * matrix.M14) + (y * matrix.M24) + (z * matrix.M34) + (w * matrix.M44) + matrix.M54; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Bulk variant of <see cref="Transform(ref Vector4, ref ColorMatrix)"/>.
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors</param>
|
|||
/// <param name="matrix">The transformation color matrix.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Transform(Span<Vector4> vectors, ref ColorMatrix matrix) |
|||
{ |
|||
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); |
|||
|
|||
for (int i = 0; i < vectors.Length; i++) |
|||
{ |
|||
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); |
|||
Transform(ref v, ref matrix); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,379 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp |
|||
{ |
|||
/// <summary>
|
|||
/// Provides common mathematical methods.
|
|||
/// </summary>
|
|||
internal static class ImageMaths |
|||
{ |
|||
/// <summary>
|
|||
/// Vector for converting pixel to gray value as specified by ITU-R Recommendation BT.709.
|
|||
/// </summary>
|
|||
private static readonly Vector4 Bt709 = new Vector4(.2126f, .7152f, .0722f, 0.0f); |
|||
|
|||
/// <summary>
|
|||
/// Convert a pixel value to grayscale using ITU-R Recommendation BT.709.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector to get the luminance from.</param>
|
|||
/// <param name="luminanceLevels">The number of luminance levels (256 for 8 bit, 65536 for 16 bit grayscale images)</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static int GetBT709Luminance(ref Vector4 vector, int luminanceLevels) |
|||
=> (int)MathF.Round(Vector4.Dot(vector, Bt709) * (luminanceLevels - 1)); |
|||
|
|||
/// <summary>
|
|||
/// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component.</param>
|
|||
/// <param name="g">The green component.</param>
|
|||
/// <param name="b">The blue component.</param>
|
|||
/// <returns>The <see cref="byte"/>.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static byte Get8BitBT709Luminance(byte r, byte g, byte b) => |
|||
(byte)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F); |
|||
|
|||
/// <summary>
|
|||
/// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component.</param>
|
|||
/// <param name="g">The green component.</param>
|
|||
/// <param name="b">The blue component.</param>
|
|||
/// <returns>The <see cref="ushort"/>.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static ushort Get16BitBT709Luminance(ushort r, ushort g, ushort b) => |
|||
(ushort)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F); |
|||
|
|||
/// <summary>
|
|||
/// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component.</param>
|
|||
/// <param name="g">The green component.</param>
|
|||
/// <param name="b">The blue component.</param>
|
|||
/// <returns>The <see cref="ushort"/>.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static ushort Get16BitBT709Luminance(float r, float g, float b) => |
|||
(ushort)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F); |
|||
|
|||
/// <summary>
|
|||
/// Scales a value from a 16 bit <see cref="ushort"/> to it's 8 bit <see cref="byte"/> equivalent.
|
|||
/// </summary>
|
|||
/// <param name="component">The 8 bit component value.</param>
|
|||
/// <returns>The <see cref="byte"/></returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static byte DownScaleFrom16BitTo8Bit(ushort component) |
|||
{ |
|||
// To scale to 8 bits From a 16-bit value V the required value (from the PNG specification) is:
|
|||
//
|
|||
// (V * 255) / 65535
|
|||
//
|
|||
// This reduces to round(V / 257), or floor((V + 128.5)/257)
|
|||
//
|
|||
// Represent V as the two byte value vhi.vlo. Make a guess that the
|
|||
// result is the top byte of V, vhi, then the correction to this value
|
|||
// is:
|
|||
//
|
|||
// error = floor(((V-vhi.vhi) + 128.5) / 257)
|
|||
// = floor(((vlo-vhi) + 128.5) / 257)
|
|||
//
|
|||
// This can be approximated using integer arithmetic (and a signed
|
|||
// shift):
|
|||
//
|
|||
// error = (vlo-vhi+128) >> 8;
|
|||
//
|
|||
// The approximate differs from the exact answer only when (vlo-vhi) is
|
|||
// 128; it then gives a correction of +1 when the exact correction is
|
|||
// 0. This gives 128 errors. The exact answer (correct for all 16-bit
|
|||
// input values) is:
|
|||
//
|
|||
// error = (vlo-vhi+128)*65535 >> 24;
|
|||
//
|
|||
// An alternative arithmetic calculation which also gives no errors is:
|
|||
//
|
|||
// (V * 255 + 32895) >> 16
|
|||
return (byte)(((component * 255) + 32895) >> 16); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Scales a value from an 8 bit <see cref="byte"/> to it's 16 bit <see cref="ushort"/> equivalent.
|
|||
/// </summary>
|
|||
/// <param name="component">The 8 bit component value.</param>
|
|||
/// <returns>The <see cref="ushort"/></returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static ushort UpscaleFrom8BitTo16Bit(byte component) => (ushort)(component * 257); |
|||
|
|||
/// <summary>
|
|||
/// Determine the Greatest CommonDivisor (GCD) of two numbers.
|
|||
/// </summary>
|
|||
public static int GreatestCommonDivisor(int a, int b) |
|||
{ |
|||
while (b != 0) |
|||
{ |
|||
int temp = b; |
|||
b = a % b; |
|||
a = temp; |
|||
} |
|||
|
|||
return a; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Determine the Least Common Multiple (LCM) of two numbers.
|
|||
/// </summary>
|
|||
public static int LeastCommonMultiple(int a, int b) |
|||
{ |
|||
// https://en.wikipedia.org/wiki/Least_common_multiple#Reduction_by_the_greatest_common_divisor
|
|||
return (a / GreatestCommonDivisor(a, b)) * b; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Calculates <paramref name="x"/> % 2
|
|||
/// </summary>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static int Modulo2(int x) => x & 1; |
|||
|
|||
/// <summary>
|
|||
/// Calculates <paramref name="x"/> % 4
|
|||
/// </summary>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static int Modulo4(int x) => x & 3; |
|||
|
|||
/// <summary>
|
|||
/// Calculates <paramref name="x"/> % 8
|
|||
/// </summary>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static int Modulo8(int x) => x & 7; |
|||
|
|||
/// <summary>
|
|||
/// Fast (x mod m) calculator, with the restriction that
|
|||
/// <paramref name="m"/> should be power of 2.
|
|||
/// </summary>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static int ModuloP2(int x, int m) => x & (m - 1); |
|||
|
|||
/// <summary>
|
|||
/// Returns the absolute value of a 32-bit signed integer. Uses bit shifting to speed up the operation.
|
|||
/// </summary>
|
|||
/// <param name="x">
|
|||
/// A number that is greater than <see cref="int.MinValue"/>, but less than or equal to <see cref="int.MaxValue"/>
|
|||
/// </param>
|
|||
/// <returns>The <see cref="int"/></returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static int FastAbs(int x) |
|||
{ |
|||
int y = x >> 31; |
|||
return (x ^ y) - y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a specified number raised to the power of 2
|
|||
/// </summary>
|
|||
/// <param name="x">A single-precision floating-point number</param>
|
|||
/// <returns>The number <paramref name="x" /> raised to the power of 2.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float Pow2(float x) => x * x; |
|||
|
|||
/// <summary>
|
|||
/// Returns a specified number raised to the power of 3
|
|||
/// </summary>
|
|||
/// <param name="x">A single-precision floating-point number</param>
|
|||
/// <returns>The number <paramref name="x" /> raised to the power of 3.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float Pow3(float x) => x * x * x; |
|||
|
|||
/// <summary>
|
|||
/// Returns how many bits are required to store the specified number of colors.
|
|||
/// Performs a Log2() on the value.
|
|||
/// </summary>
|
|||
/// <param name="colors">The number of colors.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="int"/>
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static int GetBitsNeededForColorDepth(int colors) => Math.Max(1, (int)Math.Ceiling(Math.Log(colors, 2))); |
|||
|
|||
/// <summary>
|
|||
/// Returns how many colors will be created by the specified number of bits.
|
|||
/// </summary>
|
|||
/// <param name="bitDepth">The bit depth.</param>
|
|||
/// <returns>The <see cref="int"/></returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static int GetColorCountForBitDepth(int bitDepth) => 1 << bitDepth; |
|||
|
|||
/// <summary>
|
|||
/// Implementation of 1D Gaussian G(x) function
|
|||
/// </summary>
|
|||
/// <param name="x">The x provided to G(x).</param>
|
|||
/// <param name="sigma">The spread of the blur.</param>
|
|||
/// <returns>The Gaussian G(x)</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float Gaussian(float x, float sigma) |
|||
{ |
|||
const float Numerator = 1.0f; |
|||
float denominator = MathF.Sqrt(2 * MathF.PI) * sigma; |
|||
|
|||
float exponentNumerator = -x * x; |
|||
float exponentDenominator = 2 * Pow2(sigma); |
|||
|
|||
float left = Numerator / denominator; |
|||
float right = MathF.Exp(exponentNumerator / exponentDenominator); |
|||
|
|||
return left * right; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the result of a normalized sine cardinal function for the given value.
|
|||
/// SinC(x) = sin(pi*x)/(pi*x).
|
|||
/// </summary>
|
|||
/// <param name="f">A single-precision floating-point number to calculate the result for.</param>
|
|||
/// <returns>
|
|||
/// The sine cardinal of <paramref name="f" />.
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float SinC(float f) |
|||
{ |
|||
if (MathF.Abs(f) > Constants.Epsilon) |
|||
{ |
|||
f *= MathF.PI; |
|||
float result = MathF.Sin(f) / f; |
|||
return MathF.Abs(result) < Constants.Epsilon ? 0F : result; |
|||
} |
|||
|
|||
return 1F; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the bounding <see cref="Rectangle"/> from the given points.
|
|||
/// </summary>
|
|||
/// <param name="topLeft">
|
|||
/// The <see cref="Point"/> designating the top left position.
|
|||
/// </param>
|
|||
/// <param name="bottomRight">
|
|||
/// The <see cref="Point"/> designating the bottom right position.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// The bounding <see cref="Rectangle"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static Rectangle GetBoundingRectangle(Point topLeft, Point bottomRight) => new Rectangle(topLeft.X, topLeft.Y, bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y); |
|||
|
|||
/// <summary>
|
|||
/// Finds the bounding rectangle based on the first instance of any color component other
|
|||
/// than the given one.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="bitmap">The <see cref="Image{TPixel}"/> to search within.</param>
|
|||
/// <param name="componentValue">The color component value to remove.</param>
|
|||
/// <param name="channel">The <see cref="RgbaComponent"/> channel to test against.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rectangle"/>.
|
|||
/// </returns>
|
|||
public static Rectangle GetFilteredBoundingRectangle<TPixel>(ImageFrame<TPixel> bitmap, float componentValue, RgbaComponent channel = RgbaComponent.B) |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
int width = bitmap.Width; |
|||
int height = bitmap.Height; |
|||
Point topLeft = default; |
|||
Point bottomRight = default; |
|||
|
|||
Func<ImageFrame<TPixel>, int, int, float, bool> delegateFunc; |
|||
|
|||
// Determine which channel to check against
|
|||
switch (channel) |
|||
{ |
|||
case RgbaComponent.R: |
|||
delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().X - b) > Constants.Epsilon; |
|||
break; |
|||
|
|||
case RgbaComponent.G: |
|||
delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().Y - b) > Constants.Epsilon; |
|||
break; |
|||
|
|||
case RgbaComponent.B: |
|||
delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().Z - b) > Constants.Epsilon; |
|||
break; |
|||
|
|||
default: |
|||
delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().W - b) > Constants.Epsilon; |
|||
break; |
|||
} |
|||
|
|||
int GetMinY(ImageFrame<TPixel> pixels) |
|||
{ |
|||
for (int y = 0; y < height; y++) |
|||
{ |
|||
for (int x = 0; x < width; x++) |
|||
{ |
|||
if (delegateFunc(pixels, x, y, componentValue)) |
|||
{ |
|||
return y; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int GetMaxY(ImageFrame<TPixel> pixels) |
|||
{ |
|||
for (int y = height - 1; y > -1; y--) |
|||
{ |
|||
for (int x = 0; x < width; x++) |
|||
{ |
|||
if (delegateFunc(pixels, x, y, componentValue)) |
|||
{ |
|||
return y; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return height; |
|||
} |
|||
|
|||
int GetMinX(ImageFrame<TPixel> pixels) |
|||
{ |
|||
for (int x = 0; x < width; x++) |
|||
{ |
|||
for (int y = 0; y < height; y++) |
|||
{ |
|||
if (delegateFunc(pixels, x, y, componentValue)) |
|||
{ |
|||
return x; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int GetMaxX(ImageFrame<TPixel> pixels) |
|||
{ |
|||
for (int x = width - 1; x > -1; x--) |
|||
{ |
|||
for (int y = 0; y < height; y++) |
|||
{ |
|||
if (delegateFunc(pixels, x, y, componentValue)) |
|||
{ |
|||
return x; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return width; |
|||
} |
|||
|
|||
topLeft.Y = GetMinY(bitmap); |
|||
topLeft.X = GetMinX(bitmap); |
|||
bottomRight.Y = (GetMaxY(bitmap) + 1).Clamp(0, height); |
|||
bottomRight.X = (GetMaxX(bitmap) + 1).Clamp(0, width); |
|||
|
|||
return GetBoundingRectangle(topLeft, bottomRight); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,551 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
#if SUPPORTS_RUNTIME_INTRINSICS
|
|||
using System.Runtime.Intrinsics; |
|||
using System.Runtime.Intrinsics.X86; |
|||
#endif
|
|||
|
|||
namespace SixLabors.ImageSharp |
|||
{ |
|||
/// <summary>
|
|||
/// Provides optimized static methods for trigonometric, logarithmic,
|
|||
/// and other common mathematical functions.
|
|||
/// </summary>
|
|||
internal static class Numerics |
|||
{ |
|||
#if SUPPORTS_RUNTIME_INTRINSICS
|
|||
private const int BlendAlphaControl = 0b_10_00_10_00; |
|||
private const int ShuffleAlphaControl = 0b_11_11_11_11; |
|||
#endif
|
|||
|
|||
/// <summary>
|
|||
/// Determine the Greatest CommonDivisor (GCD) of two numbers.
|
|||
/// </summary>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static int GreatestCommonDivisor(int a, int b) |
|||
{ |
|||
while (b != 0) |
|||
{ |
|||
int temp = b; |
|||
b = a % b; |
|||
a = temp; |
|||
} |
|||
|
|||
return a; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Determine the Least Common Multiple (LCM) of two numbers.
|
|||
/// </summary>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static int LeastCommonMultiple(int a, int b) |
|||
{ |
|||
// https://en.wikipedia.org/wiki/Least_common_multiple#Reduction_by_the_greatest_common_divisor
|
|||
return (a / GreatestCommonDivisor(a, b)) * b; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Calculates <paramref name="x"/> % 2
|
|||
/// </summary>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static int Modulo2(int x) => x & 1; |
|||
|
|||
/// <summary>
|
|||
/// Calculates <paramref name="x"/> % 4
|
|||
/// </summary>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static int Modulo4(int x) => x & 3; |
|||
|
|||
/// <summary>
|
|||
/// Calculates <paramref name="x"/> % 8
|
|||
/// </summary>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static int Modulo8(int x) => x & 7; |
|||
|
|||
/// <summary>
|
|||
/// Fast (x mod m) calculator, with the restriction that
|
|||
/// <paramref name="m"/> should be power of 2.
|
|||
/// </summary>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static int ModuloP2(int x, int m) => x & (m - 1); |
|||
|
|||
/// <summary>
|
|||
/// Returns the absolute value of a 32-bit signed integer.
|
|||
/// Uses bit shifting to speed up the operation compared to <see cref="Math"/>.
|
|||
/// </summary>
|
|||
/// <param name="x">
|
|||
/// A number that is greater than <see cref="int.MinValue"/>, but less than
|
|||
/// or equal to <see cref="int.MaxValue"/>
|
|||
/// </param>
|
|||
/// <returns>The <see cref="int"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static int Abs(int x) |
|||
{ |
|||
int y = x >> 31; |
|||
return (x ^ y) - y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a specified number raised to the power of 2
|
|||
/// </summary>
|
|||
/// <param name="x">A single-precision floating-point number</param>
|
|||
/// <returns>The number <paramref name="x" /> raised to the power of 2.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Pow2(float x) => x * x; |
|||
|
|||
/// <summary>
|
|||
/// Returns a specified number raised to the power of 3
|
|||
/// </summary>
|
|||
/// <param name="x">A single-precision floating-point number</param>
|
|||
/// <returns>The number <paramref name="x" /> raised to the power of 3.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Pow3(float x) => x * x * x; |
|||
|
|||
/// <summary>
|
|||
/// Implementation of 1D Gaussian G(x) function
|
|||
/// </summary>
|
|||
/// <param name="x">The x provided to G(x).</param>
|
|||
/// <param name="sigma">The spread of the blur.</param>
|
|||
/// <returns>The Gaussian G(x)</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Gaussian(float x, float sigma) |
|||
{ |
|||
const float Numerator = 1.0f; |
|||
float denominator = MathF.Sqrt(2 * MathF.PI) * sigma; |
|||
|
|||
float exponentNumerator = -x * x; |
|||
float exponentDenominator = 2 * Pow2(sigma); |
|||
|
|||
float left = Numerator / denominator; |
|||
float right = MathF.Exp(exponentNumerator / exponentDenominator); |
|||
|
|||
return left * right; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the result of a normalized sine cardinal function for the given value.
|
|||
/// SinC(x) = sin(pi*x)/(pi*x).
|
|||
/// </summary>
|
|||
/// <param name="f">A single-precision floating-point number to calculate the result for.</param>
|
|||
/// <returns>
|
|||
/// The sine cardinal of <paramref name="f" />.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float SinC(float f) |
|||
{ |
|||
if (MathF.Abs(f) > Constants.Epsilon) |
|||
{ |
|||
f *= MathF.PI; |
|||
float result = MathF.Sin(f) / f; |
|||
return MathF.Abs(result) < Constants.Epsilon ? 0F : result; |
|||
} |
|||
|
|||
return 1F; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the value clamped to the inclusive range of min and max.
|
|||
/// </summary>
|
|||
/// <param name="value">The value to clamp.</param>
|
|||
/// <param name="min">The minimum inclusive value.</param>
|
|||
/// <param name="max">The maximum inclusive value.</param>
|
|||
/// <returns>The clamped <see cref="byte"/>.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static byte Clamp(byte value, byte min, byte max) |
|||
{ |
|||
// Order is important here as someone might set min to higher than max.
|
|||
if (value > max) |
|||
{ |
|||
return max; |
|||
} |
|||
|
|||
if (value < min) |
|||
{ |
|||
return min; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the value clamped to the inclusive range of min and max.
|
|||
/// </summary>
|
|||
/// <param name="value">The value to clamp.</param>
|
|||
/// <param name="min">The minimum inclusive value.</param>
|
|||
/// <param name="max">The maximum inclusive value.</param>
|
|||
/// <returns>The clamped <see cref="uint"/>.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static uint Clamp(uint value, uint min, uint max) |
|||
{ |
|||
if (value > max) |
|||
{ |
|||
return max; |
|||
} |
|||
|
|||
if (value < min) |
|||
{ |
|||
return min; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the value clamped to the inclusive range of min and max.
|
|||
/// </summary>
|
|||
/// <param name="value">The value to clamp.</param>
|
|||
/// <param name="min">The minimum inclusive value.</param>
|
|||
/// <param name="max">The maximum inclusive value.</param>
|
|||
/// <returns>The clamped <see cref="uint"/>.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static int Clamp(int value, int min, int max) |
|||
{ |
|||
if (value > max) |
|||
{ |
|||
return max; |
|||
} |
|||
|
|||
if (value < min) |
|||
{ |
|||
return min; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the value clamped to the inclusive range of min and max.
|
|||
/// </summary>
|
|||
/// <param name="value">The value to clamp.</param>
|
|||
/// <param name="min">The minimum inclusive value.</param>
|
|||
/// <param name="max">The maximum inclusive value.</param>
|
|||
/// <returns>The clamped <see cref="float"/>.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Clamp(float value, float min, float max) |
|||
{ |
|||
if (value > max) |
|||
{ |
|||
return max; |
|||
} |
|||
|
|||
if (value < min) |
|||
{ |
|||
return min; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the value clamped to the inclusive range of min and max.
|
|||
/// </summary>
|
|||
/// <param name="value">The value to clamp.</param>
|
|||
/// <param name="min">The minimum inclusive value.</param>
|
|||
/// <param name="max">The maximum inclusive value.</param>
|
|||
/// <returns>The clamped <see cref="double"/>.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static double Clamp(double value, double min, double max) |
|||
{ |
|||
if (value > max) |
|||
{ |
|||
return max; |
|||
} |
|||
|
|||
if (value < min) |
|||
{ |
|||
return min; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the value clamped to the inclusive range of min and max.
|
|||
/// 5x Faster than <see cref="Vector4.Clamp(Vector4, Vector4, Vector4)"/>
|
|||
/// on platforms < NET 5.
|
|||
/// </summary>
|
|||
/// <param name="value">The value to clamp.</param>
|
|||
/// <param name="min">The minimum inclusive value.</param>
|
|||
/// <param name="max">The maximum inclusive value.</param>
|
|||
/// <returns>The clamped <see cref="Vector4"/>.</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Vector4 Clamp(Vector4 value, Vector4 min, Vector4 max) |
|||
=> Vector4.Min(Vector4.Max(value, min), max); |
|||
|
|||
/// <summary>
|
|||
/// Clamps the span values to the inclusive range of min and max.
|
|||
/// </summary>
|
|||
/// <param name="span">The span containing the values to clamp.</param>
|
|||
/// <param name="min">The minimum inclusive value.</param>
|
|||
/// <param name="max">The maximum inclusive value.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Clamp(Span<byte> span, byte min, byte max) |
|||
{ |
|||
Span<byte> remainder = span.Slice(ClampReduce(span, min, max)); |
|||
|
|||
if (remainder.Length > 0) |
|||
{ |
|||
for (int i = 0; i < remainder.Length; i++) |
|||
{ |
|||
ref byte v = ref remainder[i]; |
|||
v = Clamp(v, min, max); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Clamps the span values to the inclusive range of min and max.
|
|||
/// </summary>
|
|||
/// <param name="span">The span containing the values to clamp.</param>
|
|||
/// <param name="min">The minimum inclusive value.</param>
|
|||
/// <param name="max">The maximum inclusive value.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Clamp(Span<uint> span, uint min, uint max) |
|||
{ |
|||
Span<uint> remainder = span.Slice(ClampReduce(span, min, max)); |
|||
|
|||
if (remainder.Length > 0) |
|||
{ |
|||
for (int i = 0; i < remainder.Length; i++) |
|||
{ |
|||
ref uint v = ref remainder[i]; |
|||
v = Clamp(v, min, max); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Clamps the span values to the inclusive range of min and max.
|
|||
/// </summary>
|
|||
/// <param name="span">The span containing the values to clamp.</param>
|
|||
/// <param name="min">The minimum inclusive value.</param>
|
|||
/// <param name="max">The maximum inclusive value.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Clamp(Span<int> span, int min, int max) |
|||
{ |
|||
Span<int> remainder = span.Slice(ClampReduce(span, min, max)); |
|||
|
|||
if (remainder.Length > 0) |
|||
{ |
|||
for (int i = 0; i < remainder.Length; i++) |
|||
{ |
|||
ref int v = ref remainder[i]; |
|||
v = Clamp(v, min, max); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Clamps the span values to the inclusive range of min and max.
|
|||
/// </summary>
|
|||
/// <param name="span">The span containing the values to clamp.</param>
|
|||
/// <param name="min">The minimum inclusive value.</param>
|
|||
/// <param name="max">The maximum inclusive value.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Clamp(Span<float> span, float min, float max) |
|||
{ |
|||
Span<float> remainder = span.Slice(ClampReduce(span, min, max)); |
|||
|
|||
if (remainder.Length > 0) |
|||
{ |
|||
for (int i = 0; i < remainder.Length; i++) |
|||
{ |
|||
ref float v = ref remainder[i]; |
|||
v = Clamp(v, min, max); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Clamps the span values to the inclusive range of min and max.
|
|||
/// </summary>
|
|||
/// <param name="span">The span containing the values to clamp.</param>
|
|||
/// <param name="min">The minimum inclusive value.</param>
|
|||
/// <param name="max">The maximum inclusive value.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Clamp(Span<double> span, double min, double max) |
|||
{ |
|||
Span<double> remainder = span.Slice(ClampReduce(span, min, max)); |
|||
|
|||
if (remainder.Length > 0) |
|||
{ |
|||
for (int i = 0; i < remainder.Length; i++) |
|||
{ |
|||
ref double v = ref remainder[i]; |
|||
v = Clamp(v, min, max); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static int ClampReduce<T>(Span<T> span, T min, T max) |
|||
where T : unmanaged |
|||
{ |
|||
if (Vector.IsHardwareAccelerated && span.Length >= Vector<T>.Count) |
|||
{ |
|||
int remainder = ModuloP2(span.Length, Vector<T>.Count); |
|||
int adjustedCount = span.Length - remainder; |
|||
|
|||
if (adjustedCount > 0) |
|||
{ |
|||
ClampImpl(span.Slice(0, adjustedCount), min, max); |
|||
} |
|||
|
|||
return adjustedCount; |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static void ClampImpl<T>(Span<T> span, T min, T max) |
|||
where T : unmanaged |
|||
{ |
|||
ref T sRef = ref MemoryMarshal.GetReference(span); |
|||
ref Vector<T> vsBase = ref Unsafe.As<T, Vector<T>>(ref MemoryMarshal.GetReference(span)); |
|||
var vmin = new Vector<T>(min); |
|||
var vmax = new Vector<T>(max); |
|||
|
|||
int n = span.Length / Vector<T>.Count; |
|||
int m = Modulo4(n); |
|||
int u = n - m; |
|||
|
|||
for (int i = 0; i < u; i += 4) |
|||
{ |
|||
ref Vector<T> vs0 = ref Unsafe.Add(ref vsBase, i); |
|||
ref Vector<T> vs1 = ref Unsafe.Add(ref vs0, 1); |
|||
ref Vector<T> vs2 = ref Unsafe.Add(ref vs0, 2); |
|||
ref Vector<T> vs3 = ref Unsafe.Add(ref vs0, 3); |
|||
|
|||
vs0 = Vector.Min(Vector.Max(vmin, vs0), vmax); |
|||
vs1 = Vector.Min(Vector.Max(vmin, vs1), vmax); |
|||
vs2 = Vector.Min(Vector.Max(vmin, vs2), vmax); |
|||
vs3 = Vector.Min(Vector.Max(vmin, vs3), vmax); |
|||
} |
|||
|
|||
if (m > 0) |
|||
{ |
|||
for (int i = u; i < n; i++) |
|||
{ |
|||
ref Vector<T> vs0 = ref Unsafe.Add(ref vsBase, i); |
|||
vs0 = Vector.Min(Vector.Max(vmin, vs0), vmax); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Pre-multiplies the "x", "y", "z" components of a vector by its "w" component leaving the "w" component intact.
|
|||
/// </summary>
|
|||
/// <param name="source">The <see cref="Vector4"/> to premultiply</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Premultiply(ref Vector4 source) |
|||
{ |
|||
float w = source.W; |
|||
source *= w; |
|||
source.W = w; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Reverses the result of premultiplying a vector via <see cref="Premultiply(ref Vector4)"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The <see cref="Vector4"/> to premultiply</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void UnPremultiply(ref Vector4 source) |
|||
{ |
|||
float w = source.W; |
|||
source /= w; |
|||
source.W = w; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Bulk variant of <see cref="Premultiply(ref Vector4)"/>
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Premultiply(Span<Vector4> vectors) |
|||
{ |
|||
#if SUPPORTS_RUNTIME_INTRINSICS
|
|||
if (Avx2.IsSupported && vectors.Length >= 2) |
|||
{ |
|||
ref Vector256<float> vectorsBase = |
|||
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors)); |
|||
|
|||
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
|
|||
ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u)); |
|||
|
|||
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) |
|||
{ |
|||
Vector256<float> source = vectorsBase; |
|||
Vector256<float> multiply = Avx.Shuffle(source, source, ShuffleAlphaControl); |
|||
vectorsBase = Avx.Blend(Avx.Multiply(source, multiply), source, BlendAlphaControl); |
|||
vectorsBase = ref Unsafe.Add(ref vectorsBase, 1); |
|||
} |
|||
|
|||
if (Modulo2(vectors.Length) != 0) |
|||
{ |
|||
// Vector4 fits neatly in pairs. Any overlap has to be equal to 1.
|
|||
Premultiply(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1))); |
|||
} |
|||
} |
|||
else |
|||
#endif
|
|||
{ |
|||
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); |
|||
|
|||
for (int i = 0; i < vectors.Length; i++) |
|||
{ |
|||
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); |
|||
Premultiply(ref v); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Bulk variant of <see cref="UnPremultiply(ref Vector4)"/>
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void UnPremultiply(Span<Vector4> vectors) |
|||
{ |
|||
#if SUPPORTS_RUNTIME_INTRINSICS
|
|||
if (Avx2.IsSupported && vectors.Length >= 2) |
|||
{ |
|||
ref Vector256<float> vectorsBase = |
|||
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors)); |
|||
|
|||
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
|
|||
ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u)); |
|||
|
|||
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) |
|||
{ |
|||
Vector256<float> source = vectorsBase; |
|||
Vector256<float> multiply = Avx.Shuffle(source, source, ShuffleAlphaControl); |
|||
vectorsBase = Avx.Blend(Avx.Divide(source, multiply), source, BlendAlphaControl); |
|||
vectorsBase = ref Unsafe.Add(ref vectorsBase, 1); |
|||
} |
|||
|
|||
if (Modulo2(vectors.Length) != 0) |
|||
{ |
|||
// Vector4 fits neatly in pairs. Any overlap has to be equal to 1.
|
|||
UnPremultiply(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1))); |
|||
} |
|||
} |
|||
else |
|||
#endif
|
|||
{ |
|||
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); |
|||
|
|||
for (int i = 0; i < vectors.Length; i++) |
|||
{ |
|||
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); |
|||
UnPremultiply(ref v); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,181 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
#if SUPPORTS_RUNTIME_INTRINSICS
|
|||
using System.Runtime.Intrinsics; |
|||
using System.Runtime.Intrinsics.X86; |
|||
#endif
|
|||
|
|||
namespace SixLabors.ImageSharp |
|||
{ |
|||
/// <summary>
|
|||
/// Utility methods for the <see cref="Vector4"/> struct.
|
|||
/// </summary>
|
|||
internal static class Vector4Utilities |
|||
{ |
|||
private const int BlendAlphaControl = 0b_10_00_10_00; |
|||
private const int ShuffleAlphaControl = 0b_11_11_11_11; |
|||
|
|||
/// <summary>
|
|||
/// Restricts a vector between a minimum and a maximum value.
|
|||
/// 5x Faster then <see cref="Vector4.Clamp(Vector4, Vector4, Vector4)"/>.
|
|||
/// </summary>
|
|||
/// <param name="x">The vector to restrict.</param>
|
|||
/// <param name="min">The minimum value.</param>
|
|||
/// <param name="max">The maximum value.</param>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static Vector4 FastClamp(Vector4 x, Vector4 min, Vector4 max) |
|||
=> Vector4.Min(Vector4.Max(x, min), max); |
|||
|
|||
/// <summary>
|
|||
/// Pre-multiplies the "x", "y", "z" components of a vector by its "w" component leaving the "w" component intact.
|
|||
/// </summary>
|
|||
/// <param name="source">The <see cref="Vector4"/> to premultiply</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static void Premultiply(ref Vector4 source) |
|||
{ |
|||
float w = source.W; |
|||
source *= w; |
|||
source.W = w; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Reverses the result of premultiplying a vector via <see cref="Premultiply(ref Vector4)"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The <see cref="Vector4"/> to premultiply</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static void UnPremultiply(ref Vector4 source) |
|||
{ |
|||
float w = source.W; |
|||
source /= w; |
|||
source.W = w; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Bulk variant of <see cref="Premultiply(ref Vector4)"/>
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static void Premultiply(Span<Vector4> vectors) |
|||
{ |
|||
#if SUPPORTS_RUNTIME_INTRINSICS
|
|||
if (Avx2.IsSupported && vectors.Length >= 2) |
|||
{ |
|||
ref Vector256<float> vectorsBase = |
|||
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors)); |
|||
|
|||
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
|
|||
ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u)); |
|||
|
|||
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) |
|||
{ |
|||
Vector256<float> source = vectorsBase; |
|||
Vector256<float> multiply = Avx.Shuffle(source, source, ShuffleAlphaControl); |
|||
vectorsBase = Avx.Blend(Avx.Multiply(source, multiply), source, BlendAlphaControl); |
|||
vectorsBase = ref Unsafe.Add(ref vectorsBase, 1); |
|||
} |
|||
|
|||
if (ImageMaths.Modulo2(vectors.Length) != 0) |
|||
{ |
|||
// Vector4 fits neatly in pairs. Any overlap has to be equal to 1.
|
|||
Premultiply(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1))); |
|||
} |
|||
} |
|||
else |
|||
#endif
|
|||
{ |
|||
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); |
|||
|
|||
for (int i = 0; i < vectors.Length; i++) |
|||
{ |
|||
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); |
|||
Premultiply(ref v); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Bulk variant of <see cref="UnPremultiply(ref Vector4)"/>
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static void UnPremultiply(Span<Vector4> vectors) |
|||
{ |
|||
#if SUPPORTS_RUNTIME_INTRINSICS
|
|||
if (Avx2.IsSupported && vectors.Length >= 2) |
|||
{ |
|||
ref Vector256<float> vectorsBase = |
|||
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors)); |
|||
|
|||
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
|
|||
ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u)); |
|||
|
|||
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) |
|||
{ |
|||
Vector256<float> source = vectorsBase; |
|||
Vector256<float> multiply = Avx.Shuffle(source, source, ShuffleAlphaControl); |
|||
vectorsBase = Avx.Blend(Avx.Divide(source, multiply), source, BlendAlphaControl); |
|||
vectorsBase = ref Unsafe.Add(ref vectorsBase, 1); |
|||
} |
|||
|
|||
if (ImageMaths.Modulo2(vectors.Length) != 0) |
|||
{ |
|||
// Vector4 fits neatly in pairs. Any overlap has to be equal to 1.
|
|||
UnPremultiply(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1))); |
|||
} |
|||
} |
|||
else |
|||
#endif
|
|||
{ |
|||
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); |
|||
|
|||
for (int i = 0; i < vectors.Length; i++) |
|||
{ |
|||
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); |
|||
UnPremultiply(ref v); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Transforms a vector by the given matrix.
|
|||
/// </summary>
|
|||
/// <param name="vector">The source vector.</param>
|
|||
/// <param name="matrix">The transformation matrix.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static void Transform(ref Vector4 vector, ref ColorMatrix matrix) |
|||
{ |
|||
float x = vector.X; |
|||
float y = vector.Y; |
|||
float z = vector.Z; |
|||
float w = vector.W; |
|||
|
|||
vector.X = (x * matrix.M11) + (y * matrix.M21) + (z * matrix.M31) + (w * matrix.M41) + matrix.M51; |
|||
vector.Y = (x * matrix.M12) + (y * matrix.M22) + (z * matrix.M32) + (w * matrix.M42) + matrix.M52; |
|||
vector.Z = (x * matrix.M13) + (y * matrix.M23) + (z * matrix.M33) + (w * matrix.M43) + matrix.M53; |
|||
vector.W = (x * matrix.M14) + (y * matrix.M24) + (z * matrix.M34) + (w * matrix.M44) + matrix.M54; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Bulk variant of <see cref="Transform(ref Vector4, ref ColorMatrix)"/>.
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors</param>
|
|||
/// <param name="matrix">The transformation matrix.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static void Transform(Span<Vector4> vectors, ref ColorMatrix matrix) |
|||
{ |
|||
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); |
|||
|
|||
for (int i = 0; i < vectors.Length; i++) |
|||
{ |
|||
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); |
|||
Transform(ref v, ref matrix); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,32 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
namespace SixLabors.ImageSharp.PixelFormats |
|||
{ |
|||
/// <summary>
|
|||
/// Provides enumeration of the alpha value transparency behavior of a pixel format.
|
|||
/// </summary>
|
|||
public enum PixelAlphaRepresentation |
|||
{ |
|||
/// <summary>
|
|||
/// Indicates that the pixel format does not contain an alpha channel.
|
|||
/// </summary>
|
|||
None, |
|||
|
|||
/// <summary>
|
|||
/// Indicates that the transparency behavior is premultiplied.
|
|||
/// Each color is first scaled by the alpha value. The alpha value itself is the same
|
|||
/// in both straight and premultiplied alpha. Typically, no color channel value is
|
|||
/// greater than the alpha channel value.
|
|||
/// If a color channel value in a premultiplied format is greater than the alpha
|
|||
/// channel, the standard source-over blending math results in an additive blend.
|
|||
/// </summary>
|
|||
Associated, |
|||
|
|||
/// <summary>
|
|||
/// Indicates that the transparency behavior is not premultiplied.
|
|||
/// The alpha channel indicates the transparency of the color.
|
|||
/// </summary>
|
|||
Unassociated |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,26 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using SixLabors.ImageSharp.Formats; |
|||
|
|||
namespace SixLabors.ImageSharp.PixelFormats |
|||
{ |
|||
/// <content>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </content>
|
|||
public partial struct A8 |
|||
{ |
|||
/// <summary>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </summary>
|
|||
internal class PixelOperations : PixelOperations<A8> |
|||
{ |
|||
private static readonly Lazy<PixelTypeInfo> LazyInfo = |
|||
new Lazy<PixelTypeInfo>(() => PixelTypeInfo.Create<A8>(PixelAlphaRepresentation.Unassociated), true); |
|||
|
|||
/// <inheritdoc />
|
|||
public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using SixLabors.ImageSharp.Formats; |
|||
|
|||
namespace SixLabors.ImageSharp.PixelFormats |
|||
{ |
|||
/// <content>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </content>
|
|||
public partial struct Argb32 |
|||
{ |
|||
/// <summary>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </summary>
|
|||
internal partial class PixelOperations : PixelOperations<Argb32> |
|||
{ |
|||
private static readonly Lazy<PixelTypeInfo> LazyInfo = |
|||
new Lazy<PixelTypeInfo>(() => PixelTypeInfo.Create<Argb32>(PixelAlphaRepresentation.Unassociated), true); |
|||
|
|||
/// <inheritdoc />
|
|||
public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using SixLabors.ImageSharp.Formats; |
|||
|
|||
namespace SixLabors.ImageSharp.PixelFormats |
|||
{ |
|||
/// <content>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </content>
|
|||
public partial struct Bgr24 |
|||
{ |
|||
/// <summary>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </summary>
|
|||
internal partial class PixelOperations : PixelOperations<Bgr24> |
|||
{ |
|||
private static readonly Lazy<PixelTypeInfo> LazyInfo = |
|||
new Lazy<PixelTypeInfo>(() => PixelTypeInfo.Create<Bgr24>(PixelAlphaRepresentation.None), true); |
|||
|
|||
/// <inheritdoc />
|
|||
public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using SixLabors.ImageSharp.Formats; |
|||
|
|||
namespace SixLabors.ImageSharp.PixelFormats |
|||
{ |
|||
/// <content>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </content>
|
|||
public partial struct Bgr565 |
|||
{ |
|||
/// <summary>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </summary>
|
|||
internal class PixelOperations : PixelOperations<Bgr565> |
|||
{ |
|||
private static readonly Lazy<PixelTypeInfo> LazyInfo = |
|||
new Lazy<PixelTypeInfo>(() => PixelTypeInfo.Create<Bgr565>(PixelAlphaRepresentation.None), true); |
|||
|
|||
/// <inheritdoc />
|
|||
public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using SixLabors.ImageSharp.Formats; |
|||
|
|||
namespace SixLabors.ImageSharp.PixelFormats |
|||
{ |
|||
/// <content>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </content>
|
|||
public partial struct Bgra32 |
|||
{ |
|||
/// <summary>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </summary>
|
|||
internal partial class PixelOperations : PixelOperations<Bgra32> |
|||
{ |
|||
private static readonly Lazy<PixelTypeInfo> LazyInfo = |
|||
new Lazy<PixelTypeInfo>(() => PixelTypeInfo.Create<Bgra32>(PixelAlphaRepresentation.Unassociated), true); |
|||
|
|||
/// <inheritdoc />
|
|||
public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using SixLabors.ImageSharp.Formats; |
|||
|
|||
namespace SixLabors.ImageSharp.PixelFormats |
|||
{ |
|||
/// <content>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </content>
|
|||
public partial struct Bgra4444 |
|||
{ |
|||
/// <summary>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </summary>
|
|||
internal class PixelOperations : PixelOperations<Bgra4444> |
|||
{ |
|||
private static readonly Lazy<PixelTypeInfo> LazyInfo = |
|||
new Lazy<PixelTypeInfo>(() => PixelTypeInfo.Create<Bgra4444>(PixelAlphaRepresentation.Unassociated), true); |
|||
|
|||
/// <inheritdoc />
|
|||
public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using SixLabors.ImageSharp.Formats; |
|||
|
|||
namespace SixLabors.ImageSharp.PixelFormats |
|||
{ |
|||
/// <content>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </content>
|
|||
public partial struct Bgra5551 |
|||
{ |
|||
/// <summary>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </summary>
|
|||
internal partial class PixelOperations : PixelOperations<Bgra5551> |
|||
{ |
|||
private static readonly Lazy<PixelTypeInfo> LazyInfo = |
|||
new Lazy<PixelTypeInfo>(() => PixelTypeInfo.Create<Bgra5551>(PixelAlphaRepresentation.Unassociated), true); |
|||
|
|||
/// <inheritdoc />
|
|||
public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using SixLabors.ImageSharp.Formats; |
|||
|
|||
namespace SixLabors.ImageSharp.PixelFormats |
|||
{ |
|||
/// <content>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </content>
|
|||
public partial struct Byte4 |
|||
{ |
|||
/// <summary>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </summary>
|
|||
internal class PixelOperations : PixelOperations<Byte4> |
|||
{ |
|||
private static readonly Lazy<PixelTypeInfo> LazyInfo = |
|||
new Lazy<PixelTypeInfo>(() => PixelTypeInfo.Create<Byte4>(PixelAlphaRepresentation.Unassociated), true); |
|||
|
|||
/// <inheritdoc />
|
|||
public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; |
|||
} |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue