diff --git a/.editorconfig b/.editorconfig index 0e4883082c..83670fa830 100644 --- a/.editorconfig +++ b/.editorconfig @@ -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. +########################################## diff --git a/.gitattributes b/.gitattributes index c0bff6e189..416dd0d06f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,9 +2,13 @@ # Set default behavior to: # treat as text and # normalize to Unix-style line endings +############################################################################### * text eol=lf - +############################################################################### # Set explicit file behavior to: +# treat as text and +# normalize to Unix-style line endings +############################################################################### *.asm text eol=lf *.c text eol=lf *.clj text eol=lf @@ -49,45 +53,58 @@ *.txt text eol=lf *.vb text eol=lf *.yml text eol=lf +############################################################################### +# Set explicit file behavior to: # treat as text # normalize to Unix-style line endings and # diff as csharp +############################################################################### *.cs text eol=lf diff=csharp +############################################################################### +# Set explicit file behavior to: +# treat as text +# normalize to Unix-style line endings and # use a union merge when resoling conflicts +############################################################################### *.csproj text eol=lf merge=union *.dbproj text eol=lf merge=union *.fsproj text eol=lf merge=union *.ncrunchproject text eol=lf merge=union *.vbproj text eol=lf merge=union +############################################################################### +# Set explicit file behavior to: +# treat as text # normalize to Windows-style line endings and +# use a union merge when resoling conflicts +############################################################################### *.sln text eol=crlf merge=union +############################################################################### +# Set explicit file behavior to: # treat as binary +############################################################################### *.basis binary -*.bmp binary -*.dds binary *.dll binary *.eot binary *.exe binary -*.gif binary -*.jpg binary *.ktx binary *.otf binary *.pbm binary *.pdf binary -*.png binary *.ppt binary *.pptx binary *.pvr binary *.snk binary -*.tga binary *.ttc binary *.ttf binary -*.webp binary +*.wbmp binary *.woff binary *.woff2 binary *.xls binary *.xlsx binary +############################################################################### +# Set explicit file behavior to: # diff as plain text +############################################################################### *.doc diff=astextplain *.docx diff=astextplain *.dot diff=astextplain @@ -95,12 +112,16 @@ *.pptx diff=astextplain *.rtf diff=astextplain *.svg diff=astextplain -*.jpg filter=lfs diff=lfs merge=lfs -text -*.jpeg filter=lfs diff=lfs merge=lfs -text -*.bmp filter=lfs diff=lfs merge=lfs -text -*.gif filter=lfs diff=lfs merge=lfs -text -*.png filter=lfs diff=lfs merge=lfs -text -*.tif filter=lfs diff=lfs merge=lfs -text -*.tiff filter=lfs diff=lfs merge=lfs -text -*.tga filter=lfs diff=lfs merge=lfs -text -*.webp filter=lfs diff=lfs merge=lfs -text +############################################################################### +# Handle image files by git lfs +############################################################################### +*.jpg filter=lfs diff=lfs merge=lfs -text +*.jpeg filter=lfs diff=lfs merge=lfs -text +*.bmp filter=lfs diff=lfs merge=lfs -text +*.gif filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.tif filter=lfs diff=lfs merge=lfs -text +*.tiff filter=lfs diff=lfs merge=lfs -text +*.tga filter=lfs diff=lfs merge=lfs -text +*.webp filter=lfs diff=lfs merge=lfs -text +*.dds filter=lfs diff=lfs merge=lfs -text diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 89d1a75f27..0943ab4eb7 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -29,7 +29,7 @@ #### **Running tests and Debugging** * Expected test output is pulled in as a submodule from the [ImageSharp.Tests.Images repository](https://github.com/SixLabors/Imagesharp.Tests.Images/tree/master/ReferenceOutput). To succesfully run tests, make sure that you have updated the submodules! -* Debugging (running tests in Debug mode) is only supported on .NET Core 2.1, because of JIT Code Generation bugs like [dotnet/coreclr#16443](https://github.com/dotnet/coreclr/issues/16443) or [dotnet/coreclr#20657](https://github.com/dotnet/coreclr/issues/20657) +* Debugging (running tests in Debug mode) is only supported on .NET Core 2.1+, because of JIT Code Generation bugs like [dotnet/coreclr#16443](https://github.com/dotnet/coreclr/issues/16443) or [dotnet/coreclr#20657](https://github.com/dotnet/coreclr/issues/20657) #### **Do you have questions about consuming the library or the source code?** diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index cf9f787526..1326c72e86 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,7 +1,7 @@ blank_issues_enabled: false contact_links: - name: Ask a Question - url: https://github.com/SixLabors/ImageSharp/discussions?discussions_q=category%3AHelp + url: https://github.com/SixLabors/ImageSharp/discussions?discussions_q=category%3AQ%26A about: Ask a question about this project. - name: Feature Request url: https://github.com/SixLabors/ImageSharp/discussions?discussions_q=category%3AIdeas diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 0e093a8347..4828f4f21f 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -15,13 +15,29 @@ jobs: matrix: options: - os: ubuntu-latest - framework: netcoreapp3.1 + framework: net5.0 + runtime: -x64 + codecov: false + - os: macos-latest + framework: net5.0 runtime: -x64 codecov: false - os: windows-latest + framework: net5.0 + runtime: -x64 + codecov: false + - os: ubuntu-latest framework: netcoreapp3.1 runtime: -x64 codecov: true + - os: macos-latest + framework: netcoreapp3.1 + runtime: -x64 + codecov: false + - os: windows-latest + framework: netcoreapp3.1 + runtime: -x64 + codecov: false - os: windows-latest framework: netcoreapp2.1 runtime: -x64 @@ -40,6 +56,20 @@ jobs: steps: - uses: actions/checkout@v2 + + # See https://github.com/actions/checkout/issues/165#issuecomment-657673315 + - name: Create LFS file list + run: git lfs ls-files -l | cut -d' ' -f1 | sort > .lfs-assets-id + + - name: Restore LFS cache + uses: actions/cache@v2 + id: lfs-cache + with: + path: .git/lfs + key: ${{ runner.os }}-lfs-${{ hashFiles('.lfs-assets-id') }}-v1 + + - name: Git LFS Pull + run: git lfs pull - name: Install NuGet uses: NuGet/setup-nuget@v1 @@ -52,17 +82,34 @@ jobs: git fetch --prune --unshallow git submodule -q update --init --recursive + - name: Setup NuGet Cache + uses: actions/cache@v2 + id: nuget-cache + with: + path: ~/.nuget + key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/*.props', '**/*.targets') }} + restore-keys: ${{ runner.os }}-nuget- + - name: Build shell: pwsh run: ./ci-build.ps1 "${{matrix.options.framework}}" + env: + SIXLABORS_TESTING: True - name: Test shell: pwsh run: ./ci-test.ps1 "${{matrix.options.os}}" "${{matrix.options.framework}}" "${{matrix.options.runtime}}" "${{matrix.options.codecov}}" env: - CI: True + SIXLABORS_TESTING: True XUNIT_PATH: .\tests\ImageSharp.Tests # Required for xunit + - name: Export Failed Output + uses: actions/upload-artifact@v2 + if: failure() + with: + name: actual_output_${{ runner.os }}_${{ matrix.options.framework }}${{ matrix.options.runtime }}.zip + path: tests/Images/ActualOutput/ + - name: Update Codecov uses: codecov/codecov-action@v1 if: matrix.options.codecov == true && startsWith(github.repository, 'SixLabors') diff --git a/.gitignore b/.gitignore index a89cfcf104..475d6e76b0 100644 --- a/.gitignore +++ b/.gitignore @@ -221,3 +221,4 @@ artifacts/ # Tests **/Images/ActualOutput **/Images/ReferenceOutput +.DS_Store diff --git a/.gitmodules b/.gitmodules index 55389121f2..94d28dd526 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,3 @@ -[submodule "tests/Images/External"] - path = tests/Images/External - url = https://github.com/SixLabors/Imagesharp.Tests.Images.git - branch = master [submodule "shared-infrastructure"] path = shared-infrastructure url = https://github.com/SixLabors/SharedInfrastructure diff --git a/.runsettings b/.runsettings new file mode 100644 index 0000000000..ca48342bd6 --- /dev/null +++ b/.runsettings @@ -0,0 +1,7 @@ + + + + + category!=failing + + diff --git a/Directory.Build.props b/Directory.Build.props index 0f9c5bdde2..3a133efe7a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -10,131 +10,12 @@ that is done by the file that imports us. --> - - $(MSBuildThisFileDirectory)artifacts/ - $(SixLaborsProjectCategory)/$(MSBuildProjectName) - https://github.com/SixLabors/ImageSharp/ + + $(MSBuildThisFileDirectory) - - - true - $(BaseArtifactsPath)obj/$(BaseArtifactsPathSuffix)/ - portable - full - disable - true - true - - - - - - $(DefineConstants);SUPPORTS_MATHF - $(DefineConstants);SUPPORTS_HASHCODE - $(DefineConstants);SUPPORTS_EXTENDED_INTRINSICS - $(DefineConstants);SUPPORTS_SPAN_STREAM - $(DefineConstants);SUPPORTS_ENCODING_STRING - $(DefineConstants);SUPPORTS_RUNTIME_INTRINSICS - $(DefineConstants);SUPPORTS_CODECOVERAGE - $(DefineConstants);SUPPORTS_HOTPATH - $(DefineConstants);SUPPORTS_CREATESPAN - - - $(DefineConstants);SUPPORTS_MATHF - $(DefineConstants);SUPPORTS_HASHCODE - $(DefineConstants);SUPPORTS_EXTENDED_INTRINSICS - $(DefineConstants);SUPPORTS_SPAN_STREAM - $(DefineConstants);SUPPORTS_ENCODING_STRING - $(DefineConstants);SUPPORTS_CODECOVERAGE - $(DefineConstants);SUPPORTS_CREATESPAN - - - $(DefineConstants);SUPPORTS_MATHF - $(DefineConstants);SUPPORTS_CODECOVERAGE - $(DefineConstants);SUPPORTS_CREATESPAN - - - $(DefineConstants);SUPPORTS_MATHF - $(DefineConstants);SUPPORTS_HASHCODE - $(DefineConstants);SUPPORTS_SPAN_STREAM - $(DefineConstants);SUPPORTS_ENCODING_STRING - $(DefineConstants);SUPPORTS_CODECOVERAGE - $(DefineConstants);SUPPORTS_CREATESPAN - - - $(DefineConstants);SUPPORTS_CODECOVERAGE - - - $(DefineConstants);SUPPORTS_EXTENDED_INTRINSICS - $(DefineConstants);SUPPORTS_CODECOVERAGE - - - - - Six Labors and contributors - $(BaseArtifactsPath)bin/$(BaseArtifactsPathSuffix)/ - Six Labors - $(BaseArtifactsPath)pkg/$(BaseArtifactsPathSuffix)/$(Configuration)/ - SixLabors.ImageSharp - 0.0.1 - $(PackageVersion) - - - - - - v - normal - - - - - Copyright © Six Labors - strict;IOperation - true - 8.0 - en - true - sixlabors.imagesharp.128.png - Apache-2.0 - $(RepositoryUrl) - true - git - - https://www.myget.org/F/sixlabors/api/v3/index.json; - https://api.nuget.org/v3/index.json; - - https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json; - - true - $(MSBuildThisFileDirectory)shared-infrastructure/SixLabors.snk - 00240000048000009400000006020000002400005253413100040000010001000147e6fe6766715eec6cfed61f1e7dcdbf69748a3e355c67e9d8dfd953acab1d5e012ba34b23308166fdc61ee1d0390d5f36d814a6091dd4b5ed9eda5a26afced924c683b4bfb4b3d64b0586a57eff9f02b1f84e3cb0ddd518bd1697f2c84dcbb97eb8bb5c7801be12112ed0ec86db934b0e9a5171e6bb1384b6d2f7d54dfa97 - true - - - - - - - - - - - + + diff --git a/Directory.Build.targets b/Directory.Build.targets index 4e7ab9e6b7..9730219482 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -5,39 +5,12 @@ Directory.Build.targets is automatically picked up and imported by Microsoft.Common.targets. This file needs to exist, even if empty so that files in the parent directory tree, with the same name, are not imported - instead. The import fairly late and most other props/targets will have been + instead. They import fairly late and most other props/targets will have been imported beforehand. We also don't need to add ourselves to MSBuildAllProjects, as that is done by the file that imports us. --> - - - $(DefineConstants);$(OS) - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/ImageSharp.sln b/ImageSharp.sln index 509dcf96bf..8dfab6033c 100644 --- a/ImageSharp.sln +++ b/ImageSharp.sln @@ -3,18 +3,18 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.28902.138 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C317F1B1-D75E-4C6D-83EB-80367343E0D7}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_root", "_root", "{C317F1B1-D75E-4C6D-83EB-80367343E0D7}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig .gitattributes = .gitattributes .gitignore = .gitignore .gitmodules = .gitmodules + .runsettings = .runsettings ci-build.ps1 = ci-build.ps1 ci-pack.ps1 = ci-pack.ps1 ci-test.ps1 = ci-test.ps1 Directory.Build.props = Directory.Build.props Directory.Build.targets = Directory.Build.targets - GitVersion.yml = GitVersion.yml LICENSE = LICENSE README.md = README.md EndProjectSection @@ -45,6 +45,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{56801022 ProjectSection(SolutionItems) = preProject tests\Directory.Build.props = tests\Directory.Build.props tests\Directory.Build.targets = tests\Directory.Build.targets + tests\ImageSharp.Tests.ruleset = tests\ImageSharp.Tests.ruleset EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Images", "Images", "{FA55F5DE-11A6-487D-ABA4-BC93A02717DD}" @@ -53,16 +54,23 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Input", "Input", "{9DA226A1 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Bmp", "Bmp", "{1A82C5F6-90E0-4E97-BE16-A825C046B493}" ProjectSection(SolutionItems) = preProject + tests\Images\Input\Bmp\9S.BMP = tests\Images\Input\Bmp\9S.BMP + tests\Images\Input\Bmp\ba-bm.bmp = tests\Images\Input\Bmp\ba-bm.bmp tests\Images\Input\Bmp\BitmapCoreHeaderQR.bmp = tests\Images\Input\Bmp\BitmapCoreHeaderQR.bmp tests\Images\Input\Bmp\BITMAPV5HEADER.bmp = tests\Images\Input\Bmp\BITMAPV5HEADER.bmp tests\Images\Input\Bmp\Car.bmp = tests\Images\Input\Bmp\Car.bmp + tests\Images\Input\Bmp\DIAMOND.BMP = tests\Images\Input\Bmp\DIAMOND.BMP tests\Images\Input\Bmp\F.bmp = tests\Images\Input\Bmp\F.bmp + tests\Images\Input\Bmp\GMARBLE.BMP = tests\Images\Input\Bmp\GMARBLE.BMP + tests\Images\Input\Bmp\invalidPaletteSize.bmp = tests\Images\Input\Bmp\invalidPaletteSize.bmp tests\Images\Input\Bmp\issue735.bmp = tests\Images\Input\Bmp\issue735.bmp tests\Images\Input\Bmp\neg_height.bmp = tests\Images\Input\Bmp\neg_height.bmp tests\Images\Input\Bmp\pal1.bmp = tests\Images\Input\Bmp\pal1.bmp tests\Images\Input\Bmp\pal1p1.bmp = tests\Images\Input\Bmp\pal1p1.bmp tests\Images\Input\Bmp\pal4.bmp = tests\Images\Input\Bmp\pal4.bmp tests\Images\Input\Bmp\pal4rle.bmp = tests\Images\Input\Bmp\pal4rle.bmp + tests\Images\Input\Bmp\pal4rlecut.bmp = tests\Images\Input\Bmp\pal4rlecut.bmp + tests\Images\Input\Bmp\pal4rletrns.bmp = tests\Images\Input\Bmp\pal4rletrns.bmp tests\Images\Input\Bmp\pal8-0.bmp = tests\Images\Input\Bmp\pal8-0.bmp tests\Images\Input\Bmp\pal8gs.bmp = tests\Images\Input\Bmp\pal8gs.bmp tests\Images\Input\Bmp\pal8offs.bmp = tests\Images\Input\Bmp\pal8offs.bmp @@ -70,26 +78,45 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Bmp", "Bmp", "{1A82C5F6-90E tests\Images\Input\Bmp\pal8os2v1_winv2.bmp = tests\Images\Input\Bmp\pal8os2v1_winv2.bmp tests\Images\Input\Bmp\pal8os2v2-16.bmp = tests\Images\Input\Bmp\pal8os2v2-16.bmp tests\Images\Input\Bmp\pal8os2v2.bmp = tests\Images\Input\Bmp\pal8os2v2.bmp + tests\Images\Input\Bmp\pal8oversizepal.bmp = tests\Images\Input\Bmp\pal8oversizepal.bmp + tests\Images\Input\Bmp\pal8rlecut.bmp = tests\Images\Input\Bmp\pal8rlecut.bmp + tests\Images\Input\Bmp\pal8rletrns.bmp = tests\Images\Input\Bmp\pal8rletrns.bmp tests\Images\Input\Bmp\pal8v4.bmp = tests\Images\Input\Bmp\pal8v4.bmp tests\Images\Input\Bmp\pal8v5.bmp = tests\Images\Input\Bmp\pal8v5.bmp + tests\Images\Input\Bmp\PINES.BMP = tests\Images\Input\Bmp\PINES.BMP tests\Images\Input\Bmp\rgb16-565.bmp = tests\Images\Input\Bmp\rgb16-565.bmp tests\Images\Input\Bmp\rgb16-565pal.bmp = tests\Images\Input\Bmp\rgb16-565pal.bmp tests\Images\Input\Bmp\rgb16.bmp = tests\Images\Input\Bmp\rgb16.bmp tests\Images\Input\Bmp\rgb16bfdef.bmp = tests\Images\Input\Bmp\rgb16bfdef.bmp tests\Images\Input\Bmp\rgb24.bmp = tests\Images\Input\Bmp\rgb24.bmp + tests\Images\Input\Bmp\rgb24jpeg.bmp = tests\Images\Input\Bmp\rgb24jpeg.bmp + tests\Images\Input\Bmp\rgb24largepal.bmp = tests\Images\Input\Bmp\rgb24largepal.bmp + tests\Images\Input\Bmp\rgb24png.bmp = tests\Images\Input\Bmp\rgb24png.bmp + tests\Images\Input\Bmp\rgb24rle24.bmp = tests\Images\Input\Bmp\rgb24rle24.bmp tests\Images\Input\Bmp\rgb32.bmp = tests\Images\Input\Bmp\rgb32.bmp tests\Images\Input\Bmp\rgb32bf.bmp = tests\Images\Input\Bmp\rgb32bf.bmp tests\Images\Input\Bmp\rgb32bfdef.bmp = tests\Images\Input\Bmp\rgb32bfdef.bmp + tests\Images\Input\Bmp\rgb32h52.bmp = tests\Images\Input\Bmp\rgb32h52.bmp tests\Images\Input\Bmp\rgba32-1010102.bmp = tests\Images\Input\Bmp\rgba32-1010102.bmp tests\Images\Input\Bmp\rgba32.bmp = tests\Images\Input\Bmp\rgba32.bmp tests\Images\Input\Bmp\rgba32abf.bmp = tests\Images\Input\Bmp\rgba32abf.bmp tests\Images\Input\Bmp\rgba32h56.bmp = tests\Images\Input\Bmp\rgba32h56.bmp + tests\Images\Input\Bmp\rgba32v4.bmp = tests\Images\Input\Bmp\rgba32v4.bmp + tests\Images\Input\Bmp\rle24rlecut.bmp = tests\Images\Input\Bmp\rle24rlecut.bmp + tests\Images\Input\Bmp\rle24rletrns.bmp = tests\Images\Input\Bmp\rle24rletrns.bmp + tests\Images\Input\Bmp\rle4-delta-320x240.bmp = tests\Images\Input\Bmp\rle4-delta-320x240.bmp + tests\Images\Input\Bmp\rle8-blank-160x120.bmp = tests\Images\Input\Bmp\rle8-blank-160x120.bmp + tests\Images\Input\Bmp\rle8-delta-320x240.bmp = tests\Images\Input\Bmp\rle8-delta-320x240.bmp tests\Images\Input\Bmp\RunLengthEncoded-inverted.bmp = tests\Images\Input\Bmp\RunLengthEncoded-inverted.bmp tests\Images\Input\Bmp\RunLengthEncoded.bmp = tests\Images\Input\Bmp\RunLengthEncoded.bmp + tests\Images\Input\Bmp\SKATER.BMP = tests\Images\Input\Bmp\SKATER.BMP + tests\Images\Input\Bmp\SPADE.BMP = tests\Images\Input\Bmp\SPADE.BMP + tests\Images\Input\Bmp\SUNFLOW.BMP = tests\Images\Input\Bmp\SUNFLOW.BMP tests\Images\Input\Bmp\test16-inverted.bmp = tests\Images\Input\Bmp\test16-inverted.bmp tests\Images\Input\Bmp\test16.bmp = tests\Images\Input\Bmp\test16.bmp tests\Images\Input\Bmp\test8-inverted.bmp = tests\Images\Input\Bmp\test8-inverted.bmp tests\Images\Input\Bmp\test8.bmp = tests\Images\Input\Bmp\test8.bmp + tests\Images\Input\Bmp\WARPD.BMP = tests\Images\Input\Bmp\WARPD.BMP EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Gif", "Gif", "{EE3FB0B3-1C31-41E9-93AB-BA800560A868}" @@ -98,8 +125,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Gif", "Gif", "{EE3FB0B3-1C3 tests\Images\Input\Gif\base_4x1.gif = tests\Images\Input\Gif\base_4x1.gif tests\Images\Input\Gif\cheers.gif = tests\Images\Input\Gif\cheers.gif tests\Images\Input\Gif\giphy.gif = tests\Images\Input\Gif\giphy.gif + tests\Images\Input\Gif\GlobalQuantizationTest.gif = tests\Images\Input\Gif\GlobalQuantizationTest.gif + tests\Images\Input\Gif\image-zero-height.gif = tests\Images\Input\Gif\image-zero-height.gif + tests\Images\Input\Gif\image-zero-size.gif = tests\Images\Input\Gif\image-zero-size.gif + tests\Images\Input\Gif\image-zero-width.gif = tests\Images\Input\Gif\image-zero-width.gif tests\Images\Input\Gif\kumin.gif = tests\Images\Input\Gif\kumin.gif + tests\Images\Input\Gif\large_comment.gif = tests\Images\Input\Gif\large_comment.gif tests\Images\Input\Gif\leo.gif = tests\Images\Input\Gif\leo.gif + tests\Images\Input\Gif\max-height.gif = tests\Images\Input\Gif\max-height.gif + tests\Images\Input\Gif\max-width.gif = tests\Images\Input\Gif\max-width.gif + tests\Images\Input\Gif\receipt.gif = tests\Images\Input\Gif\receipt.gif tests\Images\Input\Gif\rings.gif = tests\Images\Input\Gif\rings.gif tests\Images\Input\Gif\trans.gif = tests\Images\Input\Gif\trans.gif EndProjectSection @@ -115,6 +150,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Jpg", "Jpg", "{DB21FED7-E8C EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "baseline", "baseline", "{195BA3D3-3E9F-4BC5-AB40-5F9FEB638146}" ProjectSection(SolutionItems) = preProject + tests\Images\Input\Jpg\baseline\640px-Unequalized_Hawkes_Bay_NZ.jpg = tests\Images\Input\Jpg\baseline\640px-Unequalized_Hawkes_Bay_NZ.jpg tests\Images\Input\Jpg\baseline\AsianCarvingLowContrast.jpg = tests\Images\Input\Jpg\baseline\AsianCarvingLowContrast.jpg tests\Images\Input\Jpg\baseline\badeof.jpg = tests\Images\Input\Jpg\baseline\badeof.jpg tests\Images\Input\Jpg\baseline\badrst.jpg = tests\Images\Input\Jpg\baseline\badrst.jpg @@ -124,6 +160,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "baseline", "baseline", "{19 tests\Images\Input\Jpg\baseline\Floorplan.jpg = tests\Images\Input\Jpg\baseline\Floorplan.jpg tests\Images\Input\Jpg\baseline\gamma_dalai_lama_gray.jpg = tests\Images\Input\Jpg\baseline\gamma_dalai_lama_gray.jpg tests\Images\Input\Jpg\baseline\Hiyamugi.jpg = tests\Images\Input\Jpg\baseline\Hiyamugi.jpg + tests\Images\Input\Jpg\baseline\iptc-psAPP13-wIPTCempty.jpg = tests\Images\Input\Jpg\baseline\iptc-psAPP13-wIPTCempty.jpg + tests\Images\Input\Jpg\baseline\iptc.jpg = tests\Images\Input\Jpg\baseline\iptc.jpg tests\Images\Input\Jpg\baseline\jpeg400jfif.jpg = tests\Images\Input\Jpg\baseline\jpeg400jfif.jpg tests\Images\Input\Jpg\baseline\jpeg420exif.jpg = tests\Images\Input\Jpg\baseline\jpeg420exif.jpg tests\Images\Input\Jpg\baseline\jpeg420small.jpg = tests\Images\Input\Jpg\baseline\jpeg420small.jpg @@ -166,6 +204,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "JpegSnoopReports", "JpegSno EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "issues", "issues", "{5C9B689F-B96D-47BE-A208-C23B1B2A8570}" ProjectSection(SolutionItems) = preProject + tests\Images\Input\Jpg\issues\issue-1076-invalid-subsampling.jpg = tests\Images\Input\Jpg\issues\issue-1076-invalid-subsampling.jpg + tests\Images\Input\Jpg\issues\issue-1221-identify-multi-frame.jpg = tests\Images\Input\Jpg\issues\issue-1221-identify-multi-frame.jpg + tests\Images\Input\Jpg\issues\issue1006-incorrect-resize.jpg = tests\Images\Input\Jpg\issues\issue1006-incorrect-resize.jpg + tests\Images\Input\Jpg\issues\issue1049-exif-resize.jpg = tests\Images\Input\Jpg\issues\issue1049-exif-resize.jpg tests\Images\Input\Jpg\issues\Issue159-MissingFF00-Progressive-Bedroom.jpg = tests\Images\Input\Jpg\issues\Issue159-MissingFF00-Progressive-Bedroom.jpg tests\Images\Input\Jpg\issues\Issue159-MissingFF00-Progressive-Girl.jpg = tests\Images\Input\Jpg\issues\Issue159-MissingFF00-Progressive-Girl.jpg tests\Images\Input\Jpg\issues\Issue178-BadCoeffsProgressive-Lemon.jpg = tests\Images\Input\Jpg\issues\Issue178-BadCoeffsProgressive-Lemon.jpg @@ -213,6 +255,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "fuzz", "fuzz", "{516A3532-6 tests\Images\Input\Jpg\issues\fuzz\Issue826-ArgumentException-C.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue826-ArgumentException-C.jpg tests\Images\Input\Jpg\issues\fuzz\Issue827-AccessViolationException.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue827-AccessViolationException.jpg tests\Images\Input\Jpg\issues\fuzz\Issue839-ExecutionEngineException.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue839-ExecutionEngineException.jpg + tests\Images\Input\Jpg\issues\fuzz\Issue922-AccessViolationException.jpg = tests\Images\Input\Jpg\issues\fuzz\Issue922-AccessViolationException.jpg EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "JpegSnoopReports", "JpegSnoopReports", "{714CDEA1-9AE6-4F76-B8B1-A7DB8C1DB82F}" @@ -260,16 +303,24 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Png", "Png", "{E1C42A6F-913 ProjectSection(SolutionItems) = preProject tests\Images\Input\Png\banner7-adam.png = tests\Images\Input\Png\banner7-adam.png tests\Images\Input\Png\banner8-index.png = tests\Images\Input\Png\banner8-index.png + tests\Images\Input\Png\basn3p01.png = tests\Images\Input\Png\basn3p01.png + tests\Images\Input\Png\basn3p02.png = tests\Images\Input\Png\basn3p02.png + tests\Images\Input\Png\basn3p04.png = tests\Images\Input\Png\basn3p04.png + tests\Images\Input\Png\basn3p08.png = tests\Images\Input\Png\basn3p08.png tests\Images\Input\Png\big-corrupted-chunk.png = tests\Images\Input\Png\big-corrupted-chunk.png + tests\Images\Input\Png\bike-small.png = tests\Images\Input\Png\bike-small.png tests\Images\Input\Png\Bike.png = tests\Images\Input\Png\Bike.png tests\Images\Input\Png\BikeGrayscale.png = tests\Images\Input\Png\BikeGrayscale.png tests\Images\Input\Png\blur.png = tests\Images\Input\Png\blur.png tests\Images\Input\Png\bpp1.png = tests\Images\Input\Png\bpp1.png + tests\Images\Input\Png\Bradley01.png = tests\Images\Input\Png\Bradley01.png + tests\Images\Input\Png\Bradley02.png = tests\Images\Input\Png\Bradley02.png tests\Images\Input\Png\CalliphoraPartial.png = tests\Images\Input\Png\CalliphoraPartial.png tests\Images\Input\Png\CalliphoraPartialGrayscale.png = tests\Images\Input\Png\CalliphoraPartialGrayscale.png tests\Images\Input\Png\chunklength1.png = tests\Images\Input\Png\chunklength1.png tests\Images\Input\Png\chunklength2.png = tests\Images\Input\Png\chunklength2.png tests\Images\Input\Png\cross.png = tests\Images\Input\Png\cross.png + tests\Images\Input\Png\david.png = tests\Images\Input\Png\david.png tests\Images\Input\Png\ducky.png = tests\Images\Input\Png\ducky.png tests\Images\Input\Png\filter0.png = tests\Images\Input\Png\filter0.png tests\Images\Input\Png\filter1.png = tests\Images\Input\Png\filter1.png @@ -292,6 +343,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Png", "Png", "{E1C42A6F-913 tests\Images\Input\Png\iftbbn0g04.png = tests\Images\Input\Png\iftbbn0g04.png tests\Images\Input\Png\indexed.png = tests\Images\Input\Png\indexed.png tests\Images\Input\Png\interlaced.png = tests\Images\Input\Png\interlaced.png + tests\Images\Input\Png\InvalidTextData.png = tests\Images\Input\Png\InvalidTextData.png tests\Images\Input\Png\kaboom.png = tests\Images\Input\Png\kaboom.png tests\Images\Input\Png\low-variance.png = tests\Images\Input\Png\low-variance.png tests\Images\Input\Png\palette-8bpp.png = tests\Images\Input\Png\palette-8bpp.png @@ -299,6 +351,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Png", "Png", "{E1C42A6F-913 tests\Images\Input\Png\pd-source.png = tests\Images\Input\Png\pd-source.png tests\Images\Input\Png\pd.png = tests\Images\Input\Png\pd.png tests\Images\Input\Png\pl.png = tests\Images\Input\Png\pl.png + tests\Images\Input\Png\PngWithMetaData.png = tests\Images\Input\Png\PngWithMetaData.png tests\Images\Input\Png\pp.png = tests\Images\Input\Png\pp.png tests\Images\Input\Png\rainbow.png = tests\Images\Input\Png\rainbow.png tests\Images\Input\Png\ratio-1x4.png = tests\Images\Input\Png\ratio-1x4.png @@ -316,7 +369,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Png", "Png", "{E1C42A6F-913 tests\Images\Input\Png\versioning-1_2.png = tests\Images\Input\Png\versioning-1_2.png tests\Images\Input\Png\vim16x16_1.png = tests\Images\Input\Png\vim16x16_1.png tests\Images\Input\Png\vim16x16_2.png = tests\Images\Input\Png\vim16x16_2.png + tests\Images\Input\Png\xc1n0g08.png = tests\Images\Input\Png\xc1n0g08.png + tests\Images\Input\Png\xc9n2c08.png = tests\Images\Input\Png\xc9n2c08.png + tests\Images\Input\Png\xd0n2c08.png = tests\Images\Input\Png\xd0n2c08.png + tests\Images\Input\Png\xd3n2c08.png = tests\Images\Input\Png\xd3n2c08.png + tests\Images\Input\Png\xdtn0g01.png = tests\Images\Input\Png\xdtn0g01.png tests\Images\Input\Png\zlib-overflow.png = tests\Images\Input\Png\zlib-overflow.png + tests\Images\Input\Png\zlib-overflow2.png = tests\Images\Input\Png\zlib-overflow2.png + tests\Images\Input\Png\zlib-ztxt-bad-header.png = tests\Images\Input\Png\zlib-ztxt-bad-header.png EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp.Tests", "tests\ImageSharp.Tests\ImageSharp.Tests.csproj", "{EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}" @@ -332,6 +392,87 @@ Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SharedInfrastructure", "sha EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageSharp.Tests.ProfilingSandbox", "tests\ImageSharp.Tests.ProfilingSandbox\ImageSharp.Tests.ProfilingSandbox.csproj", "{FC527290-2F22-432C-B77B-6E815726B02C}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "issues", "issues", "{670DD46C-82E9-499A-B2D2-00A802ED0141}" + ProjectSection(SolutionItems) = preProject + tests\Images\Input\Png\issues\Issue_1014_1.png = tests\Images\Input\Png\issues\Issue_1014_1.png + tests\Images\Input\Png\issues\Issue_1014_2.png = tests\Images\Input\Png\issues\Issue_1014_2.png + tests\Images\Input\Png\issues\Issue_1014_3.png = tests\Images\Input\Png\issues\Issue_1014_3.png + tests\Images\Input\Png\issues\Issue_1014_4.png = tests\Images\Input\Png\issues\Issue_1014_4.png + tests\Images\Input\Png\issues\Issue_1014_5.png = tests\Images\Input\Png\issues\Issue_1014_5.png + tests\Images\Input\Png\issues\Issue_1014_6.png = tests\Images\Input\Png\issues\Issue_1014_6.png + tests\Images\Input\Png\issues\Issue_1047.png = tests\Images\Input\Png\issues\Issue_1047.png + tests\Images\Input\Png\issues\Issue_1127.png = tests\Images\Input\Png\issues\Issue_1127.png + tests\Images\Input\Png\issues\Issue_1177_1.png = tests\Images\Input\Png\issues\Issue_1177_1.png + tests\Images\Input\Png\issues\Issue_1177_2.png = tests\Images\Input\Png\issues\Issue_1177_2.png + tests\Images\Input\Png\issues\Issue_410.png = tests\Images\Input\Png\issues\Issue_410.png + tests\Images\Input\Png\issues\Issue_935.png = tests\Images\Input\Png\issues\Issue_935.png + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tga", "Tga", "{5DFC394F-136F-4B76-9BCA-3BA786515EFC}" + ProjectSection(SolutionItems) = preProject + tests\Images\Input\Tga\16bit_noalphabits.tga = tests\Images\Input\Tga\16bit_noalphabits.tga + tests\Images\Input\Tga\16bit_rle_noalphabits.tga = tests\Images\Input\Tga\16bit_rle_noalphabits.tga + tests\Images\Input\Tga\32bit_no_alphabits.tga = tests\Images\Input\Tga\32bit_no_alphabits.tga + tests\Images\Input\Tga\32bit_rle_no_alphabits.tga = tests\Images\Input\Tga\32bit_rle_no_alphabits.tga + tests\Images\Input\Tga\ccm8.tga = tests\Images\Input\Tga\ccm8.tga + tests\Images\Input\Tga\grayscale_a_LL.tga = tests\Images\Input\Tga\grayscale_a_LL.tga + tests\Images\Input\Tga\grayscale_a_LR.tga = tests\Images\Input\Tga\grayscale_a_LR.tga + tests\Images\Input\Tga\grayscale_a_rle_LL.tga = tests\Images\Input\Tga\grayscale_a_rle_LL.tga + tests\Images\Input\Tga\grayscale_a_rle_LR.tga = tests\Images\Input\Tga\grayscale_a_rle_LR.tga + tests\Images\Input\Tga\grayscale_a_rle_UL.tga = tests\Images\Input\Tga\grayscale_a_rle_UL.tga + tests\Images\Input\Tga\grayscale_a_rle_UR.tga = tests\Images\Input\Tga\grayscale_a_rle_UR.tga + tests\Images\Input\Tga\grayscale_a_UL.tga = tests\Images\Input\Tga\grayscale_a_UL.tga + tests\Images\Input\Tga\grayscale_a_UR.tga = tests\Images\Input\Tga\grayscale_a_UR.tga + tests\Images\Input\Tga\grayscale_LL.tga = tests\Images\Input\Tga\grayscale_LL.tga + tests\Images\Input\Tga\grayscale_LR.tga = tests\Images\Input\Tga\grayscale_LR.tga + tests\Images\Input\Tga\grayscale_rle_LR.tga = tests\Images\Input\Tga\grayscale_rle_LR.tga + tests\Images\Input\Tga\grayscale_rle_UL.tga = tests\Images\Input\Tga\grayscale_rle_UL.tga + tests\Images\Input\Tga\grayscale_rle_UR.tga = tests\Images\Input\Tga\grayscale_rle_UR.tga + tests\Images\Input\Tga\grayscale_UL.tga = tests\Images\Input\Tga\grayscale_UL.tga + tests\Images\Input\Tga\grayscale_UR.tga = tests\Images\Input\Tga\grayscale_UR.tga + tests\Images\Input\Tga\indexed_a_LL.tga = tests\Images\Input\Tga\indexed_a_LL.tga + tests\Images\Input\Tga\indexed_a_LR.tga = tests\Images\Input\Tga\indexed_a_LR.tga + tests\Images\Input\Tga\indexed_a_rle_LL.tga = tests\Images\Input\Tga\indexed_a_rle_LL.tga + tests\Images\Input\Tga\indexed_a_rle_LR.tga = tests\Images\Input\Tga\indexed_a_rle_LR.tga + tests\Images\Input\Tga\indexed_a_rle_UL.tga = tests\Images\Input\Tga\indexed_a_rle_UL.tga + tests\Images\Input\Tga\indexed_a_rle_UR.tga = tests\Images\Input\Tga\indexed_a_rle_UR.tga + tests\Images\Input\Tga\indexed_a_UL.tga = tests\Images\Input\Tga\indexed_a_UL.tga + tests\Images\Input\Tga\indexed_a_UR.tga = tests\Images\Input\Tga\indexed_a_UR.tga + tests\Images\Input\Tga\indexed_LR.tga = tests\Images\Input\Tga\indexed_LR.tga + tests\Images\Input\Tga\indexed_rle_LL.tga = tests\Images\Input\Tga\indexed_rle_LL.tga + tests\Images\Input\Tga\indexed_rle_LR.tga = tests\Images\Input\Tga\indexed_rle_LR.tga + tests\Images\Input\Tga\indexed_rle_UL.tga = tests\Images\Input\Tga\indexed_rle_UL.tga + tests\Images\Input\Tga\indexed_rle_UR.tga = tests\Images\Input\Tga\indexed_rle_UR.tga + tests\Images\Input\Tga\indexed_UL.tga = tests\Images\Input\Tga\indexed_UL.tga + tests\Images\Input\Tga\indexed_UR.tga = tests\Images\Input\Tga\indexed_UR.tga + tests\Images\Input\Tga\rgb15.tga = tests\Images\Input\Tga\rgb15.tga + tests\Images\Input\Tga\rgb15rle.tga = tests\Images\Input\Tga\rgb15rle.tga + tests\Images\Input\Tga\rgb24_top_left.tga = tests\Images\Input\Tga\rgb24_top_left.tga + tests\Images\Input\Tga\rgb_a_LL.tga = tests\Images\Input\Tga\rgb_a_LL.tga + tests\Images\Input\Tga\rgb_a_LR.tga = tests\Images\Input\Tga\rgb_a_LR.tga + tests\Images\Input\Tga\rgb_a_rle_LR.tga = tests\Images\Input\Tga\rgb_a_rle_LR.tga + tests\Images\Input\Tga\rgb_a_rle_UL.tga = tests\Images\Input\Tga\rgb_a_rle_UL.tga + tests\Images\Input\Tga\rgb_a_rle_UR.tga = tests\Images\Input\Tga\rgb_a_rle_UR.tga + tests\Images\Input\Tga\rgb_a_UL.tga = tests\Images\Input\Tga\rgb_a_UL.tga + tests\Images\Input\Tga\rgb_a_UR.tga = tests\Images\Input\Tga\rgb_a_UR.tga + tests\Images\Input\Tga\rgb_LR.tga = tests\Images\Input\Tga\rgb_LR.tga + tests\Images\Input\Tga\rgb_rle_LR.tga = tests\Images\Input\Tga\rgb_rle_LR.tga + tests\Images\Input\Tga\rgb_rle_UR.tga = tests\Images\Input\Tga\rgb_rle_UR.tga + tests\Images\Input\Tga\rgb_UR.tga = tests\Images\Input\Tga\rgb_UR.tga + tests\Images\Input\Tga\targa_16bit.tga = tests\Images\Input\Tga\targa_16bit.tga + tests\Images\Input\Tga\targa_16bit_pal.tga = tests\Images\Input\Tga\targa_16bit_pal.tga + tests\Images\Input\Tga\targa_16bit_rle.tga = tests\Images\Input\Tga\targa_16bit_rle.tga + tests\Images\Input\Tga\targa_24bit.tga = tests\Images\Input\Tga\targa_24bit.tga + tests\Images\Input\Tga\targa_24bit_pal.tga = tests\Images\Input\Tga\targa_24bit_pal.tga + tests\Images\Input\Tga\targa_24bit_pal_origin_topleft.tga = tests\Images\Input\Tga\targa_24bit_pal_origin_topleft.tga + tests\Images\Input\Tga\targa_24bit_rle.tga = tests\Images\Input\Tga\targa_24bit_rle.tga + tests\Images\Input\Tga\targa_24bit_rle_origin_topleft.tga = tests\Images\Input\Tga\targa_24bit_rle_origin_topleft.tga + tests\Images\Input\Tga\targa_32bit.tga = tests\Images\Input\Tga\targa_32bit.tga + tests\Images\Input\Tga\targa_32bit_rle.tga = tests\Images\Input\Tga\targa_32bit_rle.tga + tests\Images\Input\Tga\targa_8bit.tga = tests\Images\Input\Tga\targa_8bit.tga + tests\Images\Input\Tga\targa_8bit_rle.tga = tests\Images\Input\Tga\targa_8bit_rle.tga + EndProjectSection +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution shared-infrastructure\src\SharedInfrastructure\SharedInfrastructure.projitems*{2aa31a1f-142c-43f4-8687-09abca4b3a26}*SharedItemsImports = 5 @@ -399,6 +540,7 @@ Global HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution + {1799C43E-5C54-4A8F-8D64-B1475241DB0D} = {C317F1B1-D75E-4C6D-83EB-80367343E0D7} {FBE8C1AD-5AEC-4514-9B64-091D8E145865} = {1799C43E-5C54-4A8F-8D64-B1475241DB0D} {2AA31A1F-142C-43F4-8687-09ABCA4B3A26} = {815C0625-CD3D-440F-9F80-2D83856AB7AE} {FA55F5DE-11A6-487D-ABA4-BC93A02717DD} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC} @@ -420,6 +562,8 @@ Global {C0D7754B-5277-438E-ABEB-2BA34401B5A7} = {1799C43E-5C54-4A8F-8D64-B1475241DB0D} {68A8CC40-6AED-4E96-B524-31B1158FDEEA} = {815C0625-CD3D-440F-9F80-2D83856AB7AE} {FC527290-2F22-432C-B77B-6E815726B02C} = {56801022-D71A-4FBE-BC5B-CBA08E2284EC} + {670DD46C-82E9-499A-B2D2-00A802ED0141} = {E1C42A6F-913B-4A7B-B1A8-2BB62843B254} + {5DFC394F-136F-4B76-9BCA-3BA786515EFC} = {9DA226A1-8656-49A8-A58A-A8B5C081AD66} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {5F8B9D1F-CD8B-4CC5-8216-D531E25BD795} diff --git a/README.md b/README.md index 6b2fa5d0f5..6cc8e53047 100644 --- a/README.md +++ b/README.md @@ -70,13 +70,15 @@ To clone ImageSharp locally, click the "Clone in [YOUR_OS]" button above or run git clone https://github.com/SixLabors/ImageSharp ``` -If working with Windows please ensure that you have enabled log file paths in git (run as Administrator). +If working with Windows please ensure that you have enabled long file paths in git (run as Administrator). ```bash git config --system core.longpaths true ``` -This repository contains [git submodules](https://blog.github.com/2016-02-01-working-with-submodules/). To add the submodules to the project, navigate to the repository root and type: +This repository uses [Git Large File Storage](https://docs.github.com/en/github/managing-large-files/installing-git-large-file-storage). Please follow the linked instructions to ensure you have it set up in your environment. + +This repository contains [Git Submodules](https://blog.github.com/2016-02-01-working-with-submodules/). To add the submodules to the project, navigate to the repository root and type: ``` bash git submodule update --init --recursive @@ -130,4 +132,4 @@ Become a bronze sponsor with a monthly donation of $100 and get your logo (small - \ No newline at end of file + diff --git a/shared-infrastructure b/shared-infrastructure index b0d4cd9864..06a7339834 160000 --- a/shared-infrastructure +++ b/shared-infrastructure @@ -1 +1 @@ -Subproject commit b0d4cd98647996265a668e852574d901b27f22d6 +Subproject commit 06a733983486638b9e38197c7c6eb197ecac43e6 diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 650f30fe1c..d211992a94 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -5,40 +5,22 @@ Directory.Build.props is automatically picked up and imported by Microsoft.Common.props. This file needs to exist, even if empty so that files in the parent directory tree, with the same name, are not imported - instead. The import fairly early and only Sdk.props will have been + instead. They import fairly early and only Sdk.props will have been imported beforehand. We also don't need to add ourselves to MSBuildAllProjects, as that is done by the file that imports us. --> - - $(MSBuildAllProjects);$(MSBuildThisFileDirectory)..\Directory.Build.props - src - + + + - - $(MSBuildThisFileDirectory)..\shared-infrastructure\SixLabors.ruleset - true - - + true - - - true - true - - - - true - - true - snupkg - - @@ -47,6 +29,4 @@ - - diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index d1875262d3..c15c2a90cc 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -5,82 +5,15 @@ Directory.Build.targets is automatically picked up and imported by Microsoft.Common.targets. This file needs to exist, even if empty so that files in the parent directory tree, with the same name, are not imported - instead. The import fairly late and most other props/targets will have + instead. They import fairly late and most other props/targets will have been imported beforehand. We also don't need to add ourselves to MSBuildAllProjects, as that is done by the file that imports us. --> - - $(MSBuildAllProjects);$(MSBuildThisFileDirectory)..\Directory.Build.targets - + + + - - $(IntermediateOutputPath)$(MSBuildProjectName).InternalsVisibleTo$(DefaultLanguageSourceExtension) - - - - - - - <_LocalTopLevelSourceRoot Include="@(SourceRoot)" Condition="'%(SourceRoot.NestedRoot)' == ''"/> - - - - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ImageSharp/Color/Color.cs b/src/ImageSharp/Color/Color.cs index 554fcb8354..72f16528a6 100644 --- a/src/ImageSharp/Color/Color.cs +++ b/src/ImageSharp/Color/Color.cs @@ -27,19 +27,19 @@ namespace SixLabors.ImageSharp private Color(byte r, byte g, byte b, byte a) { this.data = new Rgba64( - ImageMaths.UpscaleFrom8BitTo16Bit(r), - ImageMaths.UpscaleFrom8BitTo16Bit(g), - ImageMaths.UpscaleFrom8BitTo16Bit(b), - ImageMaths.UpscaleFrom8BitTo16Bit(a)); + ColorNumerics.UpscaleFrom8BitTo16Bit(r), + ColorNumerics.UpscaleFrom8BitTo16Bit(g), + ColorNumerics.UpscaleFrom8BitTo16Bit(b), + ColorNumerics.UpscaleFrom8BitTo16Bit(a)); } [MethodImpl(InliningOptions.ShortMethod)] private Color(byte r, byte g, byte b) { this.data = new Rgba64( - ImageMaths.UpscaleFrom8BitTo16Bit(r), - ImageMaths.UpscaleFrom8BitTo16Bit(g), - ImageMaths.UpscaleFrom8BitTo16Bit(b), + ColorNumerics.UpscaleFrom8BitTo16Bit(r), + ColorNumerics.UpscaleFrom8BitTo16Bit(g), + ColorNumerics.UpscaleFrom8BitTo16Bit(b), ushort.MaxValue); } diff --git a/src/ImageSharp/ColorSpaces/Cmyk.cs b/src/ImageSharp/ColorSpaces/Cmyk.cs index 0aab295548..675f1f814c 100644 --- a/src/ImageSharp/ColorSpaces/Cmyk.cs +++ b/src/ImageSharp/ColorSpaces/Cmyk.cs @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.ColorSpaces [MethodImpl(InliningOptions.ShortMethod)] public Cmyk(Vector4 vector) { - vector = Vector4Utilities.FastClamp(vector, Min, Max); + vector = Numerics.Clamp(vector, Min, Max); this.C = vector.X; this.M = vector.Y; this.Y = vector.Z; diff --git a/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs b/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs index 719565fd81..5cd89abfd6 100644 --- a/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs +++ b/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding /// The representing the linear channel value. [MethodImpl(InliningOptions.ShortMethod)] public static float Expand(float channel) - => channel <= 0.08F ? (100F * channel) / CieConstants.Kappa : ImageMaths.Pow3((channel + 0.16F) / 1.16F); + => channel <= 0.08F ? (100F * channel) / CieConstants.Kappa : Numerics.Pow3((channel + 0.16F) / 1.16F); /// /// Compresses an uncompanded channel (linear) to its nonlinear equivalent. diff --git a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs index 2e212ad19f..dc6c960aa5 100644 --- a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs +++ b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs @@ -1,10 +1,14 @@ -// Copyright (c) Six Labors. +// 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.ColorSpaces.Companding { @@ -18,19 +22,83 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding /// public static class SRgbCompanding { + private const int Length = Scale + 2; // 256kb @ 16bit precision. + private const int Scale = (1 << 16) - 1; + + private static readonly Lazy LazyCompressTable = new Lazy( + () => + { + var result = new float[Length]; + + for (int i = 0; i < result.Length; i++) + { + double d = (double)i / Scale; + if (d <= (0.04045 / 12.92)) + { + d *= 12.92; + } + else + { + d = (1.055 * Math.Pow(d, 1.0 / 2.4)) - 0.055; + } + + result[i] = (float)d; + } + + return result; + }, + true); + + private static readonly Lazy LazyExpandTable = new Lazy( + () => + { + var result = new float[Length]; + + for (int i = 0; i < result.Length; i++) + { + double d = (double)i / Scale; + if (d <= 0.04045) + { + d /= 12.92; + } + else + { + d = Math.Pow((d + 0.055) / 1.055, 2.4); + } + + result[i] = (float)d; + } + + return result; + }, + true); + + private static float[] ExpandTable => LazyExpandTable.Value; + + private static float[] CompressTable => LazyCompressTable.Value; + /// /// Expands the companded vectors to their linear equivalents with respect to the energy. /// /// The span of vectors. - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Expand(Span vectors) { - ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx2.IsSupported && vectors.Length >= 2) + { + CompandAvx2(vectors, ExpandTable); - for (int i = 0; i < vectors.Length; i++) + if (Numerics.Modulo2(vectors.Length) != 0) + { + // Vector4 fits neatly in pairs. Any overlap has to be equal to 1. + Expand(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1))); + } + } + else +#endif { - ref Vector4 v = ref Unsafe.Add(ref baseRef, i); - Expand(ref v); + CompandScalar(vectors, ExpandTable); } } @@ -38,15 +106,24 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding /// Compresses the uncompanded vectors to their nonlinear equivalents with respect to the energy. /// /// The span of vectors. - [MethodImpl(InliningOptions.ShortMethod)] - public static void Compress(Span vectors) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void Compress(Span vectors) { - ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx2.IsSupported && vectors.Length >= 2) + { + CompandAvx2(vectors, CompressTable); - for (int i = 0; i < vectors.Length; i++) + if (Numerics.Modulo2(vectors.Length) != 0) + { + // Vector4 fits neatly in pairs. Any overlap has to be equal to 1. + Compress(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1))); + } + } + else +#endif { - ref Vector4 v = ref Unsafe.Add(ref baseRef, i); - Compress(ref v); + CompandScalar(vectors, CompressTable); } } @@ -54,9 +131,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding /// Expands a companded vector to its linear equivalent with respect to the energy. /// /// The vector. - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Expand(ref Vector4 vector) { + // Alpha is already a linear representation of opacity so we do not want to convert it. vector.X = Expand(vector.X); vector.Y = Expand(vector.Y); vector.Z = Expand(vector.Z); @@ -66,9 +144,10 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding /// Compresses an uncompanded vector (linear) to its nonlinear equivalent. /// /// The vector. - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Compress(ref Vector4 vector) { + // Alpha is already a linear representation of opacity so we do not want to convert it. vector.X = Compress(vector.X); vector.Y = Compress(vector.Y); vector.Z = Compress(vector.Z); @@ -79,15 +158,84 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding /// /// The channel value. /// The representing the linear channel value. - [MethodImpl(InliningOptions.ShortMethod)] - public static float Expand(float channel) => channel <= 0.04045F ? channel / 12.92F : MathF.Pow((channel + 0.055F) / 1.055F, 2.4F); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Expand(float channel) + => channel <= 0.04045F ? channel / 12.92F : MathF.Pow((channel + 0.055F) / 1.055F, 2.4F); /// /// Compresses an uncompanded channel (linear) to its nonlinear equivalent. /// /// The channel value. /// The representing the nonlinear channel value. - [MethodImpl(InliningOptions.ShortMethod)] - public static float Compress(float channel) => channel <= 0.0031308F ? 12.92F * channel : (1.055F * MathF.Pow(channel, 0.416666666666667F)) - 0.055F; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Compress(float channel) + => channel <= 0.0031308F ? 12.92F * channel : (1.055F * MathF.Pow(channel, 0.416666666666667F)) - 0.055F; + +#if SUPPORTS_RUNTIME_INTRINSICS + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static unsafe void CompandAvx2(Span vectors, float[] table) + { + fixed (float* tablePointer = &table[0]) + { + var scale = Vector256.Create((float)Scale); + Vector256 zero = Vector256.Zero; + var offset = Vector256.Create(1); + + // Divide by 2 as 4 elements per Vector4 and 8 per Vector256 + ref Vector256 vectorsBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(vectors)); + ref Vector256 vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u)); + + while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) + { + Vector256 multiplied = Avx.Multiply(scale, vectorsBase); + multiplied = Avx.Min(Avx.Max(zero, multiplied), scale); + + Vector256 truncated = Avx.ConvertToVector256Int32WithTruncation(multiplied); + Vector256 truncatedF = Avx.ConvertToVector256Single(truncated); + + Vector256 low = Avx2.GatherVector256(tablePointer, truncated, sizeof(float)); + Vector256 high = Avx2.GatherVector256(tablePointer, Avx2.Add(truncated, offset), sizeof(float)); + + // Alpha is already a linear representation of opacity so we do not want to convert it. + Vector256 companded = Numerics.Lerp(low, high, Avx.Subtract(multiplied, truncatedF)); + vectorsBase = Avx.Blend(companded, vectorsBase, Numerics.BlendAlphaControl); + vectorsBase = ref Unsafe.Add(ref vectorsBase, 1); + } + } + } +#endif + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static unsafe void CompandScalar(Span vectors, float[] table) + { + fixed (float* tablePointer = &table[0]) + { + Vector4 zero = Vector4.Zero; + var scale = new Vector4(Scale); + ref Vector4 vectorsBase = ref MemoryMarshal.GetReference(vectors); + ref Vector4 vectorsLast = ref Unsafe.Add(ref vectorsBase, vectors.Length); + + while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) + { + Vector4 multiplied = Numerics.Clamp(vectorsBase * Scale, zero, scale); + + float f0 = multiplied.X; + float f1 = multiplied.Y; + float f2 = multiplied.Z; + + uint i0 = (uint)f0; + uint i1 = (uint)f1; + uint i2 = (uint)f2; + + // Alpha is already a linear representation of opacity so we do not want to convert it. + vectorsBase.X = Numerics.Lerp(tablePointer[i0], tablePointer[i0 + 1], f0 - (int)i0); + vectorsBase.Y = Numerics.Lerp(tablePointer[i1], tablePointer[i1 + 1], f1 - (int)i1); + vectorsBase.Z = Numerics.Lerp(tablePointer[i2], tablePointer[i2 + 1], f2 - (int)i2); + + vectorsBase = ref Unsafe.Add(ref vectorsBase, 1); + } + } + } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs index 31c3f46330..34354efe54 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs @@ -25,11 +25,11 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion float fx = (a / 500F) + fy; float fz = fy - (b / 200F); - float fx3 = ImageMaths.Pow3(fx); - float fz3 = ImageMaths.Pow3(fz); + float fx3 = Numerics.Pow3(fx); + float fz3 = Numerics.Pow3(fz); float xr = fx3 > CieConstants.Epsilon ? fx3 : ((116F * fx) - 16F) / CieConstants.Kappa; - float yr = l > CieConstants.Kappa * CieConstants.Epsilon ? ImageMaths.Pow3((l + 16F) / 116F) : l / CieConstants.Kappa; + float yr = l > CieConstants.Kappa * CieConstants.Epsilon ? Numerics.Pow3((l + 16F) / 116F) : l / CieConstants.Kappa; float zr = fz3 > CieConstants.Epsilon ? fz3 : ((116F * fz) - 16F) / CieConstants.Kappa; var wxyz = new Vector3(input.WhitePoint.X, input.WhitePoint.Y, input.WhitePoint.Z); diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs index 7f15fc77d8..12c65105fc 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System.Runtime.CompilerServices; @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion float v0 = ComputeV0(input.WhitePoint); float y = l > CieConstants.Kappa * CieConstants.Epsilon - ? ImageMaths.Pow3((l + 16) / 116) + ? Numerics.Pow3((l + 16) / 116) : l / CieConstants.Kappa; float a = ((52 * l / (u + (13 * l * u0))) - 1) / 3; @@ -71,4 +71,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion private static float ComputeV0(in CieXyz input) => (9 * input.Y) / (input.X + (15 * input.Y) + (3 * input.Z)); } -} \ No newline at end of file +} diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs index 4c3cdba224..f120d6f3dd 100644 --- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs +++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion float ka = ComputeKa(input.WhitePoint); float kb = ComputeKb(input.WhitePoint); - float pow = ImageMaths.Pow2(l / 100F); + float pow = Numerics.Pow2(l / 100F); float sqrtPow = MathF.Sqrt(pow); float y = pow * yn; diff --git a/src/ImageSharp/ColorSpaces/YCbCr.cs b/src/ImageSharp/ColorSpaces/YCbCr.cs index eaaf7f58f4..b39fe30252 100644 --- a/src/ImageSharp/ColorSpaces/YCbCr.cs +++ b/src/ImageSharp/ColorSpaces/YCbCr.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System; @@ -100,4 +100,4 @@ namespace SixLabors.ImageSharp.ColorSpaces && this.Cr.Equals(other.Cr); } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Common/Extensions/ComparableExtensions.cs b/src/ImageSharp/Common/Extensions/ComparableExtensions.cs deleted file mode 100644 index ef3d1deac3..0000000000 --- a/src/ImageSharp/Common/Extensions/ComparableExtensions.cs +++ /dev/null @@ -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 -{ - /// - /// Extension methods for classes that implement . - /// - internal static class ComparableExtensions - { - /// - /// Restricts a to be within a specified range. - /// - /// The value to clamp. - /// The minimum value. If value is less than min, min will be returned. - /// The maximum value. If value is greater than max, max will be returned. - /// - /// The representing the clamped value. - /// - [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; - } - - /// - /// Restricts a to be within a specified range. - /// - /// The The value to clamp. - /// The minimum value. If value is less than min, min will be returned. - /// The maximum value. If value is greater than max, max will be returned. - /// - /// The representing the clamped value. - /// - [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; - } - - /// - /// Restricts a to be within a specified range. - /// - /// The The value to clamp. - /// The minimum value. If value is less than min, min will be returned. - /// The maximum value. If value is greater than max, max will be returned. - /// - /// The representing the clamped value. - /// - [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; - } - - /// - /// Restricts a to be within a specified range. - /// - /// The The value to clamp. - /// The minimum value. If value is less than min, min will be returned. - /// The maximum value. If value is greater than max, max will be returned. - /// - /// The representing the clamped value. - /// - [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; - } - - /// - /// Restricts a to be within a specified range. - /// - /// The The value to clamp. - /// The minimum value. If value is less than min, min will be returned. - /// The maximum value. If value is greater than max, max will be returned. - /// - /// The representing the clamped value. - /// - [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; - } - } -} diff --git a/src/ImageSharp/Common/Helpers/Buffer2DUtils.cs b/src/ImageSharp/Common/Helpers/Buffer2DUtils.cs deleted file mode 100644 index f4811d6ca8..0000000000 --- a/src/ImageSharp/Common/Helpers/Buffer2DUtils.cs +++ /dev/null @@ -1,109 +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; - -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; - -namespace SixLabors.ImageSharp -{ - /// - /// Extension methods for . - /// TODO: One day rewrite all this to use SIMD intrinsics. There's a lot of scope for improvement. - /// - internal static class Buffer2DUtils - { - /// - /// Computes the sum of vectors in weighted by the kernel weight values. - /// - /// The pixel format. - /// The 1D convolution kernel. - /// The source frame. - /// The target row. - /// The current row. - /// The current column. - /// The minimum working area row. - /// The maximum working area row. - /// The minimum working area column. - /// The maximum working area column. - public static void Convolve4( - Span kernel, - Buffer2D sourcePixels, - Span targetRow, - int row, - int column, - int minRow, - int maxRow, - int minColumn, - int maxColumn) - where TPixel : unmanaged, IPixel - { - ComplexVector4 vector = default; - int kernelLength = kernel.Length; - int radiusY = kernelLength >> 1; - int sourceOffsetColumnBase = column + minColumn; - ref Complex64 baseRef = ref MemoryMarshal.GetReference(kernel); - - for (int i = 0; i < kernelLength; i++) - { - int offsetY = (row + i - radiusY).Clamp(minRow, maxRow); - int offsetX = sourceOffsetColumnBase.Clamp(minColumn, maxColumn); - Span sourceRowSpan = sourcePixels.GetRowSpan(offsetY); - var currentColor = sourceRowSpan[offsetX].ToVector4(); - - vector.Sum(Unsafe.Add(ref baseRef, i) * currentColor); - } - - targetRow[column] = vector; - } - - /// - /// Computes the sum of vectors in weighted by the kernel weight values and accumulates the partial results. - /// - /// The 1D convolution kernel. - /// The source frame. - /// The target row. - /// The current row. - /// The current column. - /// The minimum working area row. - /// The maximum working area row. - /// The minimum working area column. - /// The maximum working area column. - /// The weight factor for the real component of the complex pixel values. - /// The weight factor for the imaginary component of the complex pixel values. - public static void Convolve4AndAccumulatePartials( - Span kernel, - Buffer2D sourceValues, - Span targetRow, - int row, - int column, - int minRow, - int maxRow, - int minColumn, - int maxColumn, - float z, - float w) - { - ComplexVector4 vector = default; - int kernelLength = kernel.Length; - int radiusX = kernelLength >> 1; - int sourceOffsetColumnBase = column + minColumn; - - int offsetY = row.Clamp(minRow, maxRow); - ref ComplexVector4 sourceRef = ref MemoryMarshal.GetReference(sourceValues.GetRowSpan(offsetY)); - ref Complex64 baseRef = ref MemoryMarshal.GetReference(kernel); - - for (int x = 0; x < kernelLength; x++) - { - int offsetX = (sourceOffsetColumnBase + x - radiusX).Clamp(minColumn, maxColumn); - vector.Sum(Unsafe.Add(ref baseRef, x) * Unsafe.Add(ref sourceRef, offsetX)); - } - - targetRow[column] += vector.WeightedSum(z, w); - } - } -} diff --git a/src/ImageSharp/Common/Helpers/ColorNumerics.cs b/src/ImageSharp/Common/Helpers/ColorNumerics.cs new file mode 100644 index 0000000000..6f225b1109 --- /dev/null +++ b/src/ImageSharp/Common/Helpers/ColorNumerics.cs @@ -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 +{ + /// + /// Provides optimized static methods for common mathematical functions specific + /// to color processing. + /// + internal static class ColorNumerics + { + /// + /// Vector for converting pixel to gray value as specified by + /// ITU-R Recommendation BT.709. + /// + private static readonly Vector4 Bt709 = new Vector4(.2126f, .7152f, .0722f, 0.0f); + + /// + /// Convert a pixel value to grayscale using ITU-R Recommendation BT.709. + /// + /// The vector to get the luminance from. + /// + /// The number of luminance levels (256 for 8 bit, 65536 for 16 bit grayscale images). + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetBT709Luminance(ref Vector4 vector, int luminanceLevels) + => (int)MathF.Round(Vector4.Dot(vector, Bt709) * (luminanceLevels - 1)); + + /// + /// Gets the luminance from the rgb components using the formula + /// as specified by ITU-R Recommendation BT.709. + /// + /// The red component. + /// The green component. + /// The blue component. + /// The . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static byte Get8BitBT709Luminance(byte r, byte g, byte b) + => (byte)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F); + + /// + /// Gets the luminance from the rgb components using the formula as + /// specified by ITU-R Recommendation BT.709. + /// + /// The red component. + /// The green component. + /// The blue component. + /// The . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ushort Get16BitBT709Luminance(ushort r, ushort g, ushort b) + => (ushort)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F); + + /// + /// Gets the luminance from the rgb components using the formula as specified + /// by ITU-R Recommendation BT.709. + /// + /// The red component. + /// The green component. + /// The blue component. + /// The . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ushort Get16BitBT709Luminance(float r, float g, float b) + => (ushort)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F); + + /// + /// Scales a value from a 16 bit to an + /// 8 bit equivalent. + /// + /// The 8 bit component value. + /// The + [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); + } + + /// + /// Scales a value from an 8 bit to + /// an 16 bit equivalent. + /// + /// The 8 bit component value. + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ushort UpscaleFrom8BitTo16Bit(byte component) + => (ushort)(component * 257); + + /// + /// Returns how many bits are required to store the specified number of colors. + /// Performs a Log2() on the value. + /// + /// The number of colors. + /// + /// The + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetBitsNeededForColorDepth(int colors) + => Math.Max(1, (int)Math.Ceiling(Math.Log(colors, 2))); + + /// + /// Returns how many colors will be created by the specified number of bits. + /// + /// The bit depth. + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetColorCountForBitDepth(int bitDepth) + => 1 << bitDepth; + + /// + /// Transforms a vector by the given color matrix. + /// + /// The source vector. + /// The transformation color matrix. + [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; + } + + /// + /// Bulk variant of . + /// + /// The span of vectors + /// The transformation color matrix. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Transform(Span 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); + } + } + } +} diff --git a/src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs b/src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs deleted file mode 100644 index 61f90e23e1..0000000000 --- a/src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs +++ /dev/null @@ -1,279 +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.Memory; -using SixLabors.ImageSharp.PixelFormats; - -namespace SixLabors.ImageSharp -{ - /// - /// Extension methods for . - /// TODO: One day rewrite all this to use SIMD intrinsics. There's a lot of scope for improvement. - /// - internal static class DenseMatrixUtils - { - /// - /// Computes the sum of vectors in the span referenced by weighted by the two kernel weight values. - /// Using this method the convolution filter is not applied to alpha in addition to the color channels. - /// - /// The pixel format. - /// The vertical dense matrix. - /// The horizontal dense matrix. - /// The source frame. - /// The target row base reference. - /// The current row. - /// The current column. - /// The minimum working area row. - /// The maximum working area row. - /// The minimum working area column. - /// The maximum working area column. - [MethodImpl(InliningOptions.ShortMethod)] - public static void Convolve2D3( - in DenseMatrix matrixY, - in DenseMatrix matrixX, - Buffer2D sourcePixels, - ref Vector4 targetRowRef, - int row, - int column, - int minRow, - int maxRow, - int minColumn, - int maxColumn) - where TPixel : unmanaged, IPixel - { - Convolve2DImpl( - in matrixY, - in matrixX, - sourcePixels, - row, - column, - minRow, - maxRow, - minColumn, - maxColumn, - out Vector4 vector); - - ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column); - vector.W = target.W; - - Vector4Utilities.UnPremultiply(ref vector); - target = vector; - } - - /// - /// Computes the sum of vectors in the span referenced by weighted by the two kernel weight values. - /// Using this method the convolution filter is applied to alpha in addition to the color channels. - /// - /// The pixel format. - /// The vertical dense matrix. - /// The horizontal dense matrix. - /// The source frame. - /// The target row base reference. - /// The current row. - /// The current column. - /// The minimum working area row. - /// The maximum working area row. - /// The minimum working area column. - /// The maximum working area column. - [MethodImpl(InliningOptions.ShortMethod)] - public static void Convolve2D4( - in DenseMatrix matrixY, - in DenseMatrix matrixX, - Buffer2D sourcePixels, - ref Vector4 targetRowRef, - int row, - int column, - int minRow, - int maxRow, - int minColumn, - int maxColumn) - where TPixel : unmanaged, IPixel - { - Convolve2DImpl( - in matrixY, - in matrixX, - sourcePixels, - row, - column, - minRow, - maxRow, - minColumn, - maxColumn, - out Vector4 vector); - - ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column); - Vector4Utilities.UnPremultiply(ref vector); - target = vector; - } - - [MethodImpl(InliningOptions.ShortMethod)] - public static void Convolve2DImpl( - in DenseMatrix matrixY, - in DenseMatrix matrixX, - Buffer2D sourcePixels, - int row, - int column, - int minRow, - int maxRow, - int minColumn, - int maxColumn, - out Vector4 vector) - where TPixel : unmanaged, IPixel - { - Vector4 vectorY = default; - Vector4 vectorX = default; - int matrixHeight = matrixY.Rows; - int matrixWidth = matrixY.Columns; - int radiusY = matrixHeight >> 1; - int radiusX = matrixWidth >> 1; - int sourceOffsetColumnBase = column + minColumn; - - for (int y = 0; y < matrixHeight; y++) - { - int offsetY = (row + y - radiusY).Clamp(minRow, maxRow); - Span sourceRowSpan = sourcePixels.GetRowSpan(offsetY); - - for (int x = 0; x < matrixWidth; x++) - { - int offsetX = (sourceOffsetColumnBase + x - radiusX).Clamp(minColumn, maxColumn); - var currentColor = sourceRowSpan[offsetX].ToVector4(); - Vector4Utilities.Premultiply(ref currentColor); - - vectorX += matrixX[y, x] * currentColor; - vectorY += matrixY[y, x] * currentColor; - } - } - - vector = Vector4.SquareRoot((vectorX * vectorX) + (vectorY * vectorY)); - } - - /// - /// Computes the sum of vectors in the span referenced by weighted by the kernel weight values. - /// Using this method the convolution filter is not applied to alpha in addition to the color channels. - /// - /// The pixel format. - /// The dense matrix. - /// The source frame. - /// The target row base reference. - /// The current row. - /// The current column. - /// The minimum working area row. - /// The maximum working area row. - /// The minimum working area column. - /// The maximum working area column. - [MethodImpl(InliningOptions.ShortMethod)] - public static void Convolve3( - in DenseMatrix matrix, - Buffer2D sourcePixels, - ref Vector4 targetRowRef, - int row, - int column, - int minRow, - int maxRow, - int minColumn, - int maxColumn) - where TPixel : unmanaged, IPixel - { - Vector4 vector = default; - - ConvolveImpl( - in matrix, - sourcePixels, - row, - column, - minRow, - maxRow, - minColumn, - maxColumn, - ref vector); - - ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column); - vector.W = target.W; - - Vector4Utilities.UnPremultiply(ref vector); - target = vector; - } - - /// - /// Computes the sum of vectors in the span referenced by weighted by the kernel weight values. - /// Using this method the convolution filter is applied to alpha in addition to the color channels. - /// - /// The pixel format. - /// The dense matrix. - /// The source frame. - /// The target row base reference. - /// The current row. - /// The current column. - /// The minimum working area row. - /// The maximum working area row. - /// The minimum working area column. - /// The maximum working area column. - [MethodImpl(InliningOptions.ShortMethod)] - public static void Convolve4( - in DenseMatrix matrix, - Buffer2D sourcePixels, - ref Vector4 targetRowRef, - int row, - int column, - int minRow, - int maxRow, - int minColumn, - int maxColumn) - where TPixel : unmanaged, IPixel - { - Vector4 vector = default; - - ConvolveImpl( - in matrix, - sourcePixels, - row, - column, - minRow, - maxRow, - minColumn, - maxColumn, - ref vector); - - ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column); - Vector4Utilities.UnPremultiply(ref vector); - target = vector; - } - - [MethodImpl(InliningOptions.ShortMethod)] - private static void ConvolveImpl( - in DenseMatrix matrix, - Buffer2D sourcePixels, - int row, - int column, - int minRow, - int maxRow, - int minColumn, - int maxColumn, - ref Vector4 vector) - where TPixel : unmanaged, IPixel - { - int matrixHeight = matrix.Rows; - int matrixWidth = matrix.Columns; - int radiusY = matrixHeight >> 1; - int radiusX = matrixWidth >> 1; - int sourceOffsetColumnBase = column + minColumn; - - for (int y = 0; y < matrixHeight; y++) - { - int offsetY = (row + y - radiusY).Clamp(minRow, maxRow); - Span sourceRowSpan = sourcePixels.GetRowSpan(offsetY); - - for (int x = 0; x < matrixWidth; x++) - { - int offsetX = (sourceOffsetColumnBase + x - radiusX).Clamp(minColumn, maxColumn); - var currentColor = sourceRowSpan[offsetX].ToVector4(); - Vector4Utilities.Premultiply(ref currentColor); - vector += matrix[y, x] * currentColor; - } - } - } - } -} diff --git a/src/ImageSharp/Common/Helpers/ImageMaths.cs b/src/ImageSharp/Common/Helpers/ImageMaths.cs deleted file mode 100644 index 977432f8bb..0000000000 --- a/src/ImageSharp/Common/Helpers/ImageMaths.cs +++ /dev/null @@ -1,373 +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 -{ - /// - /// Provides common mathematical methods. - /// - internal static class ImageMaths - { - /// - /// Vector for converting pixel to gray value as specified by ITU-R Recommendation BT.709. - /// - private static readonly Vector4 Bt709 = new Vector4(.2126f, .7152f, .0722f, 0.0f); - - /// - /// Convert a pixel value to grayscale using ITU-R Recommendation BT.709. - /// - /// The vector to get the luminance from. - /// The number of luminance levels (256 for 8 bit, 65536 for 16 bit grayscale images) - [MethodImpl(InliningOptions.ShortMethod)] - public static int GetBT709Luminance(ref Vector4 vector, int luminanceLevels) - => (int)MathF.Round(Vector4.Dot(vector, Bt709) * (luminanceLevels - 1)); - - /// - /// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709. - /// - /// The red component. - /// The green component. - /// The blue component. - /// The . - [MethodImpl(InliningOptions.ShortMethod)] - public static byte Get8BitBT709Luminance(byte r, byte g, byte b) => - (byte)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F); - - /// - /// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709. - /// - /// The red component. - /// The green component. - /// The blue component. - /// The . - [MethodImpl(InliningOptions.ShortMethod)] - public static ushort Get16BitBT709Luminance(ushort r, ushort g, ushort b) => - (ushort)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F); - - /// - /// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709. - /// - /// The red component. - /// The green component. - /// The blue component. - /// The . - [MethodImpl(InliningOptions.ShortMethod)] - public static ushort Get16BitBT709Luminance(float r, float g, float b) => - (ushort)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F); - - /// - /// Scales a value from a 16 bit to it's 8 bit equivalent. - /// - /// The 8 bit component value. - /// The - [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); - } - - /// - /// Scales a value from an 8 bit to it's 16 bit equivalent. - /// - /// The 8 bit component value. - /// The - [MethodImpl(InliningOptions.ShortMethod)] - public static ushort UpscaleFrom8BitTo16Bit(byte component) => (ushort)(component * 257); - - /// - /// Determine the Greatest CommonDivisor (GCD) of two numbers. - /// - public static int GreatestCommonDivisor(int a, int b) - { - while (b != 0) - { - int temp = b; - b = a % b; - a = temp; - } - - return a; - } - - /// - /// Determine the Least Common Multiple (LCM) of two numbers. - /// - 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; - } - - /// - /// Calculates % 4 - /// - [MethodImpl(InliningOptions.ShortMethod)] - public static int Modulo4(int x) => x & 3; - - /// - /// Calculates % 8 - /// - [MethodImpl(InliningOptions.ShortMethod)] - public static int Modulo8(int x) => x & 7; - - /// - /// Fast (x mod m) calculator, with the restriction that - /// should be power of 2. - /// - [MethodImpl(InliningOptions.ShortMethod)] - public static int ModuloP2(int x, int m) => x & (m - 1); - - /// - /// Returns the absolute value of a 32-bit signed integer. Uses bit shifting to speed up the operation. - /// - /// - /// A number that is greater than , but less than or equal to - /// - /// The - [MethodImpl(InliningOptions.ShortMethod)] - public static int FastAbs(int x) - { - int y = x >> 31; - return (x ^ y) - y; - } - - /// - /// Returns a specified number raised to the power of 2 - /// - /// A single-precision floating-point number - /// The number raised to the power of 2. - [MethodImpl(InliningOptions.ShortMethod)] - public static float Pow2(float x) => x * x; - - /// - /// Returns a specified number raised to the power of 3 - /// - /// A single-precision floating-point number - /// The number raised to the power of 3. - [MethodImpl(InliningOptions.ShortMethod)] - public static float Pow3(float x) => x * x * x; - - /// - /// Returns how many bits are required to store the specified number of colors. - /// Performs a Log2() on the value. - /// - /// The number of colors. - /// - /// The - /// - [MethodImpl(InliningOptions.ShortMethod)] - public static int GetBitsNeededForColorDepth(int colors) => Math.Max(1, (int)Math.Ceiling(Math.Log(colors, 2))); - - /// - /// Returns how many colors will be created by the specified number of bits. - /// - /// The bit depth. - /// The - [MethodImpl(InliningOptions.ShortMethod)] - public static int GetColorCountForBitDepth(int bitDepth) => 1 << bitDepth; - - /// - /// Implementation of 1D Gaussian G(x) function - /// - /// The x provided to G(x). - /// The spread of the blur. - /// The Gaussian G(x) - [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; - } - - /// - /// Returns the result of a normalized sine cardinal function for the given value. - /// SinC(x) = sin(pi*x)/(pi*x). - /// - /// A single-precision floating-point number to calculate the result for. - /// - /// The sine cardinal of . - /// - [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; - } - - /// - /// Gets the bounding from the given points. - /// - /// - /// The designating the top left position. - /// - /// - /// The designating the bottom right position. - /// - /// - /// The bounding . - /// - [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); - - /// - /// Finds the bounding rectangle based on the first instance of any color component other - /// than the given one. - /// - /// The pixel format. - /// The to search within. - /// The color component value to remove. - /// The channel to test against. - /// - /// The . - /// - public static Rectangle GetFilteredBoundingRectangle(ImageFrame bitmap, float componentValue, RgbaComponent channel = RgbaComponent.B) - where TPixel : unmanaged, IPixel - { - int width = bitmap.Width; - int height = bitmap.Height; - Point topLeft = default; - Point bottomRight = default; - - Func, 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 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 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 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 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); - } - } -} diff --git a/src/ImageSharp/Common/Helpers/Numerics.cs b/src/ImageSharp/Common/Helpers/Numerics.cs new file mode 100644 index 0000000000..6105422372 --- /dev/null +++ b/src/ImageSharp/Common/Helpers/Numerics.cs @@ -0,0 +1,752 @@ +// 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 +{ + /// + /// Provides optimized static methods for trigonometric, logarithmic, + /// and other common mathematical functions. + /// + internal static class Numerics + { +#if SUPPORTS_RUNTIME_INTRINSICS + public const int BlendAlphaControl = 0b_10_00_10_00; + private const int ShuffleAlphaControl = 0b_11_11_11_11; +#endif + + /// + /// Determine the Greatest CommonDivisor (GCD) of two numbers. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GreatestCommonDivisor(int a, int b) + { + while (b != 0) + { + int temp = b; + b = a % b; + a = temp; + } + + return a; + } + + /// + /// Determine the Least Common Multiple (LCM) of two numbers. + /// See https://en.wikipedia.org/wiki/Least_common_multiple#Reduction_by_the_greatest_common_divisor. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int LeastCommonMultiple(int a, int b) + => a / GreatestCommonDivisor(a, b) * b; + + /// + /// Calculates % 2 + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Modulo2(int x) => x & 1; + + /// + /// Calculates % 4 + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Modulo4(int x) => x & 3; + + /// + /// Calculates % 8 + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Modulo8(int x) => x & 7; + + /// + /// Fast (x mod m) calculator, with the restriction that + /// should be power of 2. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int ModuloP2(int x, int m) => x & (m - 1); + + /// + /// Returns the absolute value of a 32-bit signed integer. + /// Uses bit shifting to speed up the operation compared to . + /// + /// + /// A number that is greater than , but less than + /// or equal to + /// + /// The + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Abs(int x) + { + int y = x >> 31; + return (x ^ y) - y; + } + + /// + /// Returns a specified number raised to the power of 2 + /// + /// A single-precision floating-point number + /// The number raised to the power of 2. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Pow2(float x) => x * x; + + /// + /// Returns a specified number raised to the power of 3 + /// + /// A single-precision floating-point number + /// The number raised to the power of 3. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Pow3(float x) => x * x * x; + + /// + /// Implementation of 1D Gaussian G(x) function + /// + /// The x provided to G(x). + /// The spread of the blur. + /// The Gaussian G(x) + [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; + } + + /// + /// Returns the result of a normalized sine cardinal function for the given value. + /// SinC(x) = sin(pi*x)/(pi*x). + /// + /// A single-precision floating-point number to calculate the result for. + /// + /// The sine cardinal of . + /// + [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; + } + + /// + /// Returns the value clamped to the inclusive range of min and max. + /// + /// The value to clamp. + /// The minimum inclusive value. + /// The maximum inclusive value. + /// The clamped . + [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; + } + + /// + /// Returns the value clamped to the inclusive range of min and max. + /// + /// The value to clamp. + /// The minimum inclusive value. + /// The maximum inclusive value. + /// The clamped . + [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; + } + + /// + /// Returns the value clamped to the inclusive range of min and max. + /// + /// The value to clamp. + /// The minimum inclusive value. + /// The maximum inclusive value. + /// The clamped . + [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; + } + + /// + /// Returns the value clamped to the inclusive range of min and max. + /// + /// The value to clamp. + /// The minimum inclusive value. + /// The maximum inclusive value. + /// The clamped . + [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; + } + + /// + /// Returns the value clamped to the inclusive range of min and max. + /// + /// The value to clamp. + /// The minimum inclusive value. + /// The maximum inclusive value. + /// The clamped . + [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; + } + + /// + /// Returns the value clamped to the inclusive range of min and max. + /// 5x Faster than + /// on platforms < NET 5. + /// + /// The value to clamp. + /// The minimum inclusive value. + /// The maximum inclusive value. + /// The clamped . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector4 Clamp(Vector4 value, Vector4 min, Vector4 max) + => Vector4.Min(Vector4.Max(value, min), max); + + /// + /// Clamps the span values to the inclusive range of min and max. + /// + /// The span containing the values to clamp. + /// The minimum inclusive value. + /// The maximum inclusive value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Clamp(Span span, byte min, byte max) + { + Span remainder = span.Slice(ClampReduce(span, min, max)); + + if (remainder.Length > 0) + { + ref byte remainderStart = ref MemoryMarshal.GetReference(remainder); + ref byte remainderEnd = ref Unsafe.Add(ref remainderStart, remainder.Length); + + while (Unsafe.IsAddressLessThan(ref remainderStart, ref remainderEnd)) + { + remainderStart = Clamp(remainderStart, min, max); + + remainderStart = ref Unsafe.Add(ref remainderStart, 1); + } + } + } + + /// + /// Clamps the span values to the inclusive range of min and max. + /// + /// The span containing the values to clamp. + /// The minimum inclusive value. + /// The maximum inclusive value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Clamp(Span span, uint min, uint max) + { + Span remainder = span.Slice(ClampReduce(span, min, max)); + + if (remainder.Length > 0) + { + ref uint remainderStart = ref MemoryMarshal.GetReference(remainder); + ref uint remainderEnd = ref Unsafe.Add(ref remainderStart, remainder.Length); + + while (Unsafe.IsAddressLessThan(ref remainderStart, ref remainderEnd)) + { + remainderStart = Clamp(remainderStart, min, max); + + remainderStart = ref Unsafe.Add(ref remainderStart, 1); + } + } + } + + /// + /// Clamps the span values to the inclusive range of min and max. + /// + /// The span containing the values to clamp. + /// The minimum inclusive value. + /// The maximum inclusive value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Clamp(Span span, int min, int max) + { + Span remainder = span.Slice(ClampReduce(span, min, max)); + + if (remainder.Length > 0) + { + ref int remainderStart = ref MemoryMarshal.GetReference(remainder); + ref int remainderEnd = ref Unsafe.Add(ref remainderStart, remainder.Length); + + while (Unsafe.IsAddressLessThan(ref remainderStart, ref remainderEnd)) + { + remainderStart = Clamp(remainderStart, min, max); + + remainderStart = ref Unsafe.Add(ref remainderStart, 1); + } + } + } + + /// + /// Clamps the span values to the inclusive range of min and max. + /// + /// The span containing the values to clamp. + /// The minimum inclusive value. + /// The maximum inclusive value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Clamp(Span span, float min, float max) + { + Span remainder = span.Slice(ClampReduce(span, min, max)); + + if (remainder.Length > 0) + { + ref float remainderStart = ref MemoryMarshal.GetReference(remainder); + ref float remainderEnd = ref Unsafe.Add(ref remainderStart, remainder.Length); + + while (Unsafe.IsAddressLessThan(ref remainderStart, ref remainderEnd)) + { + remainderStart = Clamp(remainderStart, min, max); + + remainderStart = ref Unsafe.Add(ref remainderStart, 1); + } + } + } + + /// + /// Clamps the span values to the inclusive range of min and max. + /// + /// The span containing the values to clamp. + /// The minimum inclusive value. + /// The maximum inclusive value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Clamp(Span span, double min, double max) + { + Span remainder = span.Slice(ClampReduce(span, min, max)); + + if (remainder.Length > 0) + { + ref double remainderStart = ref MemoryMarshal.GetReference(remainder); + ref double remainderEnd = ref Unsafe.Add(ref remainderStart, remainder.Length); + + while (Unsafe.IsAddressLessThan(ref remainderStart, ref remainderEnd)) + { + remainderStart = Clamp(remainderStart, min, max); + + remainderStart = ref Unsafe.Add(ref remainderStart, 1); + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int ClampReduce(Span span, T min, T max) + where T : unmanaged + { + if (Vector.IsHardwareAccelerated && span.Length >= Vector.Count) + { + int remainder = ModuloP2(span.Length, Vector.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(Span span, T min, T max) + where T : unmanaged + { + ref T sRef = ref MemoryMarshal.GetReference(span); + var vmin = new Vector(min); + var vmax = new Vector(max); + + int n = span.Length / Vector.Count; + int m = Modulo4(n); + int u = n - m; + + ref Vector vs0 = ref Unsafe.As>(ref MemoryMarshal.GetReference(span)); + ref Vector vs1 = ref Unsafe.Add(ref vs0, 1); + ref Vector vs2 = ref Unsafe.Add(ref vs0, 2); + ref Vector vs3 = ref Unsafe.Add(ref vs0, 3); + ref Vector vsEnd = ref Unsafe.Add(ref vs0, u); + + while (Unsafe.IsAddressLessThan(ref vs0, ref vsEnd)) + { + 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); + + vs0 = ref Unsafe.Add(ref vs0, 4); + vs1 = ref Unsafe.Add(ref vs1, 4); + vs2 = ref Unsafe.Add(ref vs2, 4); + vs3 = ref Unsafe.Add(ref vs3, 4); + } + + if (m > 0) + { + vs0 = ref vsEnd; + vsEnd = ref Unsafe.Add(ref vsEnd, m); + + while (Unsafe.IsAddressLessThan(ref vs0, ref vsEnd)) + { + vs0 = Vector.Min(Vector.Max(vmin, vs0), vmax); + + vs0 = ref Unsafe.Add(ref vs0, 1); + } + } + } + + /// + /// Pre-multiplies the "x", "y", "z" components of a vector by its "w" component leaving the "w" component intact. + /// + /// The to premultiply + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Premultiply(ref Vector4 source) + { + float w = source.W; + source *= w; + source.W = w; + } + + /// + /// Reverses the result of premultiplying a vector via . + /// + /// The to premultiply + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void UnPremultiply(ref Vector4 source) + { + float w = source.W; + source /= w; + source.W = w; + } + + /// + /// Bulk variant of + /// + /// The span of vectors + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Premultiply(Span vectors) + { +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx2.IsSupported && vectors.Length >= 2) + { + // Divide by 2 as 4 elements per Vector4 and 8 per Vector256 + ref Vector256 vectorsBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(vectors)); + ref Vector256 vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u)); + + while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) + { + Vector256 source = vectorsBase; + Vector256 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 vectorsStart = ref MemoryMarshal.GetReference(vectors); + ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsStart, vectors.Length); + + while (Unsafe.IsAddressLessThan(ref vectorsStart, ref vectorsEnd)) + { + Premultiply(ref vectorsStart); + + vectorsStart = ref Unsafe.Add(ref vectorsStart, 1); + } + } + } + + /// + /// Bulk variant of + /// + /// The span of vectors + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void UnPremultiply(Span vectors) + { +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx2.IsSupported && vectors.Length >= 2) + { + // Divide by 2 as 4 elements per Vector4 and 8 per Vector256 + ref Vector256 vectorsBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(vectors)); + ref Vector256 vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u)); + + while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) + { + Vector256 source = vectorsBase; + Vector256 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 vectorsStart = ref MemoryMarshal.GetReference(vectors); + ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsStart, vectors.Length); + + while (Unsafe.IsAddressLessThan(ref vectorsStart, ref vectorsEnd)) + { + UnPremultiply(ref vectorsStart); + + vectorsStart = ref Unsafe.Add(ref vectorsStart, 1); + } + } + } + + /// + /// Calculates the cube pow of all the XYZ channels of the input vectors. + /// + /// The span of vectors + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void CubePowOnXYZ(Span vectors) + { + ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); + ref Vector4 endRef = ref Unsafe.Add(ref baseRef, vectors.Length); + + while (Unsafe.IsAddressLessThan(ref baseRef, ref endRef)) + { + Vector4 v = baseRef; + float a = v.W; + + // Fast path for the default gamma exposure, which is 3. In this case we can skip + // calling Math.Pow 3 times (one per component), as the method is an internal call and + // introduces quite a bit of overhead. Instead, we can just manually multiply the whole + // pixel in Vector4 format 3 times, and then restore the alpha channel before copying it + // back to the target index in the temporary span. The whole iteration will get completely + // inlined and traslated into vectorized instructions, with much better performance. + v = v * v * v; + v.W = a; + + baseRef = v; + baseRef = ref Unsafe.Add(ref baseRef, 1); + } + } + + /// + /// Calculates the cube root of all the XYZ channels of the input vectors. + /// + /// The span of vectors + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void CubeRootOnXYZ(Span vectors) + { +#if SUPPORTS_RUNTIME_INTRINSICS + if (Sse41.IsSupported) + { + ref Vector128 vectors128Ref = ref Unsafe.As>(ref MemoryMarshal.GetReference(vectors)); + ref Vector128 vectors128End = ref Unsafe.Add(ref vectors128Ref, vectors.Length); + + var v128_341 = Vector128.Create(341); + Vector128 v128_negativeZero = Vector128.Create(-0.0f).AsInt32(); + Vector128 v128_one = Vector128.Create(1.0f).AsInt32(); + + var v128_13rd = Vector128.Create(1 / 3f); + var v128_23rds = Vector128.Create(2 / 3f); + + while (Unsafe.IsAddressLessThan(ref vectors128Ref, ref vectors128End)) + { + Vector128 vecx = vectors128Ref; + Vector128 veax = vecx.AsInt32(); + + // If we can use SSE41 instructions, we can vectorize the entire cube root calculation, and also execute it + // directly on 32 bit floating point values. What follows is a vectorized implementation of this method: + // https://www.musicdsp.org/en/latest/Other/206-fast-cube-root-square-root-and-reciprocal-for-x86-sse-cpus.html. + // Furthermore, after the initial setup in vectorized form, we're doing two Newton approximations here + // using a different succession (the same used below), which should be less unstable due to not having cube pow. + veax = Sse2.AndNot(v128_negativeZero, veax); + veax = Sse2.Subtract(veax, v128_one); + veax = Sse2.ShiftRightArithmetic(veax, 10); + veax = Sse41.MultiplyLow(veax, v128_341); + veax = Sse2.Add(veax, v128_one); + veax = Sse2.AndNot(v128_negativeZero, veax); + veax = Sse2.Or(veax, Sse2.And(vecx.AsInt32(), v128_negativeZero)); + + Vector128 y4 = veax.AsSingle(); + + if (Fma.IsSupported) + { + y4 = Fma.MultiplyAdd(v128_23rds, y4, Sse.Multiply(v128_13rd, Sse.Divide(vecx, Sse.Multiply(y4, y4)))); + y4 = Fma.MultiplyAdd(v128_23rds, y4, Sse.Multiply(v128_13rd, Sse.Divide(vecx, Sse.Multiply(y4, y4)))); + } + else + { + y4 = Sse.Add(Sse.Multiply(v128_23rds, y4), Sse.Multiply(v128_13rd, Sse.Divide(vecx, Sse.Multiply(y4, y4)))); + y4 = Sse.Add(Sse.Multiply(v128_23rds, y4), Sse.Multiply(v128_13rd, Sse.Divide(vecx, Sse.Multiply(y4, y4)))); + } + + y4 = Sse41.Insert(y4, vecx, 0xF0); + + vectors128Ref = y4; + vectors128Ref = ref Unsafe.Add(ref vectors128Ref, 1); + } + } + else +#endif + { + ref Vector4 vectorsRef = ref MemoryMarshal.GetReference(vectors); + ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsRef, vectors.Length); + + // Fallback with scalar preprocessing and vectorized approximation steps + while (Unsafe.IsAddressLessThan(ref vectorsRef, ref vectorsEnd)) + { + Vector4 v = vectorsRef; + + double + x64 = v.X, + y64 = v.Y, + z64 = v.Z; + float a = v.W; + + ulong + xl = *(ulong*)&x64, + yl = *(ulong*)&y64, + zl = *(ulong*)&z64; + + // Here we use a trick to compute the starting value x0 for the cube root. This is because doing + // pow(x, 1 / gamma) is the same as the gamma-th root of x, and since gamme is 3 in this case, + // this means what we actually want is to find the cube root of our clamped values. + // For more info on the constant below, see: + // https://community.intel.com/t5/Intel-C-Compiler/Fast-approximate-of-transcendental-operations/td-p/1044543. + // Here we perform the same trick on all RGB channels separately to help the CPU execute them in paralle, and + // store the alpha channel to preserve it. Then we set these values to the fields of a temporary 128-bit + // register, and use it to accelerate two steps of the Newton approximation using SIMD. + xl = 0x2a9f8a7be393b600 + (xl / 3); + yl = 0x2a9f8a7be393b600 + (yl / 3); + zl = 0x2a9f8a7be393b600 + (zl / 3); + + Vector4 y4; + y4.X = (float)*(double*)&xl; + y4.Y = (float)*(double*)&yl; + y4.Z = (float)*(double*)&zl; + y4.W = 0; + + y4 = (2 / 3f * y4) + (1 / 3f * (v / (y4 * y4))); + y4 = (2 / 3f * y4) + (1 / 3f * (v / (y4 * y4))); + y4.W = a; + + vectorsRef = y4; + vectorsRef = ref Unsafe.Add(ref vectorsRef, 1); + } + } + } + +#if SUPPORTS_RUNTIME_INTRINSICS + + /// + /// Performs a linear interpolation between two values based on the given weighting. + /// + /// The first value. + /// The second value. + /// Values between 0 and 1 that indicates the weight of . + /// The . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vector256 Lerp( + in Vector256 value1, + in Vector256 value2, + in Vector256 amount) + { + Vector256 diff = Avx.Subtract(value2, value1); + if (Fma.IsSupported) + { + return Fma.MultiplyAdd(diff, amount, value1); + } + else + { + return Avx.Add(Avx.Multiply(diff, amount), value1); + } + } +#endif + + /// + /// Performs a linear interpolation between two values based on the given weighting. + /// + /// The first value. + /// The second value. + /// A value between 0 and 1 that indicates the weight of . + /// The . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Lerp(float value1, float value2, float amount) + => ((value2 - value1) * amount) + value1; + } +} diff --git a/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs b/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs new file mode 100644 index 0000000000..7687a5b95f --- /dev/null +++ b/src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs @@ -0,0 +1,193 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers.Binary; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// The JIT can detect and optimize rotation idioms ROTL (Rotate Left) +// and ROTR (Rotate Right) emitting efficient CPU instructions: +// https://github.com/dotnet/coreclr/pull/1830 +namespace SixLabors.ImageSharp +{ + /// + /// Defines the contract for methods that allow the shuffling of pixel components. + /// Used for shuffling on platforms that do not support Hardware Intrinsics. + /// + internal interface IComponentShuffle + { + /// + /// Gets the shuffle control. + /// + byte Control { get; } + + /// + /// Shuffle 8-bit integers within 128-bit lanes in + /// using the control and store the results in . + /// + /// The source span of bytes. + /// The destination span of bytes. + void RunFallbackShuffle(ReadOnlySpan source, Span dest); + } + + /// + internal interface IShuffle4 : IComponentShuffle + { + } + + internal readonly struct DefaultShuffle4 : IShuffle4 + { + private readonly byte p3; + private readonly byte p2; + private readonly byte p1; + private readonly byte p0; + + public DefaultShuffle4(byte p3, byte p2, byte p1, byte p0) + { + DebugGuard.MustBeBetweenOrEqualTo(p3, 0, 3, nameof(p3)); + DebugGuard.MustBeBetweenOrEqualTo(p2, 0, 3, nameof(p2)); + DebugGuard.MustBeBetweenOrEqualTo(p1, 0, 3, nameof(p1)); + DebugGuard.MustBeBetweenOrEqualTo(p0, 0, 3, nameof(p0)); + + this.p3 = p3; + this.p2 = p2; + this.p1 = p1; + this.p0 = p0; + this.Control = SimdUtils.Shuffle.MmShuffle(p3, p2, p1, p0); + } + + public byte Control { get; } + + [MethodImpl(InliningOptions.ShortMethod)] + public void RunFallbackShuffle(ReadOnlySpan source, Span dest) + { + ref byte sBase = ref MemoryMarshal.GetReference(source); + ref byte dBase = ref MemoryMarshal.GetReference(dest); + + int p3 = this.p3; + int p2 = this.p2; + int p1 = this.p1; + int p0 = this.p0; + + for (int i = 0; i < source.Length; i += 4) + { + Unsafe.Add(ref dBase, i) = Unsafe.Add(ref sBase, p0 + i); + Unsafe.Add(ref dBase, i + 1) = Unsafe.Add(ref sBase, p1 + i); + Unsafe.Add(ref dBase, i + 2) = Unsafe.Add(ref sBase, p2 + i); + Unsafe.Add(ref dBase, i + 3) = Unsafe.Add(ref sBase, p3 + i); + } + } + } + + internal readonly struct WXYZShuffle4 : IShuffle4 + { + public byte Control + { + [MethodImpl(InliningOptions.ShortMethod)] + get => SimdUtils.Shuffle.MmShuffle(2, 1, 0, 3); + } + + [MethodImpl(InliningOptions.ShortMethod)] + public void RunFallbackShuffle(ReadOnlySpan source, Span dest) + { + ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); + ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest)); + int n = source.Length / 4; + + for (int i = 0; i < n; i++) + { + uint packed = Unsafe.Add(ref sBase, i); + + // packed = [W Z Y X] + // ROTL(8, packed) = [Z Y X W] + Unsafe.Add(ref dBase, i) = (packed << 8) | (packed >> 24); + } + } + } + + internal readonly struct WZYXShuffle4 : IShuffle4 + { + public byte Control + { + [MethodImpl(InliningOptions.ShortMethod)] + get => SimdUtils.Shuffle.MmShuffle(0, 1, 2, 3); + } + + [MethodImpl(InliningOptions.ShortMethod)] + public void RunFallbackShuffle(ReadOnlySpan source, Span dest) + { + ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); + ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest)); + int n = source.Length / 4; + + for (int i = 0; i < n; i++) + { + uint packed = Unsafe.Add(ref sBase, i); + + // packed = [W Z Y X] + // REVERSE(packedArgb) = [X Y Z W] + Unsafe.Add(ref dBase, i) = BinaryPrimitives.ReverseEndianness(packed); + } + } + } + + internal readonly struct YZWXShuffle4 : IShuffle4 + { + public byte Control + { + [MethodImpl(InliningOptions.ShortMethod)] + get => SimdUtils.Shuffle.MmShuffle(0, 3, 2, 1); + } + + [MethodImpl(InliningOptions.ShortMethod)] + public void RunFallbackShuffle(ReadOnlySpan source, Span dest) + { + ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); + ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest)); + int n = source.Length / 4; + + for (int i = 0; i < n; i++) + { + uint packed = Unsafe.Add(ref sBase, i); + + // packed = [W Z Y X] + // ROTR(8, packedArgb) = [Y Z W X] + Unsafe.Add(ref dBase, i) = (packed >> 8) | (packed << 24); + } + } + } + + internal readonly struct ZYXWShuffle4 : IShuffle4 + { + public byte Control + { + [MethodImpl(InliningOptions.ShortMethod)] + get => SimdUtils.Shuffle.MmShuffle(3, 0, 1, 2); + } + + [MethodImpl(InliningOptions.ShortMethod)] + public void RunFallbackShuffle(ReadOnlySpan source, Span dest) + { + ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); + ref uint dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest)); + int n = source.Length / 4; + + for (int i = 0; i < n; i++) + { + uint packed = Unsafe.Add(ref sBase, i); + + // packed = [W Z Y X] + // tmp1 = [W 0 Y 0] + // tmp2 = [0 Z 0 X] + // tmp3=ROTL(16, tmp2) = [0 X 0 Z] + // tmp1 + tmp3 = [W X Y Z] + uint tmp1 = packed & 0xFF00FF00; + uint tmp2 = packed & 0x00FF00FF; + uint tmp3 = (tmp2 << 16) | (tmp2 >> 16); + + Unsafe.Add(ref dBase, i) = tmp1 + tmp3; + } + } + } +} diff --git a/src/ImageSharp/Common/Helpers/Shuffle/IPad3Shuffle4.cs b/src/ImageSharp/Common/Helpers/Shuffle/IPad3Shuffle4.cs new file mode 100644 index 0000000000..0c2b1d5082 --- /dev/null +++ b/src/ImageSharp/Common/Helpers/Shuffle/IPad3Shuffle4.cs @@ -0,0 +1,103 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace SixLabors.ImageSharp +{ + /// + internal interface IPad3Shuffle4 : IComponentShuffle + { + } + + internal readonly struct DefaultPad3Shuffle4 : IPad3Shuffle4 + { + private readonly byte p3; + private readonly byte p2; + private readonly byte p1; + private readonly byte p0; + + public DefaultPad3Shuffle4(byte p3, byte p2, byte p1, byte p0) + { + DebugGuard.MustBeBetweenOrEqualTo(p3, 0, 3, nameof(p3)); + DebugGuard.MustBeBetweenOrEqualTo(p2, 0, 3, nameof(p2)); + DebugGuard.MustBeBetweenOrEqualTo(p1, 0, 3, nameof(p1)); + DebugGuard.MustBeBetweenOrEqualTo(p0, 0, 3, nameof(p0)); + + this.p3 = p3; + this.p2 = p2; + this.p1 = p1; + this.p0 = p0; + this.Control = SimdUtils.Shuffle.MmShuffle(p3, p2, p1, p0); + } + + public byte Control { get; } + + [MethodImpl(InliningOptions.ShortMethod)] + public void RunFallbackShuffle(ReadOnlySpan source, Span dest) + { + ref byte sBase = ref MemoryMarshal.GetReference(source); + ref byte dBase = ref MemoryMarshal.GetReference(dest); + + int p3 = this.p3; + int p2 = this.p2; + int p1 = this.p1; + int p0 = this.p0; + + Span temp = stackalloc byte[4]; + ref byte t = ref MemoryMarshal.GetReference(temp); + ref uint tu = ref Unsafe.As(ref t); + + for (int i = 0, j = 0; i < source.Length; i += 3, j += 4) + { + ref var s = ref Unsafe.Add(ref sBase, i); + tu = Unsafe.As(ref s) | 0xFF000000; + + Unsafe.Add(ref dBase, j) = Unsafe.Add(ref t, p0); + Unsafe.Add(ref dBase, j + 1) = Unsafe.Add(ref t, p1); + Unsafe.Add(ref dBase, j + 2) = Unsafe.Add(ref t, p2); + Unsafe.Add(ref dBase, j + 3) = Unsafe.Add(ref t, p3); + } + } + } + + internal readonly struct XYZWPad3Shuffle4 : IPad3Shuffle4 + { + public byte Control + { + [MethodImpl(InliningOptions.ShortMethod)] + get => SimdUtils.Shuffle.MmShuffle(3, 2, 1, 0); + } + + [MethodImpl(InliningOptions.ShortMethod)] + public void RunFallbackShuffle(ReadOnlySpan source, Span dest) + { + ref byte sBase = ref MemoryMarshal.GetReference(source); + ref byte dBase = ref MemoryMarshal.GetReference(dest); + + ref byte sEnd = ref Unsafe.Add(ref sBase, source.Length); + ref byte sLoopEnd = ref Unsafe.Subtract(ref sEnd, 4); + + while (Unsafe.IsAddressLessThan(ref sBase, ref sLoopEnd)) + { + Unsafe.As(ref dBase) = Unsafe.As(ref sBase) | 0xFF000000; + + sBase = ref Unsafe.Add(ref sBase, 3); + dBase = ref Unsafe.Add(ref dBase, 4); + } + + while (Unsafe.IsAddressLessThan(ref sBase, ref sEnd)) + { + Unsafe.Add(ref dBase, 0) = Unsafe.Add(ref sBase, 0); + Unsafe.Add(ref dBase, 1) = Unsafe.Add(ref sBase, 1); + Unsafe.Add(ref dBase, 2) = Unsafe.Add(ref sBase, 2); + Unsafe.Add(ref dBase, 3) = byte.MaxValue; + + sBase = ref Unsafe.Add(ref sBase, 3); + dBase = ref Unsafe.Add(ref dBase, 4); + } + } + } +} diff --git a/src/ImageSharp/Common/Helpers/Shuffle/IShuffle3.cs b/src/ImageSharp/Common/Helpers/Shuffle/IShuffle3.cs new file mode 100644 index 0000000000..61e99890e7 --- /dev/null +++ b/src/ImageSharp/Common/Helpers/Shuffle/IShuffle3.cs @@ -0,0 +1,53 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace SixLabors.ImageSharp +{ + /// + internal interface IShuffle3 : IComponentShuffle + { + } + + internal readonly struct DefaultShuffle3 : IShuffle3 + { + private readonly byte p2; + private readonly byte p1; + private readonly byte p0; + + public DefaultShuffle3(byte p2, byte p1, byte p0) + { + DebugGuard.MustBeBetweenOrEqualTo(p2, 0, 2, nameof(p2)); + DebugGuard.MustBeBetweenOrEqualTo(p1, 0, 2, nameof(p1)); + DebugGuard.MustBeBetweenOrEqualTo(p0, 0, 2, nameof(p0)); + + this.p2 = p2; + this.p1 = p1; + this.p0 = p0; + this.Control = SimdUtils.Shuffle.MmShuffle(3, p2, p1, p0); + } + + public byte Control { get; } + + [MethodImpl(InliningOptions.ShortMethod)] + public void RunFallbackShuffle(ReadOnlySpan source, Span dest) + { + ref byte sBase = ref MemoryMarshal.GetReference(source); + ref byte dBase = ref MemoryMarshal.GetReference(dest); + + int p2 = this.p2; + int p1 = this.p1; + int p0 = this.p0; + + for (int i = 0; i < source.Length; i += 3) + { + Unsafe.Add(ref dBase, i) = Unsafe.Add(ref sBase, p0 + i); + Unsafe.Add(ref dBase, i + 1) = Unsafe.Add(ref sBase, p1 + i); + Unsafe.Add(ref dBase, i + 2) = Unsafe.Add(ref sBase, p2 + i); + } + } + } +} diff --git a/src/ImageSharp/Common/Helpers/Shuffle/IShuffle4Slice3.cs b/src/ImageSharp/Common/Helpers/Shuffle/IShuffle4Slice3.cs new file mode 100644 index 0000000000..3ecad3c5d9 --- /dev/null +++ b/src/ImageSharp/Common/Helpers/Shuffle/IShuffle4Slice3.cs @@ -0,0 +1,101 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace SixLabors.ImageSharp +{ + /// + internal interface IShuffle4Slice3 : IComponentShuffle + { + } + + internal readonly struct DefaultShuffle4Slice3 : IShuffle4Slice3 + { + private readonly byte p2; + private readonly byte p1; + private readonly byte p0; + + public DefaultShuffle4Slice3(byte p3, byte p2, byte p1, byte p0) + { + DebugGuard.MustBeBetweenOrEqualTo(p3, 0, 3, nameof(p3)); + DebugGuard.MustBeBetweenOrEqualTo(p2, 0, 3, nameof(p2)); + DebugGuard.MustBeBetweenOrEqualTo(p1, 0, 3, nameof(p1)); + DebugGuard.MustBeBetweenOrEqualTo(p0, 0, 3, nameof(p0)); + + this.p2 = p2; + this.p1 = p1; + this.p0 = p0; + this.Control = SimdUtils.Shuffle.MmShuffle(p3, p2, p1, p0); + } + + public byte Control { get; } + + [MethodImpl(InliningOptions.ShortMethod)] + public void RunFallbackShuffle(ReadOnlySpan source, Span dest) + { + ref byte sBase = ref MemoryMarshal.GetReference(source); + ref byte dBase = ref MemoryMarshal.GetReference(dest); + + int p2 = this.p2; + int p1 = this.p1; + int p0 = this.p0; + + for (int i = 0, j = 0; i < dest.Length; i += 3, j += 4) + { + Unsafe.Add(ref dBase, i) = Unsafe.Add(ref sBase, p0 + j); + Unsafe.Add(ref dBase, i + 1) = Unsafe.Add(ref sBase, p1 + j); + Unsafe.Add(ref dBase, i + 2) = Unsafe.Add(ref sBase, p2 + j); + } + } + } + + internal readonly struct XYZWShuffle4Slice3 : IShuffle4Slice3 + { + public byte Control + { + [MethodImpl(InliningOptions.ShortMethod)] + get => SimdUtils.Shuffle.MmShuffle(3, 2, 1, 0); + } + + [MethodImpl(InliningOptions.ShortMethod)] + public void RunFallbackShuffle(ReadOnlySpan source, Span dest) + { + ref uint sBase = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); + ref Byte3 dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest)); + + int n = source.Length / 4; + int m = Numerics.Modulo4(n); + int u = n - m; + + ref uint sLoopEnd = ref Unsafe.Add(ref sBase, u); + ref uint sEnd = ref Unsafe.Add(ref sBase, n); + + while (Unsafe.IsAddressLessThan(ref sBase, ref sLoopEnd)) + { + Unsafe.Add(ref dBase, 0) = Unsafe.As(ref Unsafe.Add(ref sBase, 0)); + Unsafe.Add(ref dBase, 1) = Unsafe.As(ref Unsafe.Add(ref sBase, 1)); + Unsafe.Add(ref dBase, 2) = Unsafe.As(ref Unsafe.Add(ref sBase, 2)); + Unsafe.Add(ref dBase, 3) = Unsafe.As(ref Unsafe.Add(ref sBase, 3)); + + sBase = ref Unsafe.Add(ref sBase, 4); + dBase = ref Unsafe.Add(ref dBase, 4); + } + + while (Unsafe.IsAddressLessThan(ref sBase, ref sEnd)) + { + Unsafe.Add(ref dBase, 0) = Unsafe.As(ref Unsafe.Add(ref sBase, 0)); + + sBase = ref Unsafe.Add(ref sBase, 1); + dBase = ref Unsafe.Add(ref dBase, 1); + } + } + } + + [StructLayout(LayoutKind.Explicit, Size = 3)] + internal readonly struct Byte3 + { + } +} diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.Avx2Intrinsics.cs b/src/ImageSharp/Common/Helpers/SimdUtils.Avx2Intrinsics.cs deleted file mode 100644 index b56c92dab7..0000000000 --- a/src/ImageSharp/Common/Helpers/SimdUtils.Avx2Intrinsics.cs +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -#if SUPPORTS_RUNTIME_INTRINSICS - -using System; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; - -namespace SixLabors.ImageSharp -{ - internal static partial class SimdUtils - { - public static class Avx2Intrinsics - { - private static ReadOnlySpan PermuteMaskDeinterleave8x32 => new byte[] { 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0 }; - - /// - /// as many elements as possible, slicing them down (keeping the remainder). - /// - [MethodImpl(InliningOptions.ShortMethod)] - internal static void NormalizedFloatToByteSaturateReduce( - ref ReadOnlySpan source, - ref Span dest) - { - DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); - - if (Avx2.IsSupported) - { - int remainder = ImageMaths.ModuloP2(source.Length, Vector.Count); - int adjustedCount = source.Length - remainder; - - if (adjustedCount > 0) - { - NormalizedFloatToByteSaturate( - source.Slice(0, adjustedCount), - dest.Slice(0, adjustedCount)); - - source = source.Slice(adjustedCount); - dest = dest.Slice(adjustedCount); - } - } - } - - /// - /// Implementation of , which is faster on new .NET runtime. - /// - /// - /// Implementation is based on MagicScaler code: - /// https://github.com/saucecontrol/PhotoSauce/blob/a9bd6e5162d2160419f0cf743fd4f536c079170b/src/MagicScaler/Magic/Processors/ConvertersFloat.cs#L453-L477 - /// - internal static void NormalizedFloatToByteSaturate( - ReadOnlySpan source, - Span dest) - { - VerifySpanInput(source, dest, Vector256.Count); - - int n = dest.Length / Vector256.Count; - - ref Vector256 sourceBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(source)); - ref Vector256 destBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); - - var maxBytes = Vector256.Create(255f); - ref byte maskBase = ref MemoryMarshal.GetReference(PermuteMaskDeinterleave8x32); - Vector256 mask = Unsafe.As>(ref maskBase); - - for (int i = 0; i < n; i++) - { - ref Vector256 s = ref Unsafe.Add(ref sourceBase, i * 4); - - Vector256 f0 = s; - Vector256 f1 = Unsafe.Add(ref s, 1); - Vector256 f2 = Unsafe.Add(ref s, 2); - Vector256 f3 = Unsafe.Add(ref s, 3); - - Vector256 w0 = ConvertToInt32(f0, maxBytes); - Vector256 w1 = ConvertToInt32(f1, maxBytes); - Vector256 w2 = ConvertToInt32(f2, maxBytes); - Vector256 w3 = ConvertToInt32(f3, maxBytes); - - Vector256 u0 = Avx2.PackSignedSaturate(w0, w1); - Vector256 u1 = Avx2.PackSignedSaturate(w2, w3); - Vector256 b = Avx2.PackUnsignedSaturate(u0, u1); - b = Avx2.PermuteVar8x32(b.AsInt32(), mask).AsByte(); - - Unsafe.Add(ref destBase, i) = b; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vector256 ConvertToInt32(Vector256 vf, Vector256 scale) - { - vf = Avx.Multiply(vf, scale); - return Avx.ConvertToVector256Int32(vf); - } - } - } -} -#endif diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs b/src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs index de6990db5b..75555f88a5 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs @@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp return; } - int remainder = ImageMaths.Modulo8(source.Length); + int remainder = Numerics.Modulo8(source.Length); int adjustedCount = source.Length - remainder; if (adjustedCount > 0) @@ -64,7 +64,7 @@ namespace SixLabors.ImageSharp return; } - int remainder = ImageMaths.Modulo8(source.Length); + int remainder = Numerics.Modulo8(source.Length); int adjustedCount = source.Length - remainder; if (adjustedCount > 0) diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs b/src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs index bd35d1583e..0abc0e26da 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp return; } - int remainder = ImageMaths.ModuloP2(source.Length, Vector.Count); + int remainder = Numerics.ModuloP2(source.Length, Vector.Count); int adjustedCount = source.Length - remainder; if (adjustedCount > 0) @@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp return; } - int remainder = ImageMaths.ModuloP2(source.Length, Vector.Count); + int remainder = Numerics.ModuloP2(source.Length, Vector.Count); int adjustedCount = source.Length - remainder; if (adjustedCount > 0) diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs b/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs index 1e89aaeb83..15133770f6 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs @@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp { DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); - int remainder = ImageMaths.Modulo4(source.Length); + int remainder = Numerics.Modulo4(source.Length); int adjustedCount = source.Length - remainder; if (adjustedCount > 0) @@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp { DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); - int remainder = ImageMaths.Modulo4(source.Length); + int remainder = Numerics.Modulo4(source.Length); int adjustedCount = source.Length - remainder; if (adjustedCount > 0) @@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp Vector4 s = Unsafe.Add(ref sBase, i); s *= maxBytes; s += half; - s = Vector4Utilities.FastClamp(s, Vector4.Zero, maxBytes); + s = Numerics.Clamp(s, Vector4.Zero, maxBytes); ref ByteVector4 d = ref Unsafe.Add(ref dBase, i); d.X = (byte)s.X; diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs new file mode 100644 index 0000000000..4faf577fd9 --- /dev/null +++ b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs @@ -0,0 +1,944 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +#if SUPPORTS_RUNTIME_INTRINSICS +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp +{ + internal static partial class SimdUtils + { + public static class HwIntrinsics + { + public static ReadOnlySpan PermuteMaskDeinterleave8x32 => new byte[] { 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0 }; + + public static ReadOnlySpan PermuteMaskEvenOdd8x32 => new byte[] { 0, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 7, 0, 0, 0 }; + + public static ReadOnlySpan PermuteMaskSwitchInnerDWords8x32 => new byte[] { 0, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0 }; + + private static ReadOnlySpan ShuffleMaskPad4Nx16 => new byte[] { 0, 1, 2, 0x80, 3, 4, 5, 0x80, 6, 7, 8, 0x80, 9, 10, 11, 0x80 }; + + private static ReadOnlySpan ShuffleMaskSlice4Nx16 => new byte[] { 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 0x80, 0x80, 0x80, 0x80 }; + + private static ReadOnlySpan ShuffleMaskShiftAlpha => + new byte[] + { + 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 3, 7, 11, 15, + 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 3, 7, 11, 15 + }; + + public static ReadOnlySpan PermuteMaskShiftAlpha8x32 => + new byte[] + { + 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, + 5, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0 + }; + + /// + /// Shuffle single-precision (32-bit) floating-point elements in + /// using the control and store the results in . + /// + /// The source span of floats. + /// The destination span of floats. + /// The byte control. + [MethodImpl(InliningOptions.ShortMethod)] + public static void Shuffle4Reduce( + ref ReadOnlySpan source, + ref Span dest, + byte control) + { + if (Avx.IsSupported || Sse.IsSupported) + { + int remainder = Avx.IsSupported + ? Numerics.ModuloP2(source.Length, Vector256.Count) + : Numerics.ModuloP2(source.Length, Vector128.Count); + + int adjustedCount = source.Length - remainder; + + if (adjustedCount > 0) + { + Shuffle4( + source.Slice(0, adjustedCount), + dest.Slice(0, adjustedCount), + control); + + source = source.Slice(adjustedCount); + dest = dest.Slice(adjustedCount); + } + } + } + + /// + /// Shuffle 8-bit integers within 128-bit lanes in + /// using the control and store the results in . + /// + /// The source span of bytes. + /// The destination span of bytes. + /// The byte control. + [MethodImpl(InliningOptions.ShortMethod)] + public static void Shuffle4Reduce( + ref ReadOnlySpan source, + ref Span dest, + byte control) + { + if (Avx2.IsSupported || Ssse3.IsSupported) + { + int remainder = Avx2.IsSupported + ? Numerics.ModuloP2(source.Length, Vector256.Count) + : Numerics.ModuloP2(source.Length, Vector128.Count); + + int adjustedCount = source.Length - remainder; + + if (adjustedCount > 0) + { + Shuffle4( + source.Slice(0, adjustedCount), + dest.Slice(0, adjustedCount), + control); + + source = source.Slice(adjustedCount); + dest = dest.Slice(adjustedCount); + } + } + } + + /// + /// Shuffles 8-bit integer triplets within 128-bit lanes in + /// using the control and store the results in . + /// + /// The source span of bytes. + /// The destination span of bytes. + /// The byte control. + [MethodImpl(InliningOptions.ShortMethod)] + public static void Shuffle3Reduce( + ref ReadOnlySpan source, + ref Span dest, + byte control) + { + if (Ssse3.IsSupported) + { + int remainder = source.Length % (Vector128.Count * 3); + + int adjustedCount = source.Length - remainder; + + if (adjustedCount > 0) + { + Shuffle3( + source.Slice(0, adjustedCount), + dest.Slice(0, adjustedCount), + control); + + source = source.Slice(adjustedCount); + dest = dest.Slice(adjustedCount); + } + } + } + + /// + /// Pads then shuffles 8-bit integers within 128-bit lanes in + /// using the control and store the results in . + /// + /// The source span of bytes. + /// The destination span of bytes. + /// The byte control. + [MethodImpl(InliningOptions.ShortMethod)] + public static void Pad3Shuffle4Reduce( + ref ReadOnlySpan source, + ref Span dest, + byte control) + { + if (Ssse3.IsSupported) + { + int remainder = source.Length % (Vector128.Count * 3); + + int sourceCount = source.Length - remainder; + int destCount = sourceCount * 4 / 3; + + if (sourceCount > 0) + { + Pad3Shuffle4( + source.Slice(0, sourceCount), + dest.Slice(0, destCount), + control); + + source = source.Slice(sourceCount); + dest = dest.Slice(destCount); + } + } + } + + /// + /// Shuffles then slices 8-bit integers within 128-bit lanes in + /// using the control and store the results in . + /// + /// The source span of bytes. + /// The destination span of bytes. + /// The byte control. + [MethodImpl(InliningOptions.ShortMethod)] + public static void Shuffle4Slice3Reduce( + ref ReadOnlySpan source, + ref Span dest, + byte control) + { + if (Ssse3.IsSupported) + { + int remainder = source.Length % (Vector128.Count * 4); + + int sourceCount = source.Length - remainder; + int destCount = sourceCount * 3 / 4; + + if (sourceCount > 0) + { + Shuffle4Slice3( + source.Slice(0, sourceCount), + dest.Slice(0, destCount), + control); + + source = source.Slice(sourceCount); + dest = dest.Slice(destCount); + } + } + } + + [MethodImpl(InliningOptions.ShortMethod)] + private static void Shuffle4( + ReadOnlySpan source, + Span dest, + byte control) + { + if (Avx.IsSupported) + { + ref Vector256 sourceBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(source)); + + ref Vector256 destBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); + + int n = dest.Length / Vector256.Count; + int m = Numerics.Modulo4(n); + int u = n - m; + + for (int i = 0; i < u; i += 4) + { + ref Vector256 vd0 = ref Unsafe.Add(ref destBase, i); + ref Vector256 vs0 = ref Unsafe.Add(ref sourceBase, i); + + vd0 = Avx.Permute(vs0, control); + Unsafe.Add(ref vd0, 1) = Avx.Permute(Unsafe.Add(ref vs0, 1), control); + Unsafe.Add(ref vd0, 2) = Avx.Permute(Unsafe.Add(ref vs0, 2), control); + Unsafe.Add(ref vd0, 3) = Avx.Permute(Unsafe.Add(ref vs0, 3), control); + } + + if (m > 0) + { + for (int i = u; i < n; i++) + { + Unsafe.Add(ref destBase, i) = Avx.Permute(Unsafe.Add(ref sourceBase, i), control); + } + } + } + else + { + // Sse + ref Vector128 sourceBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(source)); + + ref Vector128 destBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); + + int n = dest.Length / Vector128.Count; + int m = Numerics.Modulo4(n); + int u = n - m; + + for (int i = 0; i < u; i += 4) + { + ref Vector128 vd0 = ref Unsafe.Add(ref destBase, i); + ref Vector128 vs0 = ref Unsafe.Add(ref sourceBase, i); + + vd0 = Sse.Shuffle(vs0, vs0, control); + + Vector128 vs1 = Unsafe.Add(ref vs0, 1); + Unsafe.Add(ref vd0, 1) = Sse.Shuffle(vs1, vs1, control); + + Vector128 vs2 = Unsafe.Add(ref vs0, 2); + Unsafe.Add(ref vd0, 2) = Sse.Shuffle(vs2, vs2, control); + + Vector128 vs3 = Unsafe.Add(ref vs0, 3); + Unsafe.Add(ref vd0, 3) = Sse.Shuffle(vs3, vs3, control); + } + + if (m > 0) + { + for (int i = u; i < n; i++) + { + Vector128 vs = Unsafe.Add(ref sourceBase, i); + Unsafe.Add(ref destBase, i) = Sse.Shuffle(vs, vs, control); + } + } + } + } + + [MethodImpl(InliningOptions.ShortMethod)] + private static void Shuffle4( + ReadOnlySpan source, + Span dest, + byte control) + { + if (Avx2.IsSupported) + { + // I've chosen to do this for convenience while we determine what + // shuffle controls to add to the library. + // We can add static ROS instances if need be in the future. + Span bytes = stackalloc byte[Vector256.Count]; + Shuffle.MmShuffleSpan(ref bytes, control); + Vector256 vshuffle = Unsafe.As>(ref MemoryMarshal.GetReference(bytes)); + + ref Vector256 sourceBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(source)); + + ref Vector256 destBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); + + int n = dest.Length / Vector256.Count; + int m = Numerics.Modulo4(n); + int u = n - m; + + for (int i = 0; i < u; i += 4) + { + ref Vector256 vs0 = ref Unsafe.Add(ref sourceBase, i); + ref Vector256 vd0 = ref Unsafe.Add(ref destBase, i); + + vd0 = Avx2.Shuffle(vs0, vshuffle); + Unsafe.Add(ref vd0, 1) = Avx2.Shuffle(Unsafe.Add(ref vs0, 1), vshuffle); + Unsafe.Add(ref vd0, 2) = Avx2.Shuffle(Unsafe.Add(ref vs0, 2), vshuffle); + Unsafe.Add(ref vd0, 3) = Avx2.Shuffle(Unsafe.Add(ref vs0, 3), vshuffle); + } + + if (m > 0) + { + for (int i = u; i < n; i++) + { + Unsafe.Add(ref destBase, i) = Avx2.Shuffle(Unsafe.Add(ref sourceBase, i), vshuffle); + } + } + } + else + { + // Ssse3 + Span bytes = stackalloc byte[Vector128.Count]; + Shuffle.MmShuffleSpan(ref bytes, control); + Vector128 vshuffle = Unsafe.As>(ref MemoryMarshal.GetReference(bytes)); + + ref Vector128 sourceBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(source)); + + ref Vector128 destBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); + + int n = dest.Length / Vector128.Count; + int m = Numerics.Modulo4(n); + int u = n - m; + + for (int i = 0; i < u; i += 4) + { + ref Vector128 vs0 = ref Unsafe.Add(ref sourceBase, i); + ref Vector128 vd0 = ref Unsafe.Add(ref destBase, i); + + vd0 = Ssse3.Shuffle(vs0, vshuffle); + Unsafe.Add(ref vd0, 1) = Ssse3.Shuffle(Unsafe.Add(ref vs0, 1), vshuffle); + Unsafe.Add(ref vd0, 2) = Ssse3.Shuffle(Unsafe.Add(ref vs0, 2), vshuffle); + Unsafe.Add(ref vd0, 3) = Ssse3.Shuffle(Unsafe.Add(ref vs0, 3), vshuffle); + } + + if (m > 0) + { + for (int i = u; i < n; i++) + { + Unsafe.Add(ref destBase, i) = Ssse3.Shuffle(Unsafe.Add(ref sourceBase, i), vshuffle); + } + } + } + } + + [MethodImpl(InliningOptions.ShortMethod)] + private static void Shuffle3( + ReadOnlySpan source, + Span dest, + byte control) + { + if (Ssse3.IsSupported) + { + ref byte vmaskBase = ref MemoryMarshal.GetReference(ShuffleMaskPad4Nx16); + Vector128 vmask = Unsafe.As>(ref vmaskBase); + ref byte vmaskoBase = ref MemoryMarshal.GetReference(ShuffleMaskSlice4Nx16); + Vector128 vmasko = Unsafe.As>(ref vmaskoBase); + Vector128 vmaske = Ssse3.AlignRight(vmasko, vmasko, 12); + + Span bytes = stackalloc byte[Vector128.Count]; + Shuffle.MmShuffleSpan(ref bytes, control); + Vector128 vshuffle = Unsafe.As>(ref MemoryMarshal.GetReference(bytes)); + + ref Vector128 sourceBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(source)); + + ref Vector128 destBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); + + int n = source.Length / Vector128.Count; + + for (int i = 0; i < n; i += 3) + { + ref Vector128 vs = ref Unsafe.Add(ref sourceBase, i); + + Vector128 v0 = vs; + Vector128 v1 = Unsafe.Add(ref vs, 1); + Vector128 v2 = Unsafe.Add(ref vs, 2); + Vector128 v3 = Sse2.ShiftRightLogical128BitLane(v2, 4); + + v2 = Ssse3.AlignRight(v2, v1, 8); + v1 = Ssse3.AlignRight(v1, v0, 12); + + v0 = Ssse3.Shuffle(Ssse3.Shuffle(v0, vmask), vshuffle); + v1 = Ssse3.Shuffle(Ssse3.Shuffle(v1, vmask), vshuffle); + v2 = Ssse3.Shuffle(Ssse3.Shuffle(v2, vmask), vshuffle); + v3 = Ssse3.Shuffle(Ssse3.Shuffle(v3, vmask), vshuffle); + + v0 = Ssse3.Shuffle(v0, vmaske); + v1 = Ssse3.Shuffle(v1, vmasko); + v2 = Ssse3.Shuffle(v2, vmaske); + v3 = Ssse3.Shuffle(v3, vmasko); + + v0 = Ssse3.AlignRight(v1, v0, 4); + v3 = Ssse3.AlignRight(v3, v2, 12); + + v1 = Sse2.ShiftLeftLogical128BitLane(v1, 4); + v2 = Sse2.ShiftRightLogical128BitLane(v2, 4); + + v1 = Ssse3.AlignRight(v2, v1, 8); + + ref Vector128 vd = ref Unsafe.Add(ref destBase, i); + + vd = v0; + Unsafe.Add(ref vd, 1) = v1; + Unsafe.Add(ref vd, 2) = v3; + } + } + } + + [MethodImpl(InliningOptions.ShortMethod)] + private static void Pad3Shuffle4( + ReadOnlySpan source, + Span dest, + byte control) + { + if (Ssse3.IsSupported) + { + ref byte vmaskBase = ref MemoryMarshal.GetReference(ShuffleMaskPad4Nx16); + Vector128 vmask = Unsafe.As>(ref vmaskBase); + Vector128 vfill = Vector128.Create(0xff000000ff000000ul).AsByte(); + + Span bytes = stackalloc byte[Vector128.Count]; + Shuffle.MmShuffleSpan(ref bytes, control); + Vector128 vshuffle = Unsafe.As>(ref MemoryMarshal.GetReference(bytes)); + + ref Vector128 sourceBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(source)); + + ref Vector128 destBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); + + int n = source.Length / Vector128.Count; + + for (int i = 0, j = 0; i < n; i += 3, j += 4) + { + ref Vector128 v0 = ref Unsafe.Add(ref sourceBase, i); + Vector128 v1 = Unsafe.Add(ref v0, 1); + Vector128 v2 = Unsafe.Add(ref v0, 2); + Vector128 v3 = Sse2.ShiftRightLogical128BitLane(v2, 4); + + v2 = Ssse3.AlignRight(v2, v1, 8); + v1 = Ssse3.AlignRight(v1, v0, 12); + + ref Vector128 vd = ref Unsafe.Add(ref destBase, j); + + vd = Ssse3.Shuffle(Sse2.Or(Ssse3.Shuffle(v0, vmask), vfill), vshuffle); + Unsafe.Add(ref vd, 1) = Ssse3.Shuffle(Sse2.Or(Ssse3.Shuffle(v1, vmask), vfill), vshuffle); + Unsafe.Add(ref vd, 2) = Ssse3.Shuffle(Sse2.Or(Ssse3.Shuffle(v2, vmask), vfill), vshuffle); + Unsafe.Add(ref vd, 3) = Ssse3.Shuffle(Sse2.Or(Ssse3.Shuffle(v3, vmask), vfill), vshuffle); + } + } + } + + [MethodImpl(InliningOptions.ShortMethod)] + private static void Shuffle4Slice3( + ReadOnlySpan source, + Span dest, + byte control) + { + if (Ssse3.IsSupported) + { + ref byte vmaskoBase = ref MemoryMarshal.GetReference(ShuffleMaskSlice4Nx16); + Vector128 vmasko = Unsafe.As>(ref vmaskoBase); + Vector128 vmaske = Ssse3.AlignRight(vmasko, vmasko, 12); + + Span bytes = stackalloc byte[Vector128.Count]; + Shuffle.MmShuffleSpan(ref bytes, control); + Vector128 vshuffle = Unsafe.As>(ref MemoryMarshal.GetReference(bytes)); + + ref Vector128 sourceBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(source)); + + ref Vector128 destBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); + + int n = source.Length / Vector128.Count; + + for (int i = 0, j = 0; i < n; i += 4, j += 3) + { + ref Vector128 vs = ref Unsafe.Add(ref sourceBase, i); + + Vector128 v0 = vs; + Vector128 v1 = Unsafe.Add(ref vs, 1); + Vector128 v2 = Unsafe.Add(ref vs, 2); + Vector128 v3 = Unsafe.Add(ref vs, 3); + + v0 = Ssse3.Shuffle(Ssse3.Shuffle(v0, vshuffle), vmaske); + v1 = Ssse3.Shuffle(Ssse3.Shuffle(v1, vshuffle), vmasko); + v2 = Ssse3.Shuffle(Ssse3.Shuffle(v2, vshuffle), vmaske); + v3 = Ssse3.Shuffle(Ssse3.Shuffle(v3, vshuffle), vmasko); + + v0 = Ssse3.AlignRight(v1, v0, 4); + v3 = Ssse3.AlignRight(v3, v2, 12); + + v1 = Sse2.ShiftLeftLogical128BitLane(v1, 4); + v2 = Sse2.ShiftRightLogical128BitLane(v2, 4); + + v1 = Ssse3.AlignRight(v2, v1, 8); + + ref Vector128 vd = ref Unsafe.Add(ref destBase, j); + + vd = v0; + Unsafe.Add(ref vd, 1) = v1; + Unsafe.Add(ref vd, 2) = v3; + } + } + } + + /// + /// Performs a multiplication and an addition of the . + /// + /// The vector to add to the intermediate result. + /// The first vector to multiply. + /// The second vector to multiply. + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static Vector256 MultiplyAdd( + in Vector256 va, + in Vector256 vm0, + in Vector256 vm1) + { + if (Fma.IsSupported) + { + return Fma.MultiplyAdd(vm1, vm0, va); + } + else + { + return Avx.Add(Avx.Multiply(vm0, vm1), va); + } + } + + /// + /// as many elements as possible, slicing them down (keeping the remainder). + /// + [MethodImpl(InliningOptions.ShortMethod)] + internal static void ByteToNormalizedFloatReduce( + ref ReadOnlySpan source, + ref Span dest) + { + DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); + + if (Avx2.IsSupported || Sse2.IsSupported) + { + int remainder; + if (Avx2.IsSupported) + { + remainder = Numerics.ModuloP2(source.Length, Vector256.Count); + } + else + { + remainder = Numerics.ModuloP2(source.Length, Vector128.Count); + } + + int adjustedCount = source.Length - remainder; + + if (adjustedCount > 0) + { + ByteToNormalizedFloat(source.Slice(0, adjustedCount), dest.Slice(0, adjustedCount)); + + source = source.Slice(adjustedCount); + dest = dest.Slice(adjustedCount); + } + } + } + + /// + /// Implementation , which is faster on new RyuJIT runtime. + /// + /// + /// Implementation is based on MagicScaler code: + /// https://github.com/saucecontrol/PhotoSauce/blob/b5811908041200488aa18fdfd17df5fc457415dc/src/MagicScaler/Magic/Processors/ConvertersFloat.cs#L80-L182 + /// + internal static unsafe void ByteToNormalizedFloat( + ReadOnlySpan source, + Span dest) + { + if (Avx2.IsSupported) + { + VerifySpanInput(source, dest, Vector256.Count); + + int n = dest.Length / Vector256.Count; + + byte* sourceBase = (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(source)); + + ref Vector256 destBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); + + var scale = Vector256.Create(1 / (float)byte.MaxValue); + + for (int i = 0; i < n; i++) + { + int si = Vector256.Count * i; + Vector256 i0 = Avx2.ConvertToVector256Int32(sourceBase + si); + Vector256 i1 = Avx2.ConvertToVector256Int32(sourceBase + si + Vector256.Count); + Vector256 i2 = Avx2.ConvertToVector256Int32(sourceBase + si + (Vector256.Count * 2)); + Vector256 i3 = Avx2.ConvertToVector256Int32(sourceBase + si + (Vector256.Count * 3)); + + Vector256 f0 = Avx.Multiply(scale, Avx.ConvertToVector256Single(i0)); + Vector256 f1 = Avx.Multiply(scale, Avx.ConvertToVector256Single(i1)); + Vector256 f2 = Avx.Multiply(scale, Avx.ConvertToVector256Single(i2)); + Vector256 f3 = Avx.Multiply(scale, Avx.ConvertToVector256Single(i3)); + + ref Vector256 d = ref Unsafe.Add(ref destBase, i * 4); + + d = f0; + Unsafe.Add(ref d, 1) = f1; + Unsafe.Add(ref d, 2) = f2; + Unsafe.Add(ref d, 3) = f3; + } + } + else + { + // Sse + VerifySpanInput(source, dest, Vector128.Count); + + int n = dest.Length / Vector128.Count; + + byte* sourceBase = (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(source)); + + ref Vector128 destBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); + + var scale = Vector128.Create(1 / (float)byte.MaxValue); + Vector128 zero = Vector128.Zero; + + for (int i = 0; i < n; i++) + { + int si = Vector128.Count * i; + + Vector128 i0, i1, i2, i3; + if (Sse41.IsSupported) + { + i0 = Sse41.ConvertToVector128Int32(sourceBase + si); + i1 = Sse41.ConvertToVector128Int32(sourceBase + si + Vector128.Count); + i2 = Sse41.ConvertToVector128Int32(sourceBase + si + (Vector128.Count * 2)); + i3 = Sse41.ConvertToVector128Int32(sourceBase + si + (Vector128.Count * 3)); + } + else + { + Vector128 b = Sse2.LoadVector128(sourceBase + si); + Vector128 s0 = Sse2.UnpackLow(b, zero).AsInt16(); + Vector128 s1 = Sse2.UnpackHigh(b, zero).AsInt16(); + + i0 = Sse2.UnpackLow(s0, zero.AsInt16()).AsInt32(); + i1 = Sse2.UnpackHigh(s0, zero.AsInt16()).AsInt32(); + i2 = Sse2.UnpackLow(s1, zero.AsInt16()).AsInt32(); + i3 = Sse2.UnpackHigh(s1, zero.AsInt16()).AsInt32(); + } + + Vector128 f0 = Sse.Multiply(scale, Sse2.ConvertToVector128Single(i0)); + Vector128 f1 = Sse.Multiply(scale, Sse2.ConvertToVector128Single(i1)); + Vector128 f2 = Sse.Multiply(scale, Sse2.ConvertToVector128Single(i2)); + Vector128 f3 = Sse.Multiply(scale, Sse2.ConvertToVector128Single(i3)); + + ref Vector128 d = ref Unsafe.Add(ref destBase, i * 4); + + d = f0; + Unsafe.Add(ref d, 1) = f1; + Unsafe.Add(ref d, 2) = f2; + Unsafe.Add(ref d, 3) = f3; + } + } + } + + /// + /// as many elements as possible, slicing them down (keeping the remainder). + /// + [MethodImpl(InliningOptions.ShortMethod)] + internal static void NormalizedFloatToByteSaturateReduce( + ref ReadOnlySpan source, + ref Span dest) + { + DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); + + if (Avx2.IsSupported || Sse2.IsSupported) + { + int remainder; + if (Avx2.IsSupported) + { + remainder = Numerics.ModuloP2(source.Length, Vector256.Count); + } + else + { + remainder = Numerics.ModuloP2(source.Length, Vector128.Count); + } + + int adjustedCount = source.Length - remainder; + + if (adjustedCount > 0) + { + NormalizedFloatToByteSaturate( + source.Slice(0, adjustedCount), + dest.Slice(0, adjustedCount)); + + source = source.Slice(adjustedCount); + dest = dest.Slice(adjustedCount); + } + } + } + + /// + /// Implementation of , which is faster on new .NET runtime. + /// + /// + /// Implementation is based on MagicScaler code: + /// https://github.com/saucecontrol/PhotoSauce/blob/b5811908041200488aa18fdfd17df5fc457415dc/src/MagicScaler/Magic/Processors/ConvertersFloat.cs#L541-L622 + /// + internal static void NormalizedFloatToByteSaturate( + ReadOnlySpan source, + Span dest) + { + if (Avx2.IsSupported) + { + VerifySpanInput(source, dest, Vector256.Count); + + int n = dest.Length / Vector256.Count; + + ref Vector256 sourceBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(source)); + + ref Vector256 destBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); + + var scale = Vector256.Create((float)byte.MaxValue); + ref byte maskBase = ref MemoryMarshal.GetReference(PermuteMaskDeinterleave8x32); + Vector256 mask = Unsafe.As>(ref maskBase); + + for (int i = 0; i < n; i++) + { + ref Vector256 s = ref Unsafe.Add(ref sourceBase, i * 4); + + Vector256 f0 = Avx.Multiply(scale, s); + Vector256 f1 = Avx.Multiply(scale, Unsafe.Add(ref s, 1)); + Vector256 f2 = Avx.Multiply(scale, Unsafe.Add(ref s, 2)); + Vector256 f3 = Avx.Multiply(scale, Unsafe.Add(ref s, 3)); + + Vector256 w0 = Avx.ConvertToVector256Int32(f0); + Vector256 w1 = Avx.ConvertToVector256Int32(f1); + Vector256 w2 = Avx.ConvertToVector256Int32(f2); + Vector256 w3 = Avx.ConvertToVector256Int32(f3); + + Vector256 u0 = Avx2.PackSignedSaturate(w0, w1); + Vector256 u1 = Avx2.PackSignedSaturate(w2, w3); + Vector256 b = Avx2.PackUnsignedSaturate(u0, u1); + b = Avx2.PermuteVar8x32(b.AsInt32(), mask).AsByte(); + + Unsafe.Add(ref destBase, i) = b; + } + } + else + { + // Sse + VerifySpanInput(source, dest, Vector128.Count); + + int n = dest.Length / Vector128.Count; + + ref Vector128 sourceBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(source)); + + ref Vector128 destBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(dest)); + + var scale = Vector128.Create((float)byte.MaxValue); + + for (int i = 0; i < n; i++) + { + ref Vector128 s = ref Unsafe.Add(ref sourceBase, i * 4); + + Vector128 f0 = Sse.Multiply(scale, s); + Vector128 f1 = Sse.Multiply(scale, Unsafe.Add(ref s, 1)); + Vector128 f2 = Sse.Multiply(scale, Unsafe.Add(ref s, 2)); + Vector128 f3 = Sse.Multiply(scale, Unsafe.Add(ref s, 3)); + + Vector128 w0 = Sse2.ConvertToVector128Int32(f0); + Vector128 w1 = Sse2.ConvertToVector128Int32(f1); + Vector128 w2 = Sse2.ConvertToVector128Int32(f2); + Vector128 w3 = Sse2.ConvertToVector128Int32(f3); + + Vector128 u0 = Sse2.PackSignedSaturate(w0, w1); + Vector128 u1 = Sse2.PackSignedSaturate(w2, w3); + + Unsafe.Add(ref destBase, i) = Sse2.PackUnsignedSaturate(u0, u1); + } + } + } + + internal static void PackFromRgbPlanesAvx2Reduce( + ref ReadOnlySpan redChannel, + ref ReadOnlySpan greenChannel, + ref ReadOnlySpan blueChannel, + ref Span destination) + { + ref Vector256 rBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(redChannel)); + ref Vector256 gBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(greenChannel)); + ref Vector256 bBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(blueChannel)); + ref byte dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(destination)); + + int count = redChannel.Length / Vector256.Count; + + ref byte control1Bytes = ref MemoryMarshal.GetReference(SimdUtils.HwIntrinsics.PermuteMaskEvenOdd8x32); + Vector256 control1 = Unsafe.As>(ref control1Bytes); + + ref byte control2Bytes = ref MemoryMarshal.GetReference(PermuteMaskShiftAlpha8x32); + Vector256 control2 = Unsafe.As>(ref control2Bytes); + + Vector256 a = Vector256.Create((byte)255); + + Vector256 shuffleAlpha = Unsafe.As>(ref MemoryMarshal.GetReference(ShuffleMaskShiftAlpha)); + + for (int i = 0; i < count; i++) + { + Vector256 r0 = Unsafe.Add(ref rBase, i); + Vector256 g0 = Unsafe.Add(ref gBase, i); + Vector256 b0 = Unsafe.Add(ref bBase, i); + + r0 = Avx2.PermuteVar8x32(r0.AsUInt32(), control1).AsByte(); + g0 = Avx2.PermuteVar8x32(g0.AsUInt32(), control1).AsByte(); + b0 = Avx2.PermuteVar8x32(b0.AsUInt32(), control1).AsByte(); + + Vector256 rg = Avx2.UnpackLow(r0, g0); + Vector256 b1 = Avx2.UnpackLow(b0, a); + + Vector256 rgb1 = Avx2.UnpackLow(rg.AsUInt16(), b1.AsUInt16()).AsByte(); + Vector256 rgb2 = Avx2.UnpackHigh(rg.AsUInt16(), b1.AsUInt16()).AsByte(); + + rg = Avx2.UnpackHigh(r0, g0); + b1 = Avx2.UnpackHigh(b0, a); + + Vector256 rgb3 = Avx2.UnpackLow(rg.AsUInt16(), b1.AsUInt16()).AsByte(); + Vector256 rgb4 = Avx2.UnpackHigh(rg.AsUInt16(), b1.AsUInt16()).AsByte(); + + rgb1 = Avx2.Shuffle(rgb1, shuffleAlpha); + rgb2 = Avx2.Shuffle(rgb2, shuffleAlpha); + rgb3 = Avx2.Shuffle(rgb3, shuffleAlpha); + rgb4 = Avx2.Shuffle(rgb4, shuffleAlpha); + + rgb1 = Avx2.PermuteVar8x32(rgb1.AsUInt32(), control2).AsByte(); + rgb2 = Avx2.PermuteVar8x32(rgb2.AsUInt32(), control2).AsByte(); + rgb3 = Avx2.PermuteVar8x32(rgb3.AsUInt32(), control2).AsByte(); + rgb4 = Avx2.PermuteVar8x32(rgb4.AsUInt32(), control2).AsByte(); + + ref byte d1 = ref Unsafe.Add(ref dBase, 24 * 4 * i); + ref byte d2 = ref Unsafe.Add(ref d1, 24); + ref byte d3 = ref Unsafe.Add(ref d2, 24); + ref byte d4 = ref Unsafe.Add(ref d3, 24); + + Unsafe.As>(ref d1) = rgb1; + Unsafe.As>(ref d2) = rgb2; + Unsafe.As>(ref d3) = rgb3; + Unsafe.As>(ref d4) = rgb4; + } + + int slice = count * Vector256.Count; + redChannel = redChannel.Slice(slice); + greenChannel = greenChannel.Slice(slice); + blueChannel = blueChannel.Slice(slice); + destination = destination.Slice(slice); + } + + internal static void PackFromRgbPlanesAvx2Reduce( + ref ReadOnlySpan redChannel, + ref ReadOnlySpan greenChannel, + ref ReadOnlySpan blueChannel, + ref Span destination) + { + ref Vector256 rBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(redChannel)); + ref Vector256 gBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(greenChannel)); + ref Vector256 bBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(blueChannel)); + ref Vector256 dBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(destination)); + + int count = redChannel.Length / Vector256.Count; + + ref byte control1Bytes = ref MemoryMarshal.GetReference(SimdUtils.HwIntrinsics.PermuteMaskEvenOdd8x32); + Vector256 control1 = Unsafe.As>(ref control1Bytes); + + ref byte control2Bytes = ref MemoryMarshal.GetReference(PermuteMaskShiftAlpha8x32); + Vector256 control2 = Unsafe.As>(ref control2Bytes); + + Vector256 a = Vector256.Create((byte)255); + + Vector256 shuffleAlpha = Unsafe.As>(ref MemoryMarshal.GetReference(ShuffleMaskShiftAlpha)); + + for (int i = 0; i < count; i++) + { + Vector256 r0 = Unsafe.Add(ref rBase, i); + Vector256 g0 = Unsafe.Add(ref gBase, i); + Vector256 b0 = Unsafe.Add(ref bBase, i); + + r0 = Avx2.PermuteVar8x32(r0.AsUInt32(), control1).AsByte(); + g0 = Avx2.PermuteVar8x32(g0.AsUInt32(), control1).AsByte(); + b0 = Avx2.PermuteVar8x32(b0.AsUInt32(), control1).AsByte(); + + Vector256 rg = Avx2.UnpackLow(r0, g0); + Vector256 b1 = Avx2.UnpackLow(b0, a); + + Vector256 rgb1 = Avx2.UnpackLow(rg.AsUInt16(), b1.AsUInt16()).AsByte(); + Vector256 rgb2 = Avx2.UnpackHigh(rg.AsUInt16(), b1.AsUInt16()).AsByte(); + + rg = Avx2.UnpackHigh(r0, g0); + b1 = Avx2.UnpackHigh(b0, a); + + Vector256 rgb3 = Avx2.UnpackLow(rg.AsUInt16(), b1.AsUInt16()).AsByte(); + Vector256 rgb4 = Avx2.UnpackHigh(rg.AsUInt16(), b1.AsUInt16()).AsByte(); + + ref Vector256 d0 = ref Unsafe.Add(ref dBase, i * 4); + d0 = rgb1; + Unsafe.Add(ref d0, 1) = rgb2; + Unsafe.Add(ref d0, 2) = rgb3; + Unsafe.Add(ref d0, 3) = rgb4; + } + + int slice = count * Vector256.Count; + redChannel = redChannel.Slice(slice); + greenChannel = greenChannel.Slice(slice); + blueChannel = blueChannel.Slice(slice); + destination = destination.Slice(slice); + } + } + } +} +#endif diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.Pack.cs b/src/ImageSharp/Common/Helpers/SimdUtils.Pack.cs new file mode 100644 index 0000000000..fe02bd0072 --- /dev/null +++ b/src/ImageSharp/Common/Helpers/SimdUtils.Pack.cs @@ -0,0 +1,206 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using SixLabors.ImageSharp.PixelFormats; + +#if SUPPORTS_RUNTIME_INTRINSICS +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +#endif + +namespace SixLabors.ImageSharp +{ + internal static partial class SimdUtils + { + [MethodImpl(InliningOptions.ShortMethod)] + internal static void PackFromRgbPlanes( + Configuration configuration, + ReadOnlySpan redChannel, + ReadOnlySpan greenChannel, + ReadOnlySpan blueChannel, + Span destination) + { + DebugGuard.IsTrue(greenChannel.Length == redChannel.Length, nameof(greenChannel), "Channels must be of same size!"); + DebugGuard.IsTrue(blueChannel.Length == redChannel.Length, nameof(blueChannel), "Channels must be of same size!"); + DebugGuard.IsTrue(destination.Length > redChannel.Length + 2, nameof(destination), "'destination' must contain a padding of 3 elements!"); + +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx2.IsSupported) + { + HwIntrinsics.PackFromRgbPlanesAvx2Reduce(ref redChannel, ref greenChannel, ref blueChannel, ref destination); + } + else +#endif + { + PackFromRgbPlanesScalarBatchedReduce(ref redChannel, ref greenChannel, ref blueChannel, ref destination); + } + + PackFromRgbPlanesRemainder(redChannel, greenChannel, blueChannel, destination); + } + + [MethodImpl(InliningOptions.ShortMethod)] + internal static void PackFromRgbPlanes( + Configuration configuration, + ReadOnlySpan redChannel, + ReadOnlySpan greenChannel, + ReadOnlySpan blueChannel, + Span destination) + { + DebugGuard.IsTrue(greenChannel.Length == redChannel.Length, nameof(greenChannel), "Channels must be of same size!"); + DebugGuard.IsTrue(blueChannel.Length == redChannel.Length, nameof(blueChannel), "Channels must be of same size!"); + DebugGuard.IsTrue(destination.Length > redChannel.Length, nameof(destination), "'destination' span should not be shorter than the source channels!"); + +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx2.IsSupported) + { + HwIntrinsics.PackFromRgbPlanesAvx2Reduce(ref redChannel, ref greenChannel, ref blueChannel, ref destination); + } + else +#endif + { + PackFromRgbPlanesScalarBatchedReduce(ref redChannel, ref greenChannel, ref blueChannel, ref destination); + } + + PackFromRgbPlanesRemainder(redChannel, greenChannel, blueChannel, destination); + } + + private static void PackFromRgbPlanesScalarBatchedReduce( + ref ReadOnlySpan redChannel, + ref ReadOnlySpan greenChannel, + ref ReadOnlySpan blueChannel, + ref Span destination) + { + ref ByteTuple4 r = ref Unsafe.As(ref MemoryMarshal.GetReference(redChannel)); + ref ByteTuple4 g = ref Unsafe.As(ref MemoryMarshal.GetReference(greenChannel)); + ref ByteTuple4 b = ref Unsafe.As(ref MemoryMarshal.GetReference(blueChannel)); + ref Rgb24 rgb = ref MemoryMarshal.GetReference(destination); + + int count = redChannel.Length / 4; + for (int i = 0; i < count; i++) + { + ref Rgb24 d0 = ref Unsafe.Add(ref rgb, i * 4); + ref Rgb24 d1 = ref Unsafe.Add(ref d0, 1); + ref Rgb24 d2 = ref Unsafe.Add(ref d0, 2); + ref Rgb24 d3 = ref Unsafe.Add(ref d0, 3); + + ref ByteTuple4 rr = ref Unsafe.Add(ref r, i); + ref ByteTuple4 gg = ref Unsafe.Add(ref g, i); + ref ByteTuple4 bb = ref Unsafe.Add(ref b, i); + + d0.R = rr.V0; + d0.G = gg.V0; + d0.B = bb.V0; + + d1.R = rr.V1; + d1.G = gg.V1; + d1.B = bb.V1; + + d2.R = rr.V2; + d2.G = gg.V2; + d2.B = bb.V2; + + d3.R = rr.V3; + d3.G = gg.V3; + d3.B = bb.V3; + } + + int finished = count * 4; + redChannel = redChannel.Slice(finished); + greenChannel = greenChannel.Slice(finished); + blueChannel = blueChannel.Slice(finished); + destination = destination.Slice(finished); + } + + private static void PackFromRgbPlanesScalarBatchedReduce( + ref ReadOnlySpan redChannel, + ref ReadOnlySpan greenChannel, + ref ReadOnlySpan blueChannel, + ref Span destination) + { + ref ByteTuple4 r = ref Unsafe.As(ref MemoryMarshal.GetReference(redChannel)); + ref ByteTuple4 g = ref Unsafe.As(ref MemoryMarshal.GetReference(greenChannel)); + ref ByteTuple4 b = ref Unsafe.As(ref MemoryMarshal.GetReference(blueChannel)); + ref Rgba32 rgb = ref MemoryMarshal.GetReference(destination); + + int count = redChannel.Length / 4; + destination.Fill(new Rgba32(0, 0, 0, 255)); + for (int i = 0; i < count; i++) + { + ref Rgba32 d0 = ref Unsafe.Add(ref rgb, i * 4); + ref Rgba32 d1 = ref Unsafe.Add(ref d0, 1); + ref Rgba32 d2 = ref Unsafe.Add(ref d0, 2); + ref Rgba32 d3 = ref Unsafe.Add(ref d0, 3); + + ref ByteTuple4 rr = ref Unsafe.Add(ref r, i); + ref ByteTuple4 gg = ref Unsafe.Add(ref g, i); + ref ByteTuple4 bb = ref Unsafe.Add(ref b, i); + + d0.R = rr.V0; + d0.G = gg.V0; + d0.B = bb.V0; + + d1.R = rr.V1; + d1.G = gg.V1; + d1.B = bb.V1; + + d2.R = rr.V2; + d2.G = gg.V2; + d2.B = bb.V2; + + d3.R = rr.V3; + d3.G = gg.V3; + d3.B = bb.V3; + } + + int finished = count * 4; + redChannel = redChannel.Slice(finished); + greenChannel = greenChannel.Slice(finished); + blueChannel = blueChannel.Slice(finished); + destination = destination.Slice(finished); + } + + private static void PackFromRgbPlanesRemainder( + ReadOnlySpan redChannel, + ReadOnlySpan greenChannel, + ReadOnlySpan blueChannel, + Span destination) + { + ref byte r = ref MemoryMarshal.GetReference(redChannel); + ref byte g = ref MemoryMarshal.GetReference(greenChannel); + ref byte b = ref MemoryMarshal.GetReference(blueChannel); + ref Rgb24 rgb = ref MemoryMarshal.GetReference(destination); + + for (int i = 0; i < destination.Length; i++) + { + ref Rgb24 d = ref Unsafe.Add(ref rgb, i); + d.R = Unsafe.Add(ref r, i); + d.G = Unsafe.Add(ref g, i); + d.B = Unsafe.Add(ref b, i); + } + } + + private static void PackFromRgbPlanesRemainder( + ReadOnlySpan redChannel, + ReadOnlySpan greenChannel, + ReadOnlySpan blueChannel, + Span destination) + { + ref byte r = ref MemoryMarshal.GetReference(redChannel); + ref byte g = ref MemoryMarshal.GetReference(greenChannel); + ref byte b = ref MemoryMarshal.GetReference(blueChannel); + ref Rgba32 rgba = ref MemoryMarshal.GetReference(destination); + + for (int i = 0; i < destination.Length; i++) + { + ref Rgba32 d = ref Unsafe.Add(ref rgba, i); + d.R = Unsafe.Add(ref r, i); + d.G = Unsafe.Add(ref g, i); + d.B = Unsafe.Add(ref b, i); + d.A = 255; + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.Shuffle.cs b/src/ImageSharp/Common/Helpers/SimdUtils.Shuffle.cs new file mode 100644 index 0000000000..07744566a3 --- /dev/null +++ b/src/ImageSharp/Common/Helpers/SimdUtils.Shuffle.cs @@ -0,0 +1,275 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace SixLabors.ImageSharp +{ + internal static partial class SimdUtils + { + /// + /// Shuffle single-precision (32-bit) floating-point elements in + /// using the control and store the results in . + /// + /// The source span of floats. + /// The destination span of floats. + /// The byte control. + [MethodImpl(InliningOptions.ShortMethod)] + public static void Shuffle4( + ReadOnlySpan source, + Span dest, + byte control) + { + VerifyShuffle4SpanInput(source, dest); + +#if SUPPORTS_RUNTIME_INTRINSICS + HwIntrinsics.Shuffle4Reduce(ref source, ref dest, control); +#endif + + // Deal with the remainder: + if (source.Length > 0) + { + Shuffle4Remainder(source, dest, control); + } + } + + /// + /// Shuffle 8-bit integers within 128-bit lanes in + /// using the control and store the results in . + /// + /// The source span of bytes. + /// The destination span of bytes. + /// The type of shuffle to perform. + [MethodImpl(InliningOptions.ShortMethod)] + public static void Shuffle4( + ReadOnlySpan source, + Span dest, + TShuffle shuffle) + where TShuffle : struct, IShuffle4 + { + VerifyShuffle4SpanInput(source, dest); + +#if SUPPORTS_RUNTIME_INTRINSICS + HwIntrinsics.Shuffle4Reduce(ref source, ref dest, shuffle.Control); +#endif + + // Deal with the remainder: + if (source.Length > 0) + { + shuffle.RunFallbackShuffle(source, dest); + } + } + + /// + /// Shuffle 8-bit integer triplets within 128-bit lanes in + /// using the control and store the results in . + /// + /// The source span of bytes. + /// The destination span of bytes. + /// The type of shuffle to perform. + [MethodImpl(InliningOptions.ShortMethod)] + public static void Shuffle3( + ReadOnlySpan source, + Span dest, + TShuffle shuffle) + where TShuffle : struct, IShuffle3 + { + VerifyShuffle3SpanInput(source, dest); + +#if SUPPORTS_RUNTIME_INTRINSICS + HwIntrinsics.Shuffle3Reduce(ref source, ref dest, shuffle.Control); +#endif + + // Deal with the remainder: + if (source.Length > 0) + { + shuffle.RunFallbackShuffle(source, dest); + } + } + + /// + /// Pads then shuffles 8-bit integers within 128-bit lanes in + /// using the control and store the results in . + /// + /// The source span of bytes. + /// The destination span of bytes. + /// The type of shuffle to perform. + [MethodImpl(InliningOptions.ShortMethod)] + public static void Pad3Shuffle4( + ReadOnlySpan source, + Span dest, + TShuffle shuffle) + where TShuffle : struct, IPad3Shuffle4 + { + VerifyPad3Shuffle4SpanInput(source, dest); + +#if SUPPORTS_RUNTIME_INTRINSICS + HwIntrinsics.Pad3Shuffle4Reduce(ref source, ref dest, shuffle.Control); +#endif + + // Deal with the remainder: + if (source.Length > 0) + { + shuffle.RunFallbackShuffle(source, dest); + } + } + + /// + /// Shuffles then slices 8-bit integers within 128-bit lanes in + /// using the control and store the results in . + /// + /// The source span of bytes. + /// The destination span of bytes. + /// The type of shuffle to perform. + [MethodImpl(InliningOptions.ShortMethod)] + public static void Shuffle4Slice3( + ReadOnlySpan source, + Span dest, + TShuffle shuffle) + where TShuffle : struct, IShuffle4Slice3 + { + VerifyShuffle4Slice3SpanInput(source, dest); + +#if SUPPORTS_RUNTIME_INTRINSICS + HwIntrinsics.Shuffle4Slice3Reduce(ref source, ref dest, shuffle.Control); +#endif + + // Deal with the remainder: + if (source.Length > 0) + { + shuffle.RunFallbackShuffle(source, dest); + } + } + + private static void Shuffle4Remainder( + ReadOnlySpan source, + Span dest, + byte control) + { + ref float sBase = ref MemoryMarshal.GetReference(source); + ref float dBase = ref MemoryMarshal.GetReference(dest); + Shuffle.InverseMmShuffle(control, out int p3, out int p2, out int p1, out int p0); + + for (int i = 0; i < source.Length; i += 4) + { + Unsafe.Add(ref dBase, i) = Unsafe.Add(ref sBase, p0 + i); + Unsafe.Add(ref dBase, i + 1) = Unsafe.Add(ref sBase, p1 + i); + Unsafe.Add(ref dBase, i + 2) = Unsafe.Add(ref sBase, p2 + i); + Unsafe.Add(ref dBase, i + 3) = Unsafe.Add(ref sBase, p3 + i); + } + } + + [Conditional("DEBUG")] + private static void VerifyShuffle4SpanInput(ReadOnlySpan source, Span dest) + where T : struct + { + DebugGuard.IsTrue( + source.Length == dest.Length, + nameof(source), + "Input spans must be of same length!"); + + DebugGuard.IsTrue( + source.Length % 4 == 0, + nameof(source), + "Input spans must be divisable by 4!"); + } + + [Conditional("DEBUG")] + private static void VerifyShuffle3SpanInput(ReadOnlySpan source, Span dest) + where T : struct + { + DebugGuard.IsTrue( + source.Length == dest.Length, + nameof(source), + "Input spans must be of same length!"); + + DebugGuard.IsTrue( + source.Length % 3 == 0, + nameof(source), + "Input spans must be divisable by 3!"); + } + + [Conditional("DEBUG")] + private static void VerifyPad3Shuffle4SpanInput(ReadOnlySpan source, Span dest) + { + DebugGuard.IsTrue( + source.Length % 3 == 0, + nameof(source), + "Input span must be divisable by 3!"); + + DebugGuard.IsTrue( + dest.Length % 4 == 0, + nameof(dest), + "Output span must be divisable by 4!"); + + DebugGuard.IsTrue( + source.Length == dest.Length * 3 / 4, + nameof(source), + "Input span must be 3/4 the length of the output span!"); + } + + [Conditional("DEBUG")] + private static void VerifyShuffle4Slice3SpanInput(ReadOnlySpan source, Span dest) + { + DebugGuard.IsTrue( + source.Length % 4 == 0, + nameof(source), + "Input span must be divisable by 4!"); + + DebugGuard.IsTrue( + dest.Length % 3 == 0, + nameof(dest), + "Output span must be divisable by 3!"); + + DebugGuard.IsTrue( + dest.Length >= source.Length * 3 / 4, + nameof(source), + "Output span must be at least 3/4 the length of the input span!"); + } + + public static class Shuffle + { + [MethodImpl(InliningOptions.ShortMethod)] + public static byte MmShuffle(byte p3, byte p2, byte p1, byte p0) + => (byte)((p3 << 6) | (p2 << 4) | (p1 << 2) | p0); + + [MethodImpl(InliningOptions.ShortMethod)] + public static void MmShuffleSpan(ref Span span, byte control) + { + InverseMmShuffle( + control, + out int p3, + out int p2, + out int p1, + out int p0); + + ref byte spanBase = ref MemoryMarshal.GetReference(span); + + for (int i = 0; i < span.Length; i += 4) + { + Unsafe.Add(ref spanBase, i) = (byte)(p0 + i); + Unsafe.Add(ref spanBase, i + 1) = (byte)(p1 + i); + Unsafe.Add(ref spanBase, i + 2) = (byte)(p2 + i); + Unsafe.Add(ref spanBase, i + 3) = (byte)(p3 + i); + } + } + + [MethodImpl(InliningOptions.ShortMethod)] + public static void InverseMmShuffle( + byte control, + out int p3, + out int p2, + out int p1, + out int p0) + { + p3 = control >> 6 & 0x3; + p2 = control >> 4 & 0x3; + p1 = control >> 2 & 0x3; + p0 = control >> 0 & 0x3; + } + } + } +} diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.cs b/src/ImageSharp/Common/Helpers/SimdUtils.cs index 7f917648dc..6d82cfad01 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using SixLabors.ImageSharp.PixelFormats; #if SUPPORTS_RUNTIME_INTRINSICS using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; @@ -25,6 +26,25 @@ namespace SixLabors.ImageSharp public static bool HasVector8 { get; } = Vector.IsHardwareAccelerated && Vector.Count == 8 && Vector.Count == 8; + /// + /// Gets a value indicating whether code is being JIT-ed to SSE instructions + /// where float and integer registers are of size 128 byte. + /// + public static bool HasVector4 { get; } = + Vector.IsHardwareAccelerated && Vector.Count == 4; + + public static bool HasAvx2 + { + get + { +#if SUPPORTS_RUNTIME_INTRINSICS + return Avx2.IsSupported; +#else + return false; +#endif + } + } + /// /// Transform all scalars in 'v' in a way that converting them to would have rounding semantics. /// @@ -32,7 +52,7 @@ namespace SixLabors.ImageSharp [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Vector4 PseudoRound(this Vector4 v) { - Vector4 sign = Vector4Utilities.FastClamp(v, new Vector4(-1), new Vector4(1)); + Vector4 sign = Numerics.Clamp(v, new Vector4(-1), new Vector4(1)); return v + (sign * 0.5f); } @@ -79,8 +99,9 @@ namespace SixLabors.ImageSharp internal static void ByteToNormalizedFloat(ReadOnlySpan source, Span dest) { DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); - -#if SUPPORTS_EXTENDED_INTRINSICS +#if SUPPORTS_RUNTIME_INTRINSICS + HwIntrinsics.ByteToNormalizedFloatReduce(ref source, ref dest); +#elif SUPPORTS_EXTENDED_INTRINSICS ExtendedIntrinsics.ByteToNormalizedFloatReduce(ref source, ref dest); #else BasicIntrinsics256.ByteToNormalizedFloatReduce(ref source, ref dest); @@ -110,7 +131,7 @@ namespace SixLabors.ImageSharp DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); #if SUPPORTS_RUNTIME_INTRINSICS - Avx2Intrinsics.NormalizedFloatToByteSaturateReduce(ref source, ref dest); + HwIntrinsics.NormalizedFloatToByteSaturateReduce(ref source, ref dest); #elif SUPPORTS_EXTENDED_INTRINSICS ExtendedIntrinsics.NormalizedFloatToByteSaturateReduce(ref source, ref dest); #else @@ -170,7 +191,7 @@ namespace SixLabors.ImageSharp } [MethodImpl(InliningOptions.ShortMethod)] - private static byte ConvertToByte(float f) => (byte)ComparableExtensions.Clamp((f * 255f) + 0.5f, 0, 255f); + private static byte ConvertToByte(float f) => (byte)Numerics.Clamp((f * 255F) + 0.5F, 0, 255F); [Conditional("DEBUG")] private static void VerifyHasVector8(string operation) @@ -186,7 +207,7 @@ namespace SixLabors.ImageSharp { DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); DebugGuard.IsTrue( - ImageMaths.ModuloP2(dest.Length, shouldBeDivisibleBy) == 0, + Numerics.ModuloP2(dest.Length, shouldBeDivisibleBy) == 0, nameof(source), $"length should be divisible by {shouldBeDivisibleBy}!"); } @@ -196,9 +217,17 @@ namespace SixLabors.ImageSharp { DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); DebugGuard.IsTrue( - ImageMaths.ModuloP2(dest.Length, shouldBeDivisibleBy) == 0, + Numerics.ModuloP2(dest.Length, shouldBeDivisibleBy) == 0, nameof(source), $"length should be divisible by {shouldBeDivisibleBy}!"); } + + private struct ByteTuple4 + { + public byte V0; + public byte V1; + public byte V2; + public byte V3; + } } } diff --git a/src/ImageSharp/Common/Helpers/Vector4Utilities.cs b/src/ImageSharp/Common/Helpers/Vector4Utilities.cs deleted file mode 100644 index fccc50755d..0000000000 --- a/src/ImageSharp/Common/Helpers/Vector4Utilities.cs +++ /dev/null @@ -1,122 +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; - -namespace SixLabors.ImageSharp -{ - /// - /// Utility methods for the struct. - /// - internal static class Vector4Utilities - { - /// - /// Restricts a vector between a minimum and a maximum value. - /// 5x Faster then . - /// - /// The vector to restrict. - /// The minimum value. - /// The maximum value. - /// The . - [MethodImpl(InliningOptions.ShortMethod)] - public static Vector4 FastClamp(Vector4 x, Vector4 min, Vector4 max) - => Vector4.Min(Vector4.Max(x, min), max); - - /// - /// Pre-multiplies the "x", "y", "z" components of a vector by its "w" component leaving the "w" component intact. - /// - /// The to premultiply - [MethodImpl(InliningOptions.ShortMethod)] - public static void Premultiply(ref Vector4 source) - { - float w = source.W; - source *= w; - source.W = w; - } - - /// - /// Reverses the result of premultiplying a vector via . - /// - /// The to premultiply - [MethodImpl(InliningOptions.ShortMethod)] - public static void UnPremultiply(ref Vector4 source) - { - float w = source.W; - source /= w; - source.W = w; - } - - /// - /// Bulk variant of - /// - /// The span of vectors - [MethodImpl(InliningOptions.ShortMethod)] - public static void Premultiply(Span vectors) - { - // TODO: This method can be AVX2 optimized using Vector - 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); - } - } - - /// - /// Bulk variant of - /// - /// The span of vectors - [MethodImpl(InliningOptions.ShortMethod)] - public static void UnPremultiply(Span vectors) - { - // TODO: This method can be AVX2 optimized using Vector - 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); - } - } - - /// - /// Transforms a vector by the given matrix. - /// - /// The source vector. - /// The transformation matrix. - [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; - } - - /// - /// Bulk variant of . - /// - /// The span of vectors - /// The transformation matrix. - [MethodImpl(InliningOptions.ShortMethod)] - public static void Transform(Span 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); - } - } - } -} diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs index 6f92236372..0be0385725 100644 --- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs @@ -1385,7 +1385,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp { case BmpFileMarkerType.Bitmap: colorMapSizeBytes = this.fileHeader.Offset - BmpFileHeader.Size - this.infoHeader.HeaderSize; - int colorCountForBitDepth = ImageMaths.GetColorCountForBitDepth(this.infoHeader.BitsPerPixel); + int colorCountForBitDepth = ColorNumerics.GetColorCountForBitDepth(this.infoHeader.BitsPerPixel); bytesPerColorMapEntry = colorMapSizeBytes / colorCountForBitDepth; // Edge case for less-than-full-sized palette: bytesPerColorMapEntry should be at least 3. @@ -1399,7 +1399,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp case BmpFileMarkerType.Pointer: // OS/2 bitmaps always have 3 colors per color palette entry. bytesPerColorMapEntry = 3; - colorMapSizeBytes = ImageMaths.GetColorCountForBitDepth(this.infoHeader.BitsPerPixel) * bytesPerColorMapEntry; + colorMapSizeBytes = ColorNumerics.GetColorCountForBitDepth(this.infoHeader.BitsPerPixel) * bytesPerColorMapEntry; break; } } diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs index eb29c44050..7819b1ebdb 100644 --- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs +++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs @@ -6,7 +6,6 @@ using System.Buffers; using System.IO; using System.Runtime.InteropServices; using System.Threading; -using System.Threading.Tasks; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.Memory; @@ -171,7 +170,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp var fileHeader = new BmpFileHeader( type: BmpConstants.TypeMarkers.Bitmap, - fileSize: BmpFileHeader.Size + infoHeaderSize + infoHeader.ImageSize, + fileSize: BmpFileHeader.Size + infoHeaderSize + colorPaletteSize + infoHeader.ImageSize, reserved: 0, offset: BmpFileHeader.Size + infoHeaderSize + colorPaletteSize); @@ -263,7 +262,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp private void Write24Bit(Stream stream, Buffer2D pixels) where TPixel : unmanaged, IPixel { - using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 3)) + int width = pixels.Width; + int rowBytesWithoutPadding = width * 3; + using (IManagedByteBuffer row = this.AllocateRow(width, 3)) { for (int y = pixels.Height - 1; y >= 0; y--) { @@ -271,8 +272,8 @@ namespace SixLabors.ImageSharp.Formats.Bmp PixelOperations.Instance.ToBgr24Bytes( this.configuration, pixelSpan, - row.GetSpan(), - pixelSpan.Length); + row.Slice(0, rowBytesWithoutPadding), + width); stream.Write(row.Array, 0, row.Length()); } } @@ -287,7 +288,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp private void Write16Bit(Stream stream, Buffer2D pixels) where TPixel : unmanaged, IPixel { - using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 2)) + int width = pixels.Width; + int rowBytesWithoutPadding = width * 2; + using (IManagedByteBuffer row = this.AllocateRow(width, 2)) { for (int y = pixels.Height - 1; y >= 0; y--) { @@ -296,7 +299,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp PixelOperations.Instance.ToBgra5551Bytes( this.configuration, pixelSpan, - row.GetSpan(), + row.Slice(0, rowBytesWithoutPadding), pixelSpan.Length); stream.Write(row.Array, 0, row.Length()); @@ -342,20 +345,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp using IndexedImageFrame quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(image, image.Bounds()); ReadOnlySpan quantizedColors = quantized.Palette.Span; - var color = default(Rgba32); - - // TODO: Use bulk conversion here for better perf - int idx = 0; - foreach (TPixel quantizedColor in quantizedColors) + var quantizedColorBytes = quantizedColors.Length * 4; + PixelOperations.Instance.ToBgra32(this.configuration, quantizedColors, MemoryMarshal.Cast(colorPalette.Slice(0, quantizedColorBytes))); + Span colorPaletteAsUInt = MemoryMarshal.Cast(colorPalette); + for (int i = 0; i < colorPaletteAsUInt.Length; i++) { - quantizedColor.ToRgba32(ref color); - colorPalette[idx] = color.B; - colorPalette[idx + 1] = color.G; - colorPalette[idx + 2] = color.R; - - // Padding byte, always 0. - colorPalette[idx + 3] = 0; - idx += 4; + colorPaletteAsUInt[i] = colorPaletteAsUInt[i] & 0x00FFFFFF; // Padding byte, always 0. } stream.Write(colorPalette); diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs index 8f5cc3b5c8..2f6b45aff9 100644 --- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs @@ -535,7 +535,8 @@ namespace SixLabors.ImageSharp.Formats.Gif return; } - Buffer2DRegion pixelRegion = frame.PixelBuffer.GetRegion(this.restoreArea.Value); + var interest = Rectangle.Intersect(frame.Bounds(), this.restoreArea.Value); + Buffer2DRegion pixelRegion = frame.PixelBuffer.GetRegion(interest); pixelRegion.Clear(); this.restoreArea = null; diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs index 070864e603..9c1e95285c 100644 --- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs +++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs @@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp.Formats.Gif } // Get the number of bits. - this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length); + this.bitDepth = ColorNumerics.GetBitsNeededForColorDepth(quantized.Palette.Length); // Write the header. this.WriteHeader(stream); @@ -212,7 +212,7 @@ namespace SixLabors.ImageSharp.Formats.Gif } } - this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length); + this.bitDepth = ColorNumerics.GetBitsNeededForColorDepth(quantized.Palette.Length); this.WriteGraphicalControlExtension(frameMetadata, this.GetTransparentIndex(quantized), stream); this.WriteImageDescriptor(frame, true, stream); this.WriteColorTable(quantized, stream); @@ -468,7 +468,7 @@ namespace SixLabors.ImageSharp.Formats.Gif where TPixel : unmanaged, IPixel { // The maximum number of colors for the bit depth - int colorTableLength = ImageMaths.GetColorCountForBitDepth(this.bitDepth) * Unsafe.SizeOf(); + int colorTableLength = ColorNumerics.GetColorCountForBitDepth(this.bitDepth) * Unsafe.SizeOf(); using IManagedByteBuffer colorTable = this.memoryAllocator.AllocateManagedByteBuffer(colorTableLength, AllocationOptions.Clean); PixelOperations.Instance.ToRgb24Bytes( diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs index f6f5903684..dd5d3f1960 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs @@ -10,118 +10,38 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { internal partial struct Block8x8F { - /// - /// Transpose the block into the destination block. - /// - /// The destination block - [MethodImpl(InliningOptions.ShortMethod)] - public void TransposeInto(ref Block8x8F d) - { - d.V0L.X = V0L.X; - d.V1L.X = V0L.Y; - d.V2L.X = V0L.Z; - d.V3L.X = V0L.W; - d.V4L.X = V0R.X; - d.V5L.X = V0R.Y; - d.V6L.X = V0R.Z; - d.V7L.X = V0R.W; - - d.V0L.Y = V1L.X; - d.V1L.Y = V1L.Y; - d.V2L.Y = V1L.Z; - d.V3L.Y = V1L.W; - d.V4L.Y = V1R.X; - d.V5L.Y = V1R.Y; - d.V6L.Y = V1R.Z; - d.V7L.Y = V1R.W; - - d.V0L.Z = V2L.X; - d.V1L.Z = V2L.Y; - d.V2L.Z = V2L.Z; - d.V3L.Z = V2L.W; - d.V4L.Z = V2R.X; - d.V5L.Z = V2R.Y; - d.V6L.Z = V2R.Z; - d.V7L.Z = V2R.W; - - d.V0L.W = V3L.X; - d.V1L.W = V3L.Y; - d.V2L.W = V3L.Z; - d.V3L.W = V3L.W; - d.V4L.W = V3R.X; - d.V5L.W = V3R.Y; - d.V6L.W = V3R.Z; - d.V7L.W = V3R.W; - - d.V0R.X = V4L.X; - d.V1R.X = V4L.Y; - d.V2R.X = V4L.Z; - d.V3R.X = V4L.W; - d.V4R.X = V4R.X; - d.V5R.X = V4R.Y; - d.V6R.X = V4R.Z; - d.V7R.X = V4R.W; - - d.V0R.Y = V5L.X; - d.V1R.Y = V5L.Y; - d.V2R.Y = V5L.Z; - d.V3R.Y = V5L.W; - d.V4R.Y = V5R.X; - d.V5R.Y = V5R.Y; - d.V6R.Y = V5R.Z; - d.V7R.Y = V5R.W; - - d.V0R.Z = V6L.X; - d.V1R.Z = V6L.Y; - d.V2R.Z = V6L.Z; - d.V3R.Z = V6L.W; - d.V4R.Z = V6R.X; - d.V5R.Z = V6R.Y; - d.V6R.Z = V6R.Z; - d.V7R.Z = V6R.W; - - d.V0R.W = V7L.X; - d.V1R.W = V7L.Y; - d.V2R.W = V7L.Z; - d.V3R.W = V7L.W; - d.V4R.W = V7R.X; - d.V5R.W = V7R.Y; - d.V6R.W = V7R.Z; - d.V7R.W = V7R.W; - } - /// /// Level shift by +maximum/2, clip to [0, maximum] /// - public void NormalizeColorsInplace(float maximum) + public void NormalizeColorsInPlace(float maximum) { var CMin4 = new Vector4(0F); var CMax4 = new Vector4(maximum); var COff4 = new Vector4(MathF.Ceiling(maximum / 2)); - this.V0L = Vector4Utilities.FastClamp(this.V0L + COff4, CMin4, CMax4); - this.V0R = Vector4Utilities.FastClamp(this.V0R + COff4, CMin4, CMax4); - this.V1L = Vector4Utilities.FastClamp(this.V1L + COff4, CMin4, CMax4); - this.V1R = Vector4Utilities.FastClamp(this.V1R + COff4, CMin4, CMax4); - this.V2L = Vector4Utilities.FastClamp(this.V2L + COff4, CMin4, CMax4); - this.V2R = Vector4Utilities.FastClamp(this.V2R + COff4, CMin4, CMax4); - this.V3L = Vector4Utilities.FastClamp(this.V3L + COff4, CMin4, CMax4); - this.V3R = Vector4Utilities.FastClamp(this.V3R + COff4, CMin4, CMax4); - this.V4L = Vector4Utilities.FastClamp(this.V4L + COff4, CMin4, CMax4); - this.V4R = Vector4Utilities.FastClamp(this.V4R + COff4, CMin4, CMax4); - this.V5L = Vector4Utilities.FastClamp(this.V5L + COff4, CMin4, CMax4); - this.V5R = Vector4Utilities.FastClamp(this.V5R + COff4, CMin4, CMax4); - this.V6L = Vector4Utilities.FastClamp(this.V6L + COff4, CMin4, CMax4); - this.V6R = Vector4Utilities.FastClamp(this.V6R + COff4, CMin4, CMax4); - this.V7L = Vector4Utilities.FastClamp(this.V7L + COff4, CMin4, CMax4); - this.V7R = Vector4Utilities.FastClamp(this.V7R + COff4, CMin4, CMax4); + this.V0L = Numerics.Clamp(this.V0L + COff4, CMin4, CMax4); + this.V0R = Numerics.Clamp(this.V0R + COff4, CMin4, CMax4); + this.V1L = Numerics.Clamp(this.V1L + COff4, CMin4, CMax4); + this.V1R = Numerics.Clamp(this.V1R + COff4, CMin4, CMax4); + this.V2L = Numerics.Clamp(this.V2L + COff4, CMin4, CMax4); + this.V2R = Numerics.Clamp(this.V2R + COff4, CMin4, CMax4); + this.V3L = Numerics.Clamp(this.V3L + COff4, CMin4, CMax4); + this.V3R = Numerics.Clamp(this.V3R + COff4, CMin4, CMax4); + this.V4L = Numerics.Clamp(this.V4L + COff4, CMin4, CMax4); + this.V4R = Numerics.Clamp(this.V4R + COff4, CMin4, CMax4); + this.V5L = Numerics.Clamp(this.V5L + COff4, CMin4, CMax4); + this.V5R = Numerics.Clamp(this.V5R + COff4, CMin4, CMax4); + this.V6L = Numerics.Clamp(this.V6L + COff4, CMin4, CMax4); + this.V6R = Numerics.Clamp(this.V6R + COff4, CMin4, CMax4); + this.V7L = Numerics.Clamp(this.V7L + COff4, CMin4, CMax4); + this.V7R = Numerics.Clamp(this.V7R + COff4, CMin4, CMax4); } /// - /// AVX2-only variant for executing and in one step. + /// AVX2-only variant for executing and in one step. /// [MethodImpl(InliningOptions.ShortMethod)] - public void NormalizeColorsAndRoundInplaceVector8(float maximum) + public void NormalizeColorsAndRoundInPlaceVector8(float maximum) { var off = new Vector(MathF.Ceiling(maximum / 2)); var max = new Vector(maximum); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt index 6ee0540213..8897efbe00 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt @@ -23,42 +23,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { internal partial struct Block8x8F { - /// - /// Transpose the block into the destination block. - /// - /// The destination block - [MethodImpl(InliningOptions.ShortMethod)] - public void TransposeInto(ref Block8x8F d) - { - <# - PushIndent(" "); - - for (int i = 0; i < 8; i++) - { - char destCoord = coordz[i % 4]; - char destSide = (i / 4) % 2 == 0 ? 'L' : 'R'; - - for (int j = 0; j < 8; j++) - { - if(i > 0 && j == 0){ - WriteLine(""); - } - - char srcCoord = coordz[j % 4]; - char srcSide = (j / 4) % 2 == 0 ? 'L' : 'R'; - - var expression = $"d.V{j}{destSide}.{destCoord} = V{i}{srcSide}.{srcCoord};\r\n"; - Write(expression); - } - } - PopIndent(); - #> - } - /// /// Level shift by +maximum/2, clip to [0, maximum] /// - public void NormalizeColorsInplace(float maximum) + public void NormalizeColorsInPlace(float maximum) { var CMin4 = new Vector4(0F); var CMax4 = new Vector4(maximum); @@ -73,7 +41,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components for (int j = 0; j < 2; j++) { char side = j == 0 ? 'L' : 'R'; - Write($"this.V{i}{side} = Vector4Utilities.FastClamp(this.V{i}{side} + COff4, CMin4, CMax4);\r\n"); + Write($"this.V{i}{side} = Numerics.Clamp(this.V{i}{side} + COff4, CMin4, CMax4);\r\n"); } } PopIndent(); @@ -81,10 +49,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } /// - /// AVX2-only variant for executing and in one step. + /// AVX2-only variant for executing and in one step. /// [MethodImpl(InliningOptions.ShortMethod)] - public void NormalizeColorsAndRoundInplaceVector8(float maximum) + public void NormalizeColorsAndRoundInPlaceVector8(float maximum) { var off = new Vector(MathF.Ceiling(maximum / 2)); var max = new Vector(maximum); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs index b7835d6706..2d19f5ce26 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs @@ -6,6 +6,10 @@ using System.Diagnostics; 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 using System.Text; // ReSharper disable InconsistentNaming @@ -14,6 +18,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// Represents a Jpeg block with coefficients. /// + [StructLayout(LayoutKind.Sequential)] internal partial struct Block8x8F : IEquatable { /// @@ -47,9 +52,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components public Vector4 V7R; #pragma warning restore SA1600 // ElementsMustBeDocumented - private static readonly Vector4 NegativeOne = new Vector4(-1); - private static readonly Vector4 Offset = new Vector4(.5F); - /// /// Get/Set scalar elements at a given index /// @@ -57,7 +59,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// The float value at the specified index public float this[int idx] { - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] get { GuardBlockIndex(idx); @@ -65,7 +67,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components return Unsafe.Add(ref selfRef, idx); } - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] set { GuardBlockIndex(idx); @@ -151,10 +153,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// [MethodImpl(InliningOptions.ShortMethod)] public void Clear() - { - // The cheapest way to do this in C#: - this = default; - } + => this = default; // The cheapest way to do this in C#: /// /// Load raw 32bit floating point data from source. @@ -176,9 +175,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// Source [MethodImpl(InliningOptions.ShortMethod)] public static unsafe void LoadFrom(Block8x8F* blockPtr, Span source) - { - blockPtr->LoadFrom(source); - } + => blockPtr->LoadFrom(source); /// /// Load raw 32bit floating point data from source @@ -232,9 +229,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// The destination. [MethodImpl(InliningOptions.ShortMethod)] public static unsafe void ScaledCopyTo(Block8x8F* blockPtr, Span dest) - { - blockPtr->ScaledCopyTo(dest); - } + => blockPtr->ScaledCopyTo(dest); /// /// Copy raw 32bit floating point data to dest @@ -277,73 +272,156 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// The value to multiply by. [MethodImpl(InliningOptions.ShortMethod)] - public void MultiplyInplace(float value) - { - this.V0L *= value; - this.V0R *= value; - this.V1L *= value; - this.V1R *= value; - this.V2L *= value; - this.V2R *= value; - this.V3L *= value; - this.V3R *= value; - this.V4L *= value; - this.V4R *= value; - this.V5L *= value; - this.V5R *= value; - this.V6L *= value; - this.V6R *= value; - this.V7L *= value; - this.V7R *= value; + public void MultiplyInPlace(float value) + { +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx.IsSupported) + { + var valueVec = Vector256.Create(value); + Unsafe.As>(ref this.V0L) = Avx.Multiply(Unsafe.As>(ref this.V0L), valueVec); + Unsafe.As>(ref this.V1L) = Avx.Multiply(Unsafe.As>(ref this.V1L), valueVec); + Unsafe.As>(ref this.V2L) = Avx.Multiply(Unsafe.As>(ref this.V2L), valueVec); + Unsafe.As>(ref this.V3L) = Avx.Multiply(Unsafe.As>(ref this.V3L), valueVec); + Unsafe.As>(ref this.V4L) = Avx.Multiply(Unsafe.As>(ref this.V4L), valueVec); + Unsafe.As>(ref this.V5L) = Avx.Multiply(Unsafe.As>(ref this.V5L), valueVec); + Unsafe.As>(ref this.V6L) = Avx.Multiply(Unsafe.As>(ref this.V6L), valueVec); + Unsafe.As>(ref this.V7L) = Avx.Multiply(Unsafe.As>(ref this.V7L), valueVec); + } + else +#endif + { + var valueVec = new Vector4(value); + this.V0L *= valueVec; + this.V0R *= valueVec; + this.V1L *= valueVec; + this.V1R *= valueVec; + this.V2L *= valueVec; + this.V2R *= valueVec; + this.V3L *= valueVec; + this.V3R *= valueVec; + this.V4L *= valueVec; + this.V4R *= valueVec; + this.V5L *= valueVec; + this.V5R *= valueVec; + this.V6L *= valueVec; + this.V6R *= valueVec; + this.V7L *= valueVec; + this.V7R *= valueVec; + } } /// /// Multiply all elements of the block by the corresponding elements of 'other'. /// [MethodImpl(InliningOptions.ShortMethod)] - public void MultiplyInplace(ref Block8x8F other) - { - this.V0L *= other.V0L; - this.V0R *= other.V0R; - this.V1L *= other.V1L; - this.V1R *= other.V1R; - this.V2L *= other.V2L; - this.V2R *= other.V2R; - this.V3L *= other.V3L; - this.V3R *= other.V3R; - this.V4L *= other.V4L; - this.V4R *= other.V4R; - this.V5L *= other.V5L; - this.V5R *= other.V5R; - this.V6L *= other.V6L; - this.V6R *= other.V6R; - this.V7L *= other.V7L; - this.V7R *= other.V7R; + public unsafe void MultiplyInPlace(ref Block8x8F other) + { +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx.IsSupported) + { + Unsafe.As>(ref this.V0L) + = Avx.Multiply( + Unsafe.As>(ref this.V0L), + Unsafe.As>(ref other.V0L)); + + Unsafe.As>(ref this.V1L) + = Avx.Multiply( + Unsafe.As>(ref this.V1L), + Unsafe.As>(ref other.V1L)); + + Unsafe.As>(ref this.V2L) + = Avx.Multiply( + Unsafe.As>(ref this.V2L), + Unsafe.As>(ref other.V2L)); + + Unsafe.As>(ref this.V3L) + = Avx.Multiply( + Unsafe.As>(ref this.V3L), + Unsafe.As>(ref other.V3L)); + + Unsafe.As>(ref this.V4L) + = Avx.Multiply( + Unsafe.As>(ref this.V4L), + Unsafe.As>(ref other.V4L)); + + Unsafe.As>(ref this.V5L) + = Avx.Multiply( + Unsafe.As>(ref this.V5L), + Unsafe.As>(ref other.V5L)); + + Unsafe.As>(ref this.V6L) + = Avx.Multiply( + Unsafe.As>(ref this.V6L), + Unsafe.As>(ref other.V6L)); + + Unsafe.As>(ref this.V7L) + = Avx.Multiply( + Unsafe.As>(ref this.V7L), + Unsafe.As>(ref other.V7L)); + } + else +#endif + { + this.V0L *= other.V0L; + this.V0R *= other.V0R; + this.V1L *= other.V1L; + this.V1R *= other.V1R; + this.V2L *= other.V2L; + this.V2R *= other.V2R; + this.V3L *= other.V3L; + this.V3R *= other.V3R; + this.V4L *= other.V4L; + this.V4R *= other.V4R; + this.V5L *= other.V5L; + this.V5R *= other.V5R; + this.V6L *= other.V6L; + this.V6R *= other.V6R; + this.V7L *= other.V7L; + this.V7R *= other.V7R; + } } /// /// Adds a vector to all elements of the block. /// - /// The added vector + /// The added vector. [MethodImpl(InliningOptions.ShortMethod)] - public void AddToAllInplace(Vector4 diff) - { - this.V0L += diff; - this.V0R += diff; - this.V1L += diff; - this.V1R += diff; - this.V2L += diff; - this.V2R += diff; - this.V3L += diff; - this.V3R += diff; - this.V4L += diff; - this.V4R += diff; - this.V5L += diff; - this.V5R += diff; - this.V6L += diff; - this.V6R += diff; - this.V7L += diff; - this.V7R += diff; + public void AddInPlace(float value) + { +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx.IsSupported) + { + var valueVec = Vector256.Create(value); + Unsafe.As>(ref this.V0L) = Avx.Add(Unsafe.As>(ref this.V0L), valueVec); + Unsafe.As>(ref this.V1L) = Avx.Add(Unsafe.As>(ref this.V1L), valueVec); + Unsafe.As>(ref this.V2L) = Avx.Add(Unsafe.As>(ref this.V2L), valueVec); + Unsafe.As>(ref this.V3L) = Avx.Add(Unsafe.As>(ref this.V3L), valueVec); + Unsafe.As>(ref this.V4L) = Avx.Add(Unsafe.As>(ref this.V4L), valueVec); + Unsafe.As>(ref this.V5L) = Avx.Add(Unsafe.As>(ref this.V5L), valueVec); + Unsafe.As>(ref this.V6L) = Avx.Add(Unsafe.As>(ref this.V6L), valueVec); + Unsafe.As>(ref this.V7L) = Avx.Add(Unsafe.As>(ref this.V7L), valueVec); + } + else +#endif + { + var valueVec = new Vector4(value); + this.V0L += valueVec; + this.V0R += valueVec; + this.V1L += valueVec; + this.V1R += valueVec; + this.V2L += valueVec; + this.V2R += valueVec; + this.V3L += valueVec; + this.V3R += valueVec; + this.V4L += valueVec; + this.V4R += valueVec; + this.V5L += valueVec; + this.V5R += valueVec; + this.V6L += valueVec; + this.V6R += valueVec; + this.V7L += valueVec; + this.V7R += valueVec; + } } /// @@ -352,7 +430,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// The block pointer. /// The qt pointer. /// Unzig pointer - // [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe void DequantizeBlock(Block8x8F* blockPtr, Block8x8F* qtPtr, byte* unzigPtr) { float* b = (float*)blockPtr; @@ -398,6 +475,57 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// The source block. public static unsafe void Scale16X16To8X8(ref Block8x8F destination, ReadOnlySpan source) { +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx2.IsSupported) + { + Scale16X16To8X8Vectorized(ref destination, source); + return; + } +#endif + + Scale16X16To8X8Scalar(ref destination, source); + } + + private static void Scale16X16To8X8Vectorized(ref Block8x8F destination, ReadOnlySpan source) + { +#if SUPPORTS_RUNTIME_INTRINSICS + Debug.Assert(Avx2.IsSupported, "AVX2 is required to execute this method"); + + var f2 = Vector256.Create(2f); + var f025 = Vector256.Create(0.25f); + Vector256 switchInnerDoubleWords = Unsafe.As>(ref MemoryMarshal.GetReference(SimdUtils.HwIntrinsics.PermuteMaskSwitchInnerDWords8x32)); + ref Vector256 destRef = ref Unsafe.As>(ref destination); + + for (int i = 0; i < 2; i++) + { + ref Vector256 in1 = ref Unsafe.As>(ref Unsafe.Add(ref MemoryMarshal.GetReference(source), 2 * i)); + ref Vector256 in2 = ref Unsafe.As>(ref Unsafe.Add(ref MemoryMarshal.GetReference(source), (2 * i) + 1)); + + for (int j = 0; j < 8; j += 2) + { + Vector256 a = Unsafe.Add(ref in1, j); + Vector256 b = Unsafe.Add(ref in1, j + 1); + Vector256 c = Unsafe.Add(ref in2, j); + Vector256 d = Unsafe.Add(ref in2, j + 1); + + Vector256 calc1 = Avx.Shuffle(a, c, 0b10_00_10_00); + Vector256 calc2 = Avx.Shuffle(a, c, 0b11_01_11_01); + Vector256 calc3 = Avx.Shuffle(b, d, 0b10_00_10_00); + Vector256 calc4 = Avx.Shuffle(b, d, 0b11_01_11_01); + + Vector256 sum = Avx.Add(Avx.Add(calc1, calc2), Avx.Add(calc3, calc4)); + Vector256 add = Avx.Add(sum, f2); + Vector256 res = Avx.Multiply(add, f025); + + destRef = Avx2.PermuteVar8x32(res, switchInnerDoubleWords); + destRef = ref Unsafe.Add(ref destRef, 1); + } + } +#endif + } + + private static unsafe void Scale16X16To8X8Scalar(ref Block8x8F destination, ReadOnlySpan source) + { for (int i = 0; i < 4; i++) { int dstOff = ((i & 2) << 4) | ((i & 1) << 2); @@ -418,22 +546,60 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components [MethodImpl(InliningOptions.ShortMethod)] private static void DivideRoundAll(ref Block8x8F a, ref Block8x8F b) { - a.V0L = DivideRound(a.V0L, b.V0L); - a.V0R = DivideRound(a.V0R, b.V0R); - a.V1L = DivideRound(a.V1L, b.V1L); - a.V1R = DivideRound(a.V1R, b.V1R); - a.V2L = DivideRound(a.V2L, b.V2L); - a.V2R = DivideRound(a.V2R, b.V2R); - a.V3L = DivideRound(a.V3L, b.V3L); - a.V3R = DivideRound(a.V3R, b.V3R); - a.V4L = DivideRound(a.V4L, b.V4L); - a.V4R = DivideRound(a.V4R, b.V4R); - a.V5L = DivideRound(a.V5L, b.V5L); - a.V5R = DivideRound(a.V5R, b.V5R); - a.V6L = DivideRound(a.V6L, b.V6L); - a.V6R = DivideRound(a.V6R, b.V6R); - a.V7L = DivideRound(a.V7L, b.V7L); - a.V7R = DivideRound(a.V7R, b.V7R); +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx.IsSupported) + { + var vnegOne = Vector256.Create(-1f); + var vadd = Vector256.Create(.5F); + var vone = Vector256.Create(1f); + + ref Vector256 aBase = ref Unsafe.AsRef(Unsafe.As>(ref a.V0L)); + ref Vector256 bBase = ref Unsafe.AsRef(Unsafe.As>(ref b.V0L)); + ref Vector256 aEnd = ref Unsafe.Add(ref aBase, 8); + + do + { + Vector256 voff = Avx.Multiply(Avx.Min(Avx.Max(vnegOne, aBase), vone), vadd); + Unsafe.Add(ref aBase, 0) = Avx.Add(Avx.Divide(aBase, bBase), voff); + + aBase = ref Unsafe.Add(ref aBase, 1); + bBase = ref Unsafe.Add(ref bBase, 1); + } + while (Unsafe.IsAddressLessThan(ref aBase, ref aEnd)); + } + else +#endif + { + a.V0L = DivideRound(a.V0L, b.V0L); + a.V0R = DivideRound(a.V0R, b.V0R); + a.V1L = DivideRound(a.V1L, b.V1L); + a.V1R = DivideRound(a.V1R, b.V1R); + a.V2L = DivideRound(a.V2L, b.V2L); + a.V2R = DivideRound(a.V2R, b.V2R); + a.V3L = DivideRound(a.V3L, b.V3L); + a.V3R = DivideRound(a.V3R, b.V3R); + a.V4L = DivideRound(a.V4L, b.V4L); + a.V4R = DivideRound(a.V4R, b.V4R); + a.V5L = DivideRound(a.V5L, b.V5L); + a.V5R = DivideRound(a.V5R, b.V5R); + a.V6L = DivideRound(a.V6L, b.V6L); + a.V6R = DivideRound(a.V6R, b.V6R); + a.V7L = DivideRound(a.V7L, b.V7L); + a.V7R = DivideRound(a.V7R, b.V7R); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector4 DivideRound(Vector4 dividend, Vector4 divisor) + { + var neg = new Vector4(-1); + var add = new Vector4(.5F); + + // sign(dividend) = max(min(dividend, 1), -1) + Vector4 sign = Numerics.Clamp(dividend, neg, Vector4.One); + + // AlmostRound(dividend/divisor) = dividend/divisor + 0.5*sign(dividend) + return (dividend / divisor) + (sign * add); } public void RoundInto(ref Block8x8 dest) @@ -464,23 +630,23 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// Level shift by +maximum/2, clip to [0..maximum], and round all the values in the block. /// - public void NormalizeColorsAndRoundInplace(float maximum) + public void NormalizeColorsAndRoundInPlace(float maximum) { if (SimdUtils.HasVector8) { - this.NormalizeColorsAndRoundInplaceVector8(maximum); + this.NormalizeColorsAndRoundInPlaceVector8(maximum); } else { - this.NormalizeColorsInplace(maximum); - this.RoundInplace(); + this.NormalizeColorsInPlace(maximum); + this.RoundInPlace(); } } /// /// Rounds all values in the block. /// - public void RoundInplace() + public void RoundInPlace() { for (int i = 0; i < Size; i++) { @@ -535,8 +701,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// public bool Equals(Block8x8F other) - { - return this.V0L == other.V0L + => this.V0L == other.V0L && this.V0R == other.V0R && this.V1L == other.V1L && this.V1R == other.V1R @@ -552,7 +717,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components && this.V6R == other.V6R && this.V7L == other.V7L && this.V7R == other.V7R; - } /// public override string ToString() @@ -580,21 +744,163 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components return row.FastRound(); } - [MethodImpl(InliningOptions.ShortMethod)] - private static Vector4 DivideRound(Vector4 dividend, Vector4 divisor) - { - // sign(dividend) = max(min(dividend, 1), -1) - Vector4 sign = Vector4Utilities.FastClamp(dividend, NegativeOne, Vector4.One); - - // AlmostRound(dividend/divisor) = dividend/divisor + 0.5*sign(dividend) - return (dividend / divisor) + (sign * Offset); - } - [Conditional("DEBUG")] private static void GuardBlockIndex(int idx) { DebugGuard.MustBeLessThan(idx, Size, nameof(idx)); DebugGuard.MustBeGreaterThanOrEqualTo(idx, 0, nameof(idx)); } + + /// + /// Transpose the block into the destination block. + /// + /// The destination block + [MethodImpl(InliningOptions.ShortMethod)] + public void TransposeInto(ref Block8x8F d) + { +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx.IsSupported) + { + // https://stackoverflow.com/questions/25622745/transpose-an-8x8-float-using-avx-avx2/25627536#25627536 + Vector256 r0 = Avx.InsertVector128( + Unsafe.As>(ref this.V0L).ToVector256(), + Unsafe.As>(ref this.V4L), + 1); + + Vector256 r1 = Avx.InsertVector128( + Unsafe.As>(ref this.V1L).ToVector256(), + Unsafe.As>(ref this.V5L), + 1); + + Vector256 r2 = Avx.InsertVector128( + Unsafe.As>(ref this.V2L).ToVector256(), + Unsafe.As>(ref this.V6L), + 1); + + Vector256 r3 = Avx.InsertVector128( + Unsafe.As>(ref this.V3L).ToVector256(), + Unsafe.As>(ref this.V7L), + 1); + + Vector256 r4 = Avx.InsertVector128( + Unsafe.As>(ref this.V0R).ToVector256(), + Unsafe.As>(ref this.V4R), + 1); + + Vector256 r5 = Avx.InsertVector128( + Unsafe.As>(ref this.V1R).ToVector256(), + Unsafe.As>(ref this.V5R), + 1); + + Vector256 r6 = Avx.InsertVector128( + Unsafe.As>(ref this.V2R).ToVector256(), + Unsafe.As>(ref this.V6R), + 1); + + Vector256 r7 = Avx.InsertVector128( + Unsafe.As>(ref this.V3R).ToVector256(), + Unsafe.As>(ref this.V7R), + 1); + + Vector256 t0 = Avx.UnpackLow(r0, r1); + Vector256 t2 = Avx.UnpackLow(r2, r3); + Vector256 v = Avx.Shuffle(t0, t2, 0x4E); + Unsafe.As>(ref d.V0L) = Avx.Blend(t0, v, 0xCC); + Unsafe.As>(ref d.V1L) = Avx.Blend(t2, v, 0x33); + + Vector256 t4 = Avx.UnpackLow(r4, r5); + Vector256 t6 = Avx.UnpackLow(r6, r7); + v = Avx.Shuffle(t4, t6, 0x4E); + Unsafe.As>(ref d.V4L) = Avx.Blend(t4, v, 0xCC); + Unsafe.As>(ref d.V5L) = Avx.Blend(t6, v, 0x33); + + Vector256 t1 = Avx.UnpackHigh(r0, r1); + Vector256 t3 = Avx.UnpackHigh(r2, r3); + v = Avx.Shuffle(t1, t3, 0x4E); + Unsafe.As>(ref d.V2L) = Avx.Blend(t1, v, 0xCC); + Unsafe.As>(ref d.V3L) = Avx.Blend(t3, v, 0x33); + + Vector256 t5 = Avx.UnpackHigh(r4, r5); + Vector256 t7 = Avx.UnpackHigh(r6, r7); + v = Avx.Shuffle(t5, t7, 0x4E); + Unsafe.As>(ref d.V6L) = Avx.Blend(t5, v, 0xCC); + Unsafe.As>(ref d.V7L) = Avx.Blend(t7, v, 0x33); + } + else +#endif + { + d.V0L.X = this.V0L.X; + d.V1L.X = this.V0L.Y; + d.V2L.X = this.V0L.Z; + d.V3L.X = this.V0L.W; + d.V4L.X = this.V0R.X; + d.V5L.X = this.V0R.Y; + d.V6L.X = this.V0R.Z; + d.V7L.X = this.V0R.W; + + d.V0L.Y = this.V1L.X; + d.V1L.Y = this.V1L.Y; + d.V2L.Y = this.V1L.Z; + d.V3L.Y = this.V1L.W; + d.V4L.Y = this.V1R.X; + d.V5L.Y = this.V1R.Y; + d.V6L.Y = this.V1R.Z; + d.V7L.Y = this.V1R.W; + + d.V0L.Z = this.V2L.X; + d.V1L.Z = this.V2L.Y; + d.V2L.Z = this.V2L.Z; + d.V3L.Z = this.V2L.W; + d.V4L.Z = this.V2R.X; + d.V5L.Z = this.V2R.Y; + d.V6L.Z = this.V2R.Z; + d.V7L.Z = this.V2R.W; + + d.V0L.W = this.V3L.X; + d.V1L.W = this.V3L.Y; + d.V2L.W = this.V3L.Z; + d.V3L.W = this.V3L.W; + d.V4L.W = this.V3R.X; + d.V5L.W = this.V3R.Y; + d.V6L.W = this.V3R.Z; + d.V7L.W = this.V3R.W; + + d.V0R.X = this.V4L.X; + d.V1R.X = this.V4L.Y; + d.V2R.X = this.V4L.Z; + d.V3R.X = this.V4L.W; + d.V4R.X = this.V4R.X; + d.V5R.X = this.V4R.Y; + d.V6R.X = this.V4R.Z; + d.V7R.X = this.V4R.W; + + d.V0R.Y = this.V5L.X; + d.V1R.Y = this.V5L.Y; + d.V2R.Y = this.V5L.Z; + d.V3R.Y = this.V5L.W; + d.V4R.Y = this.V5R.X; + d.V5R.Y = this.V5R.Y; + d.V6R.Y = this.V5R.Z; + d.V7R.Y = this.V5R.W; + + d.V0R.Z = this.V6L.X; + d.V1R.Z = this.V6L.Y; + d.V2R.Z = this.V6L.Z; + d.V3R.Z = this.V6L.W; + d.V4R.Z = this.V6R.X; + d.V5R.Z = this.V6R.Y; + d.V6R.Z = this.V6R.Z; + d.V7R.Z = this.V6R.W; + + d.V0R.W = this.V7L.X; + d.V1R.W = this.V7L.Y; + d.V2R.W = this.V7L.Z; + d.V3R.W = this.V7L.W; + d.V4R.W = this.V7R.X; + d.V5R.W = this.V7R.Y; + d.V6R.W = this.V7R.Z; + d.V7R.W = this.V7R.W; + } + } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.Avx2JpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.Avx2JpegColorConverter.cs new file mode 100644 index 0000000000..90ebce3b87 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.Avx2JpegColorConverter.cs @@ -0,0 +1,18 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters +{ + internal abstract partial class JpegColorConverter + { + internal abstract class Avx2JpegColorConverter : VectorizedJpegColorConverter + { + protected Avx2JpegColorConverter(JpegColorSpace colorSpace, int precision) + : base(colorSpace, precision, 8) + { + } + + protected sealed override bool IsAvailable => SimdUtils.HasAvx2; + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.BasicJpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.BasicJpegColorConverter.cs new file mode 100644 index 0000000000..ed2e2cd762 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.BasicJpegColorConverter.cs @@ -0,0 +1,18 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters +{ + internal abstract partial class JpegColorConverter + { + internal abstract class BasicJpegColorConverter : JpegColorConverter + { + protected BasicJpegColorConverter(JpegColorSpace colorSpace, int precision) + : base(colorSpace, precision) + { + } + + protected override bool IsAvailable => true; + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs new file mode 100644 index 0000000000..f9334de73b --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs @@ -0,0 +1,81 @@ +// 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; +using static SixLabors.ImageSharp.SimdUtils; +#endif + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters +{ + internal abstract partial class JpegColorConverter + { + internal sealed class FromCmykAvx2 : Avx2JpegColorConverter + { + public FromCmykAvx2(int precision) + : base(JpegColorSpace.Cmyk, precision) + { + } + + protected override void ConvertCoreVectorized(in ComponentValues values, Span result) + { +#if SUPPORTS_RUNTIME_INTRINSICS + ref Vector256 cBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + ref Vector256 mBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); + ref Vector256 yBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); + ref Vector256 kBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3)); + + ref Vector256 resultBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(result)); + + // Used for the color conversion + var scale = Vector256.Create(1 / this.MaximumValue); + var one = Vector256.Create(1F); + + // Used for packing + ref byte control = ref MemoryMarshal.GetReference(HwIntrinsics.PermuteMaskEvenOdd8x32); + Vector256 vcontrol = Unsafe.As>(ref control); + + int n = result.Length / 8; + for (int i = 0; i < n; i++) + { + Vector256 k = Avx2.PermuteVar8x32(Unsafe.Add(ref kBase, i), vcontrol); + Vector256 c = Avx2.PermuteVar8x32(Unsafe.Add(ref cBase, i), vcontrol); + Vector256 m = Avx2.PermuteVar8x32(Unsafe.Add(ref mBase, i), vcontrol); + Vector256 y = Avx2.PermuteVar8x32(Unsafe.Add(ref yBase, i), vcontrol); + + k = Avx.Multiply(k, scale); + + c = Avx.Multiply(Avx.Multiply(c, k), scale); + m = Avx.Multiply(Avx.Multiply(m, k), scale); + y = Avx.Multiply(Avx.Multiply(y, k), scale); + + Vector256 cmLo = Avx.UnpackLow(c, m); + Vector256 yoLo = Avx.UnpackLow(y, one); + Vector256 cmHi = Avx.UnpackHigh(c, m); + Vector256 yoHi = Avx.UnpackHigh(y, one); + + ref Vector256 destination = ref Unsafe.Add(ref resultBase, i * 4); + + destination = Avx.Shuffle(cmLo, yoLo, 0b01_00_01_00); + Unsafe.Add(ref destination, 1) = Avx.Shuffle(cmLo, yoLo, 0b11_10_11_10); + Unsafe.Add(ref destination, 2) = Avx.Shuffle(cmHi, yoHi, 0b01_00_01_00); + Unsafe.Add(ref destination, 3) = Avx.Shuffle(cmHi, yoHi, 0b11_10_11_10); + } +#endif + } + + protected override void ConvertCore(in ComponentValues values, Span result) => + FromCmykBasic.ConvertCore(values, result, this.MaximumValue); + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmyk.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs similarity index 75% rename from src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmyk.cs rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs index 7b257b37da..6cbd52ec3d 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmyk.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs @@ -8,16 +8,20 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal abstract partial class JpegColorConverter { - internal sealed class FromCmyk : JpegColorConverter + internal sealed class FromCmykBasic : BasicJpegColorConverter { - public FromCmyk(int precision) + public FromCmykBasic(int precision) : base(JpegColorSpace.Cmyk, precision) { } public override void ConvertToRgba(in ComponentValues values, Span result) { - // TODO: We can optimize a lot here with Vector and SRCS.Unsafe()! + ConvertCore(values, result, this.MaximumValue); + } + + internal static void ConvertCore(in ComponentValues values, Span result, float maxValue) + { ReadOnlySpan cVals = values.Component0; ReadOnlySpan mVals = values.Component1; ReadOnlySpan yVals = values.Component2; @@ -25,7 +29,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters var v = new Vector4(0, 0, 0, 1F); - var maximum = 1 / this.MaximumValue; + var maximum = 1 / maxValue; var scale = new Vector4(maximum, maximum, maximum, 1F); for (int i = 0; i < result.Length; i++) @@ -33,7 +37,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters float c = cVals[i]; float m = mVals[i]; float y = yVals[i]; - float k = kVals[i] / this.MaximumValue; + float k = kVals[i] / maxValue; v.X = c * k; v.Y = m * k; @@ -47,4 +51,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters } } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs new file mode 100644 index 0000000000..e75634b0fa --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs @@ -0,0 +1,71 @@ +// 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; +using SixLabors.ImageSharp.Tuples; + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters +{ + internal abstract partial class JpegColorConverter + { + internal sealed class FromCmykVector8 : Vector8JpegColorConverter + { + public FromCmykVector8(int precision) + : base(JpegColorSpace.Cmyk, precision) + { + } + + protected override void ConvertCoreVectorized(in ComponentValues values, Span result) + { + ref Vector cBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + ref Vector mBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); + ref Vector yBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); + ref Vector kBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3)); + + ref Vector4Octet resultBase = + ref Unsafe.As(ref MemoryMarshal.GetReference(result)); + + Vector4Pair cc = default; + Vector4Pair mm = default; + Vector4Pair yy = default; + ref Vector ccRefAsVector = ref Unsafe.As>(ref cc); + ref Vector mmRefAsVector = ref Unsafe.As>(ref mm); + ref Vector yyRefAsVector = ref Unsafe.As>(ref yy); + + var scale = new Vector(1 / this.MaximumValue); + + // Walking 8 elements at one step: + int n = result.Length / 8; + for (int i = 0; i < n; i++) + { + Vector c = Unsafe.Add(ref cBase, i); + Vector m = Unsafe.Add(ref mBase, i); + Vector y = Unsafe.Add(ref yBase, i); + Vector k = Unsafe.Add(ref kBase, i) * scale; + + c = (c * k) * scale; + m = (m * k) * scale; + y = (y * k) * scale; + + ccRefAsVector = c; + mmRefAsVector = m; + yyRefAsVector = y; + + // Collect (c0,c1...c8) (m0,m1...m8) (y0,y1...y8) vector values in the expected (r0,g0,g1,1), (r1,g1,g2,1) ... order: + ref Vector4Octet destination = ref Unsafe.Add(ref resultBase, i); + destination.Pack(ref cc, ref mm, ref yy); + } + } + + protected override void ConvertCore(in ComponentValues values, Span result) => + FromCmykBasic.ConvertCore(values, result, this.MaximumValue); + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs new file mode 100644 index 0000000000..45846a6b56 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs @@ -0,0 +1,63 @@ +// 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; +using static SixLabors.ImageSharp.SimdUtils; +#endif + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters +{ + internal abstract partial class JpegColorConverter + { + internal sealed class FromGrayscaleAvx2 : Avx2JpegColorConverter + { + public FromGrayscaleAvx2(int precision) + : base(JpegColorSpace.Grayscale, precision) + { + } + + protected override void ConvertCoreVectorized(in ComponentValues values, Span result) + { +#if SUPPORTS_RUNTIME_INTRINSICS + ref Vector256 gBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + + ref Vector256 resultBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(result)); + + // Used for the color conversion + var scale = Vector256.Create(1 / this.MaximumValue); + var one = Vector256.Create(1F); + + // Used for packing + ref byte control = ref MemoryMarshal.GetReference(HwIntrinsics.PermuteMaskEvenOdd8x32); + Vector256 vcontrol = Unsafe.As>(ref control); + + int n = result.Length / 8; + for (int i = 0; i < n; i++) + { + Vector256 g = Avx.Multiply(Unsafe.Add(ref gBase, i), scale); + + g = Avx2.PermuteVar8x32(g, vcontrol); + + ref Vector256 destination = ref Unsafe.Add(ref resultBase, i * 4); + + destination = Avx.Blend(Avx.Permute(g, 0b00_00_00_00), one, 0b1000_1000); + Unsafe.Add(ref destination, 1) = Avx.Blend(Avx.Shuffle(g, g, 0b01_01_01_01), one, 0b1000_1000); + Unsafe.Add(ref destination, 2) = Avx.Blend(Avx.Shuffle(g, g, 0b10_10_10_10), one, 0b1000_1000); + Unsafe.Add(ref destination, 3) = Avx.Blend(Avx.Shuffle(g, g, 0b11_11_11_11), one, 0b1000_1000); + } +#endif + } + + protected override void ConvertCore(in ComponentValues values, Span result) => + FromGrayscaleBasic.ConvertCore(values, result, this.MaximumValue); + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScale.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs similarity index 74% rename from src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScale.cs rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs index cf0bc2c920..0b7a220d94 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScale.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs @@ -10,16 +10,21 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal abstract partial class JpegColorConverter { - internal sealed class FromGrayscale : JpegColorConverter + internal sealed class FromGrayscaleBasic : BasicJpegColorConverter { - public FromGrayscale(int precision) + public FromGrayscaleBasic(int precision) : base(JpegColorSpace.Grayscale, precision) { } public override void ConvertToRgba(in ComponentValues values, Span result) { - var maximum = 1 / this.MaximumValue; + ConvertCore(values, result, this.MaximumValue); + } + + internal static void ConvertCore(in ComponentValues values, Span result, float maxValue) + { + var maximum = 1 / maxValue; var scale = new Vector4(maximum, maximum, maximum, 1F); ref float sBase = ref MemoryMarshal.GetReference(values.Component0); @@ -35,4 +40,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters } } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs new file mode 100644 index 0000000000..8f04c91528 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs @@ -0,0 +1,72 @@ +// 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; +using static SixLabors.ImageSharp.SimdUtils; +#endif + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters +{ + internal abstract partial class JpegColorConverter + { + internal sealed class FromRgbAvx2 : Avx2JpegColorConverter + { + public FromRgbAvx2(int precision) + : base(JpegColorSpace.RGB, precision) + { + } + + protected override void ConvertCoreVectorized(in ComponentValues values, Span result) + { +#if SUPPORTS_RUNTIME_INTRINSICS + ref Vector256 rBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + ref Vector256 gBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); + ref Vector256 bBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); + + ref Vector256 resultBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(result)); + + // Used for the color conversion + var scale = Vector256.Create(1 / this.MaximumValue); + var one = Vector256.Create(1F); + + // Used for packing + ref byte control = ref MemoryMarshal.GetReference(HwIntrinsics.PermuteMaskEvenOdd8x32); + Vector256 vcontrol = Unsafe.As>(ref control); + + int n = result.Length / 8; + for (int i = 0; i < n; i++) + { + Vector256 r = Avx.Multiply(Avx2.PermuteVar8x32(Unsafe.Add(ref rBase, i), vcontrol), scale); + Vector256 g = Avx.Multiply(Avx2.PermuteVar8x32(Unsafe.Add(ref gBase, i), vcontrol), scale); + Vector256 b = Avx.Multiply(Avx2.PermuteVar8x32(Unsafe.Add(ref bBase, i), vcontrol), scale); + + Vector256 rgLo = Avx.UnpackLow(r, g); + Vector256 boLo = Avx.UnpackLow(b, one); + Vector256 rgHi = Avx.UnpackHigh(r, g); + Vector256 boHi = Avx.UnpackHigh(b, one); + + ref Vector256 destination = ref Unsafe.Add(ref resultBase, i * 4); + + destination = Avx.Shuffle(rgLo, boLo, 0b01_00_01_00); + Unsafe.Add(ref destination, 1) = Avx.Shuffle(rgLo, boLo, 0b11_10_11_10); + Unsafe.Add(ref destination, 2) = Avx.Shuffle(rgHi, boHi, 0b01_00_01_00); + Unsafe.Add(ref destination, 3) = Avx.Shuffle(rgHi, boHi, 0b11_10_11_10); + } +#endif + } + + protected override void ConvertCore(in ComponentValues values, Span result) => + FromRgbBasic.ConvertCore(values, result, this.MaximumValue); + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgb.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs similarity index 76% rename from src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgb.cs rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs index 25889a6dfc..ddca3fe2f6 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgb.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs @@ -8,23 +8,27 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal abstract partial class JpegColorConverter { - internal sealed class FromRgb : JpegColorConverter + internal sealed class FromRgbBasic : BasicJpegColorConverter { - public FromRgb(int precision) + public FromRgbBasic(int precision) : base(JpegColorSpace.RGB, precision) { } public override void ConvertToRgba(in ComponentValues values, Span result) { - // TODO: We can optimize a lot here with Vector and SRCS.Unsafe()! + ConvertCore(values, result, this.MaximumValue); + } + + internal static void ConvertCore(in ComponentValues values, Span result, float maxValue) + { ReadOnlySpan rVals = values.Component0; ReadOnlySpan gVals = values.Component1; ReadOnlySpan bVals = values.Component2; var v = new Vector4(0, 0, 0, 1); - var maximum = 1 / this.MaximumValue; + var maximum = 1 / maxValue; var scale = new Vector4(maximum, maximum, maximum, 1F); for (int i = 0; i < result.Length; i++) @@ -44,4 +48,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters } } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs new file mode 100644 index 0000000000..763064d1e0 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs @@ -0,0 +1,67 @@ +// 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; +using SixLabors.ImageSharp.Tuples; + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters +{ + internal abstract partial class JpegColorConverter + { + internal sealed class FromRgbVector8 : Vector8JpegColorConverter + { + public FromRgbVector8(int precision) + : base(JpegColorSpace.RGB, precision) + { + } + + protected override void ConvertCoreVectorized(in ComponentValues values, Span result) + { + ref Vector rBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + ref Vector gBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); + ref Vector bBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); + + ref Vector4Octet resultBase = + ref Unsafe.As(ref MemoryMarshal.GetReference(result)); + + Vector4Pair rr = default; + Vector4Pair gg = default; + Vector4Pair bb = default; + ref Vector rrRefAsVector = ref Unsafe.As>(ref rr); + ref Vector ggRefAsVector = ref Unsafe.As>(ref gg); + ref Vector bbRefAsVector = ref Unsafe.As>(ref bb); + + var scale = new Vector(1 / this.MaximumValue); + + // Walking 8 elements at one step: + int n = result.Length / 8; + for (int i = 0; i < n; i++) + { + Vector r = Unsafe.Add(ref rBase, i); + Vector g = Unsafe.Add(ref gBase, i); + Vector b = Unsafe.Add(ref bBase, i); + r *= scale; + g *= scale; + b *= scale; + + rrRefAsVector = r; + ggRefAsVector = g; + bbRefAsVector = b; + + // Collect (r0,r1...r8) (g0,g1...g8) (b0,b1...b8) vector values in the expected (r0,g0,g1,1), (r1,g1,g2,1) ... order: + ref Vector4Octet destination = ref Unsafe.Add(ref resultBase, i); + destination.Pack(ref rr, ref gg, ref bb); + } + } + + protected override void ConvertCore(in ComponentValues values, Span result) => + FromRgbBasic.ConvertCore(values, result, this.MaximumValue); + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs new file mode 100644 index 0000000000..f3a0636200 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs @@ -0,0 +1,101 @@ +// 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; +using static SixLabors.ImageSharp.SimdUtils; +#endif + +// ReSharper disable ImpureMethodCallOnReadonlyValueField +namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters +{ + internal abstract partial class JpegColorConverter + { + internal sealed class FromYCbCrAvx2 : Avx2JpegColorConverter + { + public FromYCbCrAvx2(int precision) + : base(JpegColorSpace.YCbCr, precision) + { + } + + protected override void ConvertCoreVectorized(in ComponentValues values, Span result) + { + #if SUPPORTS_RUNTIME_INTRINSICS + ref Vector256 yBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + ref Vector256 cbBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); + ref Vector256 crBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); + + ref Vector256 resultBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(result)); + + // Used for the color conversion + var chromaOffset = Vector256.Create(-this.HalfValue); + var scale = Vector256.Create(1 / this.MaximumValue); + var rCrMult = Vector256.Create(1.402F); + var gCbMult = Vector256.Create(-0.344136F); + var gCrMult = Vector256.Create(-0.714136F); + var bCbMult = Vector256.Create(1.772F); + + // Used for packing. + var va = Vector256.Create(1F); + ref byte control = ref MemoryMarshal.GetReference(HwIntrinsics.PermuteMaskEvenOdd8x32); + Vector256 vcontrol = Unsafe.As>(ref control); + + // Walking 8 elements at one step: + int n = result.Length / 8; + for (int i = 0; i < n; i++) + { + // y = yVals[i]; + // cb = cbVals[i] - 128F; + // cr = crVals[i] - 128F; + Vector256 y = Unsafe.Add(ref yBase, i); + Vector256 cb = Avx.Add(Unsafe.Add(ref cbBase, i), chromaOffset); + Vector256 cr = Avx.Add(Unsafe.Add(ref crBase, i), chromaOffset); + + y = Avx2.PermuteVar8x32(y, vcontrol); + cb = Avx2.PermuteVar8x32(cb, vcontrol); + cr = Avx2.PermuteVar8x32(cr, vcontrol); + + // r = y + (1.402F * cr); + // g = y - (0.344136F * cb) - (0.714136F * cr); + // b = y + (1.772F * cb); + // Adding & multiplying 8 elements at one time: + Vector256 r = HwIntrinsics.MultiplyAdd(y, cr, rCrMult); + Vector256 g = HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(y, cb, gCbMult), cr, gCrMult); + Vector256 b = HwIntrinsics.MultiplyAdd(y, cb, bCbMult); + + // TODO: We should be saving to RGBA not Vector4 + r = Avx.Multiply(Avx.RoundToNearestInteger(r), scale); + g = Avx.Multiply(Avx.RoundToNearestInteger(g), scale); + b = Avx.Multiply(Avx.RoundToNearestInteger(b), scale); + + Vector256 vte = Avx.UnpackLow(r, b); + Vector256 vto = Avx.UnpackLow(g, va); + + ref Vector256 destination = ref Unsafe.Add(ref resultBase, i * 4); + + destination = Avx.UnpackLow(vte, vto); + Unsafe.Add(ref destination, 1) = Avx.UnpackHigh(vte, vto); + + vte = Avx.UnpackHigh(r, b); + vto = Avx.UnpackHigh(g, va); + + Unsafe.Add(ref destination, 2) = Avx.UnpackLow(vte, vto); + Unsafe.Add(ref destination, 3) = Avx.UnpackHigh(vte, vto); + } +#endif + } + + protected override void ConvertCore(in ComponentValues values, Span result) => + FromYCbCrBasic.ConvertCore(values, result, this.MaximumValue, this.HalfValue); + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs index 31fc054619..352e4acb7e 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs @@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal abstract partial class JpegColorConverter { - internal sealed class FromYCbCrBasic : JpegColorConverter + internal sealed class FromYCbCrBasic : BasicJpegColorConverter { public FromYCbCrBasic(int precision) : base(JpegColorSpace.YCbCr, precision) @@ -48,4 +48,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters } } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs similarity index 56% rename from src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs index 541a03615e..42f8eef5a1 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs @@ -5,37 +5,24 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - using SixLabors.ImageSharp.Tuples; namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal abstract partial class JpegColorConverter { - internal sealed class FromYCbCrSimd : JpegColorConverter + internal sealed class FromYCbCrVector4 : VectorizedJpegColorConverter { - public FromYCbCrSimd(int precision) - : base(JpegColorSpace.YCbCr, precision) + public FromYCbCrVector4(int precision) + : base(JpegColorSpace.YCbCr, precision, 8) { } - public override void ConvertToRgba(in ComponentValues values, Span result) - { - int remainder = result.Length % 8; - int simdCount = result.Length - remainder; - if (simdCount > 0) - { - ConvertCore(values.Slice(0, simdCount), result.Slice(0, simdCount), this.MaximumValue, this.HalfValue); - } + protected override bool IsAvailable => SimdUtils.HasVector4; - FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder), this.MaximumValue, this.HalfValue); - } - - /// - /// SIMD convert using buffers of sizes divisible by 8. - /// - internal static void ConvertCore(in ComponentValues values, Span result, float maxValue, float halfValue) + protected override void ConvertCoreVectorized(in ComponentValues values, Span result) { + // TODO: Find a way to properly run & test this path on AVX2 PC-s! (Have I already mentioned that Vector is terrible?) DebugGuard.IsTrue(result.Length % 8 == 0, nameof(result), "result.Length should be divisible by 8!"); ref Vector4Pair yBase = @@ -48,7 +35,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters ref Vector4Octet resultBase = ref Unsafe.As(ref MemoryMarshal.GetReference(result)); - var chromaOffset = new Vector4(-halfValue); + var chromaOffset = new Vector4(-this.HalfValue); + var maxValue = this.MaximumValue; // Walking 8 elements at one step: int n = result.Length / 8; @@ -87,31 +75,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters tmp.MultiplyInplace(1.772F); b.AddInplace(ref tmp); - if (Vector.Count == 4) - { - // TODO: Find a way to properly run & test this path on AVX2 PC-s! (Have I already mentioned that Vector is terrible?) - r.RoundAndDownscalePreVector8(maxValue); - g.RoundAndDownscalePreVector8(maxValue); - b.RoundAndDownscalePreVector8(maxValue); - } - else if (SimdUtils.HasVector8) - { - r.RoundAndDownscaleVector8(maxValue); - g.RoundAndDownscaleVector8(maxValue); - b.RoundAndDownscaleVector8(maxValue); - } - else - { - // TODO: Run fallback scalar code here - // However, no issues expected before someone implements this: https://github.com/dotnet/coreclr/issues/12007 - JpegThrowHelper.ThrowNotImplementedException("Your CPU architecture is too modern!"); - } + r.RoundAndDownscalePreVector8(maxValue); + g.RoundAndDownscalePreVector8(maxValue); + b.RoundAndDownscalePreVector8(maxValue); // Collect (r0,r1...r8) (g0,g1...g8) (b0,b1...b8) vector values in the expected (r0,g0,g1,1), (r1,g1,g2,1) ... order: ref Vector4Octet destination = ref Unsafe.Add(ref resultBase, i); destination.Pack(ref r, ref g, ref b); } } + + protected override void ConvertCore(in ComponentValues values, Span result) => + FromYCbCrBasic.ConvertCore(values, result, this.MaximumValue, this.HalfValue); } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs similarity index 66% rename from src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs index c4d1408a2e..abacf7161b 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs @@ -1,11 +1,10 @@ -// Copyright (c) Six Labors. +// 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; - using SixLabors.ImageSharp.Tuples; // ReSharper disable ImpureMethodCallOnReadonlyValueField @@ -13,40 +12,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal abstract partial class JpegColorConverter { - internal sealed class FromYCbCrSimdVector8 : JpegColorConverter + internal sealed class FromYCbCrVector8 : Vector8JpegColorConverter { - public FromYCbCrSimdVector8(int precision) + public FromYCbCrVector8(int precision) : base(JpegColorSpace.YCbCr, precision) { } - public static bool IsAvailable => Vector.IsHardwareAccelerated && SimdUtils.HasVector8; - - public override void ConvertToRgba(in ComponentValues values, Span result) - { - int remainder = result.Length % 8; - int simdCount = result.Length - remainder; - if (simdCount > 0) - { - ConvertCore(values.Slice(0, simdCount), result.Slice(0, simdCount), this.MaximumValue, this.HalfValue); - } - - FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder), this.MaximumValue, this.HalfValue); - } - - /// - /// SIMD convert using buffers of sizes divisible by 8. - /// - internal static void ConvertCore(in ComponentValues values, Span result, float maxValue, float halfValue) + protected override void ConvertCoreVectorized(in ComponentValues values, Span result) { - // This implementation is actually AVX specific. - // An AVX register is capable of storing 8 float-s. - if (!IsAvailable) - { - throw new InvalidOperationException( - "JpegColorConverter.FromYCbCrSimd256 can be used only on architecture having 256 byte floating point SIMD registers!"); - } - ref Vector yBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); ref Vector cbBase = @@ -57,7 +31,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters ref Vector4Octet resultBase = ref Unsafe.As(ref MemoryMarshal.GetReference(result)); - var chromaOffset = new Vector(-halfValue); + var chromaOffset = new Vector(-this.HalfValue); // Walking 8 elements at one step: int n = result.Length / 8; @@ -70,7 +44,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters ref Vector ggRefAsVector = ref Unsafe.As>(ref gg); ref Vector bbRefAsVector = ref Unsafe.As>(ref bb); - var scale = new Vector(1 / maxValue); + var scale = new Vector(1 / this.MaximumValue); for (int i = 0; i < n; i++) { @@ -105,6 +79,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters destination.Pack(ref rr, ref gg, ref bb); } } + + protected override void ConvertCore(in ComponentValues values, Span result) => + FromYCbCrBasic.ConvertCore(values, result, this.MaximumValue, this.HalfValue); } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs new file mode 100644 index 0000000000..ea0132e1e9 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs @@ -0,0 +1,110 @@ +// 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; +using static SixLabors.ImageSharp.SimdUtils; +#endif + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters +{ + internal abstract partial class JpegColorConverter + { + internal sealed class FromYccKAvx2 : Avx2JpegColorConverter + { + public FromYccKAvx2(int precision) + : base(JpegColorSpace.Ycck, precision) + { + } + + protected override void ConvertCoreVectorized(in ComponentValues values, Span result) + { +#if SUPPORTS_RUNTIME_INTRINSICS + ref Vector256 yBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + ref Vector256 cbBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); + ref Vector256 crBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); + ref Vector256 kBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3)); + + ref Vector256 resultBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(result)); + + // Used for the color conversion + var chromaOffset = Vector256.Create(-this.HalfValue); + var scale = Vector256.Create(1 / this.MaximumValue); + var max = Vector256.Create(this.MaximumValue); + var rCrMult = Vector256.Create(1.402F); + var gCbMult = Vector256.Create(-0.344136F); + var gCrMult = Vector256.Create(-0.714136F); + var bCbMult = Vector256.Create(1.772F); + + // Used for packing. + var va = Vector256.Create(1F); + ref byte control = ref MemoryMarshal.GetReference(HwIntrinsics.PermuteMaskEvenOdd8x32); + Vector256 vcontrol = Unsafe.As>(ref control); + + // Walking 8 elements at one step: + int n = result.Length / 8; + for (int i = 0; i < n; i++) + { + // y = yVals[i]; + // cb = cbVals[i] - 128F; + // cr = crVals[i] - 128F; + // k = kVals[i] / 256F; + Vector256 y = Unsafe.Add(ref yBase, i); + Vector256 cb = Avx.Add(Unsafe.Add(ref cbBase, i), chromaOffset); + Vector256 cr = Avx.Add(Unsafe.Add(ref crBase, i), chromaOffset); + Vector256 k = Avx.Divide(Unsafe.Add(ref kBase, i), max); + + y = Avx2.PermuteVar8x32(y, vcontrol); + cb = Avx2.PermuteVar8x32(cb, vcontrol); + cr = Avx2.PermuteVar8x32(cr, vcontrol); + k = Avx2.PermuteVar8x32(k, vcontrol); + + // r = y + (1.402F * cr); + // g = y - (0.344136F * cb) - (0.714136F * cr); + // b = y + (1.772F * cb); + // Adding & multiplying 8 elements at one time: + Vector256 r = HwIntrinsics.MultiplyAdd(y, cr, rCrMult); + Vector256 g = + HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(y, cb, gCbMult), cr, gCrMult); + Vector256 b = HwIntrinsics.MultiplyAdd(y, cb, bCbMult); + + r = Avx.Subtract(max, Avx.RoundToNearestInteger(r)); + g = Avx.Subtract(max, Avx.RoundToNearestInteger(g)); + b = Avx.Subtract(max, Avx.RoundToNearestInteger(b)); + + r = Avx.Multiply(Avx.Multiply(r, k), scale); + g = Avx.Multiply(Avx.Multiply(g, k), scale); + b = Avx.Multiply(Avx.Multiply(b, k), scale); + + Vector256 vte = Avx.UnpackLow(r, b); + Vector256 vto = Avx.UnpackLow(g, va); + + ref Vector256 destination = ref Unsafe.Add(ref resultBase, i * 4); + + destination = Avx.UnpackLow(vte, vto); + Unsafe.Add(ref destination, 1) = Avx.UnpackHigh(vte, vto); + + vte = Avx.UnpackHigh(r, b); + vto = Avx.UnpackHigh(g, va); + + Unsafe.Add(ref destination, 2) = Avx.UnpackLow(vte, vto); + Unsafe.Add(ref destination, 3) = Avx.UnpackHigh(vte, vto); + } +#endif + } + + protected override void ConvertCore(in ComponentValues values, Span result) => + FromYccKBasic.ConvertCore(values, result, this.MaximumValue, this.HalfValue); + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccK.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs similarity index 57% rename from src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccK.cs rename to src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs index 1137cdc0ec..778e5325ff 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccK.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs @@ -8,14 +8,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { internal abstract partial class JpegColorConverter { - internal sealed class FromYccK : JpegColorConverter + internal sealed class FromYccKBasic : BasicJpegColorConverter { - public FromYccK(int precision) + public FromYccKBasic(int precision) : base(JpegColorSpace.Ycck, precision) { } public override void ConvertToRgba(in ComponentValues values, Span result) + { + ConvertCore(values, result, this.MaximumValue, this.HalfValue); + } + + internal static void ConvertCore(in ComponentValues values, Span result, float maxValue, float halfValue) { // TODO: We can optimize a lot here with Vector and SRCS.Unsafe()! ReadOnlySpan yVals = values.Component0; @@ -25,19 +30,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters var v = new Vector4(0, 0, 0, 1F); - var maximum = 1 / this.MaximumValue; + var maximum = 1 / maxValue; var scale = new Vector4(maximum, maximum, maximum, 1F); for (int i = 0; i < result.Length; i++) { float y = yVals[i]; - float cb = cbVals[i] - this.HalfValue; - float cr = crVals[i] - this.HalfValue; - float k = kVals[i] / this.MaximumValue; + float cb = cbVals[i] - halfValue; + float cr = crVals[i] - halfValue; + float k = kVals[i] / maxValue; - v.X = (this.MaximumValue - MathF.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * k; - v.Y = (this.MaximumValue - MathF.Round(y - (0.344136F * cb) - (0.714136F * cr), MidpointRounding.AwayFromZero)) * k; - v.Z = (this.MaximumValue - MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * k; + v.X = (maxValue - MathF.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * k; + v.Y = (maxValue - MathF.Round(y - (0.344136F * cb) - (0.714136F * cr), MidpointRounding.AwayFromZero)) * k; + v.Z = (maxValue - MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * k; v.W = 1F; v *= scale; @@ -47,4 +52,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters } } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs new file mode 100644 index 0000000000..c360392de8 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs @@ -0,0 +1,91 @@ +// 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; +using SixLabors.ImageSharp.Tuples; + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters +{ + internal abstract partial class JpegColorConverter + { + internal sealed class FromYccKVector8 : Vector8JpegColorConverter + { + public FromYccKVector8(int precision) + : base(JpegColorSpace.Ycck, precision) + { + } + + protected override void ConvertCoreVectorized(in ComponentValues values, Span result) + { + ref Vector yBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + ref Vector cbBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); + ref Vector crBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); + ref Vector kBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3)); + + ref Vector4Octet resultBase = + ref Unsafe.As(ref MemoryMarshal.GetReference(result)); + + var chromaOffset = new Vector(-this.HalfValue); + + // Walking 8 elements at one step: + int n = result.Length / 8; + + Vector4Pair rr = default; + Vector4Pair gg = default; + Vector4Pair bb = default; + + ref Vector rrRefAsVector = ref Unsafe.As>(ref rr); + ref Vector ggRefAsVector = ref Unsafe.As>(ref gg); + ref Vector bbRefAsVector = ref Unsafe.As>(ref bb); + + var scale = new Vector(1 / this.MaximumValue); + var max = new Vector(this.MaximumValue); + + for (int i = 0; i < n; i++) + { + // y = yVals[i]; + // cb = cbVals[i] - 128F; + // cr = crVals[i] - 128F; + // k = kVals[i] / 256F; + Vector y = Unsafe.Add(ref yBase, i); + Vector cb = Unsafe.Add(ref cbBase, i) + chromaOffset; + Vector cr = Unsafe.Add(ref crBase, i) + chromaOffset; + Vector k = Unsafe.Add(ref kBase, i) / max; + + // r = y + (1.402F * cr); + // g = y - (0.344136F * cb) - (0.714136F * cr); + // b = y + (1.772F * cb); + // Adding & multiplying 8 elements at one time: + Vector r = y + (cr * new Vector(1.402F)); + Vector g = y - (cb * new Vector(0.344136F)) - (cr * new Vector(0.714136F)); + Vector b = y + (cb * new Vector(1.772F)); + + r = (max - r.FastRound()) * k; + g = (max - g.FastRound()) * k; + b = (max - b.FastRound()) * k; + r *= scale; + g *= scale; + b *= scale; + + rrRefAsVector = r; + ggRefAsVector = g; + bbRefAsVector = b; + + // Collect (r0,r1...r8) (g0,g1...g8) (b0,b1...b8) vector values in the expected (r0,g0,g1,1), (r1,g1,g2,1) ... order: + ref Vector4Octet destination = ref Unsafe.Add(ref resultBase, i); + destination.Pack(ref rr, ref gg, ref bb); + } + } + + protected override void ConvertCore(in ComponentValues values, Span result) => + FromYccKBasic.ConvertCore(values, result, this.MaximumValue, this.HalfValue); + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.Vector8JpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.Vector8JpegColorConverter.cs new file mode 100644 index 0000000000..3e9b889db7 --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.Vector8JpegColorConverter.cs @@ -0,0 +1,18 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters +{ + internal abstract partial class JpegColorConverter + { + internal abstract class Vector8JpegColorConverter : VectorizedJpegColorConverter + { + protected Vector8JpegColorConverter(JpegColorSpace colorSpace, int precision) + : base(colorSpace, precision, 8) + { + } + + protected sealed override bool IsAvailable => SimdUtils.HasVector8; + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.VectorizedJpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.VectorizedJpegColorConverter.cs new file mode 100644 index 0000000000..522be82c2d --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.VectorizedJpegColorConverter.cs @@ -0,0 +1,46 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters +{ + internal abstract partial class JpegColorConverter + { + internal abstract class VectorizedJpegColorConverter : JpegColorConverter + { + private readonly int vectorSize; + + protected VectorizedJpegColorConverter(JpegColorSpace colorSpace, int precision, int vectorSize) + : base(colorSpace, precision) + { + this.vectorSize = vectorSize; + } + + public sealed override void ConvertToRgba(in ComponentValues values, Span result) + { + int remainder = result.Length % this.vectorSize; + int simdCount = result.Length - remainder; + if (simdCount > 0) + { + // This implementation is actually AVX specific. + // An AVX register is capable of storing 8 float-s. + if (!this.IsAvailable) + { + throw new InvalidOperationException( + "This converter can be used only on architecture having 256 byte floating point SIMD registers!"); + } + + this.ConvertCoreVectorized(values.Slice(0, simdCount), result.Slice(0, simdCount)); + } + + this.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder)); + } + + protected abstract void ConvertCoreVectorized(in ComponentValues values, Span result); + + protected abstract void ConvertCore(in ComponentValues values, Span result); + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs index f68bca0412..2d24f01dd8 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs @@ -3,8 +3,8 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Numerics; - using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Tuples; @@ -18,22 +18,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters /// /// The available converters /// - private static readonly JpegColorConverter[] Converters = - { - // 8-bit converters - GetYCbCrConverter(8), - new FromYccK(8), - new FromCmyk(8), - new FromGrayscale(8), - new FromRgb(8), - - // 12-bit converters - GetYCbCrConverter(12), - new FromYccK(12), - new FromCmyk(12), - new FromGrayscale(12), - new FromRgb(12), - }; + private static readonly JpegColorConverter[] Converters = CreateConverters(); /// /// Initializes a new instance of the class. @@ -46,6 +31,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters this.HalfValue = MathF.Ceiling(this.MaximumValue / 2); } + /// + /// Gets a value indicating whether this is available + /// on the current runtime and CPU architecture. + /// + protected abstract bool IsAvailable { get; } + /// /// Gets the of this converter. /// @@ -71,8 +62,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters /// public static JpegColorConverter GetConverter(JpegColorSpace colorSpace, int precision) { - JpegColorConverter converter = Array.Find(Converters, c => c.ColorSpace == colorSpace - && c.Precision == precision); + JpegColorConverter converter = Array.Find( + Converters, + c => c.ColorSpace == colorSpace + && c.Precision == precision); if (converter is null) { @@ -90,10 +83,88 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters public abstract void ConvertToRgba(in ComponentValues values, Span result); /// - /// Returns the for the YCbCr colorspace that matches the current CPU architecture. + /// Returns the s for all supported colorspaces and precisions. + /// + private static JpegColorConverter[] CreateConverters() + { + var converters = new List(); + + // 8-bit converters + converters.AddRange(GetYCbCrConverters(8)); + converters.AddRange(GetYccKConverters(8)); + converters.AddRange(GetCmykConverters(8)); + converters.AddRange(GetGrayScaleConverters(8)); + converters.AddRange(GetRgbConverters(8)); + + // 12-bit converters + converters.AddRange(GetYCbCrConverters(12)); + converters.AddRange(GetYccKConverters(12)); + converters.AddRange(GetCmykConverters(12)); + converters.AddRange(GetGrayScaleConverters(12)); + converters.AddRange(GetRgbConverters(12)); + + return converters.Where(x => x.IsAvailable).ToArray(); + } + + /// + /// Returns the s for the YCbCr colorspace. + /// + private static IEnumerable GetYCbCrConverters(int precision) + { +#if SUPPORTS_RUNTIME_INTRINSICS + yield return new FromYCbCrAvx2(precision); +#endif + yield return new FromYCbCrVector8(precision); + yield return new FromYCbCrVector4(precision); + yield return new FromYCbCrBasic(precision); + } + + /// + /// Returns the s for the YccK colorspace. + /// + private static IEnumerable GetYccKConverters(int precision) + { +#if SUPPORTS_RUNTIME_INTRINSICS + yield return new FromYccKAvx2(precision); +#endif + yield return new FromYccKVector8(precision); + yield return new FromYccKBasic(precision); + } + + /// + /// Returns the s for the CMYK colorspace. + /// + private static IEnumerable GetCmykConverters(int precision) + { +#if SUPPORTS_RUNTIME_INTRINSICS + yield return new FromCmykAvx2(precision); +#endif + yield return new FromCmykVector8(precision); + yield return new FromCmykBasic(precision); + } + + /// + /// Returns the s for the gray scale colorspace. + /// + private static IEnumerable GetGrayScaleConverters(int precision) + { +#if SUPPORTS_RUNTIME_INTRINSICS + yield return new FromGrayscaleAvx2(precision); +#endif + yield return new FromGrayscaleBasic(precision); + } + + /// + /// Returns the s for the RGB colorspace. /// - private static JpegColorConverter GetYCbCrConverter(int precision) => - FromYCbCrSimdVector8.IsAvailable ? (JpegColorConverter)new FromYCbCrSimdVector8(precision) : new FromYCbCrSimd(precision); + private static IEnumerable GetRgbConverters(int precision) + { +#if SUPPORTS_RUNTIME_INTRINSICS + yield return new FromRgbAvx2(precision); +#endif + yield return new FromRgbVector8(precision); + yield return new FromRgbBasic(precision); + } /// /// A stack-only struct to reference the input buffers using -s. @@ -230,6 +301,52 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters this.V7.Z = b.B.W; this.V7.W = 1f; } + + /// + /// Pack (g0,g1...g7) vector values as (g0,g0,g0,1), (g1,g1,g1,1) ... + /// + public void Pack(ref Vector4Pair g) + { + this.V0.X = g.A.X; + this.V0.Y = g.A.X; + this.V0.Z = g.A.X; + this.V0.W = 1f; + + this.V1.X = g.A.Y; + this.V1.Y = g.A.Y; + this.V1.Z = g.A.Y; + this.V1.W = 1f; + + this.V2.X = g.A.Z; + this.V2.Y = g.A.Z; + this.V2.Z = g.A.Z; + this.V2.W = 1f; + + this.V3.X = g.A.W; + this.V3.Y = g.A.W; + this.V3.Z = g.A.W; + this.V3.W = 1f; + + this.V4.X = g.B.X; + this.V4.Y = g.B.X; + this.V4.Z = g.B.X; + this.V4.W = 1f; + + this.V5.X = g.B.Y; + this.V5.Y = g.B.Y; + this.V5.Z = g.B.Y; + this.V5.W = 1f; + + this.V6.X = g.B.Z; + this.V6.Y = g.B.Z; + this.V6.Z = g.B.Z; + this.V6.W = 1f; + + this.V7.X = g.B.W; + this.V7.Y = g.B.W; + this.V7.Z = g.B.W; + this.V7.W = 1f; + } } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs index 40683e25a9..e0311dafef 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs @@ -81,14 +81,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder b.LoadFrom(ref sourceBlock); // Dequantize: - b.MultiplyInplace(ref this.DequantiazationTable); + b.MultiplyInPlace(ref this.DequantiazationTable); FastFloatingPointDCT.TransformIDCT(ref b, ref this.WorkspaceBlock1, ref this.WorkspaceBlock2); // To conform better to libjpeg we actually NEED TO loose precision here. // This is because they store blocks as Int16 between all the operations. // To be "more accurate", we need to emulate this by rounding! - this.WorkspaceBlock1.NormalizeColorsAndRoundInplace(maximumValue); + this.WorkspaceBlock1.NormalizeColorsAndRoundInPlace(maximumValue); this.WorkspaceBlock1.ScaledCopyTo( ref destAreaOrigin, diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrTables.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterLut.cs similarity index 79% rename from src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrTables.cs rename to src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterLut.cs index 236eff27cc..3c1a02c5aa 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrTables.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterLut.cs @@ -1,16 +1,17 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. +using System; using System.Runtime.CompilerServices; +using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder { /// /// Provides 8-bit lookup tables for converting from Rgb to YCbCr colorspace. /// Methods to build the tables are based on libjpeg implementation. - /// TODO: Replace this logic with SIMD conversion (similar to the one in the decoder)! /// - internal unsafe struct RgbToYCbCrTables + internal unsafe struct RgbToYCbCrConverterLut { /// /// The red luminance table @@ -63,10 +64,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder /// /// Initializes the YCbCr tables /// - /// The initialized - public static RgbToYCbCrTables Create() + /// The initialized + public static RgbToYCbCrConverterLut Create() { - RgbToYCbCrTables tables = default; + RgbToYCbCrConverterLut tables = default; for (int i = 0; i <= 255; i++) { @@ -92,11 +93,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder } /// - /// TODO: Replace this logic with SIMD conversion (similar to the one in the decoder)! /// Optimized method to allocates the correct y, cb, and cr values to the DCT blocks from the given r, g, b values. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ConvertPixelInto( + private void ConvertPixelInto( int r, int g, int b, @@ -111,10 +111,29 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder // float cb = 128F + ((-0.168736F * r) - (0.331264F * g) + (0.5F * b)); cbResult[i] = (this.CbRTable[r] + this.CbGTable[g] + this.CbBTable[b]) >> ScaleBits; - // float cr = MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero); + // float cr = 128F + ((0.5F * r) - (0.418688F * g) - (0.081312F * b)); crResult[i] = (this.CbBTable[r] + this.CrGTable[g] + this.CrBTable[b]) >> ScaleBits; } + public void Convert(Span rgbSpan, ref Block8x8F yBlock, ref Block8x8F cbBlock, ref Block8x8F crBlock) + { + ref Rgb24 rgbStart = ref rgbSpan[0]; + + for (int i = 0; i < 64; i++) + { + ref Rgb24 c = ref Unsafe.Add(ref rgbStart, i); + + this.ConvertPixelInto( + c.R, + c.G, + c.B, + ref yBlock, + ref cbBlock, + ref crBlock, + i); + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int Fix(float x) => (int)((x * (1L << ScaleBits)) + 0.5F); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterVectorized.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterVectorized.cs new file mode 100644 index 0000000000..209cc3c6ab --- /dev/null +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/RgbToYCbCrConverterVectorized.cs @@ -0,0 +1,120 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Diagnostics; +#if SUPPORTS_RUNTIME_INTRINSICS +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +#endif +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder +{ + internal static class RgbToYCbCrConverterVectorized + { + public static bool IsSupported + { + get + { +#if SUPPORTS_RUNTIME_INTRINSICS + return Avx2.IsSupported; +#else + return false; +#endif + } + } + +#if SUPPORTS_RUNTIME_INTRINSICS + private static ReadOnlySpan MoveFirst24BytesToSeparateLanes => new byte[] + { + 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, + 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 7, 0, 0, 0 + }; + + private static ReadOnlySpan MoveLast24BytesToSeparateLanes => new byte[] + { + 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 1, 0, 0, 0 + }; + + private static ReadOnlySpan ExtractRgb => new byte[] + { + 0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11, 0xFF, 0xFF, 0xFF, 0xFF, + 0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11, 0xFF, 0xFF, 0xFF, 0xFF + }; +#endif + + public static void Convert(ReadOnlySpan rgbSpan, ref Block8x8F yBlock, ref Block8x8F cbBlock, ref Block8x8F crBlock) + { + Debug.Assert(IsSupported, "AVX2 is required to run this converter"); + +#if SUPPORTS_RUNTIME_INTRINSICS + var f0299 = Vector256.Create(0.299f); + var f0587 = Vector256.Create(0.587f); + var f0114 = Vector256.Create(0.114f); + var fn0168736 = Vector256.Create(-0.168736f); + var fn0331264 = Vector256.Create(-0.331264f); + var f128 = Vector256.Create(128f); + var fn0418688 = Vector256.Create(-0.418688f); + var fn0081312F = Vector256.Create(-0.081312F); + var f05 = Vector256.Create(0.5f); + var zero = Vector256.Create(0).AsByte(); + + ref Vector256 inRef = ref Unsafe.As>(ref MemoryMarshal.GetReference(rgbSpan)); + ref Vector256 destYRef = ref Unsafe.As>(ref yBlock); + ref Vector256 destCbRef = ref Unsafe.As>(ref cbBlock); + ref Vector256 destCrRef = ref Unsafe.As>(ref crBlock); + + var extractToLanesMask = Unsafe.As>(ref MemoryMarshal.GetReference(MoveFirst24BytesToSeparateLanes)); + var extractRgbMask = Unsafe.As>(ref MemoryMarshal.GetReference(ExtractRgb)); + Vector256 rgb, rg, bx; + Vector256 r, g, b; + for (int i = 0; i < 7; i++) + { + rgb = Avx2.PermuteVar8x32(Unsafe.AddByteOffset(ref inRef, (IntPtr)(24 * i)).AsUInt32(), extractToLanesMask).AsByte(); + + rgb = Avx2.Shuffle(rgb, extractRgbMask); + + rg = Avx2.UnpackLow(rgb, zero); + bx = Avx2.UnpackHigh(rgb, zero); + + r = Avx.ConvertToVector256Single(Avx2.UnpackLow(rg, zero).AsInt32()); + g = Avx.ConvertToVector256Single(Avx2.UnpackHigh(rg, zero).AsInt32()); + b = Avx.ConvertToVector256Single(Avx2.UnpackLow(bx, zero).AsInt32()); + + // (0.299F * r) + (0.587F * g) + (0.114F * b); + Unsafe.Add(ref destYRef, i) = SimdUtils.HwIntrinsics.MultiplyAdd(SimdUtils.HwIntrinsics.MultiplyAdd(Avx.Multiply(f0114, b), f0587, g), f0299, r); + + // 128F + ((-0.168736F * r) - (0.331264F * g) + (0.5F * b)) + Unsafe.Add(ref destCbRef, i) = Avx.Add(f128, SimdUtils.HwIntrinsics.MultiplyAdd(SimdUtils.HwIntrinsics.MultiplyAdd(Avx.Multiply(f05, b), fn0331264, g), fn0168736, r)); + + // 128F + ((0.5F * r) - (0.418688F * g) - (0.081312F * b)) + Unsafe.Add(ref destCrRef, i) = Avx.Add(f128, SimdUtils.HwIntrinsics.MultiplyAdd(SimdUtils.HwIntrinsics.MultiplyAdd(Avx.Multiply(fn0081312F, b), fn0418688, g), f05, r)); + } + + extractToLanesMask = Unsafe.As>(ref MemoryMarshal.GetReference(MoveLast24BytesToSeparateLanes)); + rgb = Avx2.PermuteVar8x32(Unsafe.AddByteOffset(ref inRef, (IntPtr)160).AsUInt32(), extractToLanesMask).AsByte(); + rgb = Avx2.Shuffle(rgb, extractRgbMask); + + rg = Avx2.UnpackLow(rgb, zero); + bx = Avx2.UnpackHigh(rgb, zero); + + r = Avx.ConvertToVector256Single(Avx2.UnpackLow(rg, zero).AsInt32()); + g = Avx.ConvertToVector256Single(Avx2.UnpackHigh(rg, zero).AsInt32()); + b = Avx.ConvertToVector256Single(Avx2.UnpackLow(bx, zero).AsInt32()); + + // (0.299F * r) + (0.587F * g) + (0.114F * b); + Unsafe.Add(ref destYRef, 7) = SimdUtils.HwIntrinsics.MultiplyAdd(SimdUtils.HwIntrinsics.MultiplyAdd(Avx.Multiply(f0114, b), f0587, g), f0299, r); + + // 128F + ((-0.168736F * r) - (0.331264F * g) + (0.5F * b)) + Unsafe.Add(ref destCbRef, 7) = Avx.Add(f128, SimdUtils.HwIntrinsics.MultiplyAdd(SimdUtils.HwIntrinsics.MultiplyAdd(Avx.Multiply(f05, b), fn0331264, g), fn0168736, r)); + + // 128F + ((0.5F * r) - (0.418688F * g) - (0.081312F * b)) + Unsafe.Add(ref destCrRef, 7) = Avx.Add(f128, SimdUtils.HwIntrinsics.MultiplyAdd(SimdUtils.HwIntrinsics.MultiplyAdd(Avx.Multiply(fn0081312F, b), fn0418688, g), f05, r)); +#endif + } + } +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter{TPixel}.cs index 4d6186e22f..81e64b277b 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter{TPixel}.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; @@ -33,7 +32,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder /// /// The color conversion tables /// - private RgbToYCbCrTables colorTables; + private RgbToYCbCrConverterLut colorTables; /// /// Temporal 8x8 block to hold TPixel data @@ -48,16 +47,21 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder public static YCbCrForwardConverter Create() { var result = default(YCbCrForwardConverter); - result.colorTables = RgbToYCbCrTables.Create(); + if (!RgbToYCbCrConverterVectorized.IsSupported) + { + // Avoid creating lookup tables, when vectorized converter is supported + result.colorTables = RgbToYCbCrConverterLut.Create(); + } + return result; } /// /// Converts a 8x8 image area inside 'pixels' at position (x,y) placing the result members of the structure (, , ) /// - public void Convert(ImageFrame frame, int x, int y, in RowOctet currentRows) + public void Convert(ImageFrame frame, int x, int y, ref RowOctet currentRows) { - this.pixelBlock.LoadAndStretchEdges(frame.PixelBuffer, x, y, currentRows); + this.pixelBlock.LoadAndStretchEdges(frame.PixelBuffer, x, y, ref currentRows); Span rgbSpan = this.rgbBlock.AsSpanUnsafe(); PixelOperations.Instance.ToRgb24(frame.GetConfiguration(), this.pixelBlock.AsSpanUnsafe(), rgbSpan); @@ -65,20 +69,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder ref Block8x8F yBlock = ref this.Y; ref Block8x8F cbBlock = ref this.Cb; ref Block8x8F crBlock = ref this.Cr; - ref Rgb24 rgbStart = ref rgbSpan[0]; - for (int i = 0; i < 64; i++) + if (RgbToYCbCrConverterVectorized.IsSupported) { - ref Rgb24 c = ref Unsafe.Add(ref rgbStart, i); - - this.colorTables.ConvertPixelInto( - c.R, - c.G, - c.B, - ref yBlock, - ref cbBlock, - ref crBlock, - i); + RgbToYCbCrConverterVectorized.Convert(rgbSpan, ref yBlock, ref cbBlock, ref crBlock); + } + else + { + this.colorTables.Convert(rgbSpan, ref yBlock, ref cbBlock, ref crBlock); } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/FastFloatingPointDCT.cs b/src/ImageSharp/Formats/Jpeg/Components/FastFloatingPointDCT.cs index ee06f2bdeb..a6d0622dd8 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/FastFloatingPointDCT.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/FastFloatingPointDCT.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System.Numerics; @@ -50,8 +50,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// Temporary block provided by the caller public static void TransformIDCT(ref Block8x8F src, ref Block8x8F dest, ref Block8x8F temp) { - // TODO: Transpose is a bottleneck now. We need full AVX support to optimize it: - // https://github.com/dotnet/corefx/issues/22940 src.TransposeInto(ref temp); IDCT8x4_LeftPart(ref temp, ref dest); @@ -63,7 +61,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components IDCT8x4_RightPart(ref temp, ref dest); // TODO: What if we leave the blocks in a scaled-by-x8 state until final color packing? - dest.MultiplyInplace(C_0_125); + dest.MultiplyInPlace(C_0_125); } /// @@ -326,7 +324,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components src.TransposeInto(ref temp); if (offsetSourceByNeg128) { - temp.AddToAllInplace(new Vector4(-128)); + temp.AddInPlace(-128F); } FDCT8x4_LeftPart(ref temp, ref dest); @@ -337,7 +335,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components FDCT8x4_LeftPart(ref temp, ref dest); FDCT8x4_RightPart(ref temp, ref dest); - dest.MultiplyInplace(C_0_125); + dest.MultiplyInPlace(C_0_125); } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/Jpeg/Components/GenericBlock8x8.cs b/src/ImageSharp/Formats/Jpeg/Components/GenericBlock8x8.cs index 92ba1afd35..42c01d770e 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/GenericBlock8x8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/GenericBlock8x8.cs @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// Load a 8x8 region of an image into the block. /// The "outlying" area of the block will be stretched out with pixels on the right and bottom edge of the image. /// - public void LoadAndStretchEdges(Buffer2D source, int sourceX, int sourceY, in RowOctet currentRows) + public void LoadAndStretchEdges(Buffer2D source, int sourceX, int sourceY, ref RowOctet currentRows) { int width = Math.Min(8, source.Width - sourceX); int height = Math.Min(8, source.Height - sourceY); diff --git a/src/ImageSharp/Formats/Jpeg/Components/RowOctet.cs b/src/ImageSharp/Formats/Jpeg/Components/RowOctet.cs index ae10bfba83..16d24cf814 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/RowOctet.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/RowOctet.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System; @@ -12,39 +12,24 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// Cache 8 pixel rows on the stack, which may originate from different buffers of a . /// [StructLayout(LayoutKind.Sequential)] - internal readonly ref struct RowOctet + internal ref struct RowOctet where T : struct { - private readonly Span row0; - private readonly Span row1; - private readonly Span row2; - private readonly Span row3; - private readonly Span row4; - private readonly Span row5; - private readonly Span row6; - private readonly Span row7; - - public RowOctet(Buffer2D buffer, int startY) - { - int y = startY; - int height = buffer.Height; - this.row0 = y < height ? buffer.GetRowSpan(y++) : default; - this.row1 = y < height ? buffer.GetRowSpan(y++) : default; - this.row2 = y < height ? buffer.GetRowSpan(y++) : default; - this.row3 = y < height ? buffer.GetRowSpan(y++) : default; - this.row4 = y < height ? buffer.GetRowSpan(y++) : default; - this.row5 = y < height ? buffer.GetRowSpan(y++) : default; - this.row6 = y < height ? buffer.GetRowSpan(y++) : default; - this.row7 = y < height ? buffer.GetRowSpan(y) : default; - } + private Span row0; + private Span row1; + private Span row2; + private Span row3; + private Span row4; + private Span row5; + private Span row6; + private Span row7; + // No unsafe tricks, since Span can't be used as a generic argument public Span this[int y] { - [MethodImpl(InliningOptions.ShortMethod)] - get - { - // No unsafe tricks, since Span can't be used as a generic argument - return y switch + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => + y switch { 0 => this.row0, 1 => this.row1, @@ -56,13 +41,57 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components 7 => this.row7, _ => ThrowIndexOutOfRangeException() }; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private set + { + switch (y) + { + case 0: + this.row0 = value; + break; + case 1: + this.row1 = value; + break; + case 2: + this.row2 = value; + break; + case 3: + this.row3 = value; + break; + case 4: + this.row4 = value; + break; + case 5: + this.row5 = value; + break; + case 6: + this.row6 = value; + break; + default: + this.row7 = value; + break; + } } } - [MethodImpl(InliningOptions.ColdPath)] - private static Span ThrowIndexOutOfRangeException() + [MethodImpl(InliningOptions.ShortMethod)] + public void Update(Buffer2D buffer, int startY) { - throw new IndexOutOfRangeException(); + // We don't actually have to assign values outside of the + // frame pixel buffer since they are never requested. + int y = startY; + int yEnd = Math.Min(y + 8, buffer.Height); + + int i = 0; + while (y < yEnd) + { + this[i++] = buffer.GetRowSpan(y++); + } } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static Span ThrowIndexOutOfRangeException() + => throw new IndexOutOfRangeException(); } } diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs index c4ff1c0360..d26fbb936d 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs @@ -6,6 +6,7 @@ using System.Buffers.Binary; using System.IO; using System.Linq; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Threading; using SixLabors.ImageSharp.Common.Helpers; using SixLabors.ImageSharp.Formats.Jpeg.Components; @@ -212,8 +213,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ImageMetadata metadata = image.Metadata; // System.Drawing produces identical output for jpegs with a quality parameter of 0 and 1. - int qlty = (this.quality ?? metadata.GetJpegMetadata().Quality).Clamp(1, 100); - this.subsample = this.subsample ?? (qlty >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420); + int qlty = Numerics.Clamp(this.quality ?? metadata.GetJpegMetadata().Quality, 1, 100); + this.subsample ??= qlty >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420; // Convert from a quality rating to a scaling factor. int scale; @@ -313,7 +314,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// The packed bits. /// The number of bits - private void Emit(uint bits, uint count) + /// The reference to the emitBuffer. + [MethodImpl(InliningOptions.ShortMethod)] + private void Emit(uint bits, uint count, ref byte emitBufferBase) { count += this.bitCount; bits <<= (int)(32 - count); @@ -327,10 +330,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg while (count >= 8) { byte b = (byte)(bits >> 24); - this.emitBuffer[len++] = b; - if (b == 0xff) + Unsafe.Add(ref emitBufferBase, len++) = b; + if (b == byte.MaxValue) { - this.emitBuffer[len++] = 0x00; + Unsafe.Add(ref emitBufferBase, len++) = byte.MinValue; } bits <<= 8; @@ -352,11 +355,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// The index of the Huffman encoder /// The value to encode. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void EmitHuff(HuffIndex index, int value) + /// The reference to the emit buffer. + [MethodImpl(InliningOptions.ShortMethod)] + private void EmitHuff(HuffIndex index, int value, ref byte emitBufferBase) { uint x = HuffmanLut.TheHuffmanLut[(int)index].Values[value]; - this.Emit(x & ((1 << 24) - 1), x >> 24); + this.Emit(x & ((1 << 24) - 1), x >> 24, ref emitBufferBase); } /// @@ -365,8 +369,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// The index of the Huffman encoder /// The number of copies to encode. /// The value to encode. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void EmitHuffRLE(HuffIndex index, int runLength, int value) + /// The reference to the emit buffer. + [MethodImpl(InliningOptions.ShortMethod)] + private void EmitHuffRLE(HuffIndex index, int runLength, int value, ref byte emitBufferBase) { int a = value; int b = value; @@ -386,10 +391,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg bt = 8 + (uint)BitCountLut[a >> 8]; } - this.EmitHuff(index, (int)((uint)(runLength << 4) | bt)); + this.EmitHuff(index, (int)((uint)(runLength << 4) | bt), ref emitBufferBase); if (bt > 0) { - this.Emit((uint)b & (uint)((1 << ((int)bt)) - 1), bt); + this.Emit((uint)b & (uint)((1 << ((int)bt)) - 1), bt, ref emitBufferBase); } } @@ -399,7 +404,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// The pixel format. /// The pixel accessor providing access to the image pixels. /// The token to monitor for cancellation. - private void Encode444(Image pixels, CancellationToken cancellationToken) + /// The reference to the emit buffer. + private void Encode444(Image pixels, CancellationToken cancellationToken, ref byte emitBufferBase) where TPixel : unmanaged, IPixel { // TODO: Need a JpegScanEncoder class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.) @@ -418,15 +424,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg var pixelConverter = YCbCrForwardConverter.Create(); ImageFrame frame = pixels.Frames.RootFrame; Buffer2D pixelBuffer = frame.PixelBuffer; + RowOctet currentRows = default; for (int y = 0; y < pixels.Height; y += 8) { cancellationToken.ThrowIfCancellationRequested(); - var currentRows = new RowOctet(pixelBuffer, y); + currentRows.Update(pixelBuffer, y); for (int x = 0; x < pixels.Width; x += 8) { - pixelConverter.Convert(frame, x, y, currentRows); + pixelConverter.Convert(frame, x, y, ref currentRows); prevDCY = this.WriteBlock( QuantIndex.Luminance, @@ -435,7 +442,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ref temp1, ref temp2, ref onStackLuminanceQuantTable, - ref unzig); + ref unzig, + ref emitBufferBase); + prevDCCb = this.WriteBlock( QuantIndex.Chrominance, prevDCCb, @@ -443,7 +452,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ref temp1, ref temp2, ref onStackChrominanceQuantTable, - ref unzig); + ref unzig, + ref emitBufferBase); + prevDCCr = this.WriteBlock( QuantIndex.Chrominance, prevDCCr, @@ -451,7 +462,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ref temp1, ref temp2, ref onStackChrominanceQuantTable, - ref unzig); + ref unzig, + ref emitBufferBase); } } } @@ -517,9 +529,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// Temporal block 2 /// Quantization table /// The 8x8 Unzig block. - /// - /// The - /// + /// The reference to the emit buffer. + /// The . private int WriteBlock( QuantIndex index, int prevDC, @@ -527,7 +538,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ref Block8x8F tempDest1, ref Block8x8F tempDest2, ref Block8x8F quant, - ref ZigZag unZig) + ref ZigZag unZig, + ref byte emitBufferBase) { FastFloatingPointDCT.TransformFDCT(ref src, ref tempDest1, ref tempDest2); @@ -536,7 +548,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg int dc = (int)tempDest2[0]; // Emit the DC delta. - this.EmitHuffRLE((HuffIndex)((2 * (int)index) + 0), 0, dc - prevDC); + this.EmitHuffRLE((HuffIndex)((2 * (int)index) + 0), 0, dc - prevDC, ref emitBufferBase); // Emit the AC components. var h = (HuffIndex)((2 * (int)index) + 1); @@ -554,18 +566,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg { while (runLength > 15) { - this.EmitHuff(h, 0xf0); + this.EmitHuff(h, 0xf0, ref emitBufferBase); runLength -= 16; } - this.EmitHuffRLE(h, runLength, ac); + this.EmitHuffRLE(h, runLength, ac, ref emitBufferBase); runLength = 0; } } if (runLength > 0) { - this.EmitHuff(h, 0x00); + this.EmitHuff(h, 0x00, ref emitBufferBase); } return dc; @@ -747,9 +759,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// The length of the data the app1 marker contains. private void WriteApp1Header(int app1Length) - { - this.WriteAppHeader(app1Length, JpegConstants.Markers.APP1); - } + => this.WriteAppHeader(app1Length, JpegConstants.Markers.APP1); /// /// Writes a AppX header. @@ -953,19 +963,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg // TODO: Need a JpegScanEncoder class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.) // TODO: We should allow grayscale writing. this.outputStream.Write(SosHeaderYCbCr); - + ref byte emitBufferBase = ref MemoryMarshal.GetReference(this.emitBuffer); switch (this.subsample) { case JpegSubsample.Ratio444: - this.Encode444(image, cancellationToken); + this.Encode444(image, cancellationToken, ref emitBufferBase); break; case JpegSubsample.Ratio420: - this.Encode420(image, cancellationToken); + this.Encode420(image, cancellationToken, ref emitBufferBase); break; } // Pad the last byte with 1's. - this.Emit(0x7f, 7); + this.Emit(0x7f, 7, ref emitBufferBase); } /// @@ -975,7 +985,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// The pixel format. /// The pixel accessor providing access to the image pixels. /// The token to monitor for cancellation. - private void Encode420(Image pixels, CancellationToken cancellationToken) + /// The reference to the emit buffer. + private void Encode420(Image pixels, CancellationToken cancellationToken, ref byte emitBufferBase) where TPixel : unmanaged, IPixel { // TODO: Need a JpegScanEncoder class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.) @@ -997,6 +1008,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg int prevDCY = 0, prevDCCb = 0, prevDCCr = 0; ImageFrame frame = pixels.Frames.RootFrame; Buffer2D pixelBuffer = frame.PixelBuffer; + RowOctet currentRows = default; for (int y = 0; y < pixels.Height; y += 16) { @@ -1008,10 +1020,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg int xOff = (i & 1) * 8; int yOff = (i & 2) * 4; - // TODO: Try pushing this to the outer loop! - var currentRows = new RowOctet(pixelBuffer, y + yOff); - - pixelConverter.Convert(frame, x + xOff, y + yOff, currentRows); + currentRows.Update(pixelBuffer, y + yOff); + pixelConverter.Convert(frame, x + xOff, y + yOff, ref currentRows); cb[i] = pixelConverter.Cb; cr[i] = pixelConverter.Cr; @@ -1023,7 +1033,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ref temp1, ref temp2, ref onStackLuminanceQuantTable, - ref unzig); + ref unzig, + ref emitBufferBase); } Block8x8F.Scale16X16To8X8(ref b, cb); @@ -1034,7 +1045,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ref temp1, ref temp2, ref onStackChrominanceQuantTable, - ref unzig); + ref unzig, + ref emitBufferBase); Block8x8F.Scale16X16To8X8(ref b, cr); prevDCCr = this.WriteBlock( @@ -1044,7 +1056,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg ref temp1, ref temp2, ref onStackChrominanceQuantTable, - ref unzig); + ref unzig, + ref emitBufferBase); } } } diff --git a/src/ImageSharp/Formats/PixelTypeInfo.cs b/src/ImageSharp/Formats/PixelTypeInfo.cs index d53d496fa5..718b05e33a 100644 --- a/src/ImageSharp/Formats/PixelTypeInfo.cs +++ b/src/ImageSharp/Formats/PixelTypeInfo.cs @@ -1,8 +1,7 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System.Runtime.CompilerServices; - using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats @@ -16,9 +15,11 @@ namespace SixLabors.ImageSharp.Formats /// Initializes a new instance of the class. /// /// Color depth, in number of bits per pixel. - internal PixelTypeInfo(int bitsPerPixel) + /// Tthe pixel alpha transparency behavior. + internal PixelTypeInfo(int bitsPerPixel, PixelAlphaRepresentation? alpha = null) { this.BitsPerPixel = bitsPerPixel; + this.AlphaRepresentation = alpha; } /// @@ -26,8 +27,20 @@ namespace SixLabors.ImageSharp.Formats /// public int BitsPerPixel { get; } + /// + /// Gets the pixel alpha transparency behavior. + /// means unknown, unspecified. + /// + public PixelAlphaRepresentation? AlphaRepresentation { get; } + internal static PixelTypeInfo Create() where TPixel : unmanaged, IPixel => new PixelTypeInfo(Unsafe.SizeOf() * 8); + + internal static PixelTypeInfo Create(PixelAlphaRepresentation alpha) + where TPixel : unmanaged, IPixel + { + return new PixelTypeInfo(Unsafe.SizeOf() * 8, alpha); + } } } diff --git a/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs b/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs index 8d9f6e4156..d1c214e3d6 100644 --- a/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System; @@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters ++x; ref byte res = ref Unsafe.Add(ref resultBaseRef, x); res = (byte)(scan - (above >> 1)); - sum += ImageMaths.FastAbs(unchecked((sbyte)res)); + sum += Numerics.Abs(unchecked((sbyte)res)); } for (int xLeft = x - bytesPerPixel; x < scanline.Length; ++xLeft /* Note: ++x happens in the body to avoid one add operation */) @@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters ++x; ref byte res = ref Unsafe.Add(ref resultBaseRef, x); res = (byte)(scan - Average(left, above)); - sum += ImageMaths.FastAbs(unchecked((sbyte)res)); + sum += Numerics.Abs(unchecked((sbyte)res)); } sum -= 3; @@ -102,4 +102,4 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int Average(byte left, byte above) => (left + above) >> 1; } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs b/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs index 7b5c71a010..fab6788061 100644 --- a/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System; @@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters ++x; ref byte res = ref Unsafe.Add(ref resultBaseRef, x); res = (byte)(scan - PaethPredictor(0, above, 0)); - sum += ImageMaths.FastAbs(unchecked((sbyte)res)); + sum += Numerics.Abs(unchecked((sbyte)res)); } for (int xLeft = x - bytesPerPixel; x < scanline.Length; ++xLeft /* Note: ++x happens in the body to avoid one add operation */) @@ -91,7 +91,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters ++x; ref byte res = ref Unsafe.Add(ref resultBaseRef, x); res = (byte)(scan - PaethPredictor(left, above, upperLeft)); - sum += ImageMaths.FastAbs(unchecked((sbyte)res)); + sum += Numerics.Abs(unchecked((sbyte)res)); } sum -= 4; @@ -111,9 +111,9 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters private static byte PaethPredictor(byte left, byte above, byte upperLeft) { int p = left + above - upperLeft; - int pa = ImageMaths.FastAbs(p - left); - int pb = ImageMaths.FastAbs(p - above); - int pc = ImageMaths.FastAbs(p - upperLeft); + int pa = Numerics.Abs(p - left); + int pb = Numerics.Abs(p - above); + int pc = Numerics.Abs(p - upperLeft); if (pa <= pb && pa <= pc) { @@ -128,4 +128,4 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters return upperLeft; } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs index c448e71f43..cb4cfb471f 100644 --- a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs @@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters ++x; ref byte res = ref Unsafe.Add(ref resultBaseRef, x); res = scan; - sum += ImageMaths.FastAbs(unchecked((sbyte)res)); + sum += Numerics.Abs(unchecked((sbyte)res)); } for (int xLeft = x - bytesPerPixel; x < scanline.Length; ++xLeft /* Note: ++x happens in the body to avoid one add operation */) @@ -71,7 +71,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters ++x; ref byte res = ref Unsafe.Add(ref resultBaseRef, x); res = (byte)(scan - prev); - sum += ImageMaths.FastAbs(unchecked((sbyte)res)); + sum += Numerics.Abs(unchecked((sbyte)res)); } sum -= 1; diff --git a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs index 2a77bccb97..cf553cbb68 100644 --- a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs +++ b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs @@ -64,7 +64,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters ++x; ref byte res = ref Unsafe.Add(ref resultBaseRef, x); res = (byte)(scan - above); - sum += ImageMaths.FastAbs(unchecked((sbyte)res)); + sum += Numerics.Abs(unchecked((sbyte)res)); } sum -= 2; diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs index 5cf11099cd..5d2af8ec6a 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs @@ -284,7 +284,7 @@ namespace SixLabors.ImageSharp.Formats.Png rowSpan.Length, AllocationOptions.Clean)) { - int scaleFactor = 255 / (ImageMaths.GetColorCountForBitDepth(this.bitDepth) - 1); + int scaleFactor = 255 / (ColorNumerics.GetColorCountForBitDepth(this.bitDepth) - 1); Span tempSpan = temp.GetSpan(); // We need to first create an array of luminance bytes then scale them down to the correct bit depth. @@ -314,7 +314,7 @@ namespace SixLabors.ImageSharp.Formats.Png for (int x = 0, o = 0; x < rgbaSpan.Length; x++, o += 4) { Rgba64 rgba = Unsafe.Add(ref rgbaRef, x); - ushort luminance = ImageMaths.Get16BitBT709Luminance(rgba.R, rgba.G, rgba.B); + ushort luminance = ColorNumerics.Get16BitBT709Luminance(rgba.R, rgba.G, rgba.B); BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), luminance); BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgba.A); } @@ -329,7 +329,7 @@ namespace SixLabors.ImageSharp.Formats.Png { Unsafe.Add(ref rowSpanRef, x).ToRgba32(ref rgba); Unsafe.Add(ref rawScanlineSpanRef, o) = - ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); + ColorNumerics.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); Unsafe.Add(ref rawScanlineSpanRef, o + 1) = rgba.A; } } diff --git a/src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs b/src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs index b0311f0887..23ca869936 100644 --- a/src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs +++ b/src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs @@ -35,6 +35,15 @@ namespace SixLabors.ImageSharp.Formats.Png options.ColorType ??= pngMetadata.ColorType ?? SuggestColorType(); options.BitDepth ??= pngMetadata.BitDepth ?? SuggestBitDepth(); + // Ensure bit depth and color type are a supported combination. + // Bit8 is the only bit depth supported by all color types. + byte bits = (byte)options.BitDepth; + byte[] validBitDepths = PngConstants.ColorTypes[options.ColorType.Value]; + if (Array.IndexOf(validBitDepths, bits) == -1) + { + options.BitDepth = PngBitDepth.Bit8; + } + options.InterlaceMethod ??= pngMetadata.InterlaceMethod; use16Bit = options.BitDepth == PngBitDepth.Bit16; @@ -44,12 +53,6 @@ namespace SixLabors.ImageSharp.Formats.Png { options.ChunkFilter = PngChunkFilter.ExcludeAll; } - - // Ensure we are not allowing impossible combinations. - if (!PngConstants.ColorTypes.ContainsKey(options.ColorType.Value)) - { - throw new NotSupportedException("Color type is not supported or not valid."); - } } /// @@ -68,16 +71,11 @@ namespace SixLabors.ImageSharp.Formats.Png return null; } - byte bits = (byte)options.BitDepth; - if (Array.IndexOf(PngConstants.ColorTypes[options.ColorType.Value], bits) == -1) - { - throw new NotSupportedException("Bit depth is not supported or not valid."); - } - // Use the metadata to determine what quantization depth to use if no quantizer has been set. if (options.Quantizer is null) { - var maxColors = ImageMaths.GetColorCountForBitDepth(bits); + byte bits = (byte)options.BitDepth; + var maxColors = ColorNumerics.GetColorCountForBitDepth(bits); options.Quantizer = new WuQuantizer(new QuantizerOptions { MaxColors = maxColors }); } @@ -103,7 +101,7 @@ namespace SixLabors.ImageSharp.Formats.Png byte bitDepth; if (options.ColorType == PngColorType.Palette) { - byte quantizedBits = (byte)ImageMaths.GetBitsNeededForColorDepth(quantizedFrame.Palette.Length).Clamp(1, 8); + byte quantizedBits = (byte)Numerics.Clamp(ColorNumerics.GetBitsNeededForColorDepth(quantizedFrame.Palette.Length), 1, 8); byte bits = Math.Max((byte)options.BitDepth, quantizedBits); // Png only supports in four pixel depths: 1, 2, 4, and 8 bits when using the PLTE chunk diff --git a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs index 48ec9bdcdc..58fa5aca82 100644 --- a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs +++ b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs @@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Formats.Png TPixel pixel = default; ref byte scanlineSpanRef = ref MemoryMarshal.GetReference(scanlineSpan); ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan); - int scaleFactor = 255 / (ImageMaths.GetColorCountForBitDepth(header.BitDepth) - 1); + int scaleFactor = 255 / (ColorNumerics.GetColorCountForBitDepth(header.BitDepth) - 1); if (!hasTrans) { @@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp.Formats.Png TPixel pixel = default; ref byte scanlineSpanRef = ref MemoryMarshal.GetReference(scanlineSpan); ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan); - int scaleFactor = 255 / (ImageMaths.GetColorCountForBitDepth(header.BitDepth) - 1); + int scaleFactor = 255 / (ColorNumerics.GetColorCountForBitDepth(header.BitDepth) - 1); if (!hasTrans) { diff --git a/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs b/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs index d3a628531e..1d31ea9f4e 100644 --- a/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs +++ b/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs @@ -365,7 +365,7 @@ namespace SixLabors.ImageSharp.Formats.Tga where TPixel : unmanaged, IPixel { var vector = sourcePixel.ToVector4(); - return ImageMaths.GetBT709Luminance(ref vector, 256); + return ColorNumerics.GetBT709Luminance(ref vector, 256); } } } diff --git a/src/ImageSharp/Image.FromBytes.cs b/src/ImageSharp/Image.FromBytes.cs index 50950c192a..a33a345a0f 100644 --- a/src/ImageSharp/Image.FromBytes.cs +++ b/src/ImageSharp/Image.FromBytes.cs @@ -91,9 +91,9 @@ namespace SixLabors.ImageSharp /// The byte array containing image data. /// The configuration is null. /// The data is null. - /// A new . - public static Image Load(byte[] data) - => Load(Configuration.Default, data); + /// A new . + public static Image Load(byte[] data) + => Load(Configuration.Default, data); /// /// Load a new instance of from the given encoded byte array. diff --git a/src/ImageSharp/Image.WrapMemory.cs b/src/ImageSharp/Image.WrapMemory.cs index d89c44dc56..b0efdb60db 100644 --- a/src/ImageSharp/Image.WrapMemory.cs +++ b/src/ImageSharp/Image.WrapMemory.cs @@ -16,8 +16,22 @@ namespace SixLabors.ImageSharp public abstract partial class Image { /// - /// Wraps an existing contiguous memory area of 'width' x 'height' pixels, - /// allowing to view/manipulate it as an instance. + /// + /// Wraps an existing contiguous memory area of at least 'width' x 'height' pixels allowing viewing/manipulation as + /// an instance. + /// + /// + /// Please note: using this method does not transfer the ownership of the underlying buffer of the input + /// to the new instance. This means that consumers of this method must ensure that the input buffer + /// is either self-contained, (for example, a instance wrapping a new array that was + /// created), or that the owning object is not disposed until the returned is disposed. + /// + /// + /// If the input instance is one retrieved from an instance + /// rented from a memory pool (such as ), and that owning instance is disposed while the image is still + /// in use, this will lead to undefined behavior and possibly runtime crashes (as the same buffer might then be modified by other + /// consumers while the returned image is still working on it). Make sure to control the lifetime of the input buffers appropriately. + /// /// /// The pixel type /// The @@ -38,15 +52,29 @@ namespace SixLabors.ImageSharp { Guard.NotNull(configuration, nameof(configuration)); Guard.NotNull(metadata, nameof(metadata)); - Guard.IsTrue(pixelMemory.Length == width * height, nameof(pixelMemory), "The length of the input memory doesn't match the specified image size"); + Guard.IsTrue(pixelMemory.Length >= width * height, nameof(pixelMemory), "The length of the input memory is less than the specified image size"); var memorySource = MemoryGroup.Wrap(pixelMemory); return new Image(configuration, memorySource, width, height, metadata); } /// - /// Wraps an existing contiguous memory area of 'width' x 'height' pixels, - /// allowing to view/manipulate it as an instance. + /// + /// Wraps an existing contiguous memory area of at least 'width' x 'height' pixels allowing viewing/manipulation as + /// an instance. + /// + /// + /// Please note: using this method does not transfer the ownership of the underlying buffer of the input + /// to the new instance. This means that consumers of this method must ensure that the input buffer + /// is either self-contained, (for example, a instance wrapping a new array that was + /// created), or that the owning object is not disposed until the returned is disposed. + /// + /// + /// If the input instance is one retrieved from an instance + /// rented from a memory pool (such as ), and that owning instance is disposed while the image is still + /// in use, this will lead to undefined behavior and possibly runtime crashes (as the same buffer might then be modified by other + /// consumers while the returned image is still working on it). Make sure to control the lifetime of the input buffers appropriately. + /// /// /// The pixel type /// The @@ -64,9 +92,22 @@ namespace SixLabors.ImageSharp => WrapMemory(configuration, pixelMemory, width, height, new ImageMetadata()); /// - /// Wraps an existing contiguous memory area of 'width' x 'height' pixels, - /// allowing to view/manipulate it as an instance. - /// The memory is being observed, the caller remains responsible for managing it's lifecycle. + /// + /// Wraps an existing contiguous memory area of at least 'width' x 'height' pixels allowing viewing/manipulation as + /// an instance. + /// + /// + /// Please note: using this method does not transfer the ownership of the underlying buffer of the input + /// to the new instance. This means that consumers of this method must ensure that the input buffer + /// is either self-contained, (for example, a instance wrapping a new array that was + /// created), or that the owning object is not disposed until the returned is disposed. + /// + /// + /// If the input instance is one retrieved from an instance + /// rented from a memory pool (such as ), and that owning instance is disposed while the image is still + /// in use, this will lead to undefined behavior and possibly runtime crashes (as the same buffer might then be modified by other + /// consumers while the returned image is still working on it). Make sure to control the lifetime of the input buffers appropriately. + /// /// /// The pixel type. /// The pixel memory. @@ -81,7 +122,7 @@ namespace SixLabors.ImageSharp => WrapMemory(Configuration.Default, pixelMemory, width, height); /// - /// Wraps an existing contiguous memory area of 'width' x 'height' pixels, + /// Wraps an existing contiguous memory area of at least 'width' x 'height' pixels, /// allowing to view/manipulate it as an instance. /// The ownership of the is being transferred to the new instance, /// meaning that the caller is not allowed to dispose . @@ -106,14 +147,14 @@ namespace SixLabors.ImageSharp { Guard.NotNull(configuration, nameof(configuration)); Guard.NotNull(metadata, nameof(metadata)); - Guard.IsTrue(pixelMemoryOwner.Memory.Length == width * height, nameof(pixelMemoryOwner), "The length of the input memory doesn't match the specified image size"); + Guard.IsTrue(pixelMemoryOwner.Memory.Length >= width * height, nameof(pixelMemoryOwner), "The length of the input memory is less than the specified image size"); var memorySource = MemoryGroup.Wrap(pixelMemoryOwner); return new Image(configuration, memorySource, width, height, metadata); } /// - /// Wraps an existing contiguous memory area of 'width' x 'height' pixels, + /// Wraps an existing contiguous memory area of at least 'width' x 'height' pixels, /// allowing to view/manipulate it as an instance. /// The ownership of the is being transferred to the new instance, /// meaning that the caller is not allowed to dispose . @@ -135,7 +176,7 @@ namespace SixLabors.ImageSharp => WrapMemory(configuration, pixelMemoryOwner, width, height, new ImageMetadata()); /// - /// Wraps an existing contiguous memory area of 'width' x 'height' pixels, + /// Wraps an existing contiguous memory area of at least 'width' x 'height' pixels, /// allowing to view/manipulate it as an instance. /// The ownership of the is being transferred to the new instance, /// meaning that the caller is not allowed to dispose . @@ -154,8 +195,22 @@ namespace SixLabors.ImageSharp => WrapMemory(Configuration.Default, pixelMemoryOwner, width, height); /// - /// Wraps an existing contiguous memory area of 'width' x 'height' pixels, - /// allowing to view/manipulate it as an instance. + /// + /// Wraps an existing contiguous memory area of at least 'width' x 'height' pixels allowing viewing/manipulation as + /// an instance. + /// + /// + /// Please note: using this method does not transfer the ownership of the underlying buffer of the input + /// to the new instance. This means that consumers of this method must ensure that the input buffer + /// is either self-contained, (for example, a instance wrapping a new array that was + /// created), or that the owning object is not disposed until the returned is disposed. + /// + /// + /// If the input instance is one retrieved from an instance + /// rented from a memory pool (such as ), and that owning instance is disposed while the image is still + /// in use, this will lead to undefined behavior and possibly runtime crashes (as the same buffer might then be modified by other + /// consumers while the returned image is still working on it). Make sure to control the lifetime of the input buffers appropriately. + /// /// /// The pixel type /// The @@ -179,15 +234,29 @@ namespace SixLabors.ImageSharp var memoryManager = new ByteMemoryManager(byteMemory); - Guard.IsTrue(memoryManager.Memory.Length == width * height, nameof(byteMemory), "The length of the input memory doesn't match the specified image size"); + Guard.IsTrue(memoryManager.Memory.Length >= width * height, nameof(byteMemory), "The length of the input memory is less than the specified image size"); var memorySource = MemoryGroup.Wrap(memoryManager.Memory); return new Image(configuration, memorySource, width, height, metadata); } /// - /// Wraps an existing contiguous memory area of 'width' x 'height' pixels, - /// allowing to view/manipulate it as an instance. + /// + /// Wraps an existing contiguous memory area of at least 'width' x 'height' pixels allowing viewing/manipulation as + /// an instance. + /// + /// + /// Please note: using this method does not transfer the ownership of the underlying buffer of the input + /// to the new instance. This means that consumers of this method must ensure that the input buffer + /// is either self-contained, (for example, a instance wrapping a new array that was + /// created), or that the owning object is not disposed until the returned is disposed. + /// + /// + /// If the input instance is one retrieved from an instance + /// rented from a memory pool (such as ), and that owning instance is disposed while the image is still + /// in use, this will lead to undefined behavior and possibly runtime crashes (as the same buffer might then be modified by other + /// consumers while the returned image is still working on it). Make sure to control the lifetime of the input buffers appropriately. + /// /// /// The pixel type /// The @@ -205,9 +274,22 @@ namespace SixLabors.ImageSharp => WrapMemory(configuration, byteMemory, width, height, new ImageMetadata()); /// - /// Wraps an existing contiguous memory area of 'width' x 'height' pixels, - /// allowing to view/manipulate it as an instance. - /// The memory is being observed, the caller remains responsible for managing it's lifecycle. + /// + /// Wraps an existing contiguous memory area of at least 'width' x 'height' pixels allowing viewing/manipulation as + /// an instance. + /// + /// + /// Please note: using this method does not transfer the ownership of the underlying buffer of the input + /// to the new instance. This means that consumers of this method must ensure that the input buffer + /// is either self-contained, (for example, a instance wrapping a new array that was + /// created), or that the owning object is not disposed until the returned is disposed. + /// + /// + /// If the input instance is one retrieved from an instance + /// rented from a memory pool (such as ), and that owning instance is disposed while the image is still + /// in use, this will lead to undefined behavior and possibly runtime crashes (as the same buffer might then be modified by other + /// consumers while the returned image is still working on it). Make sure to control the lifetime of the input buffers appropriately. + /// /// /// The pixel type. /// The byte memory representing the pixel data. @@ -220,5 +302,128 @@ namespace SixLabors.ImageSharp int height) where TPixel : unmanaged, IPixel => WrapMemory(Configuration.Default, byteMemory, width, height); + + /// + /// + /// Wraps an existing contiguous memory area of at least 'width' x 'height' pixels allowing viewing/manipulation as + /// an instance. + /// + /// + /// Please note: this method relies on callers to carefully manage the target memory area being referenced by the + /// pointer and that the lifetime of such a memory area is at least equal to that of the returned + /// instance. For example, if the input pointer references an unmanaged memory area, + /// callers must ensure that the memory area is not freed as long as the returned is + /// in use and not disposed. The same applies if the input memory area points to a pinned managed object, as callers + /// must ensure that objects will remain pinned as long as the instance is in use. + /// Failing to do so constitutes undefined behavior and will likely lead to memory corruption and runtime crashes. + /// + /// + /// Note also that if you have a or an array (which can be cast to ) of + /// either or values, it is highly recommended to use one of the other + /// available overloads of this method instead (such as + /// or , to make the resulting code less error + /// prone and avoid having to pin the underlying memory buffer in use. This method is primarily meant to be used when + /// doing interop or working with buffers that are located in unmanaged memory. + /// + /// + /// The pixel type + /// The + /// The pointer to the target memory buffer to wrap. + /// The width of the memory image. + /// The height of the memory image. + /// The . + /// The configuration is null. + /// The metadata is null. + /// An instance + public static unsafe Image WrapMemory( + Configuration configuration, + void* pointer, + int width, + int height, + ImageMetadata metadata) + where TPixel : unmanaged, IPixel + { + Guard.IsFalse(pointer == null, nameof(pointer), "Pointer must be not null"); + Guard.NotNull(configuration, nameof(configuration)); + Guard.NotNull(metadata, nameof(metadata)); + + var memoryManager = new UnmanagedMemoryManager(pointer, width * height); + + var memorySource = MemoryGroup.Wrap(memoryManager.Memory); + return new Image(configuration, memorySource, width, height, metadata); + } + + /// + /// + /// Wraps an existing contiguous memory area of at least 'width' x 'height' pixels allowing viewing/manipulation as + /// an instance. + /// + /// + /// Please note: this method relies on callers to carefully manage the target memory area being referenced by the + /// pointer and that the lifetime of such a memory area is at least equal to that of the returned + /// instance. For example, if the input pointer references an unmanaged memory area, + /// callers must ensure that the memory area is not freed as long as the returned is + /// in use and not disposed. The same applies if the input memory area points to a pinned managed object, as callers + /// must ensure that objects will remain pinned as long as the instance is in use. + /// Failing to do so constitutes undefined behavior and will likely lead to memory corruption and runtime crashes. + /// + /// + /// Note also that if you have a or an array (which can be cast to ) of + /// either or values, it is highly recommended to use one of the other + /// available overloads of this method instead (such as + /// or , to make the resulting code less error + /// prone and avoid having to pin the underlying memory buffer in use. This method is primarily meant to be used when + /// doing interop or working with buffers that are located in unmanaged memory. + /// + /// + /// The pixel type + /// The + /// The pointer to the target memory buffer to wrap. + /// The width of the memory image. + /// The height of the memory image. + /// The configuration is null. + /// An instance. + public static unsafe Image WrapMemory( + Configuration configuration, + void* pointer, + int width, + int height) + where TPixel : unmanaged, IPixel + => WrapMemory(configuration, pointer, width, height, new ImageMetadata()); + + /// + /// + /// Wraps an existing contiguous memory area of at least 'width' x 'height' pixels allowing viewing/manipulation as + /// an instance. + /// + /// + /// Please note: this method relies on callers to carefully manage the target memory area being referenced by the + /// pointer and that the lifetime of such a memory area is at least equal to that of the returned + /// instance. For example, if the input pointer references an unmanaged memory area, + /// callers must ensure that the memory area is not freed as long as the returned is + /// in use and not disposed. The same applies if the input memory area points to a pinned managed object, as callers + /// must ensure that objects will remain pinned as long as the instance is in use. + /// Failing to do so constitutes undefined behavior and will likely lead to memory corruption and runtime crashes. + /// + /// + /// Note also that if you have a or an array (which can be cast to ) of + /// either or values, it is highly recommended to use one of the other + /// available overloads of this method instead (such as + /// or , to make the resulting code less error + /// prone and avoid having to pin the underlying memory buffer in use. This method is primarily meant to be used when + /// doing interop or working with buffers that are located in unmanaged memory. + /// + /// + /// The pixel type. + /// The pointer to the target memory buffer to wrap. + /// The width of the memory image. + /// The height of the memory image. + /// An instance. + public static unsafe Image WrapMemory( + void* pointer, + int width, + int height) + where TPixel : unmanaged, IPixel + => WrapMemory(Configuration.Default, pointer, width, height); } } diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index c3d9618c8c..832d551fd7 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -4,41 +4,48 @@ SixLabors.ImageSharp SixLabors.ImageSharp - A cross-platform library for the processing of image files; written in C# - en - - $(packageversion) - 0.0.1 - - netcoreapp3.1;netcoreapp2.1;netstandard2.1;netstandard2.0;netstandard1.3;net472 - - true - true - SixLabors.ImageSharp - Image Resize Crop Gif Jpg Jpeg Bitmap Png Core SixLabors.ImageSharp + SixLabors.ImageSharp + sixlabors.imagesharp.128.png + Apache-2.0 + https://github.com/SixLabors/ImageSharp/ + $(RepositoryUrl) + Image Resize Crop Gif Jpg Jpeg Bitmap Png Tga NetCore + A new, fully featured, fully managed, cross-platform, 2D graphics API for .NET + + + + net5.0;netcoreapp3.1;netcoreapp2.1;netstandard2.1;netstandard2.0;netstandard1.3;net472 + + + + + netcoreapp3.1;netcoreapp2.1;netstandard2.1;netstandard2.0;netstandard1.3;net472 + + + + - - + - - + + - - - + + + - - - - + + + + @@ -62,62 +69,62 @@ True PixelOperations{TPixel}.Generated.tt - + True True Argb32.PixelOperations.Generated.tt - + True True Bgr24.PixelOperations.Generated.tt - + True True Bgra32.PixelOperations.Generated.tt - + True True Bgra5551.PixelOperations.Generated.tt - + True True - L8.PixelOperations.Generated.tt + L16.PixelOperations.Generated.tt - + True True - L16.PixelOperations.Generated.tt + L8.PixelOperations.Generated.tt - + True True La16.PixelOperations.Generated.tt - + True True La32.PixelOperations.Generated.tt - + True True Rgb24.PixelOperations.Generated.tt - + True True - Rgba32.PixelOperations.Generated.tt + Rgb48.PixelOperations.Generated.tt - + True True - Rgb48.PixelOperations.Generated.tt + Rgba32.PixelOperations.Generated.tt - + True True Rgba64.PixelOperations.Generated.tt @@ -156,51 +163,51 @@ TextTemplatingFileGenerator PixelOperations{TPixel}.Generated.cs - + TextTemplatingFileGenerator Argb32.PixelOperations.Generated.cs - + TextTemplatingFileGenerator Bgr24.PixelOperations.Generated.cs - + TextTemplatingFileGenerator Bgra32.PixelOperations.Generated.cs - + TextTemplatingFileGenerator Bgra5551.PixelOperations.Generated.cs - + TextTemplatingFileGenerator L8.PixelOperations.Generated.cs - + TextTemplatingFileGenerator L16.PixelOperations.Generated.cs - + TextTemplatingFileGenerator La16.PixelOperations.Generated.cs - + TextTemplatingFileGenerator La32.PixelOperations.Generated.cs - + TextTemplatingFileGenerator Rgb24.PixelOperations.Generated.cs - + TextTemplatingFileGenerator Rgba32.PixelOperations.Generated.cs - + TextTemplatingFileGenerator Rgb48.PixelOperations.Generated.cs - + TextTemplatingFileGenerator Rgba64.PixelOperations.Generated.cs diff --git a/src/ImageSharp/Image{TPixel}.cs b/src/ImageSharp/Image{TPixel}.cs index 255193c8ea..83ecc37530 100644 --- a/src/ImageSharp/Image{TPixel}.cs +++ b/src/ImageSharp/Image{TPixel}.cs @@ -201,14 +201,14 @@ namespace SixLabors.ImageSharp public bool TryGetSinglePixelSpan(out Span span) { IMemoryGroup mg = this.GetPixelMemoryGroup(); - if (mg.Count > 1) + if (mg.Count == 1) { - span = default; - return false; + span = mg[0].Span; + return true; } - span = mg.Single().Span; - return true; + span = default; + return false; } /// diff --git a/src/ImageSharp/Memory/Allocators/ArrayPoolMemoryAllocator.Buffer{T}.cs b/src/ImageSharp/Memory/Allocators/ArrayPoolMemoryAllocator.Buffer{T}.cs index a7a51f77dd..0c35c88286 100644 --- a/src/ImageSharp/Memory/Allocators/ArrayPoolMemoryAllocator.Buffer{T}.cs +++ b/src/ImageSharp/Memory/Allocators/ArrayPoolMemoryAllocator.Buffer{T}.cs @@ -53,8 +53,13 @@ namespace SixLabors.ImageSharp.Memory { ThrowObjectDisposedException(); } - +#if SUPPORTS_CREATESPAN + ref byte r0 = ref MemoryMarshal.GetReference(this.Data); + return MemoryMarshal.CreateSpan(ref Unsafe.As(ref r0), this.length); +#else return MemoryMarshal.Cast(this.Data.AsSpan()).Slice(0, this.length); +#endif + } /// diff --git a/src/ImageSharp/Memory/ByteMemoryManager{T}.cs b/src/ImageSharp/Memory/ByteMemoryManager{T}.cs index 223709df65..1731639582 100644 --- a/src/ImageSharp/Memory/ByteMemoryManager{T}.cs +++ b/src/ImageSharp/Memory/ByteMemoryManager{T}.cs @@ -1,5 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. + using System; using System.Buffers; using System.Runtime.CompilerServices; diff --git a/src/ImageSharp/Memory/UnmanagedMemoryManager{T}.cs b/src/ImageSharp/Memory/UnmanagedMemoryManager{T}.cs new file mode 100644 index 0000000000..58eaee320a --- /dev/null +++ b/src/ImageSharp/Memory/UnmanagedMemoryManager{T}.cs @@ -0,0 +1,60 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; + +namespace SixLabors.ImageSharp.Memory +{ + /// + /// A custom that can wrap a rawpointer to a buffer of a specified type. + /// + /// The value type to use when casting the wrapped instance. + /// This manager doesn't own the memory buffer that it points to. + internal sealed unsafe class UnmanagedMemoryManager : MemoryManager + where T : unmanaged + { + /// + /// The pointer to the memory buffer. + /// + private readonly void* pointer; + + /// + /// The length of the memory area. + /// + private readonly int length; + + /// + /// Initializes a new instance of the class. + /// + /// The pointer to the memory buffer. + /// The length of the memory area. + public UnmanagedMemoryManager(void* pointer, int length) + { + this.pointer = pointer; + this.length = length; + } + + /// + protected override void Dispose(bool disposing) + { + } + + /// + public override Span GetSpan() + { + return new Span(this.pointer, this.length); + } + + /// + public override MemoryHandle Pin(int elementIndex = 0) + { + return new MemoryHandle(((T*)this.pointer) + elementIndex); + } + + /// + public override void Unpin() + { + } + } +} diff --git a/src/ImageSharp/Metadata/Profiles/Exif/DC-008-Translation-2019-E.pdf b/src/ImageSharp/Metadata/Profiles/Exif/DC-008-Translation-2019-E.pdf deleted file mode 100644 index 9be0c8402b..0000000000 Binary files a/src/ImageSharp/Metadata/Profiles/Exif/DC-008-Translation-2019-E.pdf and /dev/null differ diff --git a/src/ImageSharp/Metadata/Profiles/Exif/DC-X008-Translation-2019-E.pdf b/src/ImageSharp/Metadata/Profiles/Exif/DC-X008-Translation-2019-E.pdf new file mode 100644 index 0000000000..cd7141fc8d Binary files /dev/null and b/src/ImageSharp/Metadata/Profiles/Exif/DC-X008-Translation-2019-E.pdf differ diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.cs index 925a86ac20..8e9cad5636 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.cs @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// The new index position public void SetIndex(int index) { - this.currentIndex = index.Clamp(0, this.data.Length); + this.currentIndex = Numerics.Clamp(index, 0, this.data.Length); } /// diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Lut.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Lut.cs index a5eef3d237..40a1792e2d 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Lut.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Lut.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. namespace SixLabors.ImageSharp.Metadata.Profiles.Icc @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { foreach (float item in value.Values) { - this.WriteByte((byte)((item * byte.MaxValue) + 0.5f).Clamp(0, byte.MaxValue)); + this.WriteByte((byte)Numerics.Clamp((item * byte.MaxValue) + 0.5F, 0, byte.MaxValue)); } return value.Values.Length; @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { foreach (float item in value.Values) { - this.WriteUInt16((ushort)((item * ushort.MaxValue) + 0.5f).Clamp(0, ushort.MaxValue)); + this.WriteUInt16((ushort)Numerics.Clamp((item * ushort.MaxValue) + 0.5F, 0, ushort.MaxValue)); } return value.Values.Length * 2; @@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { foreach (float item in inArray) { - count += this.WriteByte((byte)((item * byte.MaxValue) + 0.5f).Clamp(0, byte.MaxValue)); + count += this.WriteByte((byte)Numerics.Clamp((item * byte.MaxValue) + 0.5F, 0, byte.MaxValue)); } } @@ -97,7 +97,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc { foreach (float item in inArray) { - count += this.WriteUInt16((ushort)((item * ushort.MaxValue) + 0.5f).Clamp(0, ushort.MaxValue)); + count += this.WriteUInt16((ushort)Numerics.Clamp((item * ushort.MaxValue) + 0.5F, 0, ushort.MaxValue)); } } diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs index 53dd5f008b..305fe47fd5 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs @@ -33,9 +33,9 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc /// the number of bytes written public int WriteVersionNumber(in IccVersion value) { - int major = value.Major.Clamp(0, byte.MaxValue); - int minor = value.Minor.Clamp(0, 15); - int bugfix = value.Patch.Clamp(0, 15); + int major = Numerics.Clamp(value.Major, 0, byte.MaxValue); + int minor = Numerics.Clamp(value.Minor, 0, 15); + int bugfix = Numerics.Clamp(value.Patch, 0, 15); int version = (major << 24) | (minor << 20) | (bugfix << 16); return this.WriteInt32(version); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs index 5fb8e57d2f..c58dd96565 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System; @@ -112,7 +112,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc const double Max = short.MaxValue + (65535d / 65536d); const double Min = short.MinValue; - value = value.Clamp(Min, Max); + value = Numerics.Clamp(value, Min, Max); value *= 65536d; return this.WriteInt32((int)Math.Round(value, MidpointRounding.AwayFromZero)); @@ -128,7 +128,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc const double Max = ushort.MaxValue + (65535d / 65536d); const double Min = ushort.MinValue; - value = value.Clamp(Min, Max); + value = Numerics.Clamp(value, Min, Max); value *= 65536d; return this.WriteUInt32((uint)Math.Round(value, MidpointRounding.AwayFromZero)); @@ -144,7 +144,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc const double Max = 1 + (32767d / 32768d); const double Min = 0; - value = value.Clamp(Min, Max); + value = Numerics.Clamp(value, Min, Max); value *= 32768d; return this.WriteUInt16((ushort)Math.Round(value, MidpointRounding.AwayFromZero)); @@ -160,7 +160,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc const double Max = byte.MaxValue + (255d / 256d); const double Min = byte.MinValue; - value = value.Clamp(Min, Max); + value = Numerics.Clamp(value, Min, Max); value *= 256d; return this.WriteUInt16((ushort)Math.Round(value, MidpointRounding.AwayFromZero)); diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs index fdbf2a4778..25454fa951 100644 --- a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs +++ b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs @@ -240,7 +240,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc count += this.WriteUInt32((uint)value.CurveData.Length); for (int i = 0; i < value.CurveData.Length; i++) { - count += this.WriteUInt16((ushort)((value.CurveData[i] * ushort.MaxValue) + 0.5f).Clamp(0, ushort.MaxValue)); + count += this.WriteUInt16((ushort)Numerics.Clamp((value.CurveData[i] * ushort.MaxValue) + 0.5F, 0, ushort.MaxValue)); } } diff --git a/src/ImageSharp/PixelFormats/PixelAlphaRepresentation.cs b/src/ImageSharp/PixelFormats/PixelAlphaRepresentation.cs new file mode 100644 index 0000000000..4690fb66ab --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelAlphaRepresentation.cs @@ -0,0 +1,32 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.PixelFormats +{ + /// + /// Provides enumeration of the alpha value transparency behavior of a pixel format. + /// + public enum PixelAlphaRepresentation + { + /// + /// Indicates that the pixel format does not contain an alpha channel. + /// + None, + + /// + /// 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. + /// + Associated, + + /// + /// Indicates that the transparency behavior is not premultiplied. + /// The alpha channel indicates the transparency of the color. + /// + Unassociated + } +} diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs b/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs index 2cb528a036..db61d9383a 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs @@ -36,14 +36,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.NormalSrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.NormalSrc(background[i], source[i], amount); @@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.NormalSrc(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.NormalSrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -74,14 +74,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplySrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.MultiplySrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.MultiplySrc(background[i], source[i], amount); @@ -93,7 +93,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.MultiplySrc(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.MultiplySrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -112,14 +112,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.AddSrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.AddSrc(background[i], source[i], amount); @@ -131,7 +131,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.AddSrc(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.AddSrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -150,14 +150,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.SubtractSrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.SubtractSrc(background[i], source[i], amount); @@ -169,7 +169,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.SubtractSrc(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.SubtractSrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -188,14 +188,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.ScreenSrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.ScreenSrc(background[i], source[i], amount); @@ -207,7 +207,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.ScreenSrc(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.ScreenSrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -226,14 +226,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.DarkenSrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.DarkenSrc(background[i], source[i], amount); @@ -245,7 +245,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.DarkenSrc(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.DarkenSrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -264,14 +264,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.LightenSrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.LightenSrc(background[i], source[i], amount); @@ -283,7 +283,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.LightenSrc(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.LightenSrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -302,14 +302,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlaySrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.OverlaySrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.OverlaySrc(background[i], source[i], amount); @@ -321,7 +321,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.OverlaySrc(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.OverlaySrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -340,14 +340,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.HardLightSrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.HardLightSrc(background[i], source[i], amount); @@ -359,7 +359,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.HardLightSrc(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.HardLightSrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -378,14 +378,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.NormalSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.NormalSrcAtop(background[i], source[i], amount); @@ -397,7 +397,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.NormalSrcAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.NormalSrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -416,14 +416,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.MultiplySrcAtop(background[i], source[i], amount); @@ -435,7 +435,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.MultiplySrcAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.MultiplySrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -454,14 +454,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.AddSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.AddSrcAtop(background[i], source[i], amount); @@ -473,7 +473,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.AddSrcAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.AddSrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -492,14 +492,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.SubtractSrcAtop(background[i], source[i], amount); @@ -511,7 +511,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.SubtractSrcAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.SubtractSrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -530,14 +530,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.ScreenSrcAtop(background[i], source[i], amount); @@ -549,7 +549,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.ScreenSrcAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.ScreenSrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -568,14 +568,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.DarkenSrcAtop(background[i], source[i], amount); @@ -587,7 +587,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.DarkenSrcAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.DarkenSrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -606,14 +606,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.LightenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.LightenSrcAtop(background[i], source[i], amount); @@ -625,7 +625,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.LightenSrcAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.LightenSrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -644,14 +644,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.OverlaySrcAtop(background[i], source[i], amount); @@ -663,7 +663,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.OverlaySrcAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.OverlaySrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -682,14 +682,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.HardLightSrcAtop(background[i], source[i], amount); @@ -701,7 +701,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.HardLightSrcAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.HardLightSrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -720,14 +720,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.NormalSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.NormalSrcOver(background[i], source[i], amount); @@ -739,7 +739,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.NormalSrcOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.NormalSrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -758,14 +758,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.MultiplySrcOver(background[i], source[i], amount); @@ -777,7 +777,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.MultiplySrcOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.MultiplySrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -796,14 +796,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.AddSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.AddSrcOver(background[i], source[i], amount); @@ -815,7 +815,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.AddSrcOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.AddSrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -834,14 +834,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.SubtractSrcOver(background[i], source[i], amount); @@ -853,7 +853,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.SubtractSrcOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.SubtractSrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -872,14 +872,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.ScreenSrcOver(background[i], source[i], amount); @@ -891,7 +891,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.ScreenSrcOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.ScreenSrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -910,14 +910,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.DarkenSrcOver(background[i], source[i], amount); @@ -929,7 +929,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.DarkenSrcOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.DarkenSrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -948,14 +948,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.LightenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.LightenSrcOver(background[i], source[i], amount); @@ -967,7 +967,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.LightenSrcOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.LightenSrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -986,14 +986,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.OverlaySrcOver(background[i], source[i], amount); @@ -1005,7 +1005,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.OverlaySrcOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.OverlaySrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1024,14 +1024,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.HardLightSrcOver(background[i], source[i], amount); @@ -1043,7 +1043,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.HardLightSrcOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.HardLightSrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1062,14 +1062,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.NormalSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.NormalSrcIn(background[i], source[i], amount); @@ -1081,7 +1081,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.NormalSrcIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.NormalSrcIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1100,14 +1100,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.MultiplySrcIn(background[i], source[i], amount); @@ -1119,7 +1119,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.MultiplySrcIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.MultiplySrcIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1138,14 +1138,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.AddSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.AddSrcIn(background[i], source[i], amount); @@ -1157,7 +1157,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.AddSrcIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.AddSrcIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1176,14 +1176,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.SubtractSrcIn(background[i], source[i], amount); @@ -1195,7 +1195,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.SubtractSrcIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.SubtractSrcIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1214,14 +1214,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.ScreenSrcIn(background[i], source[i], amount); @@ -1233,7 +1233,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.ScreenSrcIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.ScreenSrcIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1252,14 +1252,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.DarkenSrcIn(background[i], source[i], amount); @@ -1271,7 +1271,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.DarkenSrcIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.DarkenSrcIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1290,14 +1290,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.LightenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.LightenSrcIn(background[i], source[i], amount); @@ -1309,7 +1309,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.LightenSrcIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.LightenSrcIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1328,14 +1328,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.OverlaySrcIn(background[i], source[i], amount); @@ -1347,7 +1347,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.OverlaySrcIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.OverlaySrcIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1366,14 +1366,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.HardLightSrcIn(background[i], source[i], amount); @@ -1385,7 +1385,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.HardLightSrcIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.HardLightSrcIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1404,14 +1404,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.NormalSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.NormalSrcOut(background[i], source[i], amount); @@ -1423,7 +1423,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.NormalSrcOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.NormalSrcOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1442,14 +1442,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.MultiplySrcOut(background[i], source[i], amount); @@ -1461,7 +1461,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.MultiplySrcOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.MultiplySrcOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1480,14 +1480,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.AddSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.AddSrcOut(background[i], source[i], amount); @@ -1499,7 +1499,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.AddSrcOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.AddSrcOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1518,14 +1518,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.SubtractSrcOut(background[i], source[i], amount); @@ -1537,7 +1537,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.SubtractSrcOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.SubtractSrcOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1556,14 +1556,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.ScreenSrcOut(background[i], source[i], amount); @@ -1575,7 +1575,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.ScreenSrcOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.ScreenSrcOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1594,14 +1594,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.DarkenSrcOut(background[i], source[i], amount); @@ -1613,7 +1613,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.DarkenSrcOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.DarkenSrcOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1632,14 +1632,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.LightenSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.LightenSrcOut(background[i], source[i], amount); @@ -1651,7 +1651,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.LightenSrcOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.LightenSrcOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1670,14 +1670,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.OverlaySrcOut(background[i], source[i], amount); @@ -1689,7 +1689,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.OverlaySrcOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.OverlaySrcOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1708,14 +1708,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.HardLightSrcOut(background[i], source[i], amount); @@ -1727,7 +1727,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.HardLightSrcOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.HardLightSrcOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1746,14 +1746,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.NormalDest(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.NormalDest(background[i], source[i], amount); @@ -1765,7 +1765,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.NormalDest(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.NormalDest(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1784,14 +1784,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplyDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.MultiplyDest(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.MultiplyDest(background[i], source[i], amount); @@ -1803,7 +1803,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.MultiplyDest(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.MultiplyDest(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1822,14 +1822,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.AddDest(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.AddDest(background[i], source[i], amount); @@ -1841,7 +1841,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.AddDest(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.AddDest(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1860,14 +1860,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.SubtractDest(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.SubtractDest(background[i], source[i], amount); @@ -1879,7 +1879,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.SubtractDest(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.SubtractDest(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1898,14 +1898,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.ScreenDest(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.ScreenDest(background[i], source[i], amount); @@ -1917,7 +1917,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.ScreenDest(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.ScreenDest(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1936,14 +1936,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.DarkenDest(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.DarkenDest(background[i], source[i], amount); @@ -1955,7 +1955,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.DarkenDest(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.DarkenDest(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -1974,14 +1974,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.LightenDest(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.LightenDest(background[i], source[i], amount); @@ -1993,7 +1993,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.LightenDest(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.LightenDest(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2012,14 +2012,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlayDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.OverlayDest(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.OverlayDest(background[i], source[i], amount); @@ -2031,7 +2031,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.OverlayDest(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.OverlayDest(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2050,14 +2050,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightDest(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.HardLightDest(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.HardLightDest(background[i], source[i], amount); @@ -2069,7 +2069,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.HardLightDest(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.HardLightDest(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2088,14 +2088,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.NormalDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.NormalDestAtop(background[i], source[i], amount); @@ -2107,7 +2107,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.NormalDestAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.NormalDestAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2126,14 +2126,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplyDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.MultiplyDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.MultiplyDestAtop(background[i], source[i], amount); @@ -2145,7 +2145,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.MultiplyDestAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.MultiplyDestAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2164,14 +2164,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.AddDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.AddDestAtop(background[i], source[i], amount); @@ -2183,7 +2183,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.AddDestAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.AddDestAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2202,14 +2202,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.SubtractDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.SubtractDestAtop(background[i], source[i], amount); @@ -2221,7 +2221,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.SubtractDestAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.SubtractDestAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2240,14 +2240,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.ScreenDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.ScreenDestAtop(background[i], source[i], amount); @@ -2259,7 +2259,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.ScreenDestAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.ScreenDestAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2278,14 +2278,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.DarkenDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.DarkenDestAtop(background[i], source[i], amount); @@ -2297,7 +2297,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.DarkenDestAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.DarkenDestAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2316,14 +2316,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.LightenDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.LightenDestAtop(background[i], source[i], amount); @@ -2335,7 +2335,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.LightenDestAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.LightenDestAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2354,14 +2354,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlayDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.OverlayDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.OverlayDestAtop(background[i], source[i], amount); @@ -2373,7 +2373,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.OverlayDestAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.OverlayDestAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2392,14 +2392,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.HardLightDestAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.HardLightDestAtop(background[i], source[i], amount); @@ -2411,7 +2411,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.HardLightDestAtop(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.HardLightDestAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2430,14 +2430,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.NormalDestOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.NormalDestOver(background[i], source[i], amount); @@ -2449,7 +2449,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.NormalDestOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.NormalDestOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2468,14 +2468,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplyDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.MultiplyDestOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.MultiplyDestOver(background[i], source[i], amount); @@ -2487,7 +2487,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.MultiplyDestOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.MultiplyDestOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2506,14 +2506,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.AddDestOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.AddDestOver(background[i], source[i], amount); @@ -2525,7 +2525,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.AddDestOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.AddDestOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2544,14 +2544,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.SubtractDestOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.SubtractDestOver(background[i], source[i], amount); @@ -2563,7 +2563,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.SubtractDestOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.SubtractDestOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2582,14 +2582,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.ScreenDestOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.ScreenDestOver(background[i], source[i], amount); @@ -2601,7 +2601,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.ScreenDestOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.ScreenDestOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2620,14 +2620,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.DarkenDestOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.DarkenDestOver(background[i], source[i], amount); @@ -2639,7 +2639,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.DarkenDestOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.DarkenDestOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2658,14 +2658,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.LightenDestOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.LightenDestOver(background[i], source[i], amount); @@ -2677,7 +2677,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.LightenDestOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.LightenDestOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2696,14 +2696,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlayDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.OverlayDestOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.OverlayDestOver(background[i], source[i], amount); @@ -2715,7 +2715,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.OverlayDestOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.OverlayDestOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2734,14 +2734,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightDestOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.HardLightDestOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.HardLightDestOver(background[i], source[i], amount); @@ -2753,7 +2753,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.HardLightDestOver(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.HardLightDestOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2772,14 +2772,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.NormalDestIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.NormalDestIn(background[i], source[i], amount); @@ -2791,7 +2791,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.NormalDestIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.NormalDestIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2810,14 +2810,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplyDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.MultiplyDestIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.MultiplyDestIn(background[i], source[i], amount); @@ -2829,7 +2829,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.MultiplyDestIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.MultiplyDestIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2848,14 +2848,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.AddDestIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.AddDestIn(background[i], source[i], amount); @@ -2867,7 +2867,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.AddDestIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.AddDestIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2886,14 +2886,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.SubtractDestIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.SubtractDestIn(background[i], source[i], amount); @@ -2905,7 +2905,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.SubtractDestIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.SubtractDestIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2924,14 +2924,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.ScreenDestIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.ScreenDestIn(background[i], source[i], amount); @@ -2943,7 +2943,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.ScreenDestIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.ScreenDestIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -2962,14 +2962,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.DarkenDestIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.DarkenDestIn(background[i], source[i], amount); @@ -2981,7 +2981,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.DarkenDestIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.DarkenDestIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3000,14 +3000,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.LightenDestIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.LightenDestIn(background[i], source[i], amount); @@ -3019,7 +3019,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.LightenDestIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.LightenDestIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3038,14 +3038,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlayDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.OverlayDestIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.OverlayDestIn(background[i], source[i], amount); @@ -3057,7 +3057,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.OverlayDestIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.OverlayDestIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3076,14 +3076,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightDestIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.HardLightDestIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.HardLightDestIn(background[i], source[i], amount); @@ -3095,7 +3095,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.HardLightDestIn(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.HardLightDestIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3114,14 +3114,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.NormalDestOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.NormalDestOut(background[i], source[i], amount); @@ -3133,7 +3133,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.NormalDestOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.NormalDestOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3152,14 +3152,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplyDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.MultiplyDestOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.MultiplyDestOut(background[i], source[i], amount); @@ -3171,7 +3171,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.MultiplyDestOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.MultiplyDestOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3190,14 +3190,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.AddDestOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.AddDestOut(background[i], source[i], amount); @@ -3209,7 +3209,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.AddDestOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.AddDestOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3228,14 +3228,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.SubtractDestOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.SubtractDestOut(background[i], source[i], amount); @@ -3247,7 +3247,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.SubtractDestOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.SubtractDestOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3266,14 +3266,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.ScreenDestOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.ScreenDestOut(background[i], source[i], amount); @@ -3285,7 +3285,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.ScreenDestOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.ScreenDestOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3304,14 +3304,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.DarkenDestOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.DarkenDestOut(background[i], source[i], amount); @@ -3323,7 +3323,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.DarkenDestOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.DarkenDestOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3342,14 +3342,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.LightenDestOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.LightenDestOut(background[i], source[i], amount); @@ -3361,7 +3361,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.LightenDestOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.LightenDestOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3380,14 +3380,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlayDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.OverlayDestOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.OverlayDestOut(background[i], source[i], amount); @@ -3399,7 +3399,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.OverlayDestOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.OverlayDestOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3418,14 +3418,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightDestOut(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.HardLightDestOut(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.HardLightDestOut(background[i], source[i], amount); @@ -3437,7 +3437,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.HardLightDestOut(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.HardLightDestOut(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3456,14 +3456,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.NormalClear(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.NormalClear(background[i], source[i], amount); @@ -3475,7 +3475,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.NormalClear(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.NormalClear(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3494,14 +3494,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplyClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.MultiplyClear(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.MultiplyClear(background[i], source[i], amount); @@ -3513,7 +3513,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.MultiplyClear(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.MultiplyClear(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3532,14 +3532,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.AddClear(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.AddClear(background[i], source[i], amount); @@ -3551,7 +3551,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.AddClear(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.AddClear(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3570,14 +3570,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.SubtractClear(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.SubtractClear(background[i], source[i], amount); @@ -3589,7 +3589,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.SubtractClear(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.SubtractClear(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3608,14 +3608,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.ScreenClear(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.ScreenClear(background[i], source[i], amount); @@ -3627,7 +3627,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.ScreenClear(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.ScreenClear(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3646,14 +3646,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.DarkenClear(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.DarkenClear(background[i], source[i], amount); @@ -3665,7 +3665,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.DarkenClear(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.DarkenClear(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3684,14 +3684,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.LightenClear(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.LightenClear(background[i], source[i], amount); @@ -3703,7 +3703,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.LightenClear(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.LightenClear(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3722,14 +3722,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlayClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.OverlayClear(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.OverlayClear(background[i], source[i], amount); @@ -3741,7 +3741,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.OverlayClear(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.OverlayClear(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3760,14 +3760,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightClear(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.HardLightClear(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.HardLightClear(background[i], source[i], amount); @@ -3779,7 +3779,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.HardLightClear(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.HardLightClear(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3798,14 +3798,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.NormalXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.NormalXor(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.NormalXor(background[i], source[i], amount); @@ -3817,7 +3817,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.NormalXor(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.NormalXor(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3836,14 +3836,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.MultiplyXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.MultiplyXor(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.MultiplyXor(background[i], source[i], amount); @@ -3855,7 +3855,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.MultiplyXor(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.MultiplyXor(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3874,14 +3874,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.AddXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.AddXor(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.AddXor(background[i], source[i], amount); @@ -3893,7 +3893,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.AddXor(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.AddXor(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3912,14 +3912,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.SubtractXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.SubtractXor(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.SubtractXor(background[i], source[i], amount); @@ -3931,7 +3931,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.SubtractXor(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.SubtractXor(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3950,14 +3950,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.ScreenXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.ScreenXor(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.ScreenXor(background[i], source[i], amount); @@ -3969,7 +3969,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.ScreenXor(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.ScreenXor(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -3988,14 +3988,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.DarkenXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.DarkenXor(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.DarkenXor(background[i], source[i], amount); @@ -4007,7 +4007,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.DarkenXor(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.DarkenXor(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -4026,14 +4026,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.LightenXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.LightenXor(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.LightenXor(background[i], source[i], amount); @@ -4045,7 +4045,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.LightenXor(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.LightenXor(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -4064,14 +4064,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.OverlayXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.OverlayXor(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.OverlayXor(background[i], source[i], amount); @@ -4083,7 +4083,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.OverlayXor(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.OverlayXor(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } @@ -4102,14 +4102,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.HardLightXor(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.HardLightXor(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.HardLightXor(background[i], source[i], amount); @@ -4121,7 +4121,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.HardLightXor(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.HardLightXor(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt b/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt index 46990b53c9..694931fe7d 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt @@ -79,14 +79,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public override TPixel Blend(TPixel background, TPixel source, float amount) { TPixel dest = default; - dest.FromScaledVector4(PorterDuffFunctions.<#=blender_composer#>(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1))); + dest.FromScaledVector4(PorterDuffFunctions.<#=blender_composer#>(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1))); return dest; } /// protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount) { - amount = amount.Clamp(0, 1); + amount = Numerics.Clamp(amount, 0, 1); for (int i = 0; i < destination.Length; i++) { destination[i] = PorterDuffFunctions.<#=blender_composer#>(background[i], source[i], amount); @@ -98,7 +98,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders { for (int i = 0; i < destination.Length; i++) { - destination[i] = PorterDuffFunctions.<#=blender_composer#>(background[i], source[i], amount[i].Clamp(0, 1)); + destination[i] = PorterDuffFunctions.<#=blender_composer#>(background[i], source[i], Numerics.Clamp(amount[i], 0, 1)); } } } diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs index 5fccb1fa68..cd67db32bb 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs @@ -203,7 +203,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel NormalSrc(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(NormalSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -222,7 +222,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel NormalSrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(NormalSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -241,7 +241,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel NormalSrcOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(NormalSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -260,7 +260,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel NormalSrcIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(NormalSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -279,7 +279,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel NormalSrcOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(NormalSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -298,7 +298,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel NormalDest(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(NormalDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -317,7 +317,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel NormalDestAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(NormalDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -336,7 +336,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel NormalDestOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(NormalDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -355,7 +355,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel NormalDestIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(NormalDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -374,7 +374,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel NormalDestOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(NormalDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -393,7 +393,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel NormalClear(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(NormalClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -412,7 +412,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel NormalXor(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(NormalXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -608,7 +608,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel MultiplySrc(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(MultiplySrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -627,7 +627,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel MultiplySrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(MultiplySrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -646,7 +646,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel MultiplySrcOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(MultiplySrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -665,7 +665,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel MultiplySrcIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(MultiplySrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -684,7 +684,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel MultiplySrcOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(MultiplySrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -703,7 +703,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel MultiplyDest(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(MultiplyDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -722,7 +722,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel MultiplyDestAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(MultiplyDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -741,7 +741,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel MultiplyDestOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(MultiplyDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -760,7 +760,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel MultiplyDestIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(MultiplyDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -779,7 +779,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel MultiplyDestOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(MultiplyDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -798,7 +798,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel MultiplyClear(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(MultiplyClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -817,7 +817,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel MultiplyXor(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(MultiplyXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1013,7 +1013,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel AddSrc(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(AddSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1032,7 +1032,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel AddSrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(AddSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1051,7 +1051,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel AddSrcOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(AddSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1070,7 +1070,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel AddSrcIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(AddSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1089,7 +1089,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel AddSrcOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(AddSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1108,7 +1108,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel AddDest(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(AddDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1127,7 +1127,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel AddDestAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(AddDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1146,7 +1146,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel AddDestOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(AddDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1165,7 +1165,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel AddDestIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(AddDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1184,7 +1184,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel AddDestOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(AddDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1203,7 +1203,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel AddClear(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(AddClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1222,7 +1222,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel AddXor(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(AddXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1418,7 +1418,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel SubtractSrc(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(SubtractSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1437,7 +1437,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel SubtractSrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(SubtractSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1456,7 +1456,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel SubtractSrcOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(SubtractSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1475,7 +1475,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel SubtractSrcIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(SubtractSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1494,7 +1494,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel SubtractSrcOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(SubtractSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1513,7 +1513,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel SubtractDest(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(SubtractDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1532,7 +1532,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel SubtractDestAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(SubtractDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1551,7 +1551,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel SubtractDestOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(SubtractDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1570,7 +1570,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel SubtractDestIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(SubtractDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1589,7 +1589,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel SubtractDestOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(SubtractDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1608,7 +1608,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel SubtractClear(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(SubtractClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1627,7 +1627,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel SubtractXor(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(SubtractXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1823,7 +1823,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel ScreenSrc(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(ScreenSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1842,7 +1842,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel ScreenSrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(ScreenSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1861,7 +1861,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel ScreenSrcOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(ScreenSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1880,7 +1880,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel ScreenSrcIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(ScreenSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1899,7 +1899,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel ScreenSrcOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(ScreenSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1918,7 +1918,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel ScreenDest(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(ScreenDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1937,7 +1937,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel ScreenDestAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(ScreenDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1956,7 +1956,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel ScreenDestOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(ScreenDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1975,7 +1975,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel ScreenDestIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(ScreenDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -1994,7 +1994,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel ScreenDestOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(ScreenDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2013,7 +2013,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel ScreenClear(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(ScreenClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2032,7 +2032,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel ScreenXor(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(ScreenXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2228,7 +2228,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel DarkenSrc(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(DarkenSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2247,7 +2247,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel DarkenSrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(DarkenSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2266,7 +2266,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel DarkenSrcOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(DarkenSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2285,7 +2285,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel DarkenSrcIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(DarkenSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2304,7 +2304,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel DarkenSrcOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(DarkenSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2323,7 +2323,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel DarkenDest(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(DarkenDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2342,7 +2342,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel DarkenDestAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(DarkenDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2361,7 +2361,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel DarkenDestOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(DarkenDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2380,7 +2380,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel DarkenDestIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(DarkenDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2399,7 +2399,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel DarkenDestOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(DarkenDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2418,7 +2418,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel DarkenClear(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(DarkenClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2437,7 +2437,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel DarkenXor(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(DarkenXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2633,7 +2633,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel LightenSrc(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(LightenSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2652,7 +2652,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel LightenSrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(LightenSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2671,7 +2671,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel LightenSrcOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(LightenSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2690,7 +2690,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel LightenSrcIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(LightenSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2709,7 +2709,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel LightenSrcOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(LightenSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2728,7 +2728,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel LightenDest(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(LightenDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2747,7 +2747,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel LightenDestAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(LightenDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2766,7 +2766,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel LightenDestOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(LightenDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2785,7 +2785,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel LightenDestIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(LightenDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2804,7 +2804,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel LightenDestOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(LightenDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2823,7 +2823,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel LightenClear(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(LightenClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -2842,7 +2842,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel LightenXor(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(LightenXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3038,7 +3038,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel OverlaySrc(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(OverlaySrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3057,7 +3057,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel OverlaySrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(OverlaySrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3076,7 +3076,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel OverlaySrcOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(OverlaySrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3095,7 +3095,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel OverlaySrcIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(OverlaySrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3114,7 +3114,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel OverlaySrcOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(OverlaySrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3133,7 +3133,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel OverlayDest(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(OverlayDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3152,7 +3152,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel OverlayDestAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(OverlayDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3171,7 +3171,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel OverlayDestOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(OverlayDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3190,7 +3190,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel OverlayDestIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(OverlayDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3209,7 +3209,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel OverlayDestOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(OverlayDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3228,7 +3228,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel OverlayClear(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(OverlayClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3247,7 +3247,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel OverlayXor(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(OverlayXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3443,7 +3443,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel HardLightSrc(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(HardLightSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3462,7 +3462,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel HardLightSrcAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(HardLightSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3481,7 +3481,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel HardLightSrcOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(HardLightSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3500,7 +3500,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel HardLightSrcIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(HardLightSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3519,7 +3519,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel HardLightSrcOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(HardLightSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3538,7 +3538,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel HardLightDest(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(HardLightDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3557,7 +3557,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel HardLightDestAtop(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(HardLightDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3576,7 +3576,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel HardLightDestOver(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(HardLightDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3595,7 +3595,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel HardLightDestIn(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(HardLightDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3614,7 +3614,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel HardLightDestOut(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(HardLightDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3633,7 +3633,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel HardLightClear(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(HardLightClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; @@ -3652,7 +3652,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel HardLightXor(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(HardLightXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt index 31b5029080..3ce185e7d4 100644 --- a/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt @@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders public static TPixel <#=blender#><#=composer#>(TPixel backdrop, TPixel source, float opacity) where TPixel : unmanaged, IPixel { - opacity = opacity.Clamp(0, 1); + opacity = Numerics.Clamp(opacity, 0, 1); TPixel dest = default; dest.FromScaledVector4(<#=blender#><#=composer#>(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity)); return dest; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/A8.cs b/src/ImageSharp/PixelFormats/PixelImplementations/A8.cs index b19c35a0ab..77df2bc800 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/A8.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/A8.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Ranges from [0, 0, 0, 0] to [0, 0, 0, 1] in vector form. /// /// - public struct A8 : IPixel, IPackedVector + public partial struct A8 : IPixel, IPackedVector { /// /// Initializes a new instance of the struct. @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.PixelFormats public static bool operator !=(A8 left, A8 right) => !left.Equals(right); /// - public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); + public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public void FromLa32(La32 source) => this.PackedValue = ImageMaths.DownScaleFrom16BitTo8Bit(source.A); + public void FromLa32(La32 source) => this.PackedValue = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -162,6 +162,6 @@ namespace SixLabors.ImageSharp.PixelFormats /// The float containing the value to pack. /// The containing the packed values. [MethodImpl(InliningOptions.ShortMethod)] - private static byte Pack(float alpha) => (byte)Math.Round(alpha.Clamp(0, 1F) * 255F); + private static byte Pack(float alpha) => (byte)Math.Round(Numerics.Clamp(alpha, 0, 1F) * 255F); } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs index 914b31672b..3ac9b523f3 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs @@ -244,7 +244,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromL16(L16 source) { - byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue); + byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.PackedValue); this.R = rgb; this.G = rgb; this.B = rgb; @@ -265,11 +265,11 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromLa32(La32 source) { - byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.L); + byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.L); this.R = rgb; this.G = rgb; this.B = rgb; - this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A); + this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A); } /// @@ -306,9 +306,9 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgb48(Rgb48 source) { - this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R); - this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G); - this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B); + this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R); + this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G); + this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B); this.A = byte.MaxValue; } @@ -316,10 +316,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgba64(Rgba64 source) { - this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R); - this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G); - this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B); - this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A); + this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R); + this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G); + this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B); + this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A); } /// @@ -373,7 +373,7 @@ namespace SixLabors.ImageSharp.PixelFormats { vector *= MaxBytes; vector += Half; - vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes); + vector = Numerics.Clamp(vector, Vector4.Zero, MaxBytes); this.R = (byte)vector.X; this.G = (byte)vector.Y; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs index a2ec185be2..6cff5fd772 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs @@ -151,7 +151,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromL16(L16 source) { - byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue); + byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.PackedValue); this.R = rgb; this.G = rgb; this.B = rgb; @@ -170,7 +170,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromLa32(La32 source) { - byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.L); + byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.L); this.R = rgb; this.G = rgb; this.B = rgb; @@ -203,18 +203,18 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgb48(Rgb48 source) { - this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R); - this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G); - this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B); + this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R); + this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G); + this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B); } /// [MethodImpl(InliningOptions.ShortMethod)] public void FromRgba64(Rgba64 source) { - this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R); - this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G); - this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B); + this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R); + this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G); + this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B); } /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr565.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr565.cs index 21ec24a6e6..fd12b68376 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgr565.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgr565.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Ranges from [0, 0, 0, 1] to [1, 1, 1, 1] in vector form. /// /// - public struct Bgr565 : IPixel, IPackedVector + public partial struct Bgr565 : IPixel, IPackedVector { /// /// Initializes a new instance of the struct. @@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.PixelFormats public static bool operator !=(Bgr565 left, Bgr565 right) => !left.Equals(right); /// - public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); + public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs index 68dcd8287b..190345ddaf 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs @@ -197,7 +197,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromL16(L16 source) { - byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue); + byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.PackedValue); this.R = rgb; this.G = rgb; this.B = rgb; @@ -218,11 +218,11 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromLa32(La32 source) { - byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.L); + byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.L); this.R = rgb; this.G = rgb; this.B = rgb; - this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A); + this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A); } /// @@ -259,9 +259,9 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgb48(Rgb48 source) { - this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R); - this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G); - this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B); + this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R); + this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G); + this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B); this.A = byte.MaxValue; } @@ -269,10 +269,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgba64(Rgba64 source) { - this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R); - this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G); - this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B); - this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A); + this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R); + this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G); + this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B); + this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A); } /// @@ -296,7 +296,7 @@ namespace SixLabors.ImageSharp.PixelFormats { vector *= MaxBytes; vector += Half; - vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes); + vector = Numerics.Clamp(vector, Vector4.Zero, MaxBytes); this.R = (byte)vector.X; this.G = (byte)vector.Y; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs index b2af3045a3..8fa5219d53 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form. /// /// - public struct Bgra4444 : IPixel, IPackedVector + public partial struct Bgra4444 : IPixel, IPackedVector { /// /// Initializes a new instance of the struct. @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.PixelFormats public static bool operator !=(Bgra4444 left, Bgra4444 right) => !left.Equals(right); /// - public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); + public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -162,7 +162,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] private static ushort Pack(ref Vector4 vector) { - vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One); + vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One); return (ushort)((((int)Math.Round(vector.W * 15F) & 0x0F) << 12) | (((int)Math.Round(vector.X * 15F) & 0x0F) << 8) | (((int)Math.Round(vector.Y * 15F) & 0x0F) << 4) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs index 31fa0c29ce..b3a0d08960 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs @@ -163,7 +163,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] private static ushort Pack(ref Vector4 vector) { - vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One); + vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One); return (ushort)( (((int)Math.Round(vector.X * 31F) & 0x1F) << 10) | (((int)Math.Round(vector.Y * 31F) & 0x1F) << 5) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs index 9c5289b86e..e261212918 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Ranges from [0, 0, 0, 0] to [255, 255, 255, 255] in vector form. /// /// - public struct Byte4 : IPixel, IPackedVector + public partial struct Byte4 : IPixel, IPackedVector { /// /// Initializes a new instance of the struct. @@ -62,7 +62,7 @@ namespace SixLabors.ImageSharp.PixelFormats public static bool operator !=(Byte4 left, Byte4 right) => !left.Equals(right); /// - public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); + public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -171,7 +171,7 @@ namespace SixLabors.ImageSharp.PixelFormats const float Max = 255F; // Clamp the value between min and max values - vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, new Vector4(Max)); + vector = Numerics.Clamp(vector, Vector4.Zero, new Vector4(Max)); uint byte4 = (uint)Math.Round(vector.X) & 0xFF; uint byte3 = ((uint)Math.Round(vector.Y) & 0xFF) << 0x8; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs b/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs index e3e6e1383b..5c4aa1cfb6 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/HalfSingle.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Ranges from [-1, 0, 0, 1] to [1, 0, 0, 1] in vector form. /// /// - public struct HalfSingle : IPixel, IPackedVector + public partial struct HalfSingle : IPixel, IPackedVector { /// /// Initializes a new instance of the struct. @@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.PixelFormats public static bool operator !=(HalfSingle left, HalfSingle right) => !left.Equals(right); /// - public PixelOperations CreatePixelOperations() => new PixelOperations(); + public PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector2.cs b/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector2.cs index 43380eac03..39cb6f7993 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector2.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector2.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Ranges from [-1, -1, 0, 1] to [1, 1, 0, 1] in vector form. /// /// - public struct HalfVector2 : IPixel, IPackedVector + public partial struct HalfVector2 : IPixel, IPackedVector { /// /// Initializes a new instance of the struct. @@ -54,13 +54,13 @@ namespace SixLabors.ImageSharp.PixelFormats public static bool operator !=(HalfVector2 left, HalfVector2 right) => !left.Equals(right); /// - public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); + public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(InliningOptions.ShortMethod)] public void FromScaledVector4(Vector4 vector) { - var scaled = new Vector2(vector.X, vector.Y) * 2F; + Vector2 scaled = new Vector2(vector.X, vector.Y) * 2F; scaled -= Vector2.One; this.PackedValue = Pack(scaled.X, scaled.Y); } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector4.cs index cb1ae1f404..9826d61a2b 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/HalfVector4.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Ranges from [-1, -1, -1, -1] to [1, 1, 1, 1] in vector form. /// /// - public struct HalfVector4 : IPixel, IPackedVector + public partial struct HalfVector4 : IPixel, IPackedVector { /// /// Initializes a new instance of the struct. @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.PixelFormats public static bool operator !=(HalfVector4 left, HalfVector4 right) => !left.Equals(right); /// - public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); + public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/L16.cs b/src/ImageSharp/PixelFormats/PixelImplementations/L16.cs index 087becaf2c..dd31aae2fc 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/L16.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/L16.cs @@ -74,30 +74,30 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromArgb32(Argb32 source) { - this.PackedValue = ImageMaths.Get16BitBT709Luminance( - ImageMaths.UpscaleFrom8BitTo16Bit(source.R), - ImageMaths.UpscaleFrom8BitTo16Bit(source.G), - ImageMaths.UpscaleFrom8BitTo16Bit(source.B)); + this.PackedValue = ColorNumerics.Get16BitBT709Luminance( + ColorNumerics.UpscaleFrom8BitTo16Bit(source.R), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.G), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.B)); } /// [MethodImpl(InliningOptions.ShortMethod)] public void FromBgr24(Bgr24 source) { - this.PackedValue = ImageMaths.Get16BitBT709Luminance( - ImageMaths.UpscaleFrom8BitTo16Bit(source.R), - ImageMaths.UpscaleFrom8BitTo16Bit(source.G), - ImageMaths.UpscaleFrom8BitTo16Bit(source.B)); + this.PackedValue = ColorNumerics.Get16BitBT709Luminance( + ColorNumerics.UpscaleFrom8BitTo16Bit(source.R), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.G), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.B)); } /// [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) { - this.PackedValue = ImageMaths.Get16BitBT709Luminance( - ImageMaths.UpscaleFrom8BitTo16Bit(source.R), - ImageMaths.UpscaleFrom8BitTo16Bit(source.G), - ImageMaths.UpscaleFrom8BitTo16Bit(source.B)); + this.PackedValue = ColorNumerics.Get16BitBT709Luminance( + ColorNumerics.UpscaleFrom8BitTo16Bit(source.R), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.G), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.B)); } /// @@ -106,7 +106,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public void FromL8(L8 source) => this.PackedValue = ImageMaths.UpscaleFrom8BitTo16Bit(source.PackedValue); + public void FromL8(L8 source) => this.PackedValue = ColorNumerics.UpscaleFrom8BitTo16Bit(source.PackedValue); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -114,7 +114,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public void FromLa16(La16 source) => this.PackedValue = ImageMaths.UpscaleFrom8BitTo16Bit(source.L); + public void FromLa16(La16 source) => this.PackedValue = ColorNumerics.UpscaleFrom8BitTo16Bit(source.L); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -124,27 +124,27 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgb24(Rgb24 source) { - this.PackedValue = ImageMaths.Get16BitBT709Luminance( - ImageMaths.UpscaleFrom8BitTo16Bit(source.R), - ImageMaths.UpscaleFrom8BitTo16Bit(source.G), - ImageMaths.UpscaleFrom8BitTo16Bit(source.B)); + this.PackedValue = ColorNumerics.Get16BitBT709Luminance( + ColorNumerics.UpscaleFrom8BitTo16Bit(source.R), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.G), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.B)); } /// [MethodImpl(InliningOptions.ShortMethod)] public void FromRgba32(Rgba32 source) { - this.PackedValue = ImageMaths.Get16BitBT709Luminance( - ImageMaths.UpscaleFrom8BitTo16Bit(source.R), - ImageMaths.UpscaleFrom8BitTo16Bit(source.G), - ImageMaths.UpscaleFrom8BitTo16Bit(source.B)); + this.PackedValue = ColorNumerics.Get16BitBT709Luminance( + ColorNumerics.UpscaleFrom8BitTo16Bit(source.R), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.G), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.B)); } /// [MethodImpl(InliningOptions.ShortMethod)] public void ToRgba32(ref Rgba32 dest) { - byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(this.PackedValue); + byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(this.PackedValue); dest.R = rgb; dest.G = rgb; dest.B = rgb; @@ -153,11 +153,11 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public void FromRgb48(Rgb48 source) => this.PackedValue = ImageMaths.Get16BitBT709Luminance(source.R, source.G, source.B); + public void FromRgb48(Rgb48 source) => this.PackedValue = ColorNumerics.Get16BitBT709Luminance(source.R, source.G, source.B); /// [MethodImpl(InliningOptions.ShortMethod)] - public void FromRgba64(Rgba64 source) => this.PackedValue = ImageMaths.Get16BitBT709Luminance(source.R, source.G, source.B); + public void FromRgba64(Rgba64 source) => this.PackedValue = ColorNumerics.Get16BitBT709Luminance(source.R, source.G, source.B); /// public override readonly bool Equals(object obj) => obj is L16 other && this.Equals(other); @@ -176,8 +176,8 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] internal void ConvertFromRgbaScaledVector4(Vector4 vector) { - vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max; - this.PackedValue = ImageMaths.Get16BitBT709Luminance( + vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One) * Max; + this.PackedValue = ColorNumerics.Get16BitBT709Luminance( vector.X, vector.Y, vector.Z); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/L8.cs b/src/ImageSharp/PixelFormats/PixelImplementations/L8.cs index 32f963795b..c570c33a19 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/L8.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/L8.cs @@ -73,15 +73,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public void FromArgb32(Argb32 source) => this.PackedValue = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B); + public void FromArgb32(Argb32 source) => this.PackedValue = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B); /// [MethodImpl(InliningOptions.ShortMethod)] - public void FromBgr24(Bgr24 source) => this.PackedValue = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B); + public void FromBgr24(Bgr24 source) => this.PackedValue = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B); /// [MethodImpl(InliningOptions.ShortMethod)] - public void FromBgra32(Bgra32 source) => this.PackedValue = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B); + public void FromBgra32(Bgra32 source) => this.PackedValue = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -93,7 +93,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public void FromL16(L16 source) => this.PackedValue = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue); + public void FromL16(L16 source) => this.PackedValue = ColorNumerics.DownScaleFrom16BitTo8Bit(source.PackedValue); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -101,15 +101,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public void FromLa32(La32 source) => this.PackedValue = ImageMaths.DownScaleFrom16BitTo8Bit(source.L); + public void FromLa32(La32 source) => this.PackedValue = ColorNumerics.DownScaleFrom16BitTo8Bit(source.L); /// [MethodImpl(InliningOptions.ShortMethod)] - public void FromRgb24(Rgb24 source) => this.PackedValue = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B); + public void FromRgb24(Rgb24 source) => this.PackedValue = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B); /// [MethodImpl(InliningOptions.ShortMethod)] - public void FromRgba32(Rgba32 source) => this.PackedValue = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B); + public void FromRgba32(Rgba32 source) => this.PackedValue = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -124,18 +124,18 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] public void FromRgb48(Rgb48 source) - => this.PackedValue = ImageMaths.Get8BitBT709Luminance( - ImageMaths.DownScaleFrom16BitTo8Bit(source.R), - ImageMaths.DownScaleFrom16BitTo8Bit(source.G), - ImageMaths.DownScaleFrom16BitTo8Bit(source.B)); + => this.PackedValue = ColorNumerics.Get8BitBT709Luminance( + ColorNumerics.DownScaleFrom16BitTo8Bit(source.R), + ColorNumerics.DownScaleFrom16BitTo8Bit(source.G), + ColorNumerics.DownScaleFrom16BitTo8Bit(source.B)); /// [MethodImpl(InliningOptions.ShortMethod)] public void FromRgba64(Rgba64 source) - => this.PackedValue = ImageMaths.Get8BitBT709Luminance( - ImageMaths.DownScaleFrom16BitTo8Bit(source.R), - ImageMaths.DownScaleFrom16BitTo8Bit(source.G), - ImageMaths.DownScaleFrom16BitTo8Bit(source.B)); + => this.PackedValue = ColorNumerics.Get8BitBT709Luminance( + ColorNumerics.DownScaleFrom16BitTo8Bit(source.R), + ColorNumerics.DownScaleFrom16BitTo8Bit(source.G), + ColorNumerics.DownScaleFrom16BitTo8Bit(source.B)); /// public override readonly bool Equals(object obj) => obj is L8 other && this.Equals(other); @@ -156,8 +156,8 @@ namespace SixLabors.ImageSharp.PixelFormats { vector *= MaxBytes; vector += Half; - vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes); - this.PackedValue = ImageMaths.Get8BitBT709Luminance((byte)vector.X, (byte)vector.Y, (byte)vector.Z); + vector = Numerics.Clamp(vector, Vector4.Zero, MaxBytes); + this.PackedValue = ColorNumerics.Get8BitBT709Luminance((byte)vector.X, (byte)vector.Y, (byte)vector.Z); } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/La16.cs b/src/ImageSharp/PixelFormats/PixelImplementations/La16.cs index bcfe67249d..5a69431a1d 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/La16.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/La16.cs @@ -92,7 +92,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromArgb32(Argb32 source) { - this.L = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B); + this.L = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B); this.A = source.A; } @@ -100,7 +100,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgr24(Bgr24 source) { - this.L = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B); + this.L = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B); this.A = byte.MaxValue; } @@ -108,7 +108,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) { - this.L = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B); + this.L = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B); this.A = source.A; } @@ -120,7 +120,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromL16(L16 source) { - this.L = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue); + this.L = ColorNumerics.DownScaleFrom16BitTo8Bit(source.PackedValue); this.A = byte.MaxValue; } @@ -140,15 +140,15 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromLa32(La32 source) { - this.L = ImageMaths.DownScaleFrom16BitTo8Bit(source.L); - this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A); + this.L = ColorNumerics.DownScaleFrom16BitTo8Bit(source.L); + this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A); } /// [MethodImpl(InliningOptions.ShortMethod)] public void FromRgb24(Rgb24 source) { - this.L = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B); + this.L = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B); this.A = byte.MaxValue; } @@ -156,10 +156,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgb48(Rgb48 source) { - this.L = ImageMaths.Get8BitBT709Luminance( - ImageMaths.DownScaleFrom16BitTo8Bit(source.R), - ImageMaths.DownScaleFrom16BitTo8Bit(source.G), - ImageMaths.DownScaleFrom16BitTo8Bit(source.B)); + this.L = ColorNumerics.Get8BitBT709Luminance( + ColorNumerics.DownScaleFrom16BitTo8Bit(source.R), + ColorNumerics.DownScaleFrom16BitTo8Bit(source.G), + ColorNumerics.DownScaleFrom16BitTo8Bit(source.B)); this.A = byte.MaxValue; } @@ -168,19 +168,19 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgba32(Rgba32 source) { - this.L = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B); + this.L = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B); this.A = source.A; } /// public void FromRgba64(Rgba64 source) { - this.L = ImageMaths.Get8BitBT709Luminance( - ImageMaths.DownScaleFrom16BitTo8Bit(source.R), - ImageMaths.DownScaleFrom16BitTo8Bit(source.G), - ImageMaths.DownScaleFrom16BitTo8Bit(source.B)); + this.L = ColorNumerics.Get8BitBT709Luminance( + ColorNumerics.DownScaleFrom16BitTo8Bit(source.R), + ColorNumerics.DownScaleFrom16BitTo8Bit(source.G), + ColorNumerics.DownScaleFrom16BitTo8Bit(source.B)); - this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A); + this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A); } /// @@ -219,8 +219,8 @@ namespace SixLabors.ImageSharp.PixelFormats { vector *= MaxBytes; vector += Half; - vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes); - this.L = ImageMaths.Get8BitBT709Luminance((byte)vector.X, (byte)vector.Y, (byte)vector.Z); + vector = Numerics.Clamp(vector, Vector4.Zero, MaxBytes); + this.L = ColorNumerics.Get8BitBT709Luminance((byte)vector.X, (byte)vector.Y, (byte)vector.Z); this.A = (byte)vector.W; } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/La32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/La32.cs index 23f4b8e17a..66d0e38c79 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/La32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/La32.cs @@ -95,22 +95,22 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromArgb32(Argb32 source) { - this.L = ImageMaths.Get16BitBT709Luminance( - ImageMaths.UpscaleFrom8BitTo16Bit(source.R), - ImageMaths.UpscaleFrom8BitTo16Bit(source.G), - ImageMaths.UpscaleFrom8BitTo16Bit(source.B)); + this.L = ColorNumerics.Get16BitBT709Luminance( + ColorNumerics.UpscaleFrom8BitTo16Bit(source.R), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.G), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.B)); - this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A); + this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A); } /// [MethodImpl(InliningOptions.ShortMethod)] public void FromBgr24(Bgr24 source) { - this.L = ImageMaths.Get16BitBT709Luminance( - ImageMaths.UpscaleFrom8BitTo16Bit(source.R), - ImageMaths.UpscaleFrom8BitTo16Bit(source.G), - ImageMaths.UpscaleFrom8BitTo16Bit(source.B)); + this.L = ColorNumerics.Get16BitBT709Luminance( + ColorNumerics.UpscaleFrom8BitTo16Bit(source.R), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.G), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.B)); this.A = ushort.MaxValue; } @@ -119,12 +119,12 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) { - this.L = ImageMaths.Get16BitBT709Luminance( - ImageMaths.UpscaleFrom8BitTo16Bit(source.R), - ImageMaths.UpscaleFrom8BitTo16Bit(source.G), - ImageMaths.UpscaleFrom8BitTo16Bit(source.B)); + this.L = ColorNumerics.Get16BitBT709Luminance( + ColorNumerics.UpscaleFrom8BitTo16Bit(source.R), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.G), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.B)); - this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A); + this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A); } /// @@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromL8(L8 source) { - this.L = ImageMaths.UpscaleFrom8BitTo16Bit(source.PackedValue); + this.L = ColorNumerics.UpscaleFrom8BitTo16Bit(source.PackedValue); this.A = ushort.MaxValue; } @@ -151,8 +151,8 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromLa16(La16 source) { - this.L = ImageMaths.UpscaleFrom8BitTo16Bit(source.L); - this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A); + this.L = ColorNumerics.UpscaleFrom8BitTo16Bit(source.L); + this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A); } /// @@ -163,10 +163,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgb24(Rgb24 source) { - this.L = ImageMaths.Get16BitBT709Luminance( - ImageMaths.UpscaleFrom8BitTo16Bit(source.R), - ImageMaths.UpscaleFrom8BitTo16Bit(source.G), - ImageMaths.UpscaleFrom8BitTo16Bit(source.B)); + this.L = ColorNumerics.Get16BitBT709Luminance( + ColorNumerics.UpscaleFrom8BitTo16Bit(source.R), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.G), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.B)); this.A = ushort.MaxValue; } @@ -175,7 +175,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgb48(Rgb48 source) { - this.L = ImageMaths.Get16BitBT709Luminance(source.R, source.G, source.B); + this.L = ColorNumerics.Get16BitBT709Luminance(source.R, source.G, source.B); this.A = ushort.MaxValue; } @@ -183,19 +183,19 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgba32(Rgba32 source) { - this.L = ImageMaths.Get16BitBT709Luminance( - ImageMaths.UpscaleFrom8BitTo16Bit(source.R), - ImageMaths.UpscaleFrom8BitTo16Bit(source.G), - ImageMaths.UpscaleFrom8BitTo16Bit(source.B)); + this.L = ColorNumerics.Get16BitBT709Luminance( + ColorNumerics.UpscaleFrom8BitTo16Bit(source.R), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.G), + ColorNumerics.UpscaleFrom8BitTo16Bit(source.B)); - this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A); + this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A); } /// [MethodImpl(InliningOptions.ShortMethod)] public void FromRgba64(Rgba64 source) { - this.L = ImageMaths.Get16BitBT709Luminance(source.R, source.G, source.B); + this.L = ColorNumerics.Get16BitBT709Luminance(source.R, source.G, source.B); this.A = source.A; } @@ -211,11 +211,11 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void ToRgba32(ref Rgba32 dest) { - byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(this.L); + byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(this.L); dest.R = rgb; dest.G = rgb; dest.B = rgb; - dest.A = ImageMaths.DownScaleFrom16BitTo8Bit(this.A); + dest.A = ColorNumerics.DownScaleFrom16BitTo8Bit(this.A); } /// @@ -233,8 +233,8 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] internal void ConvertFromRgbaScaledVector4(Vector4 vector) { - vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max; - this.L = ImageMaths.Get16BitBT709Luminance( + vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One) * Max; + this.L = ColorNumerics.Get16BitBT709Luminance( vector.X, vector.Y, vector.Z); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte2.cs b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte2.cs index 70098b6665..8b244d391c 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte2.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte2.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Ranges from [-1, -1, 0, 1] to [1, 1, 0, 1] in vector form. /// /// - public struct NormalizedByte2 : IPixel, IPackedVector + public partial struct NormalizedByte2 : IPixel, IPackedVector { private static readonly Vector2 Half = new Vector2(127); private static readonly Vector2 MinusOne = new Vector2(-1F); @@ -60,7 +60,7 @@ namespace SixLabors.ImageSharp.PixelFormats public static bool operator !=(NormalizedByte2 left, NormalizedByte2 right) => !left.Equals(right); /// - public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); + public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs index 2762073aa1..84f0bb0224 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Ranges from [-1, -1, -1, -1] to [1, 1, 1, 1] in vector form. /// /// - public struct NormalizedByte4 : IPixel, IPackedVector + public partial struct NormalizedByte4 : IPixel, IPackedVector { private static readonly Vector4 Half = new Vector4(127); private static readonly Vector4 MinusOne = new Vector4(-1F); @@ -62,7 +62,7 @@ namespace SixLabors.ImageSharp.PixelFormats public static bool operator !=(NormalizedByte4 left, NormalizedByte4 right) => !left.Equals(right); /// - public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); + public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -174,7 +174,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] private static uint Pack(ref Vector4 vector) { - vector = Vector4Utilities.FastClamp(vector, MinusOne, Vector4.One) * Half; + vector = Numerics.Clamp(vector, MinusOne, Vector4.One) * Half; uint byte4 = ((uint)MathF.Round(vector.X) & 0xFF) << 0; uint byte3 = ((uint)MathF.Round(vector.Y) & 0xFF) << 8; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort2.cs b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort2.cs index 8eaec1411c..97bbc1206f 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort2.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort2.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Ranges from [-1, -1, 0, 1] to [1, 1, 0, 1] in vector form. /// /// - public struct NormalizedShort2 : IPixel, IPackedVector + public partial struct NormalizedShort2 : IPixel, IPackedVector { private static readonly Vector2 Max = new Vector2(0x7FFF); private static readonly Vector2 Min = Vector2.Negate(Max); @@ -60,7 +60,7 @@ namespace SixLabors.ImageSharp.PixelFormats public static bool operator !=(NormalizedShort2 left, NormalizedShort2 right) => !left.Equals(right); /// - public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); + public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs index ce7c0035f6..a3fd8989ce 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Ranges from [-1, -1, -1, -1] to [1, 1, 1, 1] in vector form. /// /// - public struct NormalizedShort4 : IPixel, IPackedVector + public partial struct NormalizedShort4 : IPixel, IPackedVector { private static readonly Vector4 Max = new Vector4(0x7FFF); private static readonly Vector4 Min = Vector4.Negate(Max); @@ -62,7 +62,7 @@ namespace SixLabors.ImageSharp.PixelFormats public static bool operator !=(NormalizedShort4 left, NormalizedShort4 right) => !left.Equals(right); /// - public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); + public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -177,7 +177,7 @@ namespace SixLabors.ImageSharp.PixelFormats private static ulong Pack(ref Vector4 vector) { vector *= Max; - vector = Vector4Utilities.FastClamp(vector, Min, Max); + vector = Numerics.Clamp(vector, Min, Max); // Round rather than truncate. ulong word4 = ((ulong)MathF.Round(vector.X) & 0xFFFF) << 0x00; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/A8.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/A8.PixelOperations.cs new file mode 100644 index 0000000000..7482a2e251 --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/A8.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct A8 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Argb32.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Argb32.PixelOperations.cs new file mode 100644 index 0000000000..f8f5715bd4 --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Argb32.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct Argb32 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal partial class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Bgr24.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Bgr24.PixelOperations.cs new file mode 100644 index 0000000000..adae64d5de --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Bgr24.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct Bgr24 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal partial class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.None), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Bgr565.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Bgr565.PixelOperations.cs new file mode 100644 index 0000000000..d75b79f5dd --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Bgr565.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct Bgr565 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.None), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Bgra32.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Bgra32.PixelOperations.cs new file mode 100644 index 0000000000..5f7e516e59 --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Bgra32.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct Bgra32 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal partial class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Bgra4444.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Bgra4444.PixelOperations.cs new file mode 100644 index 0000000000..eac8e4f170 --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Bgra4444.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct Bgra4444 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Bgra5551.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Bgra5551.PixelOperations.cs new file mode 100644 index 0000000000..d0470b7a1f --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Bgra5551.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct Bgra5551 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal partial class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Byte4.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Byte4.PixelOperations.cs new file mode 100644 index 0000000000..0a2fa10b2d --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Byte4.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct Byte4 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Argb32.PixelOperations.Generated.cs similarity index 58% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Argb32.PixelOperations.Generated.cs index 0b1292b641..cedd1762d8 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Argb32.PixelOperations.Generated.cs @@ -1,15 +1,13 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. // -using SixLabors.ImageSharp.PixelFormats.Utils; using System; -using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - +using SixLabors.ImageSharp.PixelFormats.Utils; namespace SixLabors.ImageSharp.PixelFormats { @@ -21,15 +19,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { - /// + /// public override void FromArgb32(Configuration configuration, ReadOnlySpan source, Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destinationPixels, nameof(destinationPixels)); - source.CopyTo(destinationPixels); + source.CopyTo(destinationPixels.Slice(0, source.Length)); } /// @@ -38,103 +36,140 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - sourcePixels.CopyTo(destinationPixels); + sourcePixels.CopyTo(destinationPixels.Slice(0, sourcePixels.Length)); } - /// - public override void FromVector4Destructive(Configuration configuration, Span sourceVectors, Span destinationPixels, PixelConversionModifiers modifiers) + public override void FromVector4Destructive( + Configuration configuration, + Span sourceVectors, + Span destinationPixels, + PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destinationPixels, modifiers.Remove(PixelConversionModifiers.Scale)); } /// - public override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) + public override void ToVector4( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destVectors, + PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale)); } /// - public override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); - ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels)); - - for (int i = 0; i < sourcePixels.Length; i++) - { - uint sp = Unsafe.Add(ref sourceRef, i); - Unsafe.Add(ref destRef, i) = PixelConverter.FromArgb32.ToRgba32(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromArgb32.ToRgba32(source, dest); } /// - public override void FromRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void FromRgba32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); - ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels)); - - for (int i = 0; i < sourcePixels.Length; i++) - { - uint sp = Unsafe.Add(ref sourceRef, i); - Unsafe.Add(ref destRef, i) = PixelConverter.FromRgba32.ToArgb32(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromRgba32.ToArgb32(source, dest); } /// - public override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); - ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels)); - - for (int i = 0; i < sourcePixels.Length; i++) - { - uint sp = Unsafe.Add(ref sourceRef, i); - Unsafe.Add(ref destRef, i) = PixelConverter.FromArgb32.ToBgra32(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromArgb32.ToBgra32(source, dest); } /// - public override void FromBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void FromBgra32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); - ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels)); + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromBgra32.ToArgb32(source, dest); + } + /// + public override void ToRgb24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - for (int i = 0; i < sourcePixels.Length; i++) - { - uint sp = Unsafe.Add(ref sourceRef, i); - Unsafe.Add(ref destRef, i) = PixelConverter.FromBgra32.ToArgb32(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromArgb32.ToRgb24(source, dest); } /// - public override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void FromRgb24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Bgr24 destRef = ref MemoryMarshal.GetReference(destinationPixels); - - for (int i = 0; i < sourcePixels.Length; i++) - { - ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Bgr24 dp = ref Unsafe.Add(ref destRef, i); + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromRgb24.ToArgb32(source, dest); + } + /// + public override void ToBgr24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - dp.FromArgb32(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromArgb32.ToBgr24(source, dest); } /// - public override void ToL8(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void FromBgr24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); + + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromBgr24.ToArgb32(source, dest); + } + /// + public override void ToL8( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -150,9 +185,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromArgb32(sp); } } - /// - public override void ToL16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -168,9 +205,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromArgb32(sp); } } - /// - public override void ToLa16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -186,9 +225,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromArgb32(sp); } } - /// - public override void ToLa32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -204,27 +245,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromArgb32(sp); } } - /// - public override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) - { - Guard.NotNull(configuration, nameof(configuration)); - Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - - ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Rgb24 destRef = ref MemoryMarshal.GetReference(destinationPixels); - - for (int i = 0; i < sourcePixels.Length; i++) - { - ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Rgb24 dp = ref Unsafe.Add(ref destRef, i); - - dp.FromArgb32(sp); - } - } - - /// - public override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb48( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -240,9 +265,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromArgb32(sp); } } - /// - public override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba64( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -258,9 +285,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromArgb32(sp); } } - /// - public override void ToBgra5551(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra5551( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -282,8 +311,9 @@ namespace SixLabors.ImageSharp.PixelFormats ReadOnlySpan sourcePixels, Span destinationPixels) { - PixelOperations.Instance.ToArgb32(configuration, sourcePixels, destinationPixels); + PixelOperations.Instance.ToArgb32(configuration, sourcePixels, destinationPixels.Slice(0, sourcePixels.Length)); } + } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Argb32.PixelOperations.Generated.tt similarity index 78% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.tt rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Argb32.PixelOperations.Generated.tt index 3a4c7b459d..bbee95f24c 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Argb32.PixelOperations.Generated.tt @@ -1,6 +1,5 @@ -<#@include file="_Common.ttinclude" #> +<#@include file="_Common.ttinclude" #> <#@ output extension=".cs" #> - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -11,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { <# GenerateAllDefaultConversionMethods("Argb32"); #> } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgr24.PixelOperations.Generated.cs similarity index 54% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgr24.PixelOperations.Generated.cs index b73bb8b831..c98e356568 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgr24.PixelOperations.Generated.cs @@ -1,15 +1,13 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. // -using SixLabors.ImageSharp.PixelFormats.Utils; using System; -using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - +using SixLabors.ImageSharp.PixelFormats.Utils; namespace SixLabors.ImageSharp.PixelFormats { @@ -21,15 +19,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { - /// + /// public override void FromBgr24(Configuration configuration, ReadOnlySpan source, Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destinationPixels, nameof(destinationPixels)); - source.CopyTo(destinationPixels); + source.CopyTo(destinationPixels.Slice(0, source.Length)); } /// @@ -38,167 +36,220 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - sourcePixels.CopyTo(destinationPixels); + sourcePixels.CopyTo(destinationPixels.Slice(0, sourcePixels.Length)); } - /// - public override void FromVector4Destructive(Configuration configuration, Span sourceVectors, Span destinationPixels, PixelConversionModifiers modifiers) + public override void FromVector4Destructive( + Configuration configuration, + Span sourceVectors, + Span destinationPixels, + PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destinationPixels, modifiers.Remove(PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply)); } /// - public override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) + public override void ToVector4( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destVectors, + PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply)); } - /// - public override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Argb32 destRef = ref MemoryMarshal.GetReference(destinationPixels); + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromBgr24.ToRgba32(source, dest); + } - for (int i = 0; i < sourcePixels.Length; i++) - { - ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i); - ref Argb32 dp = ref Unsafe.Add(ref destRef, i); + /// + public override void FromRgba32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - dp.FromBgr24(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromRgba32.ToBgr24(source, dest); } - /// - public override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToArgb32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Bgra32 destRef = ref MemoryMarshal.GetReference(destinationPixels); + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromBgr24.ToArgb32(source, dest); + } - for (int i = 0; i < sourcePixels.Length; i++) - { - ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i); - ref Bgra32 dp = ref Unsafe.Add(ref destRef, i); + /// + public override void FromArgb32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - dp.FromBgr24(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromArgb32.ToBgr24(source, dest); } - /// - public override void ToL8(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref L8 destRef = ref MemoryMarshal.GetReference(destinationPixels); + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromBgr24.ToBgra32(source, dest); + } - for (int i = 0; i < sourcePixels.Length; i++) - { - ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i); - ref L8 dp = ref Unsafe.Add(ref destRef, i); + /// + public override void FromBgra32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - dp.FromBgr24(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromBgra32.ToBgr24(source, dest); } - /// - public override void ToL16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref L16 destRef = ref MemoryMarshal.GetReference(destinationPixels); + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromBgr24.ToRgb24(source, dest); + } - for (int i = 0; i < sourcePixels.Length; i++) - { - ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i); - ref L16 dp = ref Unsafe.Add(ref destRef, i); + /// + public override void FromRgb24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - dp.FromBgr24(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromRgb24.ToBgr24(source, dest); } - /// - public override void ToLa16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL8( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref La16 destRef = ref MemoryMarshal.GetReference(destinationPixels); + ref L8 destRef = ref MemoryMarshal.GetReference(destinationPixels); for (int i = 0; i < sourcePixels.Length; i++) { ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i); - ref La16 dp = ref Unsafe.Add(ref destRef, i); + ref L8 dp = ref Unsafe.Add(ref destRef, i); dp.FromBgr24(sp); } } - /// - public override void ToLa32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref La32 destRef = ref MemoryMarshal.GetReference(destinationPixels); + ref L16 destRef = ref MemoryMarshal.GetReference(destinationPixels); for (int i = 0; i < sourcePixels.Length; i++) { ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i); - ref La32 dp = ref Unsafe.Add(ref destRef, i); + ref L16 dp = ref Unsafe.Add(ref destRef, i); dp.FromBgr24(sp); } } - /// - public override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Rgb24 destRef = ref MemoryMarshal.GetReference(destinationPixels); + ref La16 destRef = ref MemoryMarshal.GetReference(destinationPixels); for (int i = 0; i < sourcePixels.Length; i++) { ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i); - ref Rgb24 dp = ref Unsafe.Add(ref destRef, i); + ref La16 dp = ref Unsafe.Add(ref destRef, i); dp.FromBgr24(sp); } } - /// - public override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Rgba32 destRef = ref MemoryMarshal.GetReference(destinationPixels); + ref La32 destRef = ref MemoryMarshal.GetReference(destinationPixels); for (int i = 0; i < sourcePixels.Length; i++) { ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i); - ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); + ref La32 dp = ref Unsafe.Add(ref destRef, i); dp.FromBgr24(sp); } } - /// - public override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb48( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -214,9 +265,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgr24(sp); } } - /// - public override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba64( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -232,9 +285,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgr24(sp); } } - /// - public override void ToBgra5551(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra5551( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -256,8 +311,9 @@ namespace SixLabors.ImageSharp.PixelFormats ReadOnlySpan sourcePixels, Span destinationPixels) { - PixelOperations.Instance.ToBgr24(configuration, sourcePixels, destinationPixels); + PixelOperations.Instance.ToBgr24(configuration, sourcePixels, destinationPixels.Slice(0, sourcePixels.Length)); } + } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgr24.PixelOperations.Generated.tt similarity index 78% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.tt rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgr24.PixelOperations.Generated.tt index cfaefeda9c..48b6daa3aa 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgr24.PixelOperations.Generated.tt @@ -1,6 +1,5 @@ -<#@include file="_Common.ttinclude" #> +<#@include file="_Common.ttinclude" #> <#@ output extension=".cs" #> - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -11,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { <# GenerateAllDefaultConversionMethods("Bgr24"); #> } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgra32.PixelOperations.Generated.cs similarity index 58% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgra32.PixelOperations.Generated.cs index 5bdd10404d..02bb675328 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgra32.PixelOperations.Generated.cs @@ -1,15 +1,13 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. // -using SixLabors.ImageSharp.PixelFormats.Utils; using System; -using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - +using SixLabors.ImageSharp.PixelFormats.Utils; namespace SixLabors.ImageSharp.PixelFormats { @@ -21,15 +19,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { - /// + /// public override void FromBgra32(Configuration configuration, ReadOnlySpan source, Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destinationPixels, nameof(destinationPixels)); - source.CopyTo(destinationPixels); + source.CopyTo(destinationPixels.Slice(0, source.Length)); } /// @@ -38,103 +36,140 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - sourcePixels.CopyTo(destinationPixels); + sourcePixels.CopyTo(destinationPixels.Slice(0, sourcePixels.Length)); } - /// - public override void FromVector4Destructive(Configuration configuration, Span sourceVectors, Span destinationPixels, PixelConversionModifiers modifiers) + public override void FromVector4Destructive( + Configuration configuration, + Span sourceVectors, + Span destinationPixels, + PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destinationPixels, modifiers.Remove(PixelConversionModifiers.Scale)); } /// - public override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) + public override void ToVector4( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destVectors, + PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale)); } /// - public override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); - ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels)); - - for (int i = 0; i < sourcePixels.Length; i++) - { - uint sp = Unsafe.Add(ref sourceRef, i); - Unsafe.Add(ref destRef, i) = PixelConverter.FromBgra32.ToRgba32(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromBgra32.ToRgba32(source, dest); } /// - public override void FromRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void FromRgba32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); - ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels)); - - for (int i = 0; i < sourcePixels.Length; i++) - { - uint sp = Unsafe.Add(ref sourceRef, i); - Unsafe.Add(ref destRef, i) = PixelConverter.FromRgba32.ToBgra32(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromRgba32.ToBgra32(source, dest); } /// - public override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToArgb32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); - ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels)); - - for (int i = 0; i < sourcePixels.Length; i++) - { - uint sp = Unsafe.Add(ref sourceRef, i); - Unsafe.Add(ref destRef, i) = PixelConverter.FromBgra32.ToArgb32(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromBgra32.ToArgb32(source, dest); } /// - public override void FromArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void FromArgb32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); - ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels)); + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromArgb32.ToBgra32(source, dest); + } + /// + public override void ToRgb24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - for (int i = 0; i < sourcePixels.Length; i++) - { - uint sp = Unsafe.Add(ref sourceRef, i); - Unsafe.Add(ref destRef, i) = PixelConverter.FromArgb32.ToBgra32(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromBgra32.ToRgb24(source, dest); } /// - public override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void FromRgb24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Bgr24 destRef = ref MemoryMarshal.GetReference(destinationPixels); - - for (int i = 0; i < sourcePixels.Length; i++) - { - ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Bgr24 dp = ref Unsafe.Add(ref destRef, i); + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromRgb24.ToBgra32(source, dest); + } + /// + public override void ToBgr24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - dp.FromBgra32(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromBgra32.ToBgr24(source, dest); } /// - public override void ToL8(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void FromBgr24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); + + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromBgr24.ToBgra32(source, dest); + } + /// + public override void ToL8( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -150,9 +185,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgra32(sp); } } - /// - public override void ToL16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -168,9 +205,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgra32(sp); } } - /// - public override void ToLa16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -186,9 +225,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgra32(sp); } } - /// - public override void ToLa32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -204,27 +245,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgra32(sp); } } - /// - public override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) - { - Guard.NotNull(configuration, nameof(configuration)); - Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - - ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Rgb24 destRef = ref MemoryMarshal.GetReference(destinationPixels); - - for (int i = 0; i < sourcePixels.Length; i++) - { - ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Rgb24 dp = ref Unsafe.Add(ref destRef, i); - - dp.FromBgra32(sp); - } - } - - /// - public override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb48( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -240,9 +265,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgra32(sp); } } - /// - public override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba64( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -258,9 +285,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgra32(sp); } } - /// - public override void ToBgra5551(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra5551( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -282,8 +311,9 @@ namespace SixLabors.ImageSharp.PixelFormats ReadOnlySpan sourcePixels, Span destinationPixels) { - PixelOperations.Instance.ToBgra32(configuration, sourcePixels, destinationPixels); + PixelOperations.Instance.ToBgra32(configuration, sourcePixels, destinationPixels.Slice(0, sourcePixels.Length)); } + } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgra32.PixelOperations.Generated.tt similarity index 78% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.tt rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgra32.PixelOperations.Generated.tt index 58ecfa5a6c..7e15979890 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgra32.PixelOperations.Generated.tt @@ -1,6 +1,5 @@ -<#@include file="_Common.ttinclude" #> +<#@include file="_Common.ttinclude" #> <#@ output extension=".cs" #> - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -11,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { <# GenerateAllDefaultConversionMethods("Bgra32"); #> } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra5551.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgra5551.PixelOperations.Generated.cs similarity index 79% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra5551.PixelOperations.Generated.cs rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgra5551.PixelOperations.Generated.cs index f9662e0d04..a02ffc3a43 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra5551.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgra5551.PixelOperations.Generated.cs @@ -3,13 +3,11 @@ // -using SixLabors.ImageSharp.PixelFormats.Utils; using System; -using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - +using SixLabors.ImageSharp.PixelFormats.Utils; namespace SixLabors.ImageSharp.PixelFormats { @@ -21,15 +19,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { - /// + /// public override void FromBgra5551(Configuration configuration, ReadOnlySpan source, Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destinationPixels, nameof(destinationPixels)); - source.CopyTo(destinationPixels); + source.CopyTo(destinationPixels.Slice(0, source.Length)); } /// @@ -38,12 +36,13 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - sourcePixels.CopyTo(destinationPixels); + sourcePixels.CopyTo(destinationPixels.Slice(0, sourcePixels.Length)); } - - /// - public override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToArgb32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -59,9 +58,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgra5551(sp); } } - /// - public override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgr24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -77,9 +78,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgra5551(sp); } } - /// - public override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -95,9 +98,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgra5551(sp); } } - /// - public override void ToL8(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL8( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -113,9 +118,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgra5551(sp); } } - /// - public override void ToL16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -131,9 +138,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgra5551(sp); } } - /// - public override void ToLa16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -149,9 +158,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgra5551(sp); } } - /// - public override void ToLa32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -167,9 +178,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgra5551(sp); } } - /// - public override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -185,9 +198,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgra5551(sp); } } - /// - public override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -203,9 +218,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgra5551(sp); } } - /// - public override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb48( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -221,9 +238,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromBgra5551(sp); } } - /// - public override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba64( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -245,8 +264,9 @@ namespace SixLabors.ImageSharp.PixelFormats ReadOnlySpan sourcePixels, Span destinationPixels) { - PixelOperations.Instance.ToBgra5551(configuration, sourcePixels, destinationPixels); + PixelOperations.Instance.ToBgra5551(configuration, sourcePixels, destinationPixels.Slice(0, sourcePixels.Length)); } + } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra5551.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgra5551.PixelOperations.Generated.tt similarity index 85% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra5551.PixelOperations.Generated.tt rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgra5551.PixelOperations.Generated.tt index c4f2fc8bdd..c74dfb4bd1 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra5551.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Bgra5551.PixelOperations.Generated.tt @@ -1,6 +1,5 @@ <#@include file="_Common.ttinclude" #> <#@ output extension=".cs" #> - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -11,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { <# GenerateAllDefaultConversionMethods("Bgra5551"); #> } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/L16.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/L16.PixelOperations.Generated.cs similarity index 79% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/L16.PixelOperations.Generated.cs rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/L16.PixelOperations.Generated.cs index d0c96def18..954ef2d985 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/L16.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/L16.PixelOperations.Generated.cs @@ -1,15 +1,13 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. // -using SixLabors.ImageSharp.PixelFormats.Utils; using System; -using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - +using SixLabors.ImageSharp.PixelFormats.Utils; namespace SixLabors.ImageSharp.PixelFormats { @@ -21,15 +19,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { - /// + /// public override void FromL16(Configuration configuration, ReadOnlySpan source, Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destinationPixels, nameof(destinationPixels)); - source.CopyTo(destinationPixels); + source.CopyTo(destinationPixels.Slice(0, source.Length)); } /// @@ -38,12 +36,13 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - sourcePixels.CopyTo(destinationPixels); + sourcePixels.CopyTo(destinationPixels.Slice(0, sourcePixels.Length)); } - - /// - public override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToArgb32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -59,9 +58,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL16(sp); } } - /// - public override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgr24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -77,9 +78,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL16(sp); } } - /// - public override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -95,9 +98,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL16(sp); } } - /// - public override void ToL8(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL8( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -113,9 +118,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL16(sp); } } - /// - public override void ToLa16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -131,9 +138,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL16(sp); } } - /// - public override void ToLa32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -149,9 +158,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL16(sp); } } - /// - public override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -167,9 +178,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL16(sp); } } - /// - public override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -185,9 +198,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL16(sp); } } - /// - public override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb48( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -203,9 +218,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL16(sp); } } - /// - public override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba64( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -221,9 +238,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL16(sp); } } - /// - public override void ToBgra5551(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra5551( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -245,8 +264,9 @@ namespace SixLabors.ImageSharp.PixelFormats ReadOnlySpan sourcePixels, Span destinationPixels) { - PixelOperations.Instance.ToL16(configuration, sourcePixels, destinationPixels); + PixelOperations.Instance.ToL16(configuration, sourcePixels, destinationPixels.Slice(0, sourcePixels.Length)); } + } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/L16.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/L16.PixelOperations.Generated.tt similarity index 78% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/L16.PixelOperations.Generated.tt rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/L16.PixelOperations.Generated.tt index 937902346f..9c0f725e62 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/L16.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/L16.PixelOperations.Generated.tt @@ -1,6 +1,5 @@ -<#@include file="_Common.ttinclude" #> +<#@include file="_Common.ttinclude" #> <#@ output extension=".cs" #> - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -11,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { <# GenerateAllDefaultConversionMethods("L16"); #> } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/L8.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/L8.PixelOperations.Generated.cs similarity index 79% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/L8.PixelOperations.Generated.cs rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/L8.PixelOperations.Generated.cs index 31b1c96ec2..b3d809de5c 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/L8.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/L8.PixelOperations.Generated.cs @@ -1,15 +1,13 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. // -using SixLabors.ImageSharp.PixelFormats.Utils; using System; -using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - +using SixLabors.ImageSharp.PixelFormats.Utils; namespace SixLabors.ImageSharp.PixelFormats { @@ -21,15 +19,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { - /// + /// public override void FromL8(Configuration configuration, ReadOnlySpan source, Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destinationPixels, nameof(destinationPixels)); - source.CopyTo(destinationPixels); + source.CopyTo(destinationPixels.Slice(0, source.Length)); } /// @@ -38,12 +36,13 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - sourcePixels.CopyTo(destinationPixels); + sourcePixels.CopyTo(destinationPixels.Slice(0, sourcePixels.Length)); } - - /// - public override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToArgb32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -59,9 +58,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL8(sp); } } - /// - public override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgr24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -77,9 +78,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL8(sp); } } - /// - public override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -95,9 +98,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL8(sp); } } - /// - public override void ToL16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -113,9 +118,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL8(sp); } } - /// - public override void ToLa16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -131,9 +138,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL8(sp); } } - /// - public override void ToLa32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -149,9 +158,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL8(sp); } } - /// - public override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -167,9 +178,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL8(sp); } } - /// - public override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -185,9 +198,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL8(sp); } } - /// - public override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb48( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -203,9 +218,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL8(sp); } } - /// - public override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba64( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -221,9 +238,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromL8(sp); } } - /// - public override void ToBgra5551(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra5551( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -245,8 +264,9 @@ namespace SixLabors.ImageSharp.PixelFormats ReadOnlySpan sourcePixels, Span destinationPixels) { - PixelOperations.Instance.ToL8(configuration, sourcePixels, destinationPixels); + PixelOperations.Instance.ToL8(configuration, sourcePixels, destinationPixels.Slice(0, sourcePixels.Length)); } + } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/L8.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/L8.PixelOperations.Generated.tt similarity index 78% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/L8.PixelOperations.Generated.tt rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/L8.PixelOperations.Generated.tt index d2e802a190..e6d4a45efc 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/L8.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/L8.PixelOperations.Generated.tt @@ -1,6 +1,5 @@ -<#@include file="_Common.ttinclude" #> +<#@include file="_Common.ttinclude" #> <#@ output extension=".cs" #> - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -11,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { <# GenerateAllDefaultConversionMethods("L8"); #> } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/La16.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/La16.PixelOperations.Generated.cs similarity index 79% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/La16.PixelOperations.Generated.cs rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/La16.PixelOperations.Generated.cs index 48e7c76e5b..14618d0265 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/La16.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/La16.PixelOperations.Generated.cs @@ -3,13 +3,11 @@ // -using SixLabors.ImageSharp.PixelFormats.Utils; using System; -using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - +using SixLabors.ImageSharp.PixelFormats.Utils; namespace SixLabors.ImageSharp.PixelFormats { @@ -21,15 +19,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { - /// + /// public override void FromLa16(Configuration configuration, ReadOnlySpan source, Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destinationPixels, nameof(destinationPixels)); - source.CopyTo(destinationPixels); + source.CopyTo(destinationPixels.Slice(0, source.Length)); } /// @@ -38,12 +36,13 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - sourcePixels.CopyTo(destinationPixels); + sourcePixels.CopyTo(destinationPixels.Slice(0, sourcePixels.Length)); } - - /// - public override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToArgb32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -59,9 +58,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa16(sp); } } - /// - public override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgr24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -77,9 +78,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa16(sp); } } - /// - public override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -95,9 +98,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa16(sp); } } - /// - public override void ToL8(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL8( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -113,9 +118,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa16(sp); } } - /// - public override void ToL16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -131,9 +138,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa16(sp); } } - /// - public override void ToLa32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -149,9 +158,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa16(sp); } } - /// - public override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -167,9 +178,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa16(sp); } } - /// - public override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -185,9 +198,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa16(sp); } } - /// - public override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb48( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -203,9 +218,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa16(sp); } } - /// - public override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba64( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -221,9 +238,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa16(sp); } } - /// - public override void ToBgra5551(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra5551( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -245,8 +264,9 @@ namespace SixLabors.ImageSharp.PixelFormats ReadOnlySpan sourcePixels, Span destinationPixels) { - PixelOperations.Instance.ToLa16(configuration, sourcePixels, destinationPixels); + PixelOperations.Instance.ToLa16(configuration, sourcePixels, destinationPixels.Slice(0, sourcePixels.Length)); } + } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/La16.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/La16.PixelOperations.Generated.tt similarity index 86% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/La16.PixelOperations.Generated.tt rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/La16.PixelOperations.Generated.tt index 5d6661631d..7b88fd4f1a 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/La16.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/La16.PixelOperations.Generated.tt @@ -1,6 +1,5 @@ <#@include file="_Common.ttinclude" #> <#@ output extension=".cs" #> - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -11,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { <# GenerateAllDefaultConversionMethods("La16"); #> } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/La32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/La32.PixelOperations.Generated.cs similarity index 79% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/La32.PixelOperations.Generated.cs rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/La32.PixelOperations.Generated.cs index f8b4bedc22..9620a1df4d 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/La32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/La32.PixelOperations.Generated.cs @@ -3,13 +3,11 @@ // -using SixLabors.ImageSharp.PixelFormats.Utils; using System; -using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - +using SixLabors.ImageSharp.PixelFormats.Utils; namespace SixLabors.ImageSharp.PixelFormats { @@ -21,15 +19,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { - /// + /// public override void FromLa32(Configuration configuration, ReadOnlySpan source, Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destinationPixels, nameof(destinationPixels)); - source.CopyTo(destinationPixels); + source.CopyTo(destinationPixels.Slice(0, source.Length)); } /// @@ -38,12 +36,13 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - sourcePixels.CopyTo(destinationPixels); + sourcePixels.CopyTo(destinationPixels.Slice(0, sourcePixels.Length)); } - - /// - public override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToArgb32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -59,9 +58,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa32(sp); } } - /// - public override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgr24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -77,9 +78,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa32(sp); } } - /// - public override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -95,9 +98,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa32(sp); } } - /// - public override void ToL8(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL8( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -113,9 +118,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa32(sp); } } - /// - public override void ToL16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -131,9 +138,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa32(sp); } } - /// - public override void ToLa16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -149,9 +158,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa32(sp); } } - /// - public override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -167,9 +178,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa32(sp); } } - /// - public override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -185,9 +198,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa32(sp); } } - /// - public override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb48( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -203,9 +218,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa32(sp); } } - /// - public override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba64( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -221,9 +238,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromLa32(sp); } } - /// - public override void ToBgra5551(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra5551( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -245,8 +264,9 @@ namespace SixLabors.ImageSharp.PixelFormats ReadOnlySpan sourcePixels, Span destinationPixels) { - PixelOperations.Instance.ToLa32(configuration, sourcePixels, destinationPixels); + PixelOperations.Instance.ToLa32(configuration, sourcePixels, destinationPixels.Slice(0, sourcePixels.Length)); } + } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/La32.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/La32.PixelOperations.Generated.tt similarity index 86% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/La32.PixelOperations.Generated.tt rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/La32.PixelOperations.Generated.tt index e2fb4867a9..f85652cad9 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/La32.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/La32.PixelOperations.Generated.tt @@ -1,6 +1,5 @@ <#@include file="_Common.ttinclude" #> <#@ output extension=".cs" #> - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -11,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { <# GenerateAllDefaultConversionMethods("La32"); #> } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgb24.PixelOperations.Generated.cs similarity index 54% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgb24.PixelOperations.Generated.cs index 332683fc7f..2fe7f3c20a 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgb24.PixelOperations.Generated.cs @@ -1,15 +1,13 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. // -using SixLabors.ImageSharp.PixelFormats.Utils; using System; -using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - +using SixLabors.ImageSharp.PixelFormats.Utils; namespace SixLabors.ImageSharp.PixelFormats { @@ -21,15 +19,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { - /// + /// public override void FromRgb24(Configuration configuration, ReadOnlySpan source, Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destinationPixels, nameof(destinationPixels)); - source.CopyTo(destinationPixels); + source.CopyTo(destinationPixels.Slice(0, source.Length)); } /// @@ -38,77 +36,140 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - sourcePixels.CopyTo(destinationPixels); + sourcePixels.CopyTo(destinationPixels.Slice(0, sourcePixels.Length)); } - /// - public override void FromVector4Destructive(Configuration configuration, Span sourceVectors, Span destinationPixels, PixelConversionModifiers modifiers) + public override void FromVector4Destructive( + Configuration configuration, + Span sourceVectors, + Span destinationPixels, + PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destinationPixels, modifiers.Remove(PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply)); } /// - public override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers) + public override void ToVector4( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destVectors, + PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply)); } - /// - public override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Argb32 destRef = ref MemoryMarshal.GetReference(destinationPixels); + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromRgb24.ToRgba32(source, dest); + } - for (int i = 0; i < sourcePixels.Length; i++) - { - ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i); - ref Argb32 dp = ref Unsafe.Add(ref destRef, i); + /// + public override void FromRgba32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - dp.FromRgb24(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromRgba32.ToRgb24(source, dest); } - /// - public override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToArgb32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Bgr24 destRef = ref MemoryMarshal.GetReference(destinationPixels); + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromRgb24.ToArgb32(source, dest); + } - for (int i = 0; i < sourcePixels.Length; i++) - { - ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i); - ref Bgr24 dp = ref Unsafe.Add(ref destRef, i); + /// + public override void FromArgb32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - dp.FromRgb24(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromArgb32.ToRgb24(source, dest); } - /// - public override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Bgra32 destRef = ref MemoryMarshal.GetReference(destinationPixels); + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromRgb24.ToBgra32(source, dest); + } - for (int i = 0; i < sourcePixels.Length; i++) - { - ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i); - ref Bgra32 dp = ref Unsafe.Add(ref destRef, i); + /// + public override void FromBgra32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - dp.FromRgb24(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromBgra32.ToRgb24(source, dest); + } + /// + public override void ToBgr24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); + + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromRgb24.ToBgr24(source, dest); } /// - public override void ToL8(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void FromBgr24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); + + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromBgr24.ToRgb24(source, dest); + } + /// + public override void ToL8( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -124,9 +185,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb24(sp); } } - /// - public override void ToL16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -142,9 +205,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb24(sp); } } - /// - public override void ToLa16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -160,9 +225,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb24(sp); } } - /// - public override void ToLa32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -178,27 +245,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb24(sp); } } - - /// - public override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) - { - Guard.NotNull(configuration, nameof(configuration)); - Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - - ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Rgba32 destRef = ref MemoryMarshal.GetReference(destinationPixels); - - for (int i = 0; i < sourcePixels.Length; i++) - { - ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i); - ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); - - dp.FromRgb24(sp); - } - } - /// - public override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb48( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -214,9 +265,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb24(sp); } } - /// - public override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba64( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -232,9 +285,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb24(sp); } } - /// - public override void ToBgra5551(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra5551( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -256,8 +311,9 @@ namespace SixLabors.ImageSharp.PixelFormats ReadOnlySpan sourcePixels, Span destinationPixels) { - PixelOperations.Instance.ToRgb24(configuration, sourcePixels, destinationPixels); + PixelOperations.Instance.ToRgb24(configuration, sourcePixels, destinationPixels.Slice(0, sourcePixels.Length)); } + } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgb24.PixelOperations.Generated.tt similarity index 78% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.tt rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgb24.PixelOperations.Generated.tt index fc149b2380..056c2a2797 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgb24.PixelOperations.Generated.tt @@ -1,6 +1,5 @@ -<#@include file="_Common.ttinclude" #> +<#@include file="_Common.ttinclude" #> <#@ output extension=".cs" #> - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -11,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { <# GenerateAllDefaultConversionMethods("Rgb24"); #> } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgb48.PixelOperations.Generated.cs similarity index 79% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgb48.PixelOperations.Generated.cs index 9423aa2c8f..031008fe1c 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgb48.PixelOperations.Generated.cs @@ -1,15 +1,13 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. // -using SixLabors.ImageSharp.PixelFormats.Utils; using System; -using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - +using SixLabors.ImageSharp.PixelFormats.Utils; namespace SixLabors.ImageSharp.PixelFormats { @@ -21,15 +19,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { - /// + /// public override void FromRgb48(Configuration configuration, ReadOnlySpan source, Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destinationPixels, nameof(destinationPixels)); - source.CopyTo(destinationPixels); + source.CopyTo(destinationPixels.Slice(0, source.Length)); } /// @@ -38,12 +36,13 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - sourcePixels.CopyTo(destinationPixels); + sourcePixels.CopyTo(destinationPixels.Slice(0, sourcePixels.Length)); } - - /// - public override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToArgb32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -59,9 +58,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb48(sp); } } - /// - public override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgr24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -77,9 +78,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb48(sp); } } - /// - public override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -95,9 +98,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb48(sp); } } - /// - public override void ToL8(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL8( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -113,9 +118,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb48(sp); } } - /// - public override void ToL16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -131,9 +138,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb48(sp); } } - /// - public override void ToLa16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -149,9 +158,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb48(sp); } } - /// - public override void ToLa32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -167,9 +178,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb48(sp); } } - /// - public override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -185,9 +198,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb48(sp); } } - /// - public override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -203,9 +218,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb48(sp); } } - /// - public override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba64( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -221,9 +238,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgb48(sp); } } - /// - public override void ToBgra5551(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra5551( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -245,8 +264,9 @@ namespace SixLabors.ImageSharp.PixelFormats ReadOnlySpan sourcePixels, Span destinationPixels) { - PixelOperations.Instance.ToRgb48(configuration, sourcePixels, destinationPixels); + PixelOperations.Instance.ToRgb48(configuration, sourcePixels, destinationPixels.Slice(0, sourcePixels.Length)); } + } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgb48.PixelOperations.Generated.tt similarity index 78% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.tt rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgb48.PixelOperations.Generated.tt index 957c8f886c..f46493e621 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb48.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgb48.PixelOperations.Generated.tt @@ -1,6 +1,5 @@ -<#@include file="_Common.ttinclude" #> +<#@include file="_Common.ttinclude" #> <#@ output extension=".cs" #> - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -11,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { <# GenerateAllDefaultConversionMethods("Rgb48"); #> } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgba32.PixelOperations.Generated.cs similarity index 59% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgba32.PixelOperations.Generated.cs index b05c62f1f7..16f96d2da1 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgba32.PixelOperations.Generated.cs @@ -1,15 +1,13 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. // -using SixLabors.ImageSharp.PixelFormats.Utils; using System; -using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - +using SixLabors.ImageSharp.PixelFormats.Utils; namespace SixLabors.ImageSharp.PixelFormats { @@ -23,13 +21,13 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal partial class PixelOperations : PixelOperations { - /// + /// public override void FromRgba32(Configuration configuration, ReadOnlySpan source, Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destinationPixels, nameof(destinationPixels)); - source.CopyTo(destinationPixels); + source.CopyTo(destinationPixels.Slice(0, source.Length)); } /// @@ -38,92 +36,121 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - sourcePixels.CopyTo(destinationPixels); + sourcePixels.CopyTo(destinationPixels.Slice(0, sourcePixels.Length)); } - /// - public override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToArgb32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); - ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels)); - - for (int i = 0; i < sourcePixels.Length; i++) - { - uint sp = Unsafe.Add(ref sourceRef, i); - Unsafe.Add(ref destRef, i) = PixelConverter.FromRgba32.ToArgb32(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromRgba32.ToArgb32(source, dest); } /// - public override void FromArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void FromArgb32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); - ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels)); - - for (int i = 0; i < sourcePixels.Length; i++) - { - uint sp = Unsafe.Add(ref sourceRef, i); - Unsafe.Add(ref destRef, i) = PixelConverter.FromArgb32.ToRgba32(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromArgb32.ToRgba32(source, dest); } /// - public override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); - ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels)); - - for (int i = 0; i < sourcePixels.Length; i++) - { - uint sp = Unsafe.Add(ref sourceRef, i); - Unsafe.Add(ref destRef, i) = PixelConverter.FromRgba32.ToBgra32(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromRgba32.ToBgra32(source, dest); } /// - public override void FromBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void FromBgra32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels)); - ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels)); + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromBgra32.ToRgba32(source, dest); + } + /// + public override void ToRgb24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - for (int i = 0; i < sourcePixels.Length; i++) - { - uint sp = Unsafe.Add(ref sourceRef, i); - Unsafe.Add(ref destRef, i) = PixelConverter.FromBgra32.ToRgba32(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromRgba32.ToRgb24(source, dest); } /// - public override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void FromRgb24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Bgr24 destRef = ref MemoryMarshal.GetReference(destinationPixels); - - for (int i = 0; i < sourcePixels.Length; i++) - { - ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Bgr24 dp = ref Unsafe.Add(ref destRef, i); + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromRgb24.ToRgba32(source, dest); + } + /// + public override void ToBgr24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - dp.FromRgba32(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromRgba32.ToBgr24(source, dest); } /// - public override void ToL8(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void FromBgr24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Guard.NotNull(configuration, nameof(configuration)); + Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); + + ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels); + Span dest = MemoryMarshal.Cast(destinationPixels); + PixelConverter.FromBgr24.ToRgba32(source, dest); + } + /// + public override void ToL8( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -139,9 +166,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba32(sp); } } - /// - public override void ToL16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -157,9 +186,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba32(sp); } } - /// - public override void ToLa16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -175,9 +206,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba32(sp); } } - /// - public override void ToLa32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -193,27 +226,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba32(sp); } } - - /// - public override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) - { - Guard.NotNull(configuration, nameof(configuration)); - Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - - ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); - ref Rgb24 destRef = ref MemoryMarshal.GetReference(destinationPixels); - - for (int i = 0; i < sourcePixels.Length; i++) - { - ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); - ref Rgb24 dp = ref Unsafe.Add(ref destRef, i); - - dp.FromRgba32(sp); - } - } - /// - public override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb48( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -229,9 +246,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba32(sp); } } - /// - public override void ToRgba64(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba64( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -247,9 +266,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba32(sp); } } - /// - public override void ToBgra5551(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra5551( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -271,8 +292,9 @@ namespace SixLabors.ImageSharp.PixelFormats ReadOnlySpan sourcePixels, Span destinationPixels) { - PixelOperations.Instance.ToRgba32(configuration, sourcePixels, destinationPixels); + PixelOperations.Instance.ToRgba32(configuration, sourcePixels, destinationPixels.Slice(0, sourcePixels.Length)); } + } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgba32.PixelOperations.Generated.tt similarity index 91% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.tt rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgba32.PixelOperations.Generated.tt index 905e2cc58f..6a6cac4e36 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgba32.PixelOperations.Generated.tt @@ -1,6 +1,5 @@ -<#@include file="_Common.ttinclude" #> +<#@include file="_Common.ttinclude" #> <#@ output extension=".cs" #> - namespace SixLabors.ImageSharp.PixelFormats { /// diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgba64.PixelOperations.Generated.cs similarity index 79% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgba64.PixelOperations.Generated.cs index 3fface03b6..1f1571e91d 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgba64.PixelOperations.Generated.cs @@ -1,15 +1,13 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. // -using SixLabors.ImageSharp.PixelFormats.Utils; using System; -using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - +using SixLabors.ImageSharp.PixelFormats.Utils; namespace SixLabors.ImageSharp.PixelFormats { @@ -21,15 +19,15 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { - /// + /// public override void FromRgba64(Configuration configuration, ReadOnlySpan source, Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destinationPixels, nameof(destinationPixels)); - source.CopyTo(destinationPixels); + source.CopyTo(destinationPixels.Slice(0, source.Length)); } /// @@ -38,12 +36,13 @@ namespace SixLabors.ImageSharp.PixelFormats Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - sourcePixels.CopyTo(destinationPixels); + sourcePixels.CopyTo(destinationPixels.Slice(0, sourcePixels.Length)); } - - /// - public override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToArgb32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -59,9 +58,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba64(sp); } } - /// - public override void ToBgr24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgr24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -77,9 +78,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba64(sp); } } - /// - public override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -95,9 +98,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba64(sp); } } - /// - public override void ToL8(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL8( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -113,9 +118,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba64(sp); } } - /// - public override void ToL16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -131,9 +138,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba64(sp); } } - /// - public override void ToLa16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -149,9 +158,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba64(sp); } } - /// - public override void ToLa32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToLa32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -167,9 +178,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba64(sp); } } - /// - public override void ToRgb24(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb24( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -185,9 +198,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba64(sp); } } - /// - public override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgba32( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -203,9 +218,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba64(sp); } } - /// - public override void ToRgb48(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToRgb48( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -221,9 +238,11 @@ namespace SixLabors.ImageSharp.PixelFormats dp.FromRgba64(sp); } } - /// - public override void ToBgra5551(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToBgra5551( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -245,8 +264,9 @@ namespace SixLabors.ImageSharp.PixelFormats ReadOnlySpan sourcePixels, Span destinationPixels) { - PixelOperations.Instance.ToRgba64(configuration, sourcePixels, destinationPixels); + PixelOperations.Instance.ToRgba64(configuration, sourcePixels, destinationPixels.Slice(0, sourcePixels.Length)); } + } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgba64.PixelOperations.Generated.tt similarity index 78% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.tt rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgba64.PixelOperations.Generated.tt index 03179a3920..cf02d38ee0 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba64.PixelOperations.Generated.tt +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/Rgba64.PixelOperations.Generated.tt @@ -1,6 +1,5 @@ -<#@include file="_Common.ttinclude" #> +<#@include file="_Common.ttinclude" #> <#@ output extension=".cs" #> - namespace SixLabors.ImageSharp.PixelFormats { /// @@ -11,7 +10,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// /// Provides optimized overrides for bulk operations. /// - internal class PixelOperations : PixelOperations + internal partial class PixelOperations : PixelOperations { <# GenerateAllDefaultConversionMethods("Rgba64"); #> } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/_Common.ttinclude similarity index 63% rename from src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/_Common.ttinclude index 5d56731ba6..784ecf6fb8 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Generated/_Common.ttinclude @@ -8,19 +8,45 @@ // -using SixLabors.ImageSharp.PixelFormats.Utils; using System; -using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using SixLabors.ImageSharp.PixelFormats.Utils; <#+ - static readonly string[] CommonPixelTypes = { "Argb32", "Bgr24", "Bgra32", "L8", "L16", "La16", "La32", "Rgb24", "Rgba32", "Rgb48", "Rgba64", "Bgra5551" }; - - static readonly string[] Optimized32BitTypes = { "Rgba32", "Argb32", "Bgra32" }; - - // Types with Rgba32-combatible to/from Vector4 conversion - static readonly string[] Rgba32CompatibleTypes = { "Argb32", "Bgra32", "Rgb24", "Bgr24" }; + private static readonly string[] CommonPixelTypes = + { + "Argb32", + "Bgr24", + "Bgra32", + "L8", + "L16", + "La16", + "La32", + "Rgb24", + "Rgba32", + "Rgb48", + "Rgba64", + "Bgra5551" + }; + + private static readonly string[] OptimizedPixelTypes = + { + "Rgba32", + "Argb32", + "Bgra32", + "Rgb24", + "Bgr24" + }; + + // Types with Rgba32-combatable to/from Vector4 conversion + private static readonly string[] Rgba32CompatibleTypes = + { + "Argb32", + "Bgra32", + "Rgb24", + "Bgr24" + }; void GenerateGenericConverterMethods(string pixelType) { @@ -31,21 +57,22 @@ using System.Runtime.InteropServices; ReadOnlySpan sourcePixels, Span<<#=pixelType#>> destinationPixels) { - PixelOperations.Instance.To<#=pixelType#>(configuration, sourcePixels, destinationPixels); + PixelOperations.Instance.To<#=pixelType#>(configuration, sourcePixels, destinationPixels.Slice(0, sourcePixels.Length)); } + <#+ } void GenerateDefaultSelfConversionMethods(string pixelType) { #> -/// + /// public override void From<#=pixelType#>(Configuration configuration, ReadOnlySpan<<#=pixelType#>> source, Span<<#=pixelType#>> destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(source, destinationPixels, nameof(destinationPixels)); - source.CopyTo(destinationPixels); + source.CopyTo(destinationPixels.Slice(0, source.Length)); } /// @@ -54,18 +81,19 @@ using System.Runtime.InteropServices; Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - sourcePixels.CopyTo(destinationPixels); + sourcePixels.CopyTo(destinationPixels.Slice(0, sourcePixels.Length)); } - <#+ } void GenerateDefaultConvertToMethod(string fromPixelType, string toPixelType) { #> - /// - public override void To<#=toPixelType#>(Configuration configuration, ReadOnlySpan<<#=fromPixelType#>> sourcePixels, Span<<#=toPixelType#>> destinationPixels) + public override void To<#=toPixelType#>( + Configuration configuration, + ReadOnlySpan<<#=fromPixelType#>> sourcePixels, + Span<<#=toPixelType#>> destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -88,35 +116,31 @@ using System.Runtime.InteropServices; { #> /// - public override void To<#=otherPixelType#>(Configuration configuration, ReadOnlySpan<<#=thisPixelType#>> sourcePixels, Span<<#=otherPixelType#>> destinationPixels) + public override void To<#=otherPixelType#>( + Configuration configuration, + ReadOnlySpan<<#=thisPixelType#>> sourcePixels, + Span<<#=otherPixelType#>> destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref uint sourceRef = ref Unsafe.As<<#=thisPixelType#>,uint>(ref MemoryMarshal.GetReference(sourcePixels)); - ref uint destRef = ref Unsafe.As<<#=otherPixelType#>, uint>(ref MemoryMarshal.GetReference(destinationPixels)); - - for (int i = 0; i < sourcePixels.Length; i++) - { - uint sp = Unsafe.Add(ref sourceRef, i); - Unsafe.Add(ref destRef, i) = PixelConverter.From<#=thisPixelType#>.To<#=otherPixelType#>(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast<<#=thisPixelType#>, byte>(sourcePixels); + Span dest = MemoryMarshal.Cast<<#=otherPixelType#>, byte>(destinationPixels); + PixelConverter.From<#=thisPixelType#>.To<#=otherPixelType#>(source, dest); } /// - public override void From<#=otherPixelType#>(Configuration configuration, ReadOnlySpan<<#=otherPixelType#>> sourcePixels, Span<<#=thisPixelType#>> destinationPixels) + public override void From<#=otherPixelType#>( + Configuration configuration, + ReadOnlySpan<<#=otherPixelType#>> sourcePixels, + Span<<#=thisPixelType#>> destinationPixels) { Guard.NotNull(configuration, nameof(configuration)); Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); - ref uint sourceRef = ref Unsafe.As<<#=otherPixelType#>,uint>(ref MemoryMarshal.GetReference(sourcePixels)); - ref uint destRef = ref Unsafe.As<<#=thisPixelType#>, uint>(ref MemoryMarshal.GetReference(destinationPixels)); - - for (int i = 0; i < sourcePixels.Length; i++) - { - uint sp = Unsafe.Add(ref sourceRef, i); - Unsafe.Add(ref destRef, i) = PixelConverter.From<#=otherPixelType#>.To<#=thisPixelType#>(sp); - } + ReadOnlySpan source = MemoryMarshal.Cast<<#=otherPixelType#>, byte>(sourcePixels); + Span dest = MemoryMarshal.Cast<<#=thisPixelType#>, byte>(destinationPixels); + PixelConverter.From<#=otherPixelType#>.To<#=thisPixelType#>(source, dest); } <#+ } @@ -130,13 +154,21 @@ using System.Runtime.InteropServices; } #> /// - public override void FromVector4Destructive(Configuration configuration, Span sourceVectors, Span<<#=pixelType#>> destinationPixels, PixelConversionModifiers modifiers) + public override void FromVector4Destructive( + Configuration configuration, + Span sourceVectors, + Span<<#=pixelType#>> destinationPixels, + PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destinationPixels, modifiers.Remove(<#=removeTheseModifiers#>)); } /// - public override void ToVector4(Configuration configuration, ReadOnlySpan<<#=pixelType#>> sourcePixels, Span destVectors, PixelConversionModifiers modifiers) + public override void ToVector4( + Configuration configuration, + ReadOnlySpan<<#=pixelType#>> sourcePixels, + Span destVectors, + PixelConversionModifiers modifiers) { Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(<#=removeTheseModifiers#>)); } @@ -152,8 +184,8 @@ using System.Runtime.InteropServices; GenerateRgba32CompatibleVector4ConversionMethods(pixelType, pixelType.EndsWith("32")); } - var matching32BitTypes = Optimized32BitTypes.Contains(pixelType) ? - Optimized32BitTypes.Where(p => p != pixelType) : + var matching32BitTypes = OptimizedPixelTypes.Contains(pixelType) ? + OptimizedPixelTypes.Where(p => p != pixelType) : Enumerable.Empty(); foreach (string destPixelType in matching32BitTypes) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/HalfSingle.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/HalfSingle.PixelOperations.cs new file mode 100644 index 0000000000..81b5f76b30 --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/HalfSingle.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct HalfSingle + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.None), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/HalfVector2.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/HalfVector2.PixelOperations.cs new file mode 100644 index 0000000000..228bb5c04c --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/HalfVector2.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct HalfVector2 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.None), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/HalfVector4.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/HalfVector4.PixelOperations.cs new file mode 100644 index 0000000000..9ef132077b --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/HalfVector4.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct HalfVector4 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/L16.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/L16.PixelOperations.cs new file mode 100644 index 0000000000..3a9c24f46f --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/L16.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct L16 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal partial class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.None), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/L8.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/L8.PixelOperations.cs new file mode 100644 index 0000000000..18a9a4c8a1 --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/L8.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct L8 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal partial class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.None), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/La16.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/La16.PixelOperations.cs new file mode 100644 index 0000000000..bd7ddaebbc --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/La16.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct La16 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal partial class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/La32.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/La32.PixelOperations.cs new file mode 100644 index 0000000000..c0e6cdd4f0 --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/La32.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct La32 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal partial class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/NormalizedByte2.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/NormalizedByte2.PixelOperations.cs new file mode 100644 index 0000000000..8d2739b2c5 --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/NormalizedByte2.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct NormalizedByte2 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.None), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/NormalizedByte4.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/NormalizedByte4.PixelOperations.cs new file mode 100644 index 0000000000..7825d16790 --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/NormalizedByte4.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct NormalizedByte4 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/NormalizedShort2.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/NormalizedShort2.PixelOperations.cs new file mode 100644 index 0000000000..35cf605c1c --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/NormalizedShort2.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct NormalizedShort2 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.None), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/NormalizedShort4.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/NormalizedShort4.PixelOperations.cs new file mode 100644 index 0000000000..d298c85f58 --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/NormalizedShort4.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct NormalizedShort4 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rg32.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rg32.PixelOperations.cs new file mode 100644 index 0000000000..c0a5ae920a --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rg32.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct Rg32 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.None), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb24.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb24.PixelOperations.cs new file mode 100644 index 0000000000..f345f58bcd --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb24.PixelOperations.cs @@ -0,0 +1,43 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using SixLabors.ImageSharp.Formats; + +namespace SixLabors.ImageSharp.PixelFormats +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct Rgb24 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal partial class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.None), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + + /// + internal override void PackFromRgbPlanes( + Configuration configuration, + ReadOnlySpan redChannel, + ReadOnlySpan greenChannel, + ReadOnlySpan blueChannel, + Span destination) + { + Guard.NotNull(configuration, nameof(configuration)); + int count = redChannel.Length; + Guard.IsTrue(greenChannel.Length == count, nameof(greenChannel), "Channels must be of same size!"); + Guard.IsTrue(blueChannel.Length == count, nameof(blueChannel), "Channels must be of same size!"); + Guard.IsTrue(destination.Length > count + 2, nameof(destination), "'destination' must contain a padding of 3 elements!"); + + SimdUtils.PackFromRgbPlanes(configuration, redChannel, greenChannel, blueChannel, destination); + } + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb48.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb48.PixelOperations.cs new file mode 100644 index 0000000000..4c26f1b0ff --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb48.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct Rgb48 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal partial class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.None), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba1010102.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba1010102.PixelOperations.cs new file mode 100644 index 0000000000..60fa98ed16 --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba1010102.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct Rgba1010102 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba32.PixelOperations.cs similarity index 63% rename from src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba32.PixelOperations.cs index dcf304e9b0..9633059774 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba32.PixelOperations.cs @@ -4,7 +4,7 @@ using System; using System.Numerics; using System.Runtime.InteropServices; - +using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.PixelFormats.Utils; namespace SixLabors.ImageSharp.PixelFormats @@ -19,6 +19,12 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal partial class PixelOperations : PixelOperations { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + /// public override void ToVector4( Configuration configuration, @@ -50,6 +56,23 @@ namespace SixLabors.ImageSharp.PixelFormats MemoryMarshal.Cast(sourceVectors), MemoryMarshal.Cast(destinationPixels)); } + + /// + internal override void PackFromRgbPlanes( + Configuration configuration, + ReadOnlySpan redChannel, + ReadOnlySpan greenChannel, + ReadOnlySpan blueChannel, + Span destination) + { + Guard.NotNull(configuration, nameof(configuration)); + int count = redChannel.Length; + Guard.IsTrue(greenChannel.Length == count, nameof(greenChannel), "Channels must be of same size!"); + Guard.IsTrue(blueChannel.Length == count, nameof(blueChannel), "Channels must be of same size!"); + Guard.IsTrue(destination.Length > count, nameof(destination), "'destination' span should not be shorter than the source channels!"); + + SimdUtils.PackFromRgbPlanes(configuration, redChannel, greenChannel, blueChannel, destination); + } } } } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba64.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba64.PixelOperations.cs new file mode 100644 index 0000000000..055b87286d --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba64.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct Rgba64 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal partial class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/RgbaVector.PixelOperations.cs similarity index 72% rename from src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs rename to src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/RgbaVector.PixelOperations.cs index aa0791d0cf..c66526bbe5 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/RgbaVector.PixelOperations.cs @@ -5,7 +5,7 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - +using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.PixelFormats.Utils; namespace SixLabors.ImageSharp.PixelFormats @@ -20,6 +20,23 @@ namespace SixLabors.ImageSharp.PixelFormats /// internal class PixelOperations : PixelOperations { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + + /// + public override void From( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) + { + Span destinationVectors = MemoryMarshal.Cast(destinationPixels); + + PixelOperations.Instance.ToVector4(configuration, sourcePixels, destinationVectors); + } + /// public override void FromVector4Destructive( Configuration configuration, @@ -46,7 +63,10 @@ namespace SixLabors.ImageSharp.PixelFormats Vector4Converters.ApplyForwardConversionModifiers(destinationVectors, modifiers); } - public override void ToL8(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL8( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); @@ -62,7 +82,10 @@ namespace SixLabors.ImageSharp.PixelFormats } } - public override void ToL16(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels) + public override void ToL16( + Configuration configuration, + ReadOnlySpan sourcePixels, + Span destinationPixels) { Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Short2.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Short2.PixelOperations.cs new file mode 100644 index 0000000000..e8a6bac3a1 --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Short2.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct Short2 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.None), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Short4.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Short4.PixelOperations.cs new file mode 100644 index 0000000000..8b99713d6e --- /dev/null +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Short4.PixelOperations.cs @@ -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 +{ + /// + /// Provides optimized overrides for bulk operations. + /// + public partial struct Short4 + { + /// + /// Provides optimized overrides for bulk operations. + /// + internal class PixelOperations : PixelOperations + { + private static readonly Lazy LazyInfo = + new Lazy(() => PixelTypeInfo.Create(PixelAlphaRepresentation.Unassociated), true); + + /// + public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + } + } +} diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rg32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rg32.cs index 7c805f1480..d7e6f53cf2 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rg32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rg32.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Ranges from [0, 0, 0, 1] to [1, 1, 0, 1] in vector form. /// /// - public struct Rg32 : IPixel, IPackedVector + public partial struct Rg32 : IPixel, IPackedVector { private static readonly Vector2 Max = new Vector2(ushort.MaxValue); @@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.PixelFormats public static bool operator !=(Rg32 left, Rg32 right) => !left.Equals(right); /// - public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); + public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs index a50c18d42c..7fd63c6766 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs @@ -166,7 +166,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromL16(L16 source) { - byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue); + byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.PackedValue); this.R = rgb; this.G = rgb; this.B = rgb; @@ -185,7 +185,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromLa32(La32 source) { - byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.L); + byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.L); this.R = rgb; this.G = rgb; this.B = rgb; @@ -227,18 +227,18 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgb48(Rgb48 source) { - this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R); - this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G); - this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B); + this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R); + this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G); + this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B); } /// [MethodImpl(InliningOptions.ShortMethod)] public void FromRgba64(Rgba64 source) { - this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R); - this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G); - this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B); + this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R); + this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G); + this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B); } /// @@ -264,7 +264,7 @@ namespace SixLabors.ImageSharp.PixelFormats { vector *= MaxBytes; vector += Half; - vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes); + vector = Numerics.Clamp(vector, Vector4.Zero, MaxBytes); this.R = (byte)vector.X; this.G = (byte)vector.Y; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs index 08f3bcc712..e3738b70c1 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs @@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromVector4(Vector4 vector) { - vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max; + vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One) * Max; this.R = (ushort)MathF.Round(vector.X); this.G = (ushort)MathF.Round(vector.Y); this.B = (ushort)MathF.Round(vector.Z); @@ -99,27 +99,27 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromArgb32(Argb32 source) { - this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); - this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); - this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); + this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R); + this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G); + this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B); } /// [MethodImpl(InliningOptions.ShortMethod)] public void FromBgr24(Bgr24 source) { - this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); - this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); - this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); + this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R); + this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G); + this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B); } /// [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) { - this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); - this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); - this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); + this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R); + this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G); + this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B); } /// @@ -134,7 +134,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromL8(L8 source) { - ushort rgb = ImageMaths.UpscaleFrom8BitTo16Bit(source.PackedValue); + ushort rgb = ColorNumerics.UpscaleFrom8BitTo16Bit(source.PackedValue); this.R = rgb; this.G = rgb; this.B = rgb; @@ -153,7 +153,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromLa16(La16 source) { - ushort rgb = ImageMaths.UpscaleFrom8BitTo16Bit(source.L); + ushort rgb = ColorNumerics.UpscaleFrom8BitTo16Bit(source.L); this.R = rgb; this.G = rgb; this.B = rgb; @@ -172,27 +172,27 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgb24(Rgb24 source) { - this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); - this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); - this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); + this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R); + this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G); + this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B); } /// [MethodImpl(InliningOptions.ShortMethod)] public void FromRgba32(Rgba32 source) { - this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); - this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); - this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); + this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R); + this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G); + this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B); } /// [MethodImpl(InliningOptions.ShortMethod)] public void ToRgba32(ref Rgba32 dest) { - dest.R = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); - dest.G = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); - dest.B = ImageMaths.DownScaleFrom16BitTo8Bit(this.B); + dest.R = ColorNumerics.DownScaleFrom16BitTo8Bit(this.R); + dest.G = ColorNumerics.DownScaleFrom16BitTo8Bit(this.G); + dest.B = ColorNumerics.DownScaleFrom16BitTo8Bit(this.B); dest.A = byte.MaxValue; } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs index 2bf9350f8f..dee2f9fcb6 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs @@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form. /// /// - public struct Rgba1010102 : IPixel, IPackedVector + public partial struct Rgba1010102 : IPixel, IPackedVector { private static readonly Vector4 Multiplier = new Vector4(1023F, 1023F, 1023F, 3F); @@ -62,7 +62,7 @@ namespace SixLabors.ImageSharp.PixelFormats public static bool operator !=(Rgba1010102 left, Rgba1010102 right) => !left.Equals(right); /// - public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); + public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -163,7 +163,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] private static uint Pack(ref Vector4 vector) { - vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Multiplier; + vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One) * Multiplier; return (uint)( (((int)Math.Round(vector.X) & 0x03FF) << 0) diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs index 0b42351011..868165e9c4 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs @@ -351,7 +351,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromL16(L16 source) { - byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue); + byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.PackedValue); this.R = rgb; this.G = rgb; this.B = rgb; @@ -372,11 +372,11 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromLa32(La32 source) { - byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.L); + byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.L); this.R = rgb; this.G = rgb; this.B = rgb; - this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A); + this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A); } /// @@ -402,9 +402,9 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgb48(Rgb48 source) { - this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R); - this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G); - this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B); + this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R); + this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G); + this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B); this.A = byte.MaxValue; } @@ -412,10 +412,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgba64(Rgba64 source) { - this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R); - this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G); - this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B); - this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A); + this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R); + this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G); + this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B); + this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A); } /// @@ -452,7 +452,7 @@ namespace SixLabors.ImageSharp.PixelFormats { vector *= MaxBytes; vector += Half; - vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes); + vector = Numerics.Clamp(vector, Vector4.Zero, MaxBytes); return new Rgba32((byte)vector.X, (byte)vector.Y, (byte)vector.Z, (byte)vector.W); } @@ -491,7 +491,7 @@ namespace SixLabors.ImageSharp.PixelFormats { vector *= MaxBytes; vector += Half; - vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes); + vector = Numerics.Clamp(vector, Vector4.Zero, MaxBytes); this.R = (byte)vector.X; this.G = (byte)vector.Y; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs index 22f58ca4ad..9add3d7180 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs @@ -62,10 +62,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public Rgba64(Rgba32 source) { - this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); - this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); - this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); - this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A); + this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R); + this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G); + this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B); + this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A); } /// @@ -75,10 +75,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public Rgba64(Bgra32 source) { - this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); - this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); - this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); - this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A); + this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R); + this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G); + this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B); + this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A); } /// @@ -88,10 +88,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public Rgba64(Argb32 source) { - this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); - this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); - this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); - this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A); + this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R); + this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G); + this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B); + this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A); } /// @@ -101,9 +101,9 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public Rgba64(Rgb24 source) { - this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); - this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); - this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); + this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R); + this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G); + this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B); this.A = ushort.MaxValue; } @@ -114,9 +114,9 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public Rgba64(Bgr24 source) { - this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); - this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); - this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); + this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R); + this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G); + this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B); this.A = ushort.MaxValue; } @@ -127,7 +127,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public Rgba64(Vector4 vector) { - vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max; + vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One) * Max; this.R = (ushort)MathF.Round(vector.X); this.G = (ushort)MathF.Round(vector.Y); this.B = (ushort)MathF.Round(vector.Z); @@ -209,7 +209,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromVector4(Vector4 vector) { - vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max; + vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One) * Max; this.R = (ushort)MathF.Round(vector.X); this.G = (ushort)MathF.Round(vector.Y); this.B = (ushort)MathF.Round(vector.Z); @@ -224,19 +224,19 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromArgb32(Argb32 source) { - this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); - this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); - this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); - this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A); + this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R); + this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G); + this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B); + this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A); } /// [MethodImpl(InliningOptions.ShortMethod)] public void FromBgr24(Bgr24 source) { - this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); - this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); - this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); + this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R); + this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G); + this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B); this.A = ushort.MaxValue; } @@ -244,10 +244,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromBgra32(Bgra32 source) { - this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); - this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); - this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); - this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A); + this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R); + this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G); + this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B); + this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A); } /// @@ -258,7 +258,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromL8(L8 source) { - ushort rgb = ImageMaths.UpscaleFrom8BitTo16Bit(source.PackedValue); + ushort rgb = ColorNumerics.UpscaleFrom8BitTo16Bit(source.PackedValue); this.R = rgb; this.G = rgb; this.B = rgb; @@ -279,11 +279,11 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromLa16(La16 source) { - ushort rgb = ImageMaths.UpscaleFrom8BitTo16Bit(source.L); + ushort rgb = ColorNumerics.UpscaleFrom8BitTo16Bit(source.L); this.R = rgb; this.G = rgb; this.B = rgb; - this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A); + this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A); } /// @@ -300,9 +300,9 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgb24(Rgb24 source) { - this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); - this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); - this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); + this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R); + this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G); + this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B); this.A = ushort.MaxValue; } @@ -310,20 +310,20 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromRgba32(Rgba32 source) { - this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R); - this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G); - this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B); - this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A); + this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R); + this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G); + this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B); + this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A); } /// [MethodImpl(InliningOptions.ShortMethod)] public void ToRgba32(ref Rgba32 dest) { - dest.R = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); - dest.G = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); - dest.B = ImageMaths.DownScaleFrom16BitTo8Bit(this.B); - dest.A = ImageMaths.DownScaleFrom16BitTo8Bit(this.A); + dest.R = ColorNumerics.DownScaleFrom16BitTo8Bit(this.R); + dest.G = ColorNumerics.DownScaleFrom16BitTo8Bit(this.G); + dest.B = ColorNumerics.DownScaleFrom16BitTo8Bit(this.B); + dest.A = ColorNumerics.DownScaleFrom16BitTo8Bit(this.A); } /// @@ -345,10 +345,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public readonly Rgba32 ToRgba32() { - byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); - byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); - byte b = ImageMaths.DownScaleFrom16BitTo8Bit(this.B); - byte a = ImageMaths.DownScaleFrom16BitTo8Bit(this.A); + byte r = ColorNumerics.DownScaleFrom16BitTo8Bit(this.R); + byte g = ColorNumerics.DownScaleFrom16BitTo8Bit(this.G); + byte b = ColorNumerics.DownScaleFrom16BitTo8Bit(this.B); + byte a = ColorNumerics.DownScaleFrom16BitTo8Bit(this.A); return new Rgba32(r, g, b, a); } @@ -359,10 +359,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public readonly Bgra32 ToBgra32() { - byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); - byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); - byte b = ImageMaths.DownScaleFrom16BitTo8Bit(this.B); - byte a = ImageMaths.DownScaleFrom16BitTo8Bit(this.A); + byte r = ColorNumerics.DownScaleFrom16BitTo8Bit(this.R); + byte g = ColorNumerics.DownScaleFrom16BitTo8Bit(this.G); + byte b = ColorNumerics.DownScaleFrom16BitTo8Bit(this.B); + byte a = ColorNumerics.DownScaleFrom16BitTo8Bit(this.A); return new Bgra32(r, g, b, a); } @@ -373,10 +373,10 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public readonly Argb32 ToArgb32() { - byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); - byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); - byte b = ImageMaths.DownScaleFrom16BitTo8Bit(this.B); - byte a = ImageMaths.DownScaleFrom16BitTo8Bit(this.A); + byte r = ColorNumerics.DownScaleFrom16BitTo8Bit(this.R); + byte g = ColorNumerics.DownScaleFrom16BitTo8Bit(this.G); + byte b = ColorNumerics.DownScaleFrom16BitTo8Bit(this.B); + byte a = ColorNumerics.DownScaleFrom16BitTo8Bit(this.A); return new Argb32(r, g, b, a); } @@ -387,9 +387,9 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public readonly Rgb24 ToRgb24() { - byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); - byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); - byte b = ImageMaths.DownScaleFrom16BitTo8Bit(this.B); + byte r = ColorNumerics.DownScaleFrom16BitTo8Bit(this.R); + byte g = ColorNumerics.DownScaleFrom16BitTo8Bit(this.G); + byte b = ColorNumerics.DownScaleFrom16BitTo8Bit(this.B); return new Rgb24(r, g, b); } @@ -400,9 +400,9 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public readonly Bgr24 ToBgr24() { - byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R); - byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G); - byte b = ImageMaths.DownScaleFrom16BitTo8Bit(this.B); + byte r = ColorNumerics.DownScaleFrom16BitTo8Bit(this.R); + byte g = ColorNumerics.DownScaleFrom16BitTo8Bit(this.G); + byte b = ColorNumerics.DownScaleFrom16BitTo8Bit(this.B); return new Bgr24(r, g, b); } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs index 6ea80ca3b9..97e103d0f2 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs @@ -111,7 +111,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] public void FromVector4(Vector4 vector) { - vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One); + vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One); this.R = vector.X; this.G = vector.Y; this.B = vector.Z; diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Short2.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Short2.cs index 91c0e9ab5a..f7a4f99945 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Short2.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Short2.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Ranges from [-32767, -32767, 0, 1] to [32767, 32767, 0, 1] in vector form. /// /// - public struct Short2 : IPixel, IPackedVector + public partial struct Short2 : IPixel, IPackedVector { // Largest two byte positive number 0xFFFF >> 1; private const float MaxPos = 0x7FFF; @@ -66,7 +66,7 @@ namespace SixLabors.ImageSharp.PixelFormats public static bool operator !=(Short2 left, Short2 right) => !left.Equals(right); /// - public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); + public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(InliningOptions.ShortMethod)] diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs index 3f74b68453..409f46c721 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs @@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// Ranges from [-37267, -37267, -37267, -37267] to [37267, 37267, 37267, 37267] in vector form. /// /// - public struct Short4 : IPixel, IPackedVector + public partial struct Short4 : IPixel, IPackedVector { // Largest two byte positive number 0xFFFF >> 1; private const float MaxPos = 0x7FFF; @@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.PixelFormats public static bool operator !=(Short4 left, Short4 right) => !left.Equals(right); /// - public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); + public readonly PixelOperations CreatePixelOperations() => new PixelOperations(); /// [MethodImpl(InliningOptions.ShortMethod)] @@ -164,7 +164,7 @@ namespace SixLabors.ImageSharp.PixelFormats /// [MethodImpl(InliningOptions.ShortMethod)] - public readonly bool Equals(Short4 other) => this.PackedValue.Equals(other); + public readonly bool Equals(Short4 other) => this.PackedValue.Equals(other.PackedValue); /// /// Gets the hash code for the current instance. @@ -183,7 +183,7 @@ namespace SixLabors.ImageSharp.PixelFormats [MethodImpl(InliningOptions.ShortMethod)] private static ulong Pack(ref Vector4 vector) { - vector = Vector4Utilities.FastClamp(vector, Min, Max); + vector = Numerics.Clamp(vector, Min, Max); // Clamp the value between min and max values ulong word4 = ((ulong)Math.Round(vector.X) & 0xFFFF) << 0x00; diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index 2fff67b58d..c5450538e4 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -4,7 +4,9 @@ using System; using System.Buffers; using System.Numerics; - +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.PixelFormats @@ -17,11 +19,19 @@ namespace SixLabors.ImageSharp.PixelFormats public partial class PixelOperations where TPixel : unmanaged, IPixel { + private static readonly Lazy LazyInfo = new Lazy(() => PixelTypeInfo.Create(), true); + /// /// Gets the global instance for the pixel type /// public static PixelOperations Instance { get; } = default(TPixel).CreatePixelOperations(); + /// + /// Gets the pixel type info for the given . + /// + /// The . + public virtual PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; + /// /// Bulk version of converting 'sourceVectors.Length' pixels into 'destinationColors'. /// The method is DESTRUCTIVE altering the contents of . @@ -108,28 +118,27 @@ namespace SixLabors.ImageSharp.PixelFormats { const int SliceLength = 1024; int numberOfSlices = sourcePixels.Length / SliceLength; - using (IMemoryOwner tempVectors = configuration.MemoryAllocator.Allocate(SliceLength)) + + using IMemoryOwner tempVectors = configuration.MemoryAllocator.Allocate(SliceLength); + Span vectorSpan = tempVectors.GetSpan(); + for (int i = 0; i < numberOfSlices; i++) { - Span vectorSpan = tempVectors.GetSpan(); - for (int i = 0; i < numberOfSlices; i++) - { - int start = i * SliceLength; - ReadOnlySpan s = sourcePixels.Slice(start, SliceLength); - Span d = destinationPixels.Slice(start, SliceLength); - PixelOperations.Instance.ToVector4(configuration, s, vectorSpan); - this.FromVector4Destructive(configuration, vectorSpan, d); - } - - int endOfCompleteSlices = numberOfSlices * SliceLength; - int remainder = sourcePixels.Length - endOfCompleteSlices; - if (remainder > 0) - { - ReadOnlySpan s = sourcePixels.Slice(endOfCompleteSlices); - Span d = destinationPixels.Slice(endOfCompleteSlices); - vectorSpan = vectorSpan.Slice(0, remainder); - PixelOperations.Instance.ToVector4(configuration, s, vectorSpan); - this.FromVector4Destructive(configuration, vectorSpan, d); - } + int start = i * SliceLength; + ReadOnlySpan s = sourcePixels.Slice(start, SliceLength); + Span d = destinationPixels.Slice(start, SliceLength); + PixelOperations.Instance.ToVector4(configuration, s, vectorSpan); + this.FromVector4Destructive(configuration, vectorSpan, d); + } + + int endOfCompleteSlices = numberOfSlices * SliceLength; + int remainder = sourcePixels.Length - endOfCompleteSlices; + if (remainder > 0) + { + ReadOnlySpan s = sourcePixels.Slice(endOfCompleteSlices); + Span d = destinationPixels.Slice(endOfCompleteSlices); + vectorSpan = vectorSpan.Slice(0, remainder); + PixelOperations.Instance.ToVector4(configuration, s, vectorSpan); + this.FromVector4Destructive(configuration, vectorSpan, d); } } @@ -152,5 +161,45 @@ namespace SixLabors.ImageSharp.PixelFormats PixelOperations.Instance.From(configuration, sourcePixels, destinationPixels); } + + /// + /// Bulk operation that packs 3 seperate RGB channels to . + /// The destination must have a padding of 3. + /// + /// A to configure internal operations. + /// A to the red values. + /// A to the green values. + /// A to the blue values. + /// A to the destination pixels. + internal virtual void PackFromRgbPlanes( + Configuration configuration, + ReadOnlySpan redChannel, + ReadOnlySpan greenChannel, + ReadOnlySpan blueChannel, + Span destination) + { + Guard.NotNull(configuration, nameof(configuration)); + + int count = redChannel.Length; + Guard.IsTrue(greenChannel.Length == count, nameof(greenChannel), "Channels must be of same size!"); + Guard.IsTrue(blueChannel.Length == count, nameof(blueChannel), "Channels must be of same size!"); + Guard.IsTrue(destination.Length > count + 2, nameof(destination), "'destination' must contain a padding of 3 elements!"); + + Guard.DestinationShouldNotBeTooShort(redChannel, destination, nameof(destination)); + + Rgb24 rgb24 = default; + ref byte r = ref MemoryMarshal.GetReference(redChannel); + ref byte g = ref MemoryMarshal.GetReference(greenChannel); + ref byte b = ref MemoryMarshal.GetReference(blueChannel); + ref TPixel d = ref MemoryMarshal.GetReference(destination); + + for (int i = 0; i < count; i++) + { + rgb24.R = Unsafe.Add(ref r, i); + rgb24.G = Unsafe.Add(ref g, i); + rgb24.B = Unsafe.Add(ref b, i); + Unsafe.Add(ref d, i).FromRgb24(rgb24); + } + } } } diff --git a/src/ImageSharp/PixelFormats/Utils/PixelConverter.cs b/src/ImageSharp/PixelFormats/Utils/PixelConverter.cs index 8142640848..7215fa860b 100644 --- a/src/ImageSharp/PixelFormats/Utils/PixelConverter.cs +++ b/src/ImageSharp/PixelFormats/Utils/PixelConverter.cs @@ -1,7 +1,7 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -using System.Buffers.Binary; +using System; using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.PixelFormats.Utils @@ -21,88 +21,196 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils public static class FromRgba32 { /// - /// Converts a packed to . + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. /// [MethodImpl(InliningOptions.ShortMethod)] - public static uint ToArgb32(uint packedRgba) - { - // packedRgba = [aa bb gg rr] - // ROTL(8, packedRgba) = [bb gg rr aa] - return (packedRgba << 8) | (packedRgba >> 24); - } + public static void ToArgb32(ReadOnlySpan source, Span dest) + => SimdUtils.Shuffle4(source, dest, default); /// - /// Converts a packed to . + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. /// [MethodImpl(InliningOptions.ShortMethod)] - public static uint ToBgra32(uint packedRgba) - { - // packedRgba = [aa bb gg rr] - // tmp1 = [aa 00 gg 00] - // tmp2 = [00 bb 00 rr] - // tmp3=ROTL(16, tmp2) = [00 rr 00 bb] - // tmp1 + tmp3 = [aa rr gg bb] - uint tmp1 = packedRgba & 0xFF00FF00; - uint tmp2 = packedRgba & 0x00FF00FF; - uint tmp3 = (tmp2 << 16) | (tmp2 >> 16); - return tmp1 + tmp3; - } + public static void ToBgra32(ReadOnlySpan source, Span dest) + => SimdUtils.Shuffle4(source, dest, default); + + /// + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static void ToRgb24(ReadOnlySpan source, Span dest) + => SimdUtils.Shuffle4Slice3(source, dest, default); + + /// + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static void ToBgr24(ReadOnlySpan source, Span dest) + => SimdUtils.Shuffle4Slice3(source, dest, new DefaultShuffle4Slice3(3, 0, 1, 2)); } public static class FromArgb32 { /// - /// Converts a packed to . + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static void ToRgba32(ReadOnlySpan source, Span dest) + => SimdUtils.Shuffle4(source, dest, default); + + /// + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static void ToBgra32(ReadOnlySpan source, Span dest) + => SimdUtils.Shuffle4(source, dest, default); + + /// + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. /// [MethodImpl(InliningOptions.ShortMethod)] - public static uint ToRgba32(uint packedArgb) - { - // packedArgb = [bb gg rr aa] - // ROTR(8, packedArgb) = [aa bb gg rr] - return (packedArgb >> 8) | (packedArgb << 24); - } + public static void ToRgb24(ReadOnlySpan source, Span dest) + => SimdUtils.Shuffle4Slice3(source, dest, new DefaultShuffle4Slice3(0, 3, 2, 1)); /// - /// Converts a packed to . + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. /// [MethodImpl(InliningOptions.ShortMethod)] - public static uint ToBgra32(uint packedArgb) - { - // packedArgb = [bb gg rr aa] - // REVERSE(packedArgb) = [aa rr gg bb] - return BinaryPrimitives.ReverseEndianness(packedArgb); - } + public static void ToBgr24(ReadOnlySpan source, Span dest) + => SimdUtils.Shuffle4Slice3(source, dest, new DefaultShuffle4Slice3(0, 1, 2, 3)); } public static class FromBgra32 { /// - /// Converts a packed to . + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static void ToArgb32(ReadOnlySpan source, Span dest) + => SimdUtils.Shuffle4(source, dest, default); + + /// + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static void ToRgba32(ReadOnlySpan source, Span dest) + => SimdUtils.Shuffle4(source, dest, default); + + /// + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static void ToRgb24(ReadOnlySpan source, Span dest) + => SimdUtils.Shuffle4Slice3(source, dest, new DefaultShuffle4Slice3(3, 0, 1, 2)); + + /// + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static void ToBgr24(ReadOnlySpan source, Span dest) + => SimdUtils.Shuffle4Slice3(source, dest, default); + } + + public static class FromRgb24 + { + /// + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static void ToRgba32(ReadOnlySpan source, Span dest) + => SimdUtils.Pad3Shuffle4(source, dest, default); + + /// + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static void ToArgb32(ReadOnlySpan source, Span dest) + => SimdUtils.Pad3Shuffle4(source, dest, new DefaultPad3Shuffle4(2, 1, 0, 3)); + + /// + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static void ToBgra32(ReadOnlySpan source, Span dest) + => SimdUtils.Pad3Shuffle4(source, dest, new DefaultPad3Shuffle4(3, 0, 1, 2)); + + /// + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static void ToBgr24(ReadOnlySpan source, Span dest) + => SimdUtils.Shuffle3(source, dest, new DefaultShuffle3(0, 1, 2)); + } + + public static class FromBgr24 + { + /// + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static void ToArgb32(ReadOnlySpan source, Span dest) + => SimdUtils.Pad3Shuffle4(source, dest, new DefaultPad3Shuffle4(0, 1, 2, 3)); + + /// + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. + /// + [MethodImpl(InliningOptions.ShortMethod)] + public static void ToRgba32(ReadOnlySpan source, Span dest) + => SimdUtils.Pad3Shuffle4(source, dest, new DefaultPad3Shuffle4(3, 0, 1, 2)); + + /// + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. /// [MethodImpl(InliningOptions.ShortMethod)] - public static uint ToArgb32(uint packedBgra) - { - // packedBgra = [aa rr gg bb] - // REVERSE(packedBgra) = [bb gg rr aa] - return BinaryPrimitives.ReverseEndianness(packedBgra); - } + public static void ToBgra32(ReadOnlySpan source, Span dest) + => SimdUtils.Pad3Shuffle4(source, dest, default); /// - /// Converts a packed to . + /// Converts a representing a collection of + /// pixels to a representing + /// a collection of pixels. /// [MethodImpl(InliningOptions.ShortMethod)] - public static uint ToRgba32(uint packedBgra) - { - // packedRgba = [aa rr gg bb] - // tmp1 = [aa 00 gg 00] - // tmp2 = [00 rr 00 bb] - // tmp3=ROTL(16, tmp2) = [00 bb 00 rr] - // tmp1 + tmp3 = [aa bb gg rr] - uint tmp1 = packedBgra & 0xFF00FF00; - uint tmp2 = packedBgra & 0x00FF00FF; - uint tmp3 = (tmp2 << 16) | (tmp2 >> 16); - return tmp1 + tmp3; - } + public static void ToRgb24(ReadOnlySpan source, Span dest) + => SimdUtils.Shuffle3(source, dest, new DefaultShuffle3(0, 1, 2)); } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs index 999f6325bc..6b6ff4319f 100644 --- a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs @@ -88,14 +88,16 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils Span destPixels) where TPixel : unmanaged, IPixel { - ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors); + ref Vector4 sourceStart = ref MemoryMarshal.GetReference(sourceVectors); + ref Vector4 sourceEnd = ref Unsafe.Add(ref sourceStart, sourceVectors.Length); ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels); - for (int i = 0; i < sourceVectors.Length; i++) + while (Unsafe.IsAddressLessThan(ref sourceStart, ref sourceEnd)) { - ref Vector4 sp = ref Unsafe.Add(ref sourceRef, i); - ref TPixel dp = ref Unsafe.Add(ref destRef, i); - dp.FromVector4(sp); + destRef.FromVector4(sourceStart); + + sourceStart = ref Unsafe.Add(ref sourceStart, 1); + destRef = ref Unsafe.Add(ref destRef, 1); } } @@ -105,14 +107,16 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils Span destVectors) where TPixel : unmanaged, IPixel { - ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourcePixels); + ref TPixel sourceStart = ref MemoryMarshal.GetReference(sourcePixels); + ref TPixel sourceEnd = ref Unsafe.Add(ref sourceStart, sourcePixels.Length); ref Vector4 destRef = ref MemoryMarshal.GetReference(destVectors); - for (int i = 0; i < sourcePixels.Length; i++) + while (Unsafe.IsAddressLessThan(ref sourceStart, ref sourceEnd)) { - ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); - ref Vector4 dp = ref Unsafe.Add(ref destRef, i); - dp = sp.ToVector4(); + destRef = sourceStart.ToVector4(); + + sourceStart = ref Unsafe.Add(ref sourceStart, 1); + destRef = ref Unsafe.Add(ref destRef, 1); } } @@ -122,14 +126,16 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils Span destinationColors) where TPixel : unmanaged, IPixel { - ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceVectors); + ref Vector4 sourceStart = ref MemoryMarshal.GetReference(sourceVectors); + ref Vector4 sourceEnd = ref Unsafe.Add(ref sourceStart, sourceVectors.Length); ref TPixel destRef = ref MemoryMarshal.GetReference(destinationColors); - for (int i = 0; i < sourceVectors.Length; i++) + while (Unsafe.IsAddressLessThan(ref sourceStart, ref sourceEnd)) { - ref Vector4 sp = ref Unsafe.Add(ref sourceRef, i); - ref TPixel dp = ref Unsafe.Add(ref destRef, i); - dp.FromScaledVector4(sp); + destRef.FromScaledVector4(sourceStart); + + sourceStart = ref Unsafe.Add(ref sourceStart, 1); + destRef = ref Unsafe.Add(ref destRef, 1); } } @@ -139,16 +145,18 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils Span destinationVectors) where TPixel : unmanaged, IPixel { - ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourceColors); + ref TPixel sourceStart = ref MemoryMarshal.GetReference(sourceColors); + ref TPixel sourceEnd = ref Unsafe.Add(ref sourceStart, sourceColors.Length); ref Vector4 destRef = ref MemoryMarshal.GetReference(destinationVectors); - for (int i = 0; i < sourceColors.Length; i++) + while (Unsafe.IsAddressLessThan(ref sourceStart, ref sourceEnd)) { - ref TPixel sp = ref Unsafe.Add(ref sourceRef, i); - ref Vector4 dp = ref Unsafe.Add(ref destRef, i); - dp = sp.ToScaledVector4(); + destRef = sourceStart.ToScaledVector4(); + + sourceStart = ref Unsafe.Add(ref sourceStart, 1); + destRef = ref Unsafe.Add(ref destRef, 1); } } } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs index 2dca8f2c14..7af2662765 100644 --- a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System; @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils if (modifiers.IsDefined(PixelConversionModifiers.Premultiply)) { - Vector4Utilities.Premultiply(vectors); + Numerics.Premultiply(vectors); } } @@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils { if (modifiers.IsDefined(PixelConversionModifiers.Premultiply)) { - Vector4Utilities.UnPremultiply(vectors); + Numerics.UnPremultiply(vectors); } if (modifiers.IsDefined(PixelConversionModifiers.SRgbCompand)) @@ -45,4 +45,4 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils } } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Primitives/ComplexVector4.cs b/src/ImageSharp/Primitives/ComplexVector4.cs index 3a1d4ac460..07f074502f 100644 --- a/src/ImageSharp/Primitives/ComplexVector4.cs +++ b/src/ImageSharp/Primitives/ComplexVector4.cs @@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp /// /// The input to sum [MethodImpl(InliningOptions.ShortMethod)] - public void Sum(in ComplexVector4 value) + public void Sum(ComplexVector4 value) { this.Real += value.Real; this.Imaginary += value.Imaginary; diff --git a/src/ImageSharp/Primitives/DenseMatrix{T}.cs b/src/ImageSharp/Primitives/DenseMatrix{T}.cs index e312703368..60dadb617b 100644 --- a/src/ImageSharp/Primitives/DenseMatrix{T}.cs +++ b/src/ImageSharp/Primitives/DenseMatrix{T}.cs @@ -109,7 +109,7 @@ namespace SixLabors.ImageSharp /// The at the specified position. public ref T this[int row, int column] { - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] get { this.CheckCoordinates(row, column); @@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp /// /// The representation on the source data. /// - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator DenseMatrix(T[,] data) => new DenseMatrix(data); /// @@ -134,7 +134,7 @@ namespace SixLabors.ImageSharp /// /// The representation on the source data. /// - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] #pragma warning disable SA1008 // Opening parenthesis should be spaced correctly public static implicit operator T[,](in DenseMatrix data) #pragma warning restore SA1008 // Opening parenthesis should be spaced correctly @@ -175,7 +175,7 @@ namespace SixLabors.ImageSharp /// Transposes the rows and columns of the dense matrix. /// /// The . - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public DenseMatrix Transpose() { var result = new DenseMatrix(this.Rows, this.Columns); @@ -196,13 +196,13 @@ namespace SixLabors.ImageSharp /// Fills the matrix with the given value /// /// The value to fill each item with - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Fill(T value) => this.Span.Fill(value); /// /// Clears the matrix setting each value to the default value for the element type /// - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Clear() => this.Span.Clear(); /// @@ -232,14 +232,14 @@ namespace SixLabors.ImageSharp => obj is DenseMatrix other && this.Equals(other); /// - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(DenseMatrix other) => this.Columns == other.Columns && this.Rows == other.Rows && this.Span.SequenceEqual(other.Span); /// - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public override int GetHashCode() { HashCode code = default; diff --git a/src/ImageSharp/Primitives/Number.cs b/src/ImageSharp/Primitives/Number.cs index f6748d8565..e33d2344a9 100644 --- a/src/ImageSharp/Primitives/Number.cs +++ b/src/ImageSharp/Primitives/Number.cs @@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp { return number.isSigned ? number.signedValue - : (int)number.unsignedValue.Clamp(0, int.MaxValue); + : (int)Numerics.Clamp(number.unsignedValue, 0, int.MaxValue); } /// @@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp public static explicit operator uint(Number number) { return number.isSigned - ? (uint)number.signedValue.Clamp(0, int.MaxValue) + ? (uint)Numerics.Clamp(number.signedValue, 0, int.MaxValue) : number.unsignedValue; } @@ -91,8 +91,8 @@ namespace SixLabors.ImageSharp public static explicit operator ushort(Number number) { return number.isSigned - ? (ushort)number.signedValue.Clamp(ushort.MinValue, ushort.MaxValue) - : (ushort)number.unsignedValue.Clamp(ushort.MinValue, ushort.MaxValue); + ? (ushort)Numerics.Clamp(number.signedValue, ushort.MinValue, ushort.MaxValue) + : (ushort)Numerics.Clamp(number.unsignedValue, ushort.MinValue, ushort.MaxValue); } /// diff --git a/src/ImageSharp/Processing/AffineTransformBuilder.cs b/src/ImageSharp/Processing/AffineTransformBuilder.cs index 75f23c6b42..ed3483dc4c 100644 --- a/src/ImageSharp/Processing/AffineTransformBuilder.cs +++ b/src/ImageSharp/Processing/AffineTransformBuilder.cs @@ -31,7 +31,7 @@ namespace SixLabors.ImageSharp.Processing /// The amount of rotation, in radians. /// The . public AffineTransformBuilder PrependRotationRadians(float radians) - => this.Prepend(size => TransformUtilities.CreateRotationMatrixRadians(radians, size)); + => this.Prepend(size => TransformUtils.CreateRotationMatrixRadians(radians, size)); /// /// Prepends a rotation matrix using the given rotation in degrees at the given origin. @@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing /// The amount of rotation, in radians. /// The . public AffineTransformBuilder AppendRotationRadians(float radians) - => this.Append(size => TransformUtilities.CreateRotationMatrixRadians(radians, size)); + => this.Append(size => TransformUtils.CreateRotationMatrixRadians(radians, size)); /// /// Appends a rotation matrix using the given rotation in degrees at the given origin. @@ -142,7 +142,7 @@ namespace SixLabors.ImageSharp.Processing /// The Y angle, in degrees. /// The . public AffineTransformBuilder PrependSkewDegrees(float degreesX, float degreesY) - => this.Prepend(size => TransformUtilities.CreateSkewMatrixDegrees(degreesX, degreesY, size)); + => this.Prepend(size => TransformUtils.CreateSkewMatrixDegrees(degreesX, degreesY, size)); /// /// Prepends a centered skew matrix from the give angles in radians. @@ -151,7 +151,7 @@ namespace SixLabors.ImageSharp.Processing /// The Y angle, in radians. /// The . public AffineTransformBuilder PrependSkewRadians(float radiansX, float radiansY) - => this.Prepend(size => TransformUtilities.CreateSkewMatrixRadians(radiansX, radiansY, size)); + => this.Prepend(size => TransformUtils.CreateSkewMatrixRadians(radiansX, radiansY, size)); /// /// Prepends a skew matrix using the given angles in degrees at the given origin. @@ -180,7 +180,7 @@ namespace SixLabors.ImageSharp.Processing /// The Y angle, in degrees. /// The . public AffineTransformBuilder AppendSkewDegrees(float degreesX, float degreesY) - => this.Append(size => TransformUtilities.CreateSkewMatrixDegrees(degreesX, degreesY, size)); + => this.Append(size => TransformUtils.CreateSkewMatrixDegrees(degreesX, degreesY, size)); /// /// Appends a centered skew matrix from the give angles in radians. @@ -189,7 +189,7 @@ namespace SixLabors.ImageSharp.Processing /// The Y angle, in radians. /// The . public AffineTransformBuilder AppendSkewRadians(float radiansX, float radiansY) - => this.Append(size => TransformUtilities.CreateSkewMatrixRadians(radiansX, radiansY, size)); + => this.Append(size => TransformUtils.CreateSkewMatrixRadians(radiansX, radiansY, size)); /// /// Appends a skew matrix using the given angles in degrees at the given origin. @@ -314,7 +314,7 @@ namespace SixLabors.ImageSharp.Processing private static void CheckDegenerate(Matrix3x2 matrix) { - if (TransformUtilities.IsDegenerate(matrix)) + if (TransformUtils.IsDegenerate(matrix)) { throw new DegenerateTransformException("Matrix is degenerate. Check input values."); } diff --git a/src/ImageSharp/Processing/BinaryThresholdMode.cs b/src/ImageSharp/Processing/BinaryThresholdMode.cs new file mode 100644 index 0000000000..0ca1f08d14 --- /dev/null +++ b/src/ImageSharp/Processing/BinaryThresholdMode.cs @@ -0,0 +1,26 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Processing +{ + /// + /// Selects the value to be compared to threshold. + /// + public enum BinaryThresholdMode + { + /// + /// Compare the color luminance (according to ITU-R Recommendation BT.709). + /// + Luminance = 0, + + /// + /// Compare the HSL saturation of the color. + /// + Saturation = 1, + + /// + /// Compare the maximum of YCbCr chroma value, i.e. Cb and Cr distance from achromatic value. + /// + MaxChroma = 2, + } +} diff --git a/src/ImageSharp/Processing/Extensions/Binarization/BinaryThresholdExtensions.cs b/src/ImageSharp/Processing/Extensions/Binarization/BinaryThresholdExtensions.cs index d21429589a..5132fd731d 100644 --- a/src/ImageSharp/Processing/Extensions/Binarization/BinaryThresholdExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Binarization/BinaryThresholdExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.Processing.Processors.Binarization; @@ -11,20 +11,51 @@ namespace SixLabors.ImageSharp.Processing /// public static class BinaryThresholdExtensions { + /// + /// Applies binarization to the image splitting the pixels at the given threshold with + /// Luminance as the color component to be compared to threshold. + /// + /// The image this method extends. + /// The threshold to apply binarization of the image. Must be between 0 and 1. + /// The to allow chaining of operations. + public static IImageProcessingContext BinaryThreshold(this IImageProcessingContext source, float threshold) + => source.ApplyProcessor(new BinaryThresholdProcessor(threshold, BinaryThresholdMode.Luminance)); + /// /// Applies binarization to the image splitting the pixels at the given threshold. /// /// The image this method extends. /// The threshold to apply binarization of the image. Must be between 0 and 1. + /// Selects the value to be compared to threshold. + /// The to allow chaining of operations. + public static IImageProcessingContext BinaryThreshold( + this IImageProcessingContext source, + float threshold, + BinaryThresholdMode mode) + => source.ApplyProcessor(new BinaryThresholdProcessor(threshold, mode)); + + /// + /// Applies binarization to the image splitting the pixels at the given threshold with + /// Luminance as the color component to be compared to threshold. + /// + /// The image this method extends. + /// The threshold to apply binarization of the image. Must be between 0 and 1. + /// + /// The structure that specifies the portion of the image object to alter. + /// /// The to allow chaining of operations. - public static IImageProcessingContext BinaryThreshold(this IImageProcessingContext source, float threshold) => - source.ApplyProcessor(new BinaryThresholdProcessor(threshold)); + public static IImageProcessingContext BinaryThreshold( + this IImageProcessingContext source, + float threshold, + Rectangle rectangle) + => source.ApplyProcessor(new BinaryThresholdProcessor(threshold, BinaryThresholdMode.Luminance), rectangle); /// /// Applies binarization to the image splitting the pixels at the given threshold. /// /// The image this method extends. /// The threshold to apply binarization of the image. Must be between 0 and 1. + /// Selects the value to be compared to threshold. /// /// The structure that specifies the portion of the image object to alter. /// @@ -32,8 +63,25 @@ namespace SixLabors.ImageSharp.Processing public static IImageProcessingContext BinaryThreshold( this IImageProcessingContext source, float threshold, - Rectangle rectangle) => - source.ApplyProcessor(new BinaryThresholdProcessor(threshold), rectangle); + BinaryThresholdMode mode, + Rectangle rectangle) + => source.ApplyProcessor(new BinaryThresholdProcessor(threshold, mode), rectangle); + + /// + /// Applies binarization to the image splitting the pixels at the given threshold with + /// Luminance as the color component to be compared to threshold. + /// + /// The image this method extends. + /// The threshold to apply binarization of the image. Must be between 0 and 1. + /// The color to use for pixels that are above the threshold. + /// The color to use for pixels that are below the threshold + /// The to allow chaining of operations. + public static IImageProcessingContext BinaryThreshold( + this IImageProcessingContext source, + float threshold, + Color upperColor, + Color lowerColor) + => source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor, BinaryThresholdMode.Luminance)); /// /// Applies binarization to the image splitting the pixels at the given threshold. @@ -42,13 +90,35 @@ namespace SixLabors.ImageSharp.Processing /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold + /// Selects the value to be compared to threshold. /// The to allow chaining of operations. public static IImageProcessingContext BinaryThreshold( this IImageProcessingContext source, float threshold, Color upperColor, - Color lowerColor) => - source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor)); + Color lowerColor, + BinaryThresholdMode mode) + => source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor, mode)); + + /// + /// Applies binarization to the image splitting the pixels at the given threshold with + /// Luminance as the color component to be compared to threshold. + /// + /// The image this method extends. + /// The threshold to apply binarization of the image. Must be between 0 and 1. + /// The color to use for pixels that are above the threshold. + /// The color to use for pixels that are below the threshold + /// + /// The structure that specifies the portion of the image object to alter. + /// + /// The to allow chaining of operations. + public static IImageProcessingContext BinaryThreshold( + this IImageProcessingContext source, + float threshold, + Color upperColor, + Color lowerColor, + Rectangle rectangle) + => source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor, BinaryThresholdMode.Luminance), rectangle); /// /// Applies binarization to the image splitting the pixels at the given threshold. @@ -57,6 +127,7 @@ namespace SixLabors.ImageSharp.Processing /// The threshold to apply binarization of the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold + /// Selects the value to be compared to threshold. /// /// The structure that specifies the portion of the image object to alter. /// @@ -66,7 +137,8 @@ namespace SixLabors.ImageSharp.Processing float threshold, Color upperColor, Color lowerColor, + BinaryThresholdMode mode, Rectangle rectangle) => - source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor), rectangle); + source.ApplyProcessor(new BinaryThresholdProcessor(threshold, upperColor, lowerColor, mode), rectangle); } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.IntegralImage.cs b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.IntegralImage.cs new file mode 100644 index 0000000000..af6d32b216 --- /dev/null +++ b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.IntegralImage.cs @@ -0,0 +1,77 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Processing +{ + /// + /// Defines extensions that allow the computation of image integrals on an + /// + public static partial class ProcessingExtensions + { + /// + /// Apply an image integral. + /// + /// The image on which to apply the integral. + /// The type of the pixel. + /// The containing all the sums. + public static Buffer2D CalculateIntegralImage(this Image source) + where TPixel : unmanaged, IPixel + { + Configuration configuration = source.GetConfiguration(); + + int endY = source.Height; + int endX = source.Width; + + Buffer2D intImage = configuration.MemoryAllocator.Allocate2D(source.Width, source.Height); + ulong sumX0 = 0; + + using (IMemoryOwner tempRow = configuration.MemoryAllocator.Allocate(source.Width)) + { + Span tempSpan = tempRow.GetSpan(); + Span sourceRow = source.GetPixelRowSpan(0); + Span destRow = intImage.GetRowSpan(0); + + PixelOperations.Instance.ToL8(configuration, sourceRow, tempSpan); + + // First row + for (int x = 0; x < endX; x++) + { + sumX0 += tempSpan[x].PackedValue; + destRow[x] = sumX0; + } + + Span previousDestRow = destRow; + + // All other rows + for (int y = 1; y < endY; y++) + { + sourceRow = source.GetPixelRowSpan(y); + destRow = intImage.GetRowSpan(y); + + PixelOperations.Instance.ToL8(configuration, sourceRow, tempSpan); + + // Process first column + sumX0 = tempSpan[0].PackedValue; + destRow[0] = sumX0 + previousDestRow[0]; + + // Process all other colmns + for (int x = 1; x < endX; x++) + { + sumX0 += tempSpan[x].PackedValue; + destRow[x] = sumX0 + previousDestRow[x]; + } + + previousDestRow = destRow; + } + } + + return intImage; + } + } +} diff --git a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs index 0bf83812d0..ac14d84231 100644 --- a/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Processing /// /// Adds extensions that allow the processing of images to the type. /// - public static class ProcessingExtensions + public static partial class ProcessingExtensions { /// /// Mutates the source image by applying the image operation to it. diff --git a/src/ImageSharp/Processing/Extensions/Transforms/SwizzleExtensions.cs b/src/ImageSharp/Processing/Extensions/Transforms/SwizzleExtensions.cs new file mode 100644 index 0000000000..c02b3a00d6 --- /dev/null +++ b/src/ImageSharp/Processing/Extensions/Transforms/SwizzleExtensions.cs @@ -0,0 +1,24 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.Processing.Processors.Transforms; + +namespace SixLabors.ImageSharp.Processing.Extensions.Transforms +{ + /// + /// Defines extensions that allow the application of swizzle operations on an + /// + public static class SwizzleExtensions + { + /// + /// Swizzles an image. + /// + /// The image to swizzle. + /// The swizzler function. + /// The swizzler function type. + /// The to allow chaining of operations. + public static IImageProcessingContext Swizzle(this IImageProcessingContext source, TSwizzler swizzler) + where TSwizzler : struct, ISwizzler + => source.ApplyProcessor(new SwizzleProcessor(swizzler)); + } +} diff --git a/src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs b/src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs index 15430b28f3..57acf78ee3 100644 --- a/src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs @@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.Processing IResampler sampler) { Matrix3x2 transform = builder.BuildMatrix(sourceRectangle); - Size targetDimensions = TransformUtilities.GetTransformedSize(sourceRectangle.Size, transform); + Size targetDimensions = TransformUtils.GetTransformedSize(sourceRectangle.Size, transform); return ctx.Transform(sourceRectangle, transform, targetDimensions, sampler); } @@ -116,7 +116,7 @@ namespace SixLabors.ImageSharp.Processing IResampler sampler) { Matrix4x4 transform = builder.BuildMatrix(sourceRectangle); - Size targetDimensions = TransformUtilities.GetTransformedSize(sourceRectangle.Size, transform); + Size targetDimensions = TransformUtils.GetTransformedSize(sourceRectangle.Size, transform); return ctx.Transform(sourceRectangle, transform, targetDimensions, sampler); } diff --git a/src/ImageSharp/Processing/KnownDitherings.cs b/src/ImageSharp/Processing/KnownDitherings.cs index 1c086b7408..9537acda18 100644 --- a/src/ImageSharp/Processing/KnownDitherings.cs +++ b/src/ImageSharp/Processing/KnownDitherings.cs @@ -30,6 +30,11 @@ namespace SixLabors.ImageSharp.Processing /// public static IDither Bayer8x8 { get; } = OrderedDither.Bayer8x8; + /// + /// Gets the order ditherer using the 16x16 Bayer dithering matrix + /// + public static IDither Bayer16x16 { get; } = OrderedDither.Bayer16x16; + /// /// Gets the error Dither that implements the Atkinson algorithm. /// diff --git a/src/ImageSharp/Processing/Processors/Binarization/AdaptiveThresholdProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Binarization/AdaptiveThresholdProcessor{TPixel}.cs index 43023c9382..6d95d51b32 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/AdaptiveThresholdProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/AdaptiveThresholdProcessor{TPixel}.cs @@ -67,7 +67,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization ref TPixel color = ref Unsafe.Add(ref rowRef, x); color.ToRgba32(ref rgb); - sum += (ulong)(rgb.R + rgb.G + rgb.G); + sum += (ulong)(rgb.R + rgb.G + rgb.B); + if (x - startX != 0) { intImage[x - startX, y - startY] = intImage[x - startX - 1, y - startY] + sum; diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs index 460a82f0a0..77fc6938d9 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs @@ -14,8 +14,19 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization /// Initializes a new instance of the class. /// /// The threshold to split the image. Must be between 0 and 1. + /// The color component to be compared to threshold. + public BinaryThresholdProcessor(float threshold, BinaryThresholdMode mode) + : this(threshold, Color.White, Color.Black, mode) + { + } + + /// + /// Initializes a new instance of the class with + /// Luminance as color component to be compared to threshold. + /// + /// The threshold to split the image. Must be between 0 and 1. public BinaryThresholdProcessor(float threshold) - : this(threshold, Color.White, Color.Black) + : this(threshold, Color.White, Color.Black, BinaryThresholdMode.Luminance) { } @@ -25,12 +36,26 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization /// The threshold to split the image. Must be between 0 and 1. /// The color to use for pixels that are above the threshold. /// The color to use for pixels that are below the threshold. - public BinaryThresholdProcessor(float threshold, Color upperColor, Color lowerColor) + /// The color component to be compared to threshold. + public BinaryThresholdProcessor(float threshold, Color upperColor, Color lowerColor, BinaryThresholdMode mode) { Guard.MustBeBetweenOrEqualTo(threshold, 0, 1, nameof(threshold)); this.Threshold = threshold; this.UpperColor = upperColor; this.LowerColor = lowerColor; + this.Mode = mode; + } + + /// + /// Initializes a new instance of the class with + /// Luminance as color component to be compared to threshold. + /// + /// The threshold to split the image. Must be between 0 and 1. + /// The color to use for pixels that are above the threshold. + /// The color to use for pixels that are below the threshold. + public BinaryThresholdProcessor(float threshold, Color upperColor, Color lowerColor) + : this(threshold, upperColor, lowerColor, BinaryThresholdMode.Luminance) + { } /// @@ -48,7 +73,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization /// public Color LowerColor { get; } - /// + /// + /// Gets the defining the value to be compared to threshold. + /// + public BinaryThresholdMode Mode { get; } + + /// public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixel : unmanaged, IPixel => new BinaryThresholdProcessor(configuration, this, source, sourceRectangle); diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs index e5672ee9df..5942c71641 100644 --- a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs @@ -3,7 +3,6 @@ using System; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; @@ -27,9 +26,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization /// The source area to process for the current processor instance. public BinaryThresholdProcessor(Configuration configuration, BinaryThresholdProcessor definition, Image source, Rectangle sourceRectangle) : base(configuration, source, sourceRectangle) - { - this.definition = definition; - } + => this.definition = definition; /// protected override void OnFrameApply(ImageFrame source) @@ -42,10 +39,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization Configuration configuration = this.Configuration; var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); - bool isAlphaOnly = typeof(TPixel) == typeof(A8); + var operation = new RowOperation( + interest.X, + source, + upper, + lower, + threshold, + this.definition.Mode, + configuration); - var operation = new RowOperation(interest, source, upper, lower, threshold, isAlphaOnly); - ParallelRowIterator.IterateRows( + ParallelRowIterator.IterateRows( configuration, interest, in operation); @@ -54,51 +57,131 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization /// /// A implementing the clone logic for . /// - private readonly struct RowOperation : IRowOperation + private readonly struct RowOperation : IRowOperation { private readonly ImageFrame source; private readonly TPixel upper; private readonly TPixel lower; private readonly byte threshold; - private readonly int minX; - private readonly int maxX; - private readonly bool isAlphaOnly; + private readonly BinaryThresholdMode mode; + private readonly int startX; + private readonly Configuration configuration; [MethodImpl(InliningOptions.ShortMethod)] public RowOperation( - Rectangle bounds, + int startX, ImageFrame source, TPixel upper, TPixel lower, byte threshold, - bool isAlphaOnly) + BinaryThresholdMode mode, + Configuration configuration) { + this.startX = startX; this.source = source; this.upper = upper; this.lower = lower; this.threshold = threshold; - this.minX = bounds.X; - this.maxX = bounds.Right; - this.isAlphaOnly = isAlphaOnly; + this.mode = mode; + this.configuration = configuration; } /// - [MethodImpl(InliningOptions.ShortMethod)] - public void Invoke(int y) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Invoke(int y, Span span) + { + TPixel upper = this.upper; + TPixel lower = this.lower; + + Span rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, span.Length); + PixelOperations.Instance.ToRgb24(this.configuration, rowSpan, span); + + switch (this.mode) + { + case BinaryThresholdMode.Luminance: + { + byte threshold = this.threshold; + for (int x = 0; x < rowSpan.Length; x++) + { + Rgb24 rgb = span[x]; + byte luminance = ColorNumerics.Get8BitBT709Luminance(rgb.R, rgb.G, rgb.B); + ref TPixel color = ref rowSpan[x]; + color = luminance >= threshold ? upper : lower; + } + + break; + } + + case BinaryThresholdMode.Saturation: + { + float threshold = this.threshold / 255F; + for (int x = 0; x < rowSpan.Length; x++) + { + float saturation = GetSaturation(span[x]); + ref TPixel color = ref rowSpan[x]; + color = saturation >= threshold ? upper : lower; + } + + break; + } + + case BinaryThresholdMode.MaxChroma: + { + float threshold = this.threshold / 2F; + for (int x = 0; x < rowSpan.Length; x++) + { + float chroma = GetMaxChroma(span[x]); + ref TPixel color = ref rowSpan[x]; + color = chroma >= threshold ? upper : lower; + } + + break; + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static float GetSaturation(Rgb24 rgb) { - Rgba32 rgba = default; - Span row = this.source.GetPixelRowSpan(y); - ref TPixel rowRef = ref MemoryMarshal.GetReference(row); + // Slimmed down RGB => HSL formula. See HslAndRgbConverter. + float r = rgb.R / 255F; + float g = rgb.G / 255F; + float b = rgb.B / 255F; - for (int x = this.minX; x < this.maxX; x++) + float max = MathF.Max(r, MathF.Max(g, b)); + float min = MathF.Min(r, MathF.Min(g, b)); + float chroma = max - min; + + if (MathF.Abs(chroma) < Constants.Epsilon) { - ref TPixel color = ref Unsafe.Add(ref rowRef, x); - color.ToRgba32(ref rgba); + return 0F; + } - // Convert to grayscale using ITU-R Recommendation BT.709 if required - byte luminance = this.isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B); - color = luminance >= this.threshold ? this.upper : this.lower; + float l = (max + min) / 2F; + + if (l <= .5F) + { + return chroma / (max + min); } + else + { + return chroma / (2F - max - min); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static float GetMaxChroma(Rgb24 rgb) + { + // Slimmed down RGB => YCbCr formula. See YCbCrAndRgbConverter. + float r = rgb.R; + float g = rgb.G; + float b = rgb.B; + const float achromatic = 127.5F; + + float cb = 128F + ((-0.168736F * r) - (0.331264F * g) + (0.5F * b)); + float cr = 128F + ((0.5F * r) - (0.418688F * g) - (0.081312F * b)); + + return MathF.Max(MathF.Abs(cb - achromatic), MathF.Abs(cr - achromatic)); } } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor.cs index 8a4c703e0c..13fe627d16 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor.cs @@ -1,6 +1,12 @@ // 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; +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing.Processors.Convolution @@ -77,5 +83,82 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) where TPixel : unmanaged, IPixel => new BokehBlurProcessor(configuration, this, source, sourceRectangle); + + /// + /// A implementing the horizontal convolution logic for . + /// + /// + /// This type is located in the non-generic class and not in , where + /// it is actually used, because it does not use any generic parameters internally. Defining in a non-generic class means that there will only + /// ever be a single instantiation of this type for the JIT/AOT compilers to process, instead of having duplicate versions for each pixel type. + /// + internal readonly struct SecondPassConvolutionRowOperation : IRowOperation + { + private readonly Rectangle bounds; + private readonly Buffer2D targetValues; + private readonly Buffer2D sourceValues; + private readonly KernelSamplingMap map; + private readonly Complex64[] kernel; + private readonly float z; + private readonly float w; + + [MethodImpl(InliningOptions.ShortMethod)] + public SecondPassConvolutionRowOperation( + Rectangle bounds, + Buffer2D targetValues, + Buffer2D sourceValues, + KernelSamplingMap map, + Complex64[] kernel, + float z, + float w) + { + this.bounds = bounds; + this.targetValues = targetValues; + this.sourceValues = sourceValues; + this.map = map; + this.kernel = kernel; + this.z = z; + this.w = w; + } + + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void Invoke(int y) + { + int boundsX = this.bounds.X; + int boundsWidth = this.bounds.Width; + int kernelSize = this.kernel.Length; + + ref int sampleRowBase = ref Unsafe.Add(ref MemoryMarshal.GetReference(this.map.GetRowOffsetSpan()), (y - this.bounds.Y) * kernelSize); + + // The target buffer is zeroed initially and then it accumulates the results + // of each partial convolution, so we don't have to clear it here as well + ref Vector4 targetBase = ref this.targetValues.GetElementUnsafe(boundsX, y); + ref Complex64 kernelStart = ref this.kernel[0]; + ref Complex64 kernelEnd = ref Unsafe.Add(ref kernelStart, kernelSize); + + while (Unsafe.IsAddressLessThan(ref kernelStart, ref kernelEnd)) + { + // Get the precalculated source sample row for this kernel row and copy to our buffer + ref ComplexVector4 sourceBase = ref this.sourceValues.GetElementUnsafe(0, sampleRowBase); + ref ComplexVector4 sourceEnd = ref Unsafe.Add(ref sourceBase, boundsWidth); + ref Vector4 targetStart = ref targetBase; + Complex64 factor = kernelStart; + + while (Unsafe.IsAddressLessThan(ref sourceBase, ref sourceEnd)) + { + ComplexVector4 partial = factor * sourceBase; + + targetStart += partial.WeightedSum(this.z, this.w); + + sourceBase = ref Unsafe.Add(ref sourceBase, 1); + targetStart = ref Unsafe.Add(ref targetStart, 1); + } + + kernelStart = ref Unsafe.Add(ref kernelStart, 1); + sampleRowBase = ref Unsafe.Add(ref sampleRowBase, 1); + } + } + } } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs index a3b3665900..241ff9db28 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs @@ -26,6 +26,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// private readonly float gamma; + /// + /// The size of each complex convolution kernel. + /// + private readonly int kernelSize; + /// /// The kernel parameters to use for the current instance (a: X, b: Y, A: Z, B: W) /// @@ -47,11 +52,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution : base(configuration, source, sourceRectangle) { this.gamma = definition.Gamma; + this.kernelSize = (definition.Radius * 2) + 1; // Get the bokeh blur data BokehBlurKernelData data = BokehBlurKernelDataProvider.GetBokehBlurKernelData( definition.Radius, - (definition.Radius * 2) + 1, + this.kernelSize, definition.Components); this.kernelParameters = data.Parameters; @@ -71,27 +77,49 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// protected override void OnFrameApply(ImageFrame source) { + var sourceRectangle = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); + // Preliminary gamma highlight pass - var gammaOperation = new ApplyGammaExposureRowOperation(this.SourceRectangle, source.PixelBuffer, this.Configuration, this.gamma); - ParallelRowIterator.IterateRows( - this.Configuration, - this.SourceRectangle, - in gammaOperation); + if (this.gamma == 3F) + { + var gammaOperation = new ApplyGamma3ExposureRowOperation(sourceRectangle, source.PixelBuffer, this.Configuration); + ParallelRowIterator.IterateRows( + this.Configuration, + sourceRectangle, + in gammaOperation); + } + else + { + var gammaOperation = new ApplyGammaExposureRowOperation(sourceRectangle, source.PixelBuffer, this.Configuration, this.gamma); + ParallelRowIterator.IterateRows( + this.Configuration, + sourceRectangle, + in gammaOperation); + } // Create a 0-filled buffer to use to store the result of the component convolutions using Buffer2D processingBuffer = this.Configuration.MemoryAllocator.Allocate2D(source.Size(), AllocationOptions.Clean); // Perform the 1D convolutions on all the kernel components and accumulate the results - this.OnFrameApplyCore(source, this.SourceRectangle, this.Configuration, processingBuffer); - - float inverseGamma = 1 / this.gamma; + this.OnFrameApplyCore(source, sourceRectangle, this.Configuration, processingBuffer); // Apply the inverse gamma exposure pass, and write the final pixel data - var operation = new ApplyInverseGammaExposureRowOperation(this.SourceRectangle, source.PixelBuffer, processingBuffer, this.Configuration, inverseGamma); - ParallelRowIterator.IterateRows( - this.Configuration, - this.SourceRectangle, - in operation); + if (this.gamma == 3F) + { + var operation = new ApplyInverseGamma3ExposureRowOperation(sourceRectangle, source.PixelBuffer, processingBuffer, this.Configuration); + ParallelRowIterator.IterateRows( + this.Configuration, + sourceRectangle, + in operation); + } + else + { + var operation = new ApplyInverseGammaExposureRowOperation(sourceRectangle, source.PixelBuffer, processingBuffer, this.Configuration, 1 / this.gamma); + ParallelRowIterator.IterateRows( + this.Configuration, + sourceRectangle, + in operation); + } } /// @@ -108,140 +136,199 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution Buffer2D processingBuffer) { // Allocate the buffer with the intermediate convolution results - using Buffer2D firstPassBuffer = this.Configuration.MemoryAllocator.Allocate2D(source.Size()); + using Buffer2D firstPassBuffer = configuration.MemoryAllocator.Allocate2D(source.Size()); + + // Unlike in the standard 2 pass convolution processor, we use a rectangle of 1x the interest width + // to speedup the actual convolution, by applying bulk pixel conversion and clamping calculation. + // The second half of the buffer will just target the temporary buffer of complex pixel values. + // This is needed because the bokeh blur operates as TPixel -> complex -> TPixel, so we cannot + // convert back to standard pixels after each separate 1D convolution pass. Like in the gaussian + // blur though, we preallocate and compute the kernel sampling maps before processing each complex + // component, to avoid recomputing the same sampling map once per convolution pass. Since we are + // doing two 1D convolutions with the same kernel, we can use a single kernel sampling map as if + // we were using a 2D kernel with each dimension being the same as the length of our kernel, and + // use the two sampling offset spans resulting from this same map. This saves some extra work. + using var mapXY = new KernelSamplingMap(configuration.MemoryAllocator); + + mapXY.BuildSamplingOffsetMap(this.kernelSize, this.kernelSize, sourceRectangle); - // Perform two 1D convolutions for each component in the current instance ref Complex64[] baseRef = ref MemoryMarshal.GetReference(this.kernels.AsSpan()); ref Vector4 paramsRef = ref MemoryMarshal.GetReference(this.kernelParameters.AsSpan()); + + // Perform two 1D convolutions for each component in the current instance for (int i = 0; i < this.kernels.Length; i++) { // Compute the resulting complex buffer for the current component Complex64[] kernel = Unsafe.Add(ref baseRef, i); Vector4 parameters = Unsafe.Add(ref paramsRef, i); - // Compute the vertical 1D convolution - var verticalOperation = new ApplyVerticalConvolutionRowOperation(sourceRectangle, firstPassBuffer, source.PixelBuffer, kernel); - ParallelRowIterator.IterateRows( + // Horizontal convolution + var horizontalOperation = new FirstPassConvolutionRowOperation( + sourceRectangle, + firstPassBuffer, + source.PixelBuffer, + mapXY, + kernel, + configuration); + + ParallelRowIterator.IterateRows( configuration, sourceRectangle, - in verticalOperation); + in horizontalOperation); + + // Vertical 1D convolutions to accumulate the partial results on the target buffer + var verticalOperation = new BokehBlurProcessor.SecondPassConvolutionRowOperation( + sourceRectangle, + processingBuffer, + firstPassBuffer, + mapXY, + kernel, + parameters.Z, + parameters.W); - // Compute the horizontal 1D convolutions and accumulate the partial results on the target buffer - var horizontalOperation = new ApplyHorizontalConvolutionRowOperation(sourceRectangle, processingBuffer, firstPassBuffer, kernel, parameters.Z, parameters.W); ParallelRowIterator.IterateRows( configuration, sourceRectangle, - in horizontalOperation); + in verticalOperation); } } /// /// A implementing the vertical convolution logic for . /// - private readonly struct ApplyVerticalConvolutionRowOperation : IRowOperation + private readonly struct FirstPassConvolutionRowOperation : IRowOperation { private readonly Rectangle bounds; private readonly Buffer2D targetValues; private readonly Buffer2D sourcePixels; + private readonly KernelSamplingMap map; private readonly Complex64[] kernel; - private readonly int maxY; - private readonly int maxX; + private readonly Configuration configuration; [MethodImpl(InliningOptions.ShortMethod)] - public ApplyVerticalConvolutionRowOperation( + public FirstPassConvolutionRowOperation( Rectangle bounds, Buffer2D targetValues, Buffer2D sourcePixels, - Complex64[] kernel) + KernelSamplingMap map, + Complex64[] kernel, + Configuration configuration) { this.bounds = bounds; - this.maxY = this.bounds.Bottom - 1; - this.maxX = this.bounds.Right - 1; this.targetValues = targetValues; this.sourcePixels = sourcePixels; + this.map = map; this.kernel = kernel; + this.configuration = configuration; } /// [MethodImpl(InliningOptions.ShortMethod)] - public void Invoke(int y) + public void Invoke(int y, Span span) { - Span targetRowSpan = this.targetValues.GetRowSpan(y).Slice(this.bounds.X); - - for (int x = 0; x < this.bounds.Width; x++) + int boundsX = this.bounds.X; + int boundsWidth = this.bounds.Width; + int kernelSize = this.kernel.Length; + + // Clear the target buffer for each row run + Span targetBuffer = this.targetValues.GetRowSpan(y); + targetBuffer.Clear(); + + // Execute the bulk pixel format conversion for the current row + Span sourceRow = this.sourcePixels.GetRowSpan(y).Slice(boundsX, boundsWidth); + PixelOperations.Instance.ToVector4(this.configuration, sourceRow, span); + + ref Vector4 sourceBase = ref MemoryMarshal.GetReference(span); + ref ComplexVector4 targetStart = ref MemoryMarshal.GetReference(targetBuffer); + ref ComplexVector4 targetEnd = ref Unsafe.Add(ref targetStart, span.Length); + ref Complex64 kernelBase = ref this.kernel[0]; + ref Complex64 kernelEnd = ref Unsafe.Add(ref kernelBase, kernelSize); + ref int sampleColumnBase = ref MemoryMarshal.GetReference(this.map.GetColumnOffsetSpan()); + + while (Unsafe.IsAddressLessThan(ref targetStart, ref targetEnd)) { - Buffer2DUtils.Convolve4(this.kernel, this.sourcePixels, targetRowSpan, y, x, this.bounds.Y, this.maxY, this.bounds.X, this.maxX); + ref Complex64 kernelStart = ref kernelBase; + ref int sampleColumnStart = ref sampleColumnBase; + + while (Unsafe.IsAddressLessThan(ref kernelStart, ref kernelEnd)) + { + Vector4 sample = Unsafe.Add(ref sourceBase, sampleColumnStart - boundsX); + + targetStart.Sum(kernelStart * sample); + + kernelStart = ref Unsafe.Add(ref kernelStart, 1); + sampleColumnStart = ref Unsafe.Add(ref sampleColumnStart, 1); + } + + // Shift the base column sampling reference by one row at the end of each outer + // iteration so that the inner tight loop indexing can skip the multiplication + sampleColumnBase = ref Unsafe.Add(ref sampleColumnBase, kernelSize); + targetStart = ref Unsafe.Add(ref targetStart, 1); } } } /// - /// A implementing the horizontal convolution logic for . + /// A implementing the gamma exposure logic for . /// - private readonly struct ApplyHorizontalConvolutionRowOperation : IRowOperation + private readonly struct ApplyGammaExposureRowOperation : IRowOperation { private readonly Rectangle bounds; - private readonly Buffer2D targetValues; - private readonly Buffer2D sourceValues; - private readonly Complex64[] kernel; - private readonly float z; - private readonly float w; - private readonly int maxY; - private readonly int maxX; + private readonly Buffer2D targetPixels; + private readonly Configuration configuration; + private readonly float gamma; [MethodImpl(InliningOptions.ShortMethod)] - public ApplyHorizontalConvolutionRowOperation( + public ApplyGammaExposureRowOperation( Rectangle bounds, - Buffer2D targetValues, - Buffer2D sourceValues, - Complex64[] kernel, - float z, - float w) + Buffer2D targetPixels, + Configuration configuration, + float gamma) { this.bounds = bounds; - this.maxY = this.bounds.Bottom - 1; - this.maxX = this.bounds.Right - 1; - this.targetValues = targetValues; - this.sourceValues = sourceValues; - this.kernel = kernel; - this.z = z; - this.w = w; + this.targetPixels = targetPixels; + this.configuration = configuration; + this.gamma = gamma; } /// [MethodImpl(InliningOptions.ShortMethod)] - public void Invoke(int y) + public void Invoke(int y, Span span) { - Span targetRowSpan = this.targetValues.GetRowSpan(y).Slice(this.bounds.X); + Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); + PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.Length), span, PixelConversionModifiers.Premultiply); + ref Vector4 baseRef = ref MemoryMarshal.GetReference(span); for (int x = 0; x < this.bounds.Width; x++) { - Buffer2DUtils.Convolve4AndAccumulatePartials(this.kernel, this.sourceValues, targetRowSpan, y, x, this.bounds.Y, this.maxY, this.bounds.X, this.maxX, this.z, this.w); + ref Vector4 v = ref Unsafe.Add(ref baseRef, x); + v.X = MathF.Pow(v.X, this.gamma); + v.Y = MathF.Pow(v.Y, this.gamma); + v.Z = MathF.Pow(v.Z, this.gamma); } + + PixelOperations.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan); } } /// - /// A implementing the gamma exposure logic for . + /// A implementing the 3F gamma exposure logic for . /// - private readonly struct ApplyGammaExposureRowOperation : IRowOperation + private readonly struct ApplyGamma3ExposureRowOperation : IRowOperation { private readonly Rectangle bounds; private readonly Buffer2D targetPixels; private readonly Configuration configuration; - private readonly float gamma; [MethodImpl(InliningOptions.ShortMethod)] - public ApplyGammaExposureRowOperation( + public ApplyGamma3ExposureRowOperation( Rectangle bounds, Buffer2D targetPixels, - Configuration configuration, - float gamma) + Configuration configuration) { this.bounds = bounds; this.targetPixels = targetPixels; this.configuration = configuration; - this.gamma = gamma; } /// @@ -249,16 +336,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution public void Invoke(int y, Span span) { Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); + PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.Length), span, PixelConversionModifiers.Premultiply); - ref Vector4 baseRef = ref MemoryMarshal.GetReference(span); - for (int x = 0; x < this.bounds.Width; x++) - { - ref Vector4 v = ref Unsafe.Add(ref baseRef, x); - v.X = MathF.Pow(v.X, this.gamma); - v.Y = MathF.Pow(v.Y, this.gamma); - v.Z = MathF.Pow(v.Z, this.gamma); - } + Numerics.CubePowOnXYZ(span); PixelOperations.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan); } @@ -304,7 +385,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution for (int x = 0; x < this.bounds.Width; x++) { ref Vector4 v = ref Unsafe.Add(ref sourceRef, x); - var clamp = Vector4Utilities.FastClamp(v, low, high); + Vector4 clamp = Numerics.Clamp(v, low, high); v.X = MathF.Pow(clamp.X, this.inverseGamma); v.Y = MathF.Pow(clamp.Y, this.inverseGamma); v.Z = MathF.Pow(clamp.Z, this.inverseGamma); @@ -313,5 +394,44 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution PixelOperations.Instance.FromVector4Destructive(this.configuration, sourceRowSpan.Slice(0, this.bounds.Width), targetPixelSpan, PixelConversionModifiers.Premultiply); } } + + /// + /// A implementing the inverse 3F gamma exposure logic for . + /// + private readonly struct ApplyInverseGamma3ExposureRowOperation : IRowOperation + { + private readonly Rectangle bounds; + private readonly Buffer2D targetPixels; + private readonly Buffer2D sourceValues; + private readonly Configuration configuration; + + [MethodImpl(InliningOptions.ShortMethod)] + public ApplyInverseGamma3ExposureRowOperation( + Rectangle bounds, + Buffer2D targetPixels, + Buffer2D sourceValues, + Configuration configuration) + { + this.bounds = bounds; + this.targetPixels = targetPixels; + this.sourceValues = sourceValues; + this.configuration = configuration; + } + + /// + [MethodImpl(InliningOptions.ShortMethod)] + public unsafe void Invoke(int y) + { + Span sourceRowSpan = this.sourceValues.GetRowSpan(y).Slice(this.bounds.X, this.bounds.Width); + ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceRowSpan); + + Numerics.Clamp(MemoryMarshal.Cast(sourceRowSpan), 0, float.PositiveInfinity); + Numerics.CubeRootOnXYZ(sourceRowSpan); + + Span targetPixelSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); + + PixelOperations.Instance.FromVector4Destructive(this.configuration, sourceRowSpan.Slice(0, this.bounds.Width), targetPixelSpan, PixelConversionModifiers.Premultiply); + } + } } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor{TPixel}.cs index 8c5358770c..5beadb0cee 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor{TPixel}.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. +using System; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing.Processors.Convolution @@ -23,24 +24,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution : base(configuration, source, sourceRectangle) { int kernelSize = (definition.Radius * 2) + 1; - this.KernelX = CreateBoxKernel(kernelSize); - this.KernelY = this.KernelX.Transpose(); + this.Kernel = CreateBoxKernel(kernelSize); } /// - /// Gets the horizontal gradient operator. + /// Gets the 1D convolution kernel. /// - public DenseMatrix KernelX { get; } - - /// - /// Gets the vertical gradient operator. - /// - public DenseMatrix KernelY { get; } + public float[] Kernel { get; } /// protected override void OnFrameApply(ImageFrame source) { - using var processor = new Convolution2PassProcessor(this.Configuration, this.KernelX, this.KernelY, false, this.Source, this.SourceRectangle); + using var processor = new Convolution2PassProcessor(this.Configuration, this.Kernel, false, this.Source, this.SourceRectangle); processor.Apply(source); } @@ -50,10 +45,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// The maximum size of the kernel in either direction. /// The . - private static DenseMatrix CreateBoxKernel(int kernelSize) + private static float[] CreateBoxKernel(int kernelSize) { - var kernel = new DenseMatrix(kernelSize, 1); - kernel.Fill(1F / kernelSize); + var kernel = new float[kernelSize]; + + kernel.AsSpan().Fill(1F / kernelSize); + return kernel; } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs index 3a5f35cd14..bb559019b7 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs @@ -1,10 +1,7 @@ // 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; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -43,12 +40,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution } /// - /// Gets the horizontal gradient operator. + /// Gets the horizontal convolution kernel. /// public DenseMatrix KernelX { get; } /// - /// Gets the vertical gradient operator. + /// Gets the vertical convolution kernel. /// public DenseMatrix KernelY { get; } @@ -60,102 +57,39 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// protected override void OnFrameApply(ImageFrame source) { - using Buffer2D targetPixels = this.Configuration.MemoryAllocator.Allocate2D(source.Width, source.Height); + MemoryAllocator allocator = this.Configuration.MemoryAllocator; + using Buffer2D targetPixels = allocator.Allocate2D(source.Width, source.Height); source.CopyTo(targetPixels); var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); - var operation = new RowOperation(interest, targetPixels, source.PixelBuffer, this.KernelY, this.KernelX, this.Configuration, this.PreserveAlpha); - ParallelRowIterator.IterateRows( - this.Configuration, - interest, - in operation); + // We use a rectangle 3x the interest width to allocate a buffer big enough + // for source and target bulk pixel conversion. + var operationBounds = new Rectangle(interest.X, interest.Y, interest.Width * 3, interest.Height); - Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels); - } - - /// - /// A implementing the convolution logic for . - /// - private readonly struct RowOperation : IRowOperation - { - private readonly Rectangle bounds; - private readonly int maxY; - private readonly int maxX; - private readonly Buffer2D targetPixels; - private readonly Buffer2D sourcePixels; - private readonly DenseMatrix kernelY; - private readonly DenseMatrix kernelX; - private readonly Configuration configuration; - private readonly bool preserveAlpha; - - [MethodImpl(InliningOptions.ShortMethod)] - public RowOperation( - Rectangle bounds, - Buffer2D targetPixels, - Buffer2D sourcePixels, - DenseMatrix kernelY, - DenseMatrix kernelX, - Configuration configuration, - bool preserveAlpha) - { - this.bounds = bounds; - this.maxY = this.bounds.Bottom - 1; - this.maxX = this.bounds.Right - 1; - this.targetPixels = targetPixels; - this.sourcePixels = sourcePixels; - this.kernelY = kernelY; - this.kernelX = kernelX; - this.configuration = configuration; - this.preserveAlpha = preserveAlpha; - } - - /// - [MethodImpl(InliningOptions.ShortMethod)] - public void Invoke(int y, Span span) + using (var map = new KernelSamplingMap(allocator)) { - ref Vector4 spanRef = ref MemoryMarshal.GetReference(span); - Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); - PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.Length), span); + // Since the kernel sizes are identical we can use a single map. + map.BuildSamplingOffsetMap(this.KernelY, interest); - if (this.preserveAlpha) - { - for (int x = 0; x < this.bounds.Width; x++) - { - DenseMatrixUtils.Convolve2D3( - in this.kernelY, - in this.kernelX, - this.sourcePixels, - ref spanRef, - y, - x, - this.bounds.Y, - this.maxY, - this.bounds.X, - this.maxX); - } - } - else - { - for (int x = 0; x < this.bounds.Width; x++) - { - DenseMatrixUtils.Convolve2D4( - in this.kernelY, - in this.kernelX, - this.sourcePixels, - ref spanRef, - y, - x, - this.bounds.Y, - this.maxY, - this.bounds.X, - this.maxX); - } - } + var operation = new Convolution2DRowOperation( + interest, + targetPixels, + source.PixelBuffer, + map, + this.KernelY, + this.KernelX, + this.Configuration, + this.PreserveAlpha); - PixelOperations.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan); + ParallelRowIterator.IterateRows, Vector4>( + this.Configuration, + operationBounds, + in operation); } + + Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels); } } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DRowOperation{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DRowOperation{TPixel}.cs new file mode 100644 index 0000000000..802d1809f2 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DRowOperation{TPixel}.cs @@ -0,0 +1,193 @@ +// 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; +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Processing.Processors.Convolution +{ + /// + /// A implementing the logic for 2D convolution. + /// + internal readonly struct Convolution2DRowOperation : IRowOperation + where TPixel : unmanaged, IPixel + { + private readonly Rectangle bounds; + private readonly Buffer2D targetPixels; + private readonly Buffer2D sourcePixels; + private readonly KernelSamplingMap map; + private readonly DenseMatrix kernelMatrixY; + private readonly DenseMatrix kernelMatrixX; + private readonly Configuration configuration; + private readonly bool preserveAlpha; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Convolution2DRowOperation( + Rectangle bounds, + Buffer2D targetPixels, + Buffer2D sourcePixels, + KernelSamplingMap map, + DenseMatrix kernelMatrixY, + DenseMatrix kernelMatrixX, + Configuration configuration, + bool preserveAlpha) + { + this.bounds = bounds; + this.targetPixels = targetPixels; + this.sourcePixels = sourcePixels; + this.map = map; + this.kernelMatrixY = kernelMatrixY; + this.kernelMatrixX = kernelMatrixX; + this.configuration = configuration; + this.preserveAlpha = preserveAlpha; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Invoke(int y, Span span) + { + if (this.preserveAlpha) + { + this.Convolve3(y, span); + } + else + { + this.Convolve4(y, span); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void Convolve3(int y, Span span) + { + // Span is 3x bounds. + int boundsX = this.bounds.X; + int boundsWidth = this.bounds.Width; + Span sourceBuffer = span.Slice(0, boundsWidth); + Span targetYBuffer = span.Slice(boundsWidth, boundsWidth); + Span targetXBuffer = span.Slice(boundsWidth * 2, boundsWidth); + + var state = new Convolution2DState(in this.kernelMatrixY, in this.kernelMatrixX, this.map); + ref int sampleRowBase = ref state.GetSampleRow(y - this.bounds.Y); + + // Clear the target buffers for each row run. + targetYBuffer.Clear(); + targetXBuffer.Clear(); + ref Vector4 targetBaseY = ref MemoryMarshal.GetReference(targetYBuffer); + ref Vector4 targetBaseX = ref MemoryMarshal.GetReference(targetXBuffer); + + ReadOnlyKernel kernelY = state.KernelY; + ReadOnlyKernel kernelX = state.KernelX; + Span sourceRow; + for (int kY = 0; kY < kernelY.Rows; kY++) + { + // Get the precalculated source sample row for this kernel row and copy to our buffer. + int sampleY = Unsafe.Add(ref sampleRowBase, kY); + sourceRow = this.sourcePixels.GetRowSpan(sampleY).Slice(boundsX, boundsWidth); + PixelOperations.Instance.ToVector4(this.configuration, sourceRow, sourceBuffer); + + ref Vector4 sourceBase = ref MemoryMarshal.GetReference(sourceBuffer); + + for (int x = 0; x < sourceBuffer.Length; x++) + { + ref int sampleColumnBase = ref state.GetSampleColumn(x); + ref Vector4 targetY = ref Unsafe.Add(ref targetBaseY, x); + ref Vector4 targetX = ref Unsafe.Add(ref targetBaseX, x); + + for (int kX = 0; kX < kernelY.Columns; kX++) + { + int sampleX = Unsafe.Add(ref sampleColumnBase, kX) - boundsX; + Vector4 sample = Unsafe.Add(ref sourceBase, sampleX); + targetY += kernelX[kY, kX] * sample; + targetX += kernelY[kY, kX] * sample; + } + } + } + + // Now we need to combine the values and copy the original alpha values + // from the source row. + sourceRow = this.sourcePixels.GetRowSpan(y).Slice(boundsX, boundsWidth); + PixelOperations.Instance.ToVector4(this.configuration, sourceRow, sourceBuffer); + + for (int x = 0; x < sourceRow.Length; x++) + { + ref Vector4 target = ref Unsafe.Add(ref targetBaseY, x); + Vector4 vectorY = target; + Vector4 vectorX = Unsafe.Add(ref targetBaseX, x); + + target = Vector4.SquareRoot((vectorX * vectorX) + (vectorY * vectorY)); + target.W = Unsafe.Add(ref MemoryMarshal.GetReference(sourceBuffer), x).W; + } + + Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(boundsX, boundsWidth); + PixelOperations.Instance.FromVector4Destructive(this.configuration, targetYBuffer, targetRowSpan); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void Convolve4(int y, Span span) + { + // Span is 3x bounds. + int boundsX = this.bounds.X; + int boundsWidth = this.bounds.Width; + Span sourceBuffer = span.Slice(0, boundsWidth); + Span targetYBuffer = span.Slice(boundsWidth, boundsWidth); + Span targetXBuffer = span.Slice(boundsWidth * 2, boundsWidth); + + var state = new Convolution2DState(in this.kernelMatrixY, in this.kernelMatrixX, this.map); + ref int sampleRowBase = ref state.GetSampleRow(y - this.bounds.Y); + + // Clear the target buffers for each row run. + targetYBuffer.Clear(); + targetXBuffer.Clear(); + ref Vector4 targetBaseY = ref MemoryMarshal.GetReference(targetYBuffer); + ref Vector4 targetBaseX = ref MemoryMarshal.GetReference(targetXBuffer); + + ReadOnlyKernel kernelY = state.KernelY; + ReadOnlyKernel kernelX = state.KernelX; + for (int kY = 0; kY < kernelY.Rows; kY++) + { + // Get the precalculated source sample row for this kernel row and copy to our buffer. + int sampleY = Unsafe.Add(ref sampleRowBase, kY); + Span sourceRow = this.sourcePixels.GetRowSpan(sampleY).Slice(boundsX, boundsWidth); + PixelOperations.Instance.ToVector4(this.configuration, sourceRow, sourceBuffer); + + Numerics.Premultiply(sourceBuffer); + ref Vector4 sourceBase = ref MemoryMarshal.GetReference(sourceBuffer); + + for (int x = 0; x < sourceBuffer.Length; x++) + { + ref int sampleColumnBase = ref state.GetSampleColumn(x); + ref Vector4 targetY = ref Unsafe.Add(ref targetBaseY, x); + ref Vector4 targetX = ref Unsafe.Add(ref targetBaseX, x); + + for (int kX = 0; kX < kernelY.Columns; kX++) + { + int sampleX = Unsafe.Add(ref sampleColumnBase, kX) - boundsX; + Vector4 sample = Unsafe.Add(ref sourceBase, sampleX); + targetY += kernelX[kY, kX] * sample; + targetX += kernelY[kY, kX] * sample; + } + } + } + + // Now we need to combine the values + for (int x = 0; x < targetYBuffer.Length; x++) + { + ref Vector4 target = ref Unsafe.Add(ref targetBaseY, x); + Vector4 vectorY = target; + Vector4 vectorX = Unsafe.Add(ref targetBaseX, x); + + target = Vector4.SquareRoot((vectorX * vectorX) + (vectorY * vectorY)); + } + + Numerics.UnPremultiply(targetYBuffer); + + Span targetRow = this.targetPixels.GetRowSpan(y).Slice(boundsX, boundsWidth); + PixelOperations.Instance.FromVector4Destructive(this.configuration, targetYBuffer, targetRow); + } + } +} diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DState.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DState.cs new file mode 100644 index 0000000000..218093ac4e --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DState.cs @@ -0,0 +1,54 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace SixLabors.ImageSharp.Processing.Processors.Convolution +{ + /// + /// A stack only struct used for reducing reference indirection during 2D convolution operations. + /// + internal readonly ref struct Convolution2DState + { + private readonly Span rowOffsetMap; + private readonly Span columnOffsetMap; + private readonly int kernelHeight; + private readonly int kernelWidth; + + public Convolution2DState( + in DenseMatrix kernelY, + in DenseMatrix kernelX, + KernelSamplingMap map) + { + // We check the kernels are the same size upstream. + this.KernelY = new ReadOnlyKernel(kernelY); + this.KernelX = new ReadOnlyKernel(kernelX); + this.kernelHeight = kernelY.Rows; + this.kernelWidth = kernelY.Columns; + this.rowOffsetMap = map.GetRowOffsetSpan(); + this.columnOffsetMap = map.GetColumnOffsetSpan(); + } + + public readonly ReadOnlyKernel KernelY + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get; + } + + public readonly ReadOnlyKernel KernelX + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly ref int GetSampleRow(int row) + => ref Unsafe.Add(ref MemoryMarshal.GetReference(this.rowOffsetMap), row * this.kernelHeight); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly ref int GetSampleColumn(int column) + => ref Unsafe.Add(ref MemoryMarshal.GetReference(this.columnOffsetMap), column * this.kernelWidth); + } +} diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs index b61690415a..365b2e2dfc 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs @@ -22,34 +22,26 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Initializes a new instance of the class. /// /// The configuration which allows altering default behaviour or extending the library. - /// The horizontal gradient operator. - /// The vertical gradient operator. + /// The 1D convolution kernel. /// Whether the convolution filter is applied to alpha as well as the color channels. /// The source for the current processor instance. /// The source area to process for the current processor instance. public Convolution2PassProcessor( Configuration configuration, - in DenseMatrix kernelX, - in DenseMatrix kernelY, + float[] kernel, bool preserveAlpha, Image source, Rectangle sourceRectangle) : base(configuration, source, sourceRectangle) { - this.KernelX = kernelX; - this.KernelY = kernelY; + this.Kernel = kernel; this.PreserveAlpha = preserveAlpha; } /// - /// Gets the horizontal gradient operator. + /// Gets the convolution kernel. /// - public DenseMatrix KernelX { get; } - - /// - /// Gets the vertical gradient operator. - /// - public DenseMatrix KernelY { get; } + public float[] Kernel { get; } /// /// Gets a value indicating whether the convolution filter is applied to alpha as well as the color channels. @@ -63,96 +55,368 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); + // We use a rectangle 2x the interest width to allocate a buffer big enough + // for source and target bulk pixel conversion. + var operationBounds = new Rectangle(interest.X, interest.Y, interest.Width * 2, interest.Height); + + // We can create a single sampling map with the size as if we were using the non separated 2D kernel + // the two 1D kernels represent, and reuse it across both convolution steps, like in the bokeh blur. + using var mapXY = new KernelSamplingMap(this.Configuration.MemoryAllocator); + + mapXY.BuildSamplingOffsetMap(this.Kernel.Length, this.Kernel.Length, interest); + // Horizontal convolution - var horizontalOperation = new RowOperation(interest, firstPassPixels, source.PixelBuffer, this.KernelX, this.Configuration, this.PreserveAlpha); - ParallelRowIterator.IterateRows( - this.Configuration, + var horizontalOperation = new HorizontalConvolutionRowOperation( interest, + firstPassPixels, + source.PixelBuffer, + mapXY, + this.Kernel, + this.Configuration, + this.PreserveAlpha); + + ParallelRowIterator.IterateRows( + this.Configuration, + operationBounds, in horizontalOperation); // Vertical convolution - var verticalOperation = new RowOperation(interest, source.PixelBuffer, firstPassPixels, this.KernelY, this.Configuration, this.PreserveAlpha); - ParallelRowIterator.IterateRows( - this.Configuration, + var verticalOperation = new VerticalConvolutionRowOperation( interest, + source.PixelBuffer, + firstPassPixels, + mapXY, + this.Kernel, + this.Configuration, + this.PreserveAlpha); + + ParallelRowIterator.IterateRows( + this.Configuration, + operationBounds, in verticalOperation); } /// - /// A implementing the convolution logic for . + /// A implementing the logic for the horizontal 1D convolution. /// - private readonly struct RowOperation : IRowOperation + internal readonly struct HorizontalConvolutionRowOperation : IRowOperation { private readonly Rectangle bounds; private readonly Buffer2D targetPixels; private readonly Buffer2D sourcePixels; - private readonly DenseMatrix kernel; + private readonly KernelSamplingMap map; + private readonly float[] kernel; private readonly Configuration configuration; private readonly bool preserveAlpha; - [MethodImpl(InliningOptions.ShortMethod)] - public RowOperation( + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public HorizontalConvolutionRowOperation( Rectangle bounds, Buffer2D targetPixels, Buffer2D sourcePixels, - DenseMatrix kernel, + KernelSamplingMap map, + float[] kernel, Configuration configuration, bool preserveAlpha) { this.bounds = bounds; this.targetPixels = targetPixels; this.sourcePixels = sourcePixels; + this.map = map; this.kernel = kernel; this.configuration = configuration; this.preserveAlpha = preserveAlpha; } /// - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Invoke(int y, Span span) { - ref Vector4 spanRef = ref MemoryMarshal.GetReference(span); + if (this.preserveAlpha) + { + this.Convolve3(y, span); + } + else + { + this.Convolve4(y, span); + } + } - int maxY = this.bounds.Bottom - 1; - int maxX = this.bounds.Right - 1; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void Convolve3(int y, Span span) + { + // Span is 2x bounds. + int boundsX = this.bounds.X; + int boundsWidth = this.bounds.Width; + int kernelSize = this.kernel.Length; - Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); - PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.Length), span); + Span sourceBuffer = span.Slice(0, this.bounds.Width); + Span targetBuffer = span.Slice(this.bounds.Width); - if (this.preserveAlpha) + // Clear the target buffer for each row run. + targetBuffer.Clear(); + + // Get the precalculated source sample row for this kernel row and copy to our buffer. + Span sourceRow = this.sourcePixels.GetRowSpan(y).Slice(boundsX, boundsWidth); + PixelOperations.Instance.ToVector4(this.configuration, sourceRow, sourceBuffer); + + ref Vector4 sourceBase = ref MemoryMarshal.GetReference(sourceBuffer); + ref Vector4 targetStart = ref MemoryMarshal.GetReference(targetBuffer); + ref Vector4 targetEnd = ref Unsafe.Add(ref targetStart, sourceBuffer.Length); + ref float kernelBase = ref this.kernel[0]; + ref float kernelEnd = ref Unsafe.Add(ref kernelBase, kernelSize); + ref int sampleColumnBase = ref MemoryMarshal.GetReference(this.map.GetColumnOffsetSpan()); + + while (Unsafe.IsAddressLessThan(ref targetStart, ref targetEnd)) { - for (int x = 0; x < this.bounds.Width; x++) + ref float kernelStart = ref kernelBase; + ref int sampleColumnStart = ref sampleColumnBase; + + while (Unsafe.IsAddressLessThan(ref kernelStart, ref kernelEnd)) { - DenseMatrixUtils.Convolve3( - in this.kernel, - this.sourcePixels, - ref spanRef, - y, - x, - this.bounds.Y, - maxY, - this.bounds.X, - maxX); + Vector4 sample = Unsafe.Add(ref sourceBase, sampleColumnStart - boundsX); + + targetStart += kernelStart * sample; + + kernelStart = ref Unsafe.Add(ref kernelStart, 1); + sampleColumnStart = ref Unsafe.Add(ref sampleColumnStart, 1); } + + targetStart = ref Unsafe.Add(ref targetStart, 1); + sampleColumnBase = ref Unsafe.Add(ref sampleColumnBase, kernelSize); + } + + // Now we need to copy the original alpha values from the source row. + sourceRow = this.sourcePixels.GetRowSpan(y).Slice(boundsX, boundsWidth); + PixelOperations.Instance.ToVector4(this.configuration, sourceRow, sourceBuffer); + + targetStart = ref MemoryMarshal.GetReference(targetBuffer); + + while (Unsafe.IsAddressLessThan(ref targetStart, ref targetEnd)) + { + targetStart.W = sourceBase.W; + + targetStart = ref Unsafe.Add(ref targetStart, 1); + sourceBase = ref Unsafe.Add(ref sourceBase, 1); + } + + Span targetRow = this.targetPixels.GetRowSpan(y).Slice(boundsX, boundsWidth); + PixelOperations.Instance.FromVector4Destructive(this.configuration, targetBuffer, targetRow); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void Convolve4(int y, Span span) + { + // Span is 2x bounds. + int boundsX = this.bounds.X; + int boundsWidth = this.bounds.Width; + int kernelSize = this.kernel.Length; + + Span sourceBuffer = span.Slice(0, this.bounds.Width); + Span targetBuffer = span.Slice(this.bounds.Width); + + // Clear the target buffer for each row run. + targetBuffer.Clear(); + + // Get the precalculated source sample row for this kernel row and copy to our buffer. + Span sourceRow = this.sourcePixels.GetRowSpan(y).Slice(boundsX, boundsWidth); + PixelOperations.Instance.ToVector4(this.configuration, sourceRow, sourceBuffer); + + Numerics.Premultiply(sourceBuffer); + + ref Vector4 sourceBase = ref MemoryMarshal.GetReference(sourceBuffer); + ref Vector4 targetStart = ref MemoryMarshal.GetReference(targetBuffer); + ref Vector4 targetEnd = ref Unsafe.Add(ref targetStart, sourceBuffer.Length); + ref float kernelBase = ref this.kernel[0]; + ref float kernelEnd = ref Unsafe.Add(ref kernelBase, kernelSize); + ref int sampleColumnBase = ref MemoryMarshal.GetReference(this.map.GetColumnOffsetSpan()); + + while (Unsafe.IsAddressLessThan(ref targetStart, ref targetEnd)) + { + ref float kernelStart = ref kernelBase; + ref int sampleColumnStart = ref sampleColumnBase; + + while (Unsafe.IsAddressLessThan(ref kernelStart, ref kernelEnd)) + { + Vector4 sample = Unsafe.Add(ref sourceBase, sampleColumnStart - boundsX); + + targetStart += kernelStart * sample; + + kernelStart = ref Unsafe.Add(ref kernelStart, 1); + sampleColumnStart = ref Unsafe.Add(ref sampleColumnStart, 1); + } + + targetStart = ref Unsafe.Add(ref targetStart, 1); + sampleColumnBase = ref Unsafe.Add(ref sampleColumnBase, kernelSize); + } + + Numerics.UnPremultiply(targetBuffer); + + Span targetRow = this.targetPixels.GetRowSpan(y).Slice(boundsX, boundsWidth); + PixelOperations.Instance.FromVector4Destructive(this.configuration, targetBuffer, targetRow); + } + } + + /// + /// A implementing the logic for the vertical 1D convolution. + /// + internal readonly struct VerticalConvolutionRowOperation : IRowOperation + { + private readonly Rectangle bounds; + private readonly Buffer2D targetPixels; + private readonly Buffer2D sourcePixels; + private readonly KernelSamplingMap map; + private readonly float[] kernel; + private readonly Configuration configuration; + private readonly bool preserveAlpha; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public VerticalConvolutionRowOperation( + Rectangle bounds, + Buffer2D targetPixels, + Buffer2D sourcePixels, + KernelSamplingMap map, + float[] kernel, + Configuration configuration, + bool preserveAlpha) + { + this.bounds = bounds; + this.targetPixels = targetPixels; + this.sourcePixels = sourcePixels; + this.map = map; + this.kernel = kernel; + this.configuration = configuration; + this.preserveAlpha = preserveAlpha; + } + + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Invoke(int y, Span span) + { + if (this.preserveAlpha) + { + this.Convolve3(y, span); } else { - for (int x = 0; x < this.bounds.Width; x++) + this.Convolve4(y, span); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void Convolve3(int y, Span span) + { + // Span is 2x bounds. + int boundsX = this.bounds.X; + int boundsWidth = this.bounds.Width; + int kernelSize = this.kernel.Length; + + Span sourceBuffer = span.Slice(0, this.bounds.Width); + Span targetBuffer = span.Slice(this.bounds.Width); + + ref int sampleRowBase = ref Unsafe.Add(ref MemoryMarshal.GetReference(this.map.GetRowOffsetSpan()), (y - this.bounds.Y) * kernelSize); + + // Clear the target buffer for each row run. + targetBuffer.Clear(); + + ref Vector4 targetBase = ref MemoryMarshal.GetReference(targetBuffer); + ref float kernelStart = ref this.kernel[0]; + ref float kernelEnd = ref Unsafe.Add(ref kernelStart, kernelSize); + + Span sourceRow; + while (Unsafe.IsAddressLessThan(ref kernelStart, ref kernelEnd)) + { + // Get the precalculated source sample row for this kernel row and copy to our buffer. + sourceRow = this.sourcePixels.GetRowSpan(sampleRowBase).Slice(boundsX, boundsWidth); + + PixelOperations.Instance.ToVector4(this.configuration, sourceRow, sourceBuffer); + + ref Vector4 sourceBase = ref MemoryMarshal.GetReference(sourceBuffer); + ref Vector4 sourceEnd = ref Unsafe.Add(ref sourceBase, sourceBuffer.Length); + ref Vector4 targetStart = ref targetBase; + float factor = kernelStart; + + while (Unsafe.IsAddressLessThan(ref sourceBase, ref sourceEnd)) + { + targetStart += factor * sourceBase; + + sourceBase = ref Unsafe.Add(ref sourceBase, 1); + targetStart = ref Unsafe.Add(ref targetStart, 1); + } + + kernelStart = ref Unsafe.Add(ref kernelStart, 1); + sampleRowBase = ref Unsafe.Add(ref sampleRowBase, 1); + } + + // Now we need to copy the original alpha values from the source row. + sourceRow = this.sourcePixels.GetRowSpan(y).Slice(boundsX, boundsWidth); + PixelOperations.Instance.ToVector4(this.configuration, sourceRow, sourceBuffer); + { + ref Vector4 sourceBase = ref MemoryMarshal.GetReference(sourceBuffer); + ref Vector4 sourceEnd = ref Unsafe.Add(ref sourceBase, sourceBuffer.Length); + + while (Unsafe.IsAddressLessThan(ref sourceBase, ref sourceEnd)) + { + targetBase.W = sourceBase.W; + + targetBase = ref Unsafe.Add(ref targetBase, 1); + sourceBase = ref Unsafe.Add(ref sourceBase, 1); + } + } + + Span targetRow = this.targetPixels.GetRowSpan(y).Slice(boundsX, boundsWidth); + PixelOperations.Instance.FromVector4Destructive(this.configuration, targetBuffer, targetRow); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void Convolve4(int y, Span span) + { + // Span is 2x bounds. + int boundsX = this.bounds.X; + int boundsWidth = this.bounds.Width; + int kernelSize = this.kernel.Length; + + Span sourceBuffer = span.Slice(0, this.bounds.Width); + Span targetBuffer = span.Slice(this.bounds.Width); + + ref int sampleRowBase = ref Unsafe.Add(ref MemoryMarshal.GetReference(this.map.GetRowOffsetSpan()), (y - this.bounds.Y) * kernelSize); + + // Clear the target buffer for each row run. + targetBuffer.Clear(); + + ref Vector4 targetBase = ref MemoryMarshal.GetReference(targetBuffer); + ref float kernelStart = ref this.kernel[0]; + ref float kernelEnd = ref Unsafe.Add(ref kernelStart, kernelSize); + + Span sourceRow; + while (Unsafe.IsAddressLessThan(ref kernelStart, ref kernelEnd)) + { + // Get the precalculated source sample row for this kernel row and copy to our buffer. + sourceRow = this.sourcePixels.GetRowSpan(sampleRowBase).Slice(boundsX, boundsWidth); + + PixelOperations.Instance.ToVector4(this.configuration, sourceRow, sourceBuffer); + + ref Vector4 sourceBase = ref MemoryMarshal.GetReference(sourceBuffer); + ref Vector4 sourceEnd = ref Unsafe.Add(ref sourceBase, sourceBuffer.Length); + ref Vector4 targetStart = ref targetBase; + float factor = kernelStart; + + while (Unsafe.IsAddressLessThan(ref sourceBase, ref sourceEnd)) { - DenseMatrixUtils.Convolve4( - in this.kernel, - this.sourcePixels, - ref spanRef, - y, - x, - this.bounds.Y, - maxY, - this.bounds.X, - maxX); + targetStart += factor * sourceBase; + + sourceBase = ref Unsafe.Add(ref sourceBase, 1); + targetStart = ref Unsafe.Add(ref targetStart, 1); } + + kernelStart = ref Unsafe.Add(ref kernelStart, 1); + sampleRowBase = ref Unsafe.Add(ref sampleRowBase, 1); } - PixelOperations.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan); + Numerics.UnPremultiply(targetBuffer); + + Span targetRow = this.targetPixels.GetRowSpan(y).Slice(boundsX, boundsWidth); + PixelOperations.Instance.FromVector4Destructive(this.configuration, targetBuffer, targetRow); } } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs index 7b1ceff276..f93cdabc47 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs @@ -12,17 +12,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// See . /// internal static int GetDefaultGaussianRadius(float sigma) - { - return (int)MathF.Ceiling(sigma * 3); - } + => (int)MathF.Ceiling(sigma * 3); /// /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function. /// - /// The . - internal static DenseMatrix CreateGaussianBlurKernel(int size, float weight) + /// The convolution kernel. + internal static float[] CreateGaussianBlurKernel(int size, float weight) { - var kernel = new DenseMatrix(size, 1); + var kernel = new float[size]; float sum = 0F; float midpoint = (size - 1) / 2F; @@ -30,15 +28,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution for (int i = 0; i < size; i++) { float x = i - midpoint; - float gx = ImageMaths.Gaussian(x, weight); + float gx = Numerics.Gaussian(x, weight); sum += gx; - kernel[0, i] = gx; + kernel[i] = gx; } // Normalize kernel so that the sum of all weights equals 1 for (int i = 0; i < size; i++) { - kernel[0, i] /= sum; + kernel[i] /= sum; } return kernel; @@ -47,10 +45,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// Create a 1 dimensional Gaussian kernel using the Gaussian G(x) function /// - /// The . - internal static DenseMatrix CreateGaussianSharpenKernel(int size, float weight) + /// The convolution kernel. + internal static float[] CreateGaussianSharpenKernel(int size, float weight) { - var kernel = new DenseMatrix(size, 1); + var kernel = new float[size]; float sum = 0; @@ -58,9 +56,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution for (int i = 0; i < size; i++) { float x = i - midpoint; - float gx = ImageMaths.Gaussian(x, weight); + float gx = Numerics.Gaussian(x, weight); sum += gx; - kernel[0, i] = gx; + kernel[i] = gx; } // Invert the kernel for sharpening. @@ -70,22 +68,22 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution if (i == midpointRounded) { // Calculate central value - kernel[0, i] = (2F * sum) - kernel[0, i]; + kernel[i] = (2F * sum) - kernel[i]; } else { // invert value - kernel[0, i] = -kernel[0, i]; + kernel[i] = -kernel[i]; } } // Normalize kernel so that the sum of all weights equals 1 for (int i = 0; i < size; i++) { - kernel[0, i] /= sum; + kernel[i] /= sum; } return kernel; } } -} \ No newline at end of file +} diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs index 95fef15f62..924a1125bd 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution } /// - /// Gets the 2d gradient operator. + /// Gets the 2d convolution kernel. /// public DenseMatrix KernelXY { get; } @@ -51,16 +51,26 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// protected override void OnFrameApply(ImageFrame source) { - using Buffer2D targetPixels = this.Configuration.MemoryAllocator.Allocate2D(source.Size()); + MemoryAllocator allocator = this.Configuration.MemoryAllocator; + using Buffer2D targetPixels = allocator.Allocate2D(source.Size()); source.CopyTo(targetPixels); var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); - var operation = new RowOperation(interest, targetPixels, source.PixelBuffer, this.KernelXY, this.Configuration, this.PreserveAlpha); - ParallelRowIterator.IterateRows( - this.Configuration, - interest, - in operation); + + // We use a rectangle 2x the interest width to allocate a buffer big enough + // for source and target bulk pixel conversion. + var operationBounds = new Rectangle(interest.X, interest.Y, interest.Width * 2, interest.Height); + using (var map = new KernelSamplingMap(allocator)) + { + map.BuildSamplingOffsetMap(this.KernelXY, interest); + + var operation = new RowOperation(interest, targetPixels, source.PixelBuffer, map, this.KernelXY, this.Configuration, this.PreserveAlpha); + ParallelRowIterator.IterateRows( + this.Configuration, + operationBounds, + in operation); + } Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels); } @@ -71,10 +81,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution private readonly struct RowOperation : IRowOperation { private readonly Rectangle bounds; - private readonly int maxY; - private readonly int maxX; private readonly Buffer2D targetPixels; private readonly Buffer2D sourcePixels; + private readonly KernelSamplingMap map; private readonly DenseMatrix kernel; private readonly Configuration configuration; private readonly bool preserveAlpha; @@ -84,15 +93,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution Rectangle bounds, Buffer2D targetPixels, Buffer2D sourcePixels, + KernelSamplingMap map, DenseMatrix kernel, Configuration configuration, bool preserveAlpha) { this.bounds = bounds; - this.maxY = this.bounds.Bottom - 1; - this.maxX = this.bounds.Right - 1; this.targetPixels = targetPixels; this.sourcePixels = sourcePixels; + this.map = map; this.kernel = kernel; this.configuration = configuration; this.preserveAlpha = preserveAlpha; @@ -102,45 +111,93 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(int y, Span span) { - ref Vector4 spanRef = ref MemoryMarshal.GetReference(span); + // Span is 2x bounds. + int boundsX = this.bounds.X; + int boundsWidth = this.bounds.Width; + Span sourceBuffer = span.Slice(0, this.bounds.Width); + Span targetBuffer = span.Slice(this.bounds.Width); + + ref Vector4 targetRowRef = ref MemoryMarshal.GetReference(span); + Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(boundsX, boundsWidth); - Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); - PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.Length), span); + var state = new ConvolutionState(in this.kernel, this.map); + int row = y - this.bounds.Y; + ref int sampleRowBase = ref state.GetSampleRow(row); if (this.preserveAlpha) { - for (int x = 0; x < this.bounds.Width; x++) + // Clear the target buffer for each row run. + targetBuffer.Clear(); + ref Vector4 targetBase = ref MemoryMarshal.GetReference(targetBuffer); + + Span sourceRow; + for (int kY = 0; kY < state.Kernel.Rows; kY++) + { + // Get the precalculated source sample row for this kernel row and copy to our buffer. + int offsetY = Unsafe.Add(ref sampleRowBase, kY); + sourceRow = this.sourcePixels.GetRowSpan(offsetY).Slice(boundsX, boundsWidth); + PixelOperations.Instance.ToVector4(this.configuration, sourceRow, sourceBuffer); + + ref Vector4 sourceBase = ref MemoryMarshal.GetReference(sourceBuffer); + + for (int x = 0; x < sourceBuffer.Length; x++) + { + ref int sampleColumnBase = ref state.GetSampleColumn(x); + ref Vector4 target = ref Unsafe.Add(ref targetBase, x); + + for (int kX = 0; kX < state.Kernel.Columns; kX++) + { + int offsetX = Unsafe.Add(ref sampleColumnBase, kX) - boundsX; + Vector4 sample = Unsafe.Add(ref sourceBase, offsetX); + target += state.Kernel[kY, kX] * sample; + } + } + } + + // Now we need to copy the original alpha values from the source row. + sourceRow = this.sourcePixels.GetRowSpan(y).Slice(boundsX, boundsWidth); + PixelOperations.Instance.ToVector4(this.configuration, sourceRow, sourceBuffer); + + for (int x = 0; x < sourceRow.Length; x++) { - DenseMatrixUtils.Convolve3( - in this.kernel, - this.sourcePixels, - ref spanRef, - y, - x, - this.bounds.Y, - this.maxY, - this.bounds.X, - this.maxX); + ref Vector4 target = ref Unsafe.Add(ref targetBase, x); + target.W = Unsafe.Add(ref MemoryMarshal.GetReference(sourceBuffer), x).W; } } else { - for (int x = 0; x < this.bounds.Width; x++) + // Clear the target buffer for each row run. + targetBuffer.Clear(); + ref Vector4 targetBase = ref MemoryMarshal.GetReference(targetBuffer); + + for (int kY = 0; kY < state.Kernel.Rows; kY++) { - DenseMatrixUtils.Convolve4( - in this.kernel, - this.sourcePixels, - ref spanRef, - y, - x, - this.bounds.Y, - this.maxY, - this.bounds.X, - this.maxX); + // Get the precalculated source sample row for this kernel row and copy to our buffer. + int offsetY = Unsafe.Add(ref sampleRowBase, kY); + Span sourceRow = this.sourcePixels.GetRowSpan(offsetY).Slice(boundsX, boundsWidth); + PixelOperations.Instance.ToVector4(this.configuration, sourceRow, sourceBuffer); + + Numerics.Premultiply(sourceBuffer); + ref Vector4 sourceBase = ref MemoryMarshal.GetReference(sourceBuffer); + + for (int x = 0; x < sourceBuffer.Length; x++) + { + ref int sampleColumnBase = ref state.GetSampleColumn(x); + ref Vector4 target = ref Unsafe.Add(ref targetBase, x); + + for (int kX = 0; kX < state.Kernel.Columns; kX++) + { + int offsetX = Unsafe.Add(ref sampleColumnBase, kX) - boundsX; + Vector4 sample = Unsafe.Add(ref sourceBase, offsetX); + target += state.Kernel[kY, kX] * sample; + } + } } + + Numerics.UnPremultiply(targetBuffer); } - PixelOperations.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan); + PixelOperations.Instance.FromVector4Destructive(this.configuration, targetBuffer, targetRowSpan); } } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionState.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionState.cs new file mode 100644 index 0000000000..3f296c67df --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionState.cs @@ -0,0 +1,45 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace SixLabors.ImageSharp.Processing.Processors.Convolution +{ + /// + /// A stack only struct used for reducing reference indirection during convolution operations. + /// + internal readonly ref struct ConvolutionState + { + private readonly Span rowOffsetMap; + private readonly Span columnOffsetMap; + private readonly int kernelHeight; + private readonly int kernelWidth; + + public ConvolutionState( + in DenseMatrix kernel, + KernelSamplingMap map) + { + this.Kernel = new ReadOnlyKernel(kernel); + this.kernelHeight = kernel.Rows; + this.kernelWidth = kernel.Columns; + this.rowOffsetMap = map.GetRowOffsetSpan(); + this.columnOffsetMap = map.GetColumnOffsetSpan(); + } + + public readonly ReadOnlyKernel Kernel + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly ref int GetSampleRow(int row) + => ref Unsafe.Add(ref MemoryMarshal.GetReference(this.rowOffsetMap), row * this.kernelHeight); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly ref int GetSampleColumn(int column) + => ref Unsafe.Add(ref MemoryMarshal.GetReference(this.columnOffsetMap), column * this.kernelWidth); + } +} diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor{TPixel}.cs index a9b692a015..4ade01f914 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor{TPixel}.cs @@ -27,24 +27,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution : base(configuration, source, sourceRectangle) { int kernelSize = (definition.Radius * 2) + 1; - this.KernelX = ConvolutionProcessorHelpers.CreateGaussianBlurKernel(kernelSize, definition.Sigma); - this.KernelY = this.KernelX.Transpose(); + this.Kernel = ConvolutionProcessorHelpers.CreateGaussianBlurKernel(kernelSize, definition.Sigma); } /// - /// Gets the horizontal gradient operator. + /// Gets the 1D convolution kernel. /// - public DenseMatrix KernelX { get; } - - /// - /// Gets the vertical gradient operator. - /// - public DenseMatrix KernelY { get; } + public float[] Kernel { get; } /// protected override void OnFrameApply(ImageFrame source) { - using var processor = new Convolution2PassProcessor(this.Configuration, this.KernelX, this.KernelY, false, this.Source, this.SourceRectangle); + using var processor = new Convolution2PassProcessor(this.Configuration, this.Kernel, false, this.Source, this.SourceRectangle); processor.Apply(source); } diff --git a/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor{TPixel}.cs index 5e20865e5c..73aaaec188 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor{TPixel}.cs @@ -27,24 +27,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution : base(configuration, source, sourceRectangle) { int kernelSize = (definition.Radius * 2) + 1; - this.KernelX = ConvolutionProcessorHelpers.CreateGaussianSharpenKernel(kernelSize, definition.Sigma); - this.KernelY = this.KernelX.Transpose(); + this.Kernel = ConvolutionProcessorHelpers.CreateGaussianSharpenKernel(kernelSize, definition.Sigma); } /// - /// Gets the horizontal gradient operator. + /// Gets the 1D convolution kernel. /// - public DenseMatrix KernelX { get; } - - /// - /// Gets the vertical gradient operator. - /// - public DenseMatrix KernelY { get; } + public float[] Kernel { get; } /// protected override void OnFrameApply(ImageFrame source) { - using var processor = new Convolution2PassProcessor(this.Configuration, this.KernelX, this.KernelY, false, this.Source, this.SourceRectangle); + using var processor = new Convolution2PassProcessor(this.Configuration, this.Kernel, false, this.Source, this.SourceRectangle); processor.Apply(source); } diff --git a/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs b/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs new file mode 100644 index 0000000000..904b599f7c --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs @@ -0,0 +1,109 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Buffers; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using SixLabors.ImageSharp.Memory; + +namespace SixLabors.ImageSharp.Processing.Processors.Convolution +{ + /// + /// Provides a map of the convolution kernel sampling offsets. + /// + internal sealed class KernelSamplingMap : IDisposable + { + private readonly MemoryAllocator allocator; + private bool isDisposed; + private IMemoryOwner yOffsets; + private IMemoryOwner xOffsets; + + /// + /// Initializes a new instance of the class. + /// + /// The memory allocator. + public KernelSamplingMap(MemoryAllocator allocator) => this.allocator = allocator; + + /// + /// Builds a map of the sampling offsets for the kernel clamped by the given bounds. + /// + /// The convolution kernel. + /// The source bounds. + public void BuildSamplingOffsetMap(DenseMatrix kernel, Rectangle bounds) + => this.BuildSamplingOffsetMap(kernel.Rows, kernel.Columns, bounds); + + /// + /// Builds a map of the sampling offsets for the kernel clamped by the given bounds. + /// + /// The height (number of rows) of the convolution kernel to use. + /// The width (number of columns) of the convolution kernel to use. + /// The source bounds. + public void BuildSamplingOffsetMap(int kernelHeight, int kernelWidth, Rectangle bounds) + { + this.yOffsets = this.allocator.Allocate(bounds.Height * kernelHeight); + this.xOffsets = this.allocator.Allocate(bounds.Width * kernelWidth); + + int minY = bounds.Y; + int maxY = bounds.Bottom - 1; + int minX = bounds.X; + int maxX = bounds.Right - 1; + + int radiusY = kernelHeight >> 1; + int radiusX = kernelWidth >> 1; + + // Calculate the y and x sampling offsets clamped to the given rectangle. + // While this isn't a hotpath we still dip into unsafe to avoid the span bounds + // checks as the can potentially be looping over large arrays. + Span ySpan = this.yOffsets.GetSpan(); + ref int ySpanBase = ref MemoryMarshal.GetReference(ySpan); + for (int row = 0; row < bounds.Height; row++) + { + int rowBase = row * kernelHeight; + for (int y = 0; y < kernelHeight; y++) + { + Unsafe.Add(ref ySpanBase, rowBase + y) = row + y + minY - radiusY; + } + } + + if (kernelHeight > 1) + { + Numerics.Clamp(ySpan, minY, maxY); + } + + Span xSpan = this.xOffsets.GetSpan(); + ref int xSpanBase = ref MemoryMarshal.GetReference(xSpan); + for (int column = 0; column < bounds.Width; column++) + { + int columnBase = column * kernelWidth; + for (int x = 0; x < kernelWidth; x++) + { + Unsafe.Add(ref xSpanBase, columnBase + x) = column + x + minX - radiusX; + } + } + + if (kernelWidth > 1) + { + Numerics.Clamp(xSpan, minX, maxX); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Span GetRowOffsetSpan() => this.yOffsets.GetSpan(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Span GetColumnOffsetSpan() => this.xOffsets.GetSpan(); + + /// + public void Dispose() + { + if (!this.isDisposed) + { + this.yOffsets?.Dispose(); + this.xOffsets?.Dispose(); + + this.isDisposed = true; + } + } + } +} diff --git a/src/ImageSharp/Processing/Processors/Convolution/ReadOnlyKernel.cs b/src/ImageSharp/Processing/Processors/Convolution/ReadOnlyKernel.cs new file mode 100644 index 0000000000..37e0060054 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Convolution/ReadOnlyKernel.cs @@ -0,0 +1,63 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace SixLabors.ImageSharp.Processing.Processors.Convolution +{ + /// + /// A stack only, readonly, kernel matrix that can be indexed without + /// bounds checks when compiled in release mode. + /// + internal readonly ref struct ReadOnlyKernel + { + private readonly ReadOnlySpan values; + + public ReadOnlyKernel(DenseMatrix matrix) + { + this.Columns = matrix.Columns; + this.Rows = matrix.Rows; + this.values = matrix.Span; + } + + public int Columns + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get; + } + + public int Rows + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get; + } + + public float this[int row, int column] + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + this.CheckCoordinates(row, column); + ref float vBase = ref MemoryMarshal.GetReference(this.values); + return Unsafe.Add(ref vBase, (row * this.Columns) + column); + } + } + + [Conditional("DEBUG")] + private void CheckCoordinates(int row, int column) + { + if (row < 0 || row >= this.Rows) + { + throw new ArgumentOutOfRangeException(nameof(row), row, $"{row} is outwith the matrix bounds."); + } + + if (column < 0 || column >= this.Columns) + { + throw new ArgumentOutOfRangeException(nameof(column), column, $"{column} is outwith the matrix bounds."); + } + } + } +} diff --git a/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs b/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs index 30ac5f135b..1a107c2cfd 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs @@ -5,7 +5,6 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Quantization; diff --git a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.KnownTypes.cs b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.KnownTypes.cs index 71ad6db973..1934604522 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.KnownTypes.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.KnownTypes.cs @@ -23,6 +23,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering /// public static OrderedDither Bayer8x8 = new OrderedDither(8); + /// + /// Applies order dithering using the 16x16 Bayer dithering matrix. + /// + public static OrderedDither Bayer16x16 = new OrderedDither(16); + /// /// Applies order dithering using the 3x3 ordered dithering matrix. /// diff --git a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs index 448eb3833b..2b7eb165eb 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs @@ -3,7 +3,6 @@ using System; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Quantization; @@ -145,30 +144,33 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering in ditherOperation); } + // Spread assumes an even colorspace distribution and precision. + // TODO: Cubed root is currently used to represent 3 color channels + // but we should introduce something to PixelTypeInfo. + // https://bisqwit.iki.fi/story/howto/dither/jy/ + // https://en.wikipedia.org/wiki/Ordered_dithering#Algorithm + internal static int CalculatePaletteSpread(int colors) + => (int)(255 / Math.Max(1, Math.Pow(colors, 1.0 / 3) - 1)); + [MethodImpl(InliningOptions.ShortMethod)] internal TPixel Dither( TPixel source, int x, int y, - int bitDepth, + int spread, float scale) where TPixel : unmanaged, IPixel { - Rgba32 rgba = default; + Unsafe.SkipInit(out Rgba32 rgba); source.ToRgba32(ref rgba); - Rgba32 attempt; + Unsafe.SkipInit(out Rgba32 attempt); - // Spread assumes an even colorspace distribution and precision. - // Calculated as 0-255/component count. 256 / bitDepth - // https://bisqwit.iki.fi/story/howto/dither/jy/ - // https://en.wikipedia.org/wiki/Ordered_dithering#Algorithm - int spread = 256 / bitDepth; float factor = spread * this.thresholdMatrix[y % this.modulusY, x % this.modulusX] * scale; - attempt.R = (byte)(rgba.R + factor).Clamp(byte.MinValue, byte.MaxValue); - attempt.G = (byte)(rgba.G + factor).Clamp(byte.MinValue, byte.MaxValue); - attempt.B = (byte)(rgba.B + factor).Clamp(byte.MinValue, byte.MaxValue); - attempt.A = (byte)(rgba.A + factor).Clamp(byte.MinValue, byte.MaxValue); + attempt.R = (byte)Numerics.Clamp(rgba.R + factor, byte.MinValue, byte.MaxValue); + attempt.G = (byte)Numerics.Clamp(rgba.G + factor, byte.MinValue, byte.MaxValue); + attempt.B = (byte)Numerics.Clamp(rgba.B + factor, byte.MinValue, byte.MaxValue); + attempt.A = (byte)Numerics.Clamp(rgba.A + factor, byte.MinValue, byte.MaxValue); TPixel result = default; result.FromRgba32(attempt); @@ -203,7 +205,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering private readonly ImageFrame source; private readonly IndexedImageFrame destination; private readonly Rectangle bounds; - private readonly int bitDepth; + private readonly int spread; [MethodImpl(InliningOptions.ShortMethod)] public QuantizeDitherRowOperation( @@ -218,23 +220,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering this.source = source; this.destination = destination; this.bounds = bounds; - this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(destination.Palette.Length); + this.spread = CalculatePaletteSpread(destination.Palette.Length); } [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(int y) { - int offsetY = this.bounds.Top; - int offsetX = this.bounds.Left; + ref TFrameQuantizer quantizer = ref Unsafe.AsRef(this.quantizer); + int spread = this.spread; float scale = this.quantizer.Options.DitherScale; - ref TPixel sourceRowRef = ref MemoryMarshal.GetReference(this.source.GetPixelRowSpan(y)); - ref byte destinationRowRef = ref MemoryMarshal.GetReference(this.destination.GetWritablePixelRowSpanUnsafe(y - offsetY)); + ReadOnlySpan sourceRow = this.source.GetPixelRowSpan(y).Slice(this.bounds.X, this.bounds.Width); + Span destRow = + this.destination.GetWritablePixelRowSpanUnsafe(y - this.bounds.Y).Slice(0, sourceRow.Length); - for (int x = this.bounds.Left; x < this.bounds.Right; x++) + for (int x = 0; x < sourceRow.Length; x++) { - TPixel dithered = this.dither.Dither(Unsafe.Add(ref sourceRowRef, x), x, y, this.bitDepth, scale); - Unsafe.Add(ref destinationRowRef, x - offsetX) = Unsafe.AsRef(this.quantizer).GetQuantizedColor(dithered, out TPixel _); + TPixel dithered = this.dither.Dither(sourceRow[x], x, y, spread, scale); + destRow[x] = quantizer.GetQuantizedColor(dithered, out TPixel _); } } } @@ -248,7 +251,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering private readonly ImageFrame source; private readonly Rectangle bounds; private readonly float scale; - private readonly int bitDepth; + private readonly int spread; [MethodImpl(InliningOptions.ShortMethod)] public PaletteDitherRowOperation( @@ -262,19 +265,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering this.source = source; this.bounds = bounds; this.scale = processor.DitherScale; - this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(processor.Palette.Length); + this.spread = CalculatePaletteSpread(processor.Palette.Length); } [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(int y) { - ref TPixel sourceRowRef = ref MemoryMarshal.GetReference(this.source.GetPixelRowSpan(y)); + ref TPaletteDitherImageProcessor processor = ref Unsafe.AsRef(this.processor); + int spread = this.spread; + float scale = this.scale; + + Span row = this.source.GetPixelRowSpan(y).Slice(this.bounds.X, this.bounds.Width); - for (int x = this.bounds.Left; x < this.bounds.Right; x++) + for (int x = 0; x < row.Length; x++) { - ref TPixel sourcePixel = ref Unsafe.Add(ref sourceRowRef, x); - TPixel dithered = this.dither.Dither(sourcePixel, x, y, this.bitDepth, this.scale); - sourcePixel = Unsafe.AsRef(this.processor).GetPaletteColor(dithered); + ref TPixel sourcePixel = ref row[x]; + TPixel dithered = this.dither.Dither(sourcePixel, x, y, spread, scale); + sourcePixel = processor.GetPaletteColor(dithered); } } } diff --git a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs index bb6614a7e0..1b321a99f1 100644 --- a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs @@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering Guard.MustBeGreaterThan(palette.Length, 0, nameof(palette)); Guard.NotNull(dither, nameof(dither)); this.Dither = dither; - this.DitherScale = ditherScale.Clamp(QuantizerConstants.MinDitherScale, QuantizerConstants.MaxDitherScale); + this.DitherScale = Numerics.Clamp(ditherScale, QuantizerConstants.MinDitherScale, QuantizerConstants.MaxDitherScale); this.Palette = palette; } diff --git a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs index 21ec8a9c74..42216417ee 100644 --- a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs @@ -137,8 +137,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects { int fyr = fy - this.radius; int offsetY = y + fyr; - - offsetY = offsetY.Clamp(0, maxY); + offsetY = Numerics.Clamp(offsetY, 0, maxY); Span sourceOffsetRow = this.source.GetPixelRowSpan(offsetY); @@ -146,7 +145,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects { int fxr = fx - this.radius; int offsetX = x + fxr; - offsetX = offsetX.Clamp(0, maxX); + offsetX = Numerics.Clamp(offsetX, 0, maxX); var vector = sourceOffsetRow[offsetX].ToVector4(); diff --git a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs index 584ba072c8..d0c8ff40d7 100644 --- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs @@ -72,11 +72,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters public void Invoke(int y, Span span) { Span rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, span.Length); - PixelOperations.Instance.ToVector4(this.configuration, rowSpan, span); + PixelOperations.Instance.ToVector4(this.configuration, rowSpan, span, PixelConversionModifiers.Scale); - Vector4Utilities.Transform(span, ref Unsafe.AsRef(this.matrix)); + ColorNumerics.Transform(span, ref Unsafe.AsRef(this.matrix)); - PixelOperations.Instance.FromVector4Destructive(this.configuration, span, rowSpan); + PixelOperations.Instance.FromVector4Destructive(this.configuration, span, rowSpan, PixelConversionModifiers.Scale); } } } diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs index b5b07d7a87..14687426d0 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs @@ -86,42 +86,39 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization new Rectangle(0, 0, sourceWidth, tileYStartPositions.Count), in operation); - ref TPixel pixelsBase = ref source.GetPixelReference(0, 0); - // Fix left column - ProcessBorderColumn(ref pixelsBase, cdfData, 0, sourceWidth, sourceHeight, this.Tiles, tileHeight, xStart: 0, xEnd: halfTileWidth, luminanceLevels); + ProcessBorderColumn(source, cdfData, 0, sourceHeight, this.Tiles, tileHeight, xStart: 0, xEnd: halfTileWidth, luminanceLevels); // Fix right column int rightBorderStartX = ((this.Tiles - 1) * tileWidth) + halfTileWidth; - ProcessBorderColumn(ref pixelsBase, cdfData, this.Tiles - 1, sourceWidth, sourceHeight, this.Tiles, tileHeight, xStart: rightBorderStartX, xEnd: sourceWidth, luminanceLevels); + ProcessBorderColumn(source, cdfData, this.Tiles - 1, sourceHeight, this.Tiles, tileHeight, xStart: rightBorderStartX, xEnd: sourceWidth, luminanceLevels); // Fix top row - ProcessBorderRow(ref pixelsBase, cdfData, 0, sourceWidth, this.Tiles, tileWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); + ProcessBorderRow(source, cdfData, 0, sourceWidth, this.Tiles, tileWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); // Fix bottom row int bottomBorderStartY = ((this.Tiles - 1) * tileHeight) + halfTileHeight; - ProcessBorderRow(ref pixelsBase, cdfData, this.Tiles - 1, sourceWidth, this.Tiles, tileWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); + ProcessBorderRow(source, cdfData, this.Tiles - 1, sourceWidth, this.Tiles, tileWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); // Left top corner - ProcessCornerTile(ref pixelsBase, cdfData, sourceWidth, 0, 0, xStart: 0, xEnd: halfTileWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); + ProcessCornerTile(source, cdfData, 0, 0, xStart: 0, xEnd: halfTileWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); // Left bottom corner - ProcessCornerTile(ref pixelsBase, cdfData, sourceWidth, 0, this.Tiles - 1, xStart: 0, xEnd: halfTileWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); + ProcessCornerTile(source, cdfData, 0, this.Tiles - 1, xStart: 0, xEnd: halfTileWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); // Right top corner - ProcessCornerTile(ref pixelsBase, cdfData, sourceWidth, this.Tiles - 1, 0, xStart: rightBorderStartX, xEnd: sourceWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); + ProcessCornerTile(source, cdfData, this.Tiles - 1, 0, xStart: rightBorderStartX, xEnd: sourceWidth, yStart: 0, yEnd: halfTileHeight, luminanceLevels); // Right bottom corner - ProcessCornerTile(ref pixelsBase, cdfData, sourceWidth, this.Tiles - 1, this.Tiles - 1, xStart: rightBorderStartX, xEnd: sourceWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); + ProcessCornerTile(source, cdfData, this.Tiles - 1, this.Tiles - 1, xStart: rightBorderStartX, xEnd: sourceWidth, yStart: bottomBorderStartY, yEnd: sourceHeight, luminanceLevels); } } /// /// Processes the part of a corner tile which was previously left out. It consists of 1 / 4 of a tile and does not need interpolation. /// - /// The output pixels base reference. + /// The source image. /// The lookup table to remap the grey values. - /// The source image width. /// The x-position in the CDF lookup map. /// The y-position in the CDF lookup map. /// X start position. @@ -133,9 +130,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// or 65536 for 16-bit grayscale images. /// private static void ProcessCornerTile( - ref TPixel pixelsBase, + ImageFrame source, CdfTileData cdfData, - int sourceWidth, int cdfX, int cdfY, int xStart, @@ -146,10 +142,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization { for (int dy = yStart; dy < yEnd; dy++) { - int dyOffSet = dy * sourceWidth; + Span rowSpan = source.GetPixelRowSpan(dy); for (int dx = xStart; dx < xEnd; dx++) { - ref TPixel pixel = ref Unsafe.Add(ref pixelsBase, dyOffSet + dx); + ref TPixel pixel = ref rowSpan[dx]; float luminanceEqualized = cdfData.RemapGreyValue(cdfX, cdfY, GetLuminance(pixel, luminanceLevels)); pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); } @@ -159,10 +155,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// /// Processes a border column of the image which is half the size of the tile width. /// - /// The output pixels reference. + /// The source image. /// The pre-computed lookup tables to remap the grey values for each tiles. /// The X index of the lookup table to use. - /// The source image width. /// The source image height. /// The number of vertical tiles. /// The height of a tile. @@ -173,10 +168,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// or 65536 for 16-bit grayscale images. /// private static void ProcessBorderColumn( - ref TPixel pixelBase, + ImageFrame source, CdfTileData cdfData, int cdfX, - int sourceWidth, int sourceHeight, int tileCount, int tileHeight, @@ -194,10 +188,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization int tileY = 0; for (int dy = y; dy < yLimit; dy++) { - int dyOffSet = dy * sourceWidth; + Span rowSpan = source.GetPixelRowSpan(dy); for (int dx = xStart; dx < xEnd; dx++) { - ref TPixel pixel = ref Unsafe.Add(ref pixelBase, dyOffSet + dx); + ref TPixel pixel = ref rowSpan[dx]; float luminanceEqualized = InterpolateBetweenTwoTiles(pixel, cdfData, cdfX, cdfY, cdfX, cdfY + 1, tileY, tileHeight, luminanceLevels); pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); } @@ -213,7 +207,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// /// Processes a border row of the image which is half of the size of the tile height. /// - /// The output pixels base reference. + /// The source image. /// The pre-computed lookup tables to remap the grey values for each tiles. /// The Y index of the lookup table to use. /// The source image width. @@ -226,7 +220,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization /// or 65536 for 16-bit grayscale images. /// private static void ProcessBorderRow( - ref TPixel pixelBase, + ImageFrame source, CdfTileData cdfData, int cdfY, int sourceWidth, @@ -244,12 +238,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization { for (int dy = yStart; dy < yEnd; dy++) { - int dyOffSet = dy * sourceWidth; + Span rowSpan = source.GetPixelRowSpan(dy); int tileX = 0; int xLimit = Math.Min(x + tileWidth, sourceWidth - 1); for (int dx = x; dx < xLimit; dx++) { - ref TPixel pixel = ref Unsafe.Add(ref pixelBase, dyOffSet + dx); + ref TPixel pixel = ref rowSpan[dx]; float luminanceEqualized = InterpolateBetweenTwoTiles(pixel, cdfData, cdfX, cdfY, cdfX + 1, cdfY, tileX, tileWidth, luminanceLevels); pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); tileX++; @@ -410,8 +404,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(in RowInterval rows) { - ref TPixel sourceBase = ref this.source.GetPixelReference(0, 0); - for (int index = rows.Min; index < rows.Max; index++) { (int y, int cdfY) tileYStartPosition = this.tileYStartPositions[index]; @@ -427,11 +419,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization int xEnd = Math.Min(x + this.tileWidth, this.sourceWidth); for (int dy = y; dy < yEnd; dy++) { - int dyOffSet = dy * this.sourceWidth; + Span rowSpan = this.source.GetPixelRowSpan(dy); int tileX = 0; for (int dx = x; dx < xEnd; dx++) { - ref TPixel pixel = ref Unsafe.Add(ref sourceBase, dyOffSet + dx); + ref TPixel pixel = ref rowSpan[dx]; float luminanceEqualized = InterpolateBetweenFourTiles( pixel, this.cdfData, @@ -597,15 +589,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(in RowInterval rows) { - ref TPixel sourceBase = ref this.source.GetPixelReference(0, 0); - for (int index = rows.Min; index < rows.Max; index++) { int cdfX = 0; int cdfY = this.tileYStartPositions[index].cdfY; int y = this.tileYStartPositions[index].y; int endY = Math.Min(y + this.tileHeight, this.sourceHeight); - ref int cdfMinBase = ref MemoryMarshal.GetReference(this.cdfMinBuffer2D.GetRowSpan(cdfY)); + Span cdfMinSpan = this.cdfMinBuffer2D.GetRowSpan(cdfY); using IMemoryOwner histogramBuffer = this.allocator.Allocate(this.luminanceLevels); Span histogram = histogramBuffer.GetSpan(); @@ -620,10 +610,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization int xlimit = Math.Min(x + this.tileWidth, this.sourceWidth); for (int dy = y; dy < endY; dy++) { - int dyOffset = dy * this.sourceWidth; + Span rowSpan = this.source.GetPixelRowSpan(dy); for (int dx = x; dx < xlimit; dx++) { - int luminance = GetLuminance(Unsafe.Add(ref sourceBase, dyOffset + dx), this.luminanceLevels); + int luminance = GetLuminance(rowSpan[dx], this.luminanceLevels); histogram[luminance]++; } } @@ -633,7 +623,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization this.processor.ClipHistogram(histogram, this.processor.ClipLimit); } - Unsafe.Add(ref cdfMinBase, cdfX) = this.processor.CalculateCdf(ref cdfBase, ref histogramBase, histogram.Length - 1); + cdfMinSpan[cdfX] += this.processor.CalculateCdf(ref cdfBase, ref histogramBase, histogram.Length - 1); cdfX++; } diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs index a61c68de3b..b9383e331e 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs @@ -182,7 +182,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization { if (y < 0) { - y = ImageMaths.FastAbs(y); + y = Numerics.Abs(y); } else if (y >= source.Height) { @@ -197,7 +197,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization int idx = 0; for (int dx = x; dx < x + tileWidth; dx++) { - rowPixels[idx] = source[ImageMaths.FastAbs(dx), y].ToVector4(); + rowPixels[idx] = source[Numerics.Abs(dx), y].ToVector4(); idx++; } @@ -259,7 +259,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization { for (int idx = 0; idx < length; idx++) { - int luminance = ImageMaths.GetBT709Luminance(ref Unsafe.Add(ref greyValuesBase, idx), luminanceLevels); + int luminance = ColorNumerics.GetBT709Luminance(ref Unsafe.Add(ref greyValuesBase, idx), luminanceLevels); Unsafe.Add(ref histogramBase, luminance)++; } } @@ -276,7 +276,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization { for (int idx = 0; idx < length; idx++) { - int luminance = ImageMaths.GetBT709Luminance(ref Unsafe.Add(ref greyValuesBase, idx), luminanceLevels); + int luminance = ColorNumerics.GetBT709Luminance(ref Unsafe.Add(ref greyValuesBase, idx), luminanceLevels); Unsafe.Add(ref histogramBase, luminance)--; } } diff --git a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs index 19514c4b6f..70d3e075da 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs @@ -6,6 +6,7 @@ using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Threading; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -51,7 +52,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization using IMemoryOwner histogramBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean); - // Build the histogram of the grayscale levels + // Build the histogram of the grayscale levels. var grayscaleOperation = new GrayscaleLevelsRowOperation(interest, histogramBuffer, source, this.LuminanceLevels); ParallelRowIterator.IterateRows( this.Configuration, @@ -106,16 +107,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization } /// +#if NETSTANDARD2_0 + // https://github.com/SixLabors/ImageSharp/issues/1204 + [MethodImpl(MethodImplOptions.NoOptimization)] +#else [MethodImpl(InliningOptions.ShortMethod)] +#endif public void Invoke(int y) { ref int histogramBase = ref MemoryMarshal.GetReference(this.histogramBuffer.GetSpan()); - ref TPixel pixelBase = ref MemoryMarshal.GetReference(this.source.GetPixelRowSpan(y)); + Span pixelRow = this.source.GetPixelRowSpan(y); + int levels = this.luminanceLevels; for (int x = 0; x < this.bounds.Width; x++) { - int luminance = GetLuminance(Unsafe.Add(ref pixelBase, x), this.luminanceLevels); - Unsafe.Add(ref histogramBase, luminance)++; + // TODO: We should bulk convert here. + var vector = pixelRow[x].ToVector4(); + int luminance = ColorNumerics.GetBT709Luminance(ref vector, levels); + Interlocked.Increment(ref Unsafe.Add(ref histogramBase, luminance)); } } } @@ -147,18 +156,27 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization } /// +#if NETSTANDARD2_0 + // https://github.com/SixLabors/ImageSharp/issues/1204 + [MethodImpl(MethodImplOptions.NoOptimization)] +#else [MethodImpl(InliningOptions.ShortMethod)] +#endif public void Invoke(int y) { ref int cdfBase = ref MemoryMarshal.GetReference(this.cdfBuffer.GetSpan()); - ref TPixel pixelBase = ref MemoryMarshal.GetReference(this.source.GetPixelRowSpan(y)); + Span pixelRow = this.source.GetPixelRowSpan(y); + int levels = this.luminanceLevels; + float noOfPixelsMinusCdfMin = this.numberOfPixelsMinusCdfMin; for (int x = 0; x < this.bounds.Width; x++) { - ref TPixel pixel = ref Unsafe.Add(ref pixelBase, x); - int luminance = GetLuminance(pixel, this.luminanceLevels); - float luminanceEqualized = Unsafe.Add(ref cdfBase, luminance) / this.numberOfPixelsMinusCdfMin; - pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W)); + // TODO: We should bulk convert here. + ref TPixel pixel = ref pixelRow[x]; + var vector = pixel.ToVector4(); + int luminance = ColorNumerics.GetBT709Luminance(ref vector, levels); + float luminanceEqualized = Unsafe.Add(ref cdfBase, luminance) / noOfPixelsMinusCdfMin; + pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, vector.W)); } } } diff --git a/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor{TPixel}.cs index 2849574bc2..59df3058d9 100644 --- a/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor{TPixel}.cs @@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization public static int GetLuminance(TPixel sourcePixel, int luminanceLevels) { var vector = sourcePixel.ToVector4(); - return ImageMaths.GetBT709Luminance(ref vector, luminanceLevels); + return ColorNumerics.GetBT709Luminance(ref vector, luminanceLevels); } } } diff --git a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs index c028903f41..78cf7f3c61 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs @@ -102,7 +102,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays for (int i = 0; i < this.bounds.Width; i++) { float distance = Vector2.Distance(this.center, new Vector2(i + this.bounds.X, y)); - span[i] = (this.blendPercent * (1 - (.95F * (distance / this.maxDistance)))).Clamp(0, 1); + span[i] = Numerics.Clamp(this.blendPercent * (1 - (.95F * (distance / this.maxDistance))), 0, 1F); } Span destination = this.source.GetPixelRowSpan(y).Slice(this.bounds.X, this.bounds.Width); diff --git a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs index d09e3b22a9..c853377adc 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs @@ -110,7 +110,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays for (int i = 0; i < this.bounds.Width; i++) { float distance = Vector2.Distance(this.center, new Vector2(i + this.bounds.X, y)); - span[i] = (this.blendPercent * (.9F * (distance / this.maxDistance))).Clamp(0, 1); + span[i] = Numerics.Clamp(this.blendPercent * (.9F * (distance / this.maxDistance)), 0, 1F); } Span destination = this.source.GetPixelRowSpan(y).Slice(this.bounds.X, this.bounds.Width); diff --git a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs index f4d55ebeb3..700314f26c 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs @@ -6,7 +6,6 @@ using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -43,7 +42,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization this.Options = options; this.maxColors = this.Options.MaxColors; - this.octree = new Octree(ImageMaths.GetBitsNeededForColorDepth(this.maxColors).Clamp(1, 8)); + this.octree = new Octree(Numerics.Clamp(ColorNumerics.GetBitsNeededForColorDepth(this.maxColors), 1, 8)); this.paletteOwner = configuration.MemoryAllocator.Allocate(this.maxColors, AllocationOptions.Clean); this.palette = default; this.pixelMap = default; @@ -96,7 +95,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization this.octree.Palletize(paletteSpan, this.maxColors, ref paletteIndex); // Length of reduced palette + transparency. - ReadOnlyMemory result = this.paletteOwner.Memory.Slice(0, Math.Min(paletteIndex + 2, QuantizerConstants.MaxColors)); + ReadOnlyMemory result = this.paletteOwner.Memory.Slice(0, Math.Min(paletteIndex + 2, this.maxColors)); this.pixelMap = new EuclideanPixelMap(this.Configuration, result); this.palette = result; diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizerOptions.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizerOptions.cs index d304810437..b983904d28 100644 --- a/src/ImageSharp/Processing/Processors/Quantization/QuantizerOptions.cs +++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizerOptions.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization public float DitherScale { get { return this.ditherScale; } - set { this.ditherScale = value.Clamp(QuantizerConstants.MinDitherScale, QuantizerConstants.MaxDitherScale); } + set { this.ditherScale = Numerics.Clamp(value, QuantizerConstants.MinDitherScale, QuantizerConstants.MaxDitherScale); } } /// @@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization public int MaxColors { get { return this.maxColors; } - set { this.maxColors = value.Clamp(QuantizerConstants.MinColors, QuantizerConstants.MaxColors); } + set { this.maxColors = Numerics.Clamp(value, QuantizerConstants.MinColors, QuantizerConstants.MaxColors); } } } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs index dd9c069385..675d6fe0d7 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs @@ -1,6 +1,8 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. +using System; +using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Binarization; @@ -48,7 +50,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms new BinaryThresholdProcessor(this.definition.Threshold).Execute(this.Configuration, temp, this.SourceRectangle); // Search for the first white pixels - rectangle = ImageMaths.GetFilteredBoundingRectangle(temp.Frames.RootFrame, 0); + rectangle = GetFilteredBoundingRectangle(temp.Frames.RootFrame, 0); } new CropProcessor(rectangle, this.Source.Size()).Execute(this.Configuration, this.Source, this.SourceRectangle); @@ -61,5 +63,136 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms { // All processing happens at the image level within BeforeImageApply(); } + + /// + /// Gets the bounding from the given points. + /// + /// + /// The designating the top left position. + /// + /// + /// The designating the bottom right position. + /// + /// + /// The bounding . + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Rectangle GetBoundingRectangle(Point topLeft, Point bottomRight) + => new Rectangle( + topLeft.X, + topLeft.Y, + bottomRight.X - topLeft.X, + bottomRight.Y - topLeft.Y); + + /// + /// Finds the bounding rectangle based on the first instance of any color component other + /// than the given one. + /// + /// The to search within. + /// The color component value to remove. + /// The channel to test against. + /// + /// The . + /// + private static Rectangle GetFilteredBoundingRectangle(ImageFrame bitmap, float componentValue, RgbaComponent channel = RgbaComponent.B) + { + int width = bitmap.Width; + int height = bitmap.Height; + Point topLeft = default; + Point bottomRight = default; + + Func, 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 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 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 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 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 = Numerics.Clamp(GetMaxY(bitmap) + 1, 0, height); + bottomRight.X = Numerics.Clamp(GetMaxX(bitmap) + 1, 0, width); + + return GetBoundingRectangle(topLeft, bottomRight); + } } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/ISwizzler.cs b/src/ImageSharp/Processing/Processors/Transforms/ISwizzler.cs new file mode 100644 index 0000000000..efa3e35a4b --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Transforms/ISwizzler.cs @@ -0,0 +1,23 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Processing.Processors.Transforms +{ + /// + /// Encapsulate an algorithm to swizzle pixels in an image. + /// + public interface ISwizzler + { + /// + /// Gets the size of the image after transformation. + /// + Size DestinationSize { get; } + + /// + /// Applies the swizzle transformation to a given point. + /// + /// Point to transform. + /// The transformed point. + Point Transform(Point point); + } +} diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs index cd7f46d926..c08f5d3d3b 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs @@ -80,8 +80,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms return; } - int yRadius = LinearTransformUtilities.GetSamplingRadius(in sampler, source.Height, destination.Height); - int xRadius = LinearTransformUtilities.GetSamplingRadius(in sampler, source.Width, destination.Width); + int yRadius = LinearTransformUtils.GetSamplingRadius(in sampler, source.Height, destination.Height); + int xRadius = LinearTransformUtils.GetSamplingRadius(in sampler, source.Width, destination.Width); var radialExtents = new Vector2(xRadius, yRadius); int yLength = (yRadius * 2) + 1; int xLength = (xRadius * 2) + 1; @@ -207,7 +207,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // Use the single precision position to calculate correct bounding pixels // otherwise we get rogue pixels outside of the bounds. var point = Vector2.Transform(new Vector2(x, y), this.matrix); - LinearTransformUtilities.Convolve( + LinearTransformUtils.Convolve( in this.sampler, point, sourceBuffer, diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtilities.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtils.cs similarity index 92% rename from src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtilities.cs rename to src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtils.cs index e198541474..e65b2cbe92 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtilities.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtils.cs @@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// /// Utility methods for affine and projective transforms. /// - internal static class LinearTransformUtilities + internal static class LinearTransformUtils { [MethodImpl(InliningOptions.ShortMethod)] internal static int GetSamplingRadius(in TResampler sampler, int sourceSize, int destinationSize) @@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms MathF.Floor(maxXY.X), MathF.Floor(maxXY.Y)); - sourceExtents = Vector4Utilities.FastClamp(sourceExtents, Vector4.Zero, maxSourceExtents); + sourceExtents = Numerics.Clamp(sourceExtents, Vector4.Zero, maxSourceExtents); int left = (int)sourceExtents.X; int top = (int)sourceExtents.Y; @@ -78,13 +78,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // Values are first premultiplied to prevent darkening of edge pixels. var current = sourcePixels[x, y].ToVector4(); - Vector4Utilities.Premultiply(ref current); + Numerics.Premultiply(ref current); sum += current * xWeight * yWeight; } } // Reverse the premultiplication - Vector4Utilities.UnPremultiply(ref sum); + Numerics.UnPremultiply(ref sum); targetRow[column] = sum; } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs index 4f75377964..f16a495b14 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs @@ -80,8 +80,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms return; } - int yRadius = LinearTransformUtilities.GetSamplingRadius(in sampler, source.Height, destination.Height); - int xRadius = LinearTransformUtilities.GetSamplingRadius(in sampler, source.Width, destination.Width); + int yRadius = LinearTransformUtils.GetSamplingRadius(in sampler, source.Height, destination.Height); + int xRadius = LinearTransformUtils.GetSamplingRadius(in sampler, source.Width, destination.Width); var radialExtents = new Vector2(xRadius, yRadius); int yLength = (yRadius * 2) + 1; int xLength = (xRadius * 2) + 1; @@ -139,7 +139,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms for (int x = 0; x < this.maxX; x++) { - Vector2 point = TransformUtilities.ProjectiveTransform2D(x, y, this.matrix); + Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, this.matrix); int px = (int)MathF.Round(point.X); int py = (int)MathF.Round(point.Y); @@ -206,8 +206,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms { // Use the single precision position to calculate correct bounding pixels // otherwise we get rogue pixels outside of the bounds. - Vector2 point = TransformUtilities.ProjectiveTransform2D(x, y, this.matrix); - LinearTransformUtilities.Convolve( + Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, this.matrix); + LinearTransformUtils.Convolve( in this.sampler, point, sourceBuffer, diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor.cs index 3b46040751..6414668476 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor.cs @@ -28,14 +28,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The source image size public RotateProcessor(float degrees, IResampler sampler, Size sourceSize) : this( - TransformUtilities.CreateRotationMatrixDegrees(degrees, sourceSize), + TransformUtils.CreateRotationMatrixDegrees(degrees, sourceSize), sampler, sourceSize) => this.Degrees = degrees; // Helper constructor private RotateProcessor(Matrix3x2 rotationMatrix, IResampler sampler, Size sourceSize) - : base(rotationMatrix, sampler, TransformUtilities.GetTransformedSize(sourceSize, rotationMatrix)) + : base(rotationMatrix, sampler, TransformUtils.GetTransformedSize(sourceSize, rotationMatrix)) { } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/SkewProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/SkewProcessor.cs index e5791b82f8..0d82d145e2 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/SkewProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/SkewProcessor.cs @@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The source image size public SkewProcessor(float degreesX, float degreesY, IResampler sampler, Size sourceSize) : this( - TransformUtilities.CreateSkewMatrixDegrees(degreesX, degreesY, sourceSize), + TransformUtils.CreateSkewMatrixDegrees(degreesX, degreesY, sourceSize), sampler, sourceSize) { @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // Helper constructor: private SkewProcessor(Matrix3x2 skewMatrix, IResampler sampler, Size sourceSize) - : base(skewMatrix, sampler, TransformUtilities.GetTransformedSize(sourceSize, skewMatrix)) + : base(skewMatrix, sampler, TransformUtils.GetTransformedSize(sourceSize, skewMatrix)) { } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/LanczosResampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/LanczosResampler.cs index 7aefd8f6f1..8742db580a 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/LanczosResampler.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/LanczosResampler.cs @@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms float radius = this.Radius; if (x < radius) { - return ImageMaths.SinC(x) * ImageMaths.SinC(x / radius); + return Numerics.SinC(x) * Numerics.SinC(x / radius); } return 0F; diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/WelchResampler.cs b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/WelchResampler.cs index 93c50af132..18859d1ada 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resamplers/WelchResampler.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resamplers/WelchResampler.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms if (x < 3F) { - return ImageMaths.SinC(x) * (1F - (x * x / 9F)); + return Numerics.SinC(x) * (1F - (x * x / 9F)); } return 0F; diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs index 35d1931d0e..66f885f23a 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs @@ -4,6 +4,11 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; +#if SUPPORTS_RUNTIME_INTRINSICS +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +#endif namespace SixLabors.ImageSharp.Processing.Processors.Transforms { @@ -61,28 +66,99 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The weighted sum [MethodImpl(InliningOptions.ShortMethod)] public Vector4 Convolve(Span rowSpan) - { - return this.ConvolveCore(ref rowSpan[this.StartIndex]); - } + => this.ConvolveCore(ref rowSpan[this.StartIndex]); [MethodImpl(InliningOptions.ShortMethod)] public Vector4 ConvolveCore(ref Vector4 rowStartRef) { - ref float horizontalValues = ref Unsafe.AsRef(this.bufferPtr); +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx2.IsSupported && Fma.IsSupported) + { + float* bufferStart = this.bufferPtr; + float* bufferEnd = bufferStart + (this.Length & ~3); + Vector256 result256_0 = Vector256.Zero; + Vector256 result256_1 = Vector256.Zero; + ReadOnlySpan maskBytes = new byte[] + { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, + }; + Vector256 mask = Unsafe.ReadUnaligned>(ref MemoryMarshal.GetReference(maskBytes)); - // Destination color components - Vector4 result = Vector4.Zero; + while (bufferStart < bufferEnd) + { + // It is important to use a single expression here so that the JIT will correctly use vfmadd231ps + // for the FMA operation, and execute it directly on the target register and reading directly from + // memory for the first parameter. This skips initializing a SIMD register, and an extra copy. + // The code below should compile in the following assembly on .NET 5 x64: + // + // vmovsd xmm2, [rax] ; load *(double*)bufferStart into xmm2 as [ab, _] + // vpermps ymm2, ymm1, ymm2 ; permute as a float YMM register to [a, a, a, a, b, b, b, b] + // vfmadd231ps ymm0, ymm2, [r8] ; result256_0 = FMA(pixels, factors) + result256_0 + // + // For tracking the codegen issue with FMA, see: https://github.com/dotnet/runtime/issues/12212. + // Additionally, we're also unrolling two computations per each loop iterations to leverage the + // fact that most CPUs have two ports to schedule multiply operations for FMA instructions. + result256_0 = Fma.MultiplyAdd( + Unsafe.As>(ref rowStartRef), + Avx2.PermuteVar8x32(Vector256.CreateScalarUnsafe(*(double*)bufferStart).AsSingle(), mask), + result256_0); - for (int i = 0; i < this.Length; i++) - { - float weight = Unsafe.Add(ref horizontalValues, i); + result256_1 = Fma.MultiplyAdd( + Unsafe.As>(ref Unsafe.Add(ref rowStartRef, 2)), + Avx2.PermuteVar8x32(Vector256.CreateScalarUnsafe(*(double*)(bufferStart + 2)).AsSingle(), mask), + result256_1); + + bufferStart += 4; + rowStartRef = ref Unsafe.Add(ref rowStartRef, 4); + } + + result256_0 = Avx.Add(result256_0, result256_1); + + if ((this.Length & 3) >= 2) + { + result256_0 = Fma.MultiplyAdd( + Unsafe.As>(ref rowStartRef), + Avx2.PermuteVar8x32(Vector256.CreateScalarUnsafe(*(double*)bufferStart).AsSingle(), mask), + result256_0); + + bufferStart += 2; + rowStartRef = ref Unsafe.Add(ref rowStartRef, 2); + } - // Vector4 v = offsetedRowSpan[i]; - Vector4 v = Unsafe.Add(ref rowStartRef, i); - result += v * weight; + Vector128 result128 = Sse.Add(result256_0.GetLower(), result256_0.GetUpper()); + + if ((this.Length & 1) != 0) + { + result128 = Fma.MultiplyAdd( + Unsafe.As>(ref rowStartRef), + Vector128.Create(*bufferStart), + result128); + } + + return *(Vector4*)&result128; } + else +#endif + { + // Destination color components + Vector4 result = Vector4.Zero; + float* bufferStart = this.bufferPtr; + float* bufferEnd = this.bufferPtr + this.Length; + + while (bufferStart < bufferEnd) + { + // Vector4 v = offsetedRowSpan[i]; + result += rowStartRef * *bufferStart; - return result; + bufferStart++; + rowStartRef = ref Unsafe.Add(ref rowStartRef, 1); + } + + return result; + } } /// @@ -91,9 +167,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// [MethodImpl(InliningOptions.ShortMethod)] internal ResizeKernel AlterLeftValue(int left) - { - return new ResizeKernel(left, this.bufferPtr, this.Length); - } + => new ResizeKernel(left, this.bufferPtr, this.Length); internal void Fill(Span values) { diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs index 7cbda76a54..ab6040c17b 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs @@ -132,7 +132,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // 'ratio' is a rational number. // Multiplying it by LCM(sourceSize, destSize)/sourceSize will result in a whole number "again". // This value is determining the length of the periods in repeating kernel map rows. - int period = ImageMaths.LeastCommonMultiple(sourceSize, destinationSize) / sourceSize; + int period = Numerics.LeastCommonMultiple(sourceSize, destinationSize) / sourceSize; // the center position at i == 0: double center0 = (ratio - 1) * 0.5; diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 576f97a938..3d69006836 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -26,6 +26,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.DestinationHeight = size.Height; this.DestinationRectangle = rectangle; this.Compand = options.Compand; + this.PremultiplyAlpha = options.PremultiplyAlpha; } /// @@ -53,6 +54,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// public bool Compand { get; } + /// + /// Gets a value indicating whether to premultiply the alpha (if it exists) during the resize operation. + /// + public bool PremultiplyAlpha { get; } + /// public override ICloningImageProcessor CreatePixelSpecificCloningProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) => new ResizeProcessor(configuration, this, source, sourceRectangle); diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs index 3c033d89e4..ec238608e9 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs @@ -21,6 +21,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly IResampler resampler; private readonly Rectangle destinationRectangle; private readonly bool compand; + private readonly bool premultiplyAlpha; private Image destination; public ResizeProcessor(Configuration configuration, ResizeProcessor definition, Image source, Rectangle sourceRectangle) @@ -30,6 +31,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.destinationHeight = definition.DestinationHeight; this.destinationRectangle = definition.DestinationRectangle; this.resampler = definition.Sampler; + this.premultiplyAlpha = definition.PremultiplyAlpha; this.compand = definition.Compand; } @@ -60,6 +62,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms Rectangle sourceRectangle = this.SourceRectangle; Rectangle destinationRectangle = this.destinationRectangle; bool compand = this.compand; + bool premultiplyAlpha = this.premultiplyAlpha; // Handle resize dimensions identical to the original if (source.Width == destination.Width @@ -128,7 +131,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms sourceRectangle, destinationRectangle, interest, - compand); + compand, + premultiplyAlpha); } } @@ -159,6 +163,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms in operation); } + private static PixelConversionModifiers GetModifiers(bool compand, bool premultiplyAlpha) + { + if (premultiplyAlpha) + { + return PixelConversionModifiers.Premultiply.ApplyCompanding(compand); + } + else + { + return PixelConversionModifiers.None.ApplyCompanding(compand); + } + } + private static void ApplyResizeFrameTransform( Configuration configuration, ImageFrame source, @@ -168,10 +184,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms Rectangle sourceRectangle, Rectangle destinationRectangle, Rectangle interest, - bool compand) + bool compand, + bool premultiplyAlpha) { - PixelConversionModifiers conversionModifiers = - PixelConversionModifiers.Premultiply.ApplyCompanding(compand); + PixelConversionModifiers conversionModifiers = GetModifiers(compand, premultiplyAlpha); Buffer2DRegion sourceRegion = source.PixelBuffer.GetRegion(sourceRectangle); diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs index 764349884d..e7207c7e63 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs @@ -105,14 +105,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms [MethodImpl(InliningOptions.ShortMethod)] public Span GetColumnSpan(int x, int startY) - { - return this.transposedFirstPassBuffer.GetRowSpan(x).Slice(startY - this.currentWindow.Min); - } + => this.transposedFirstPassBuffer.GetRowSpan(x).Slice(startY - this.currentWindow.Min); public void Initialize() - { - this.CalculateFirstPassValues(this.currentWindow); - } + => this.CalculateFirstPassValues(this.currentWindow); public void FillDestinationPixels(RowInterval rowInterval, Buffer2D destination) { diff --git a/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler,TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler,TPixel}.cs new file mode 100644 index 0000000000..aab17d2920 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler,TPixel}.cs @@ -0,0 +1,41 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Processing.Processors.Transforms +{ + internal class SwizzleProcessor : TransformProcessor + where TSwizzler : struct, ISwizzler + where TPixel : unmanaged, IPixel + { + private readonly TSwizzler swizzler; + private readonly Size destinationSize; + + public SwizzleProcessor(Configuration configuration, TSwizzler swizzler, Image source, Rectangle sourceRectangle) + : base(configuration, source, sourceRectangle) + { + this.swizzler = swizzler; + this.destinationSize = swizzler.DestinationSize; + } + + protected override Size GetDestinationSize() + => this.destinationSize; + + protected override void OnFrameApply(ImageFrame source, ImageFrame destination) + { + Point p = default; + Point newPoint; + for (p.Y = 0; p.Y < source.Height; p.Y++) + { + Span rowSpan = source.GetPixelRowSpan(p.Y); + for (p.X = 0; p.X < source.Width; p.X++) + { + newPoint = this.swizzler.Transform(p); + destination[newPoint.X, newPoint.Y] = rowSpan[p.X]; + } + } + } + } +} diff --git a/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler}.cs b/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler}.cs new file mode 100644 index 0000000000..d48257334d --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Transforms/SwizzleProcessor{TSwizzler}.cs @@ -0,0 +1,34 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Processing.Processors.Transforms +{ + /// + /// Defines a swizzle operation on an image. + /// + /// The swizzle function type. + public sealed class SwizzleProcessor : IImageProcessor + where TSwizzler : struct, ISwizzler + { + /// + /// Initializes a new instance of the class. + /// + /// The swizzler operation. + public SwizzleProcessor(TSwizzler swizzler) + { + this.Swizzler = swizzler; + } + + /// + /// Gets the swizzler operation. + /// + public TSwizzler Swizzler { get; } + + /// + public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle) + where TPixel : unmanaged, IPixel + => new SwizzleProcessor(configuration, this.Swizzler, source, sourceRectangle); + } +} diff --git a/src/ImageSharp/Processing/Processors/Transforms/TransformUtilities.cs b/src/ImageSharp/Processing/Processors/Transforms/TransformUtils.cs similarity index 99% rename from src/ImageSharp/Processing/Processors/Transforms/TransformUtilities.cs rename to src/ImageSharp/Processing/Processors/Transforms/TransformUtils.cs index 2b4c2ff149..a92aa54a59 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/TransformUtilities.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/TransformUtils.cs @@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// /// Contains utility methods for working with transforms. /// - internal static class TransformUtilities + internal static class TransformUtils { /// /// Returns a value that indicates whether the specified matrix is degenerate diff --git a/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs b/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs index d81ce2890b..d1469d43ef 100644 --- a/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs +++ b/src/ImageSharp/Processing/ProjectiveTransformBuilder.cs @@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Processing /// The amount to taper. /// The . public ProjectiveTransformBuilder PrependTaper(TaperSide side, TaperCorner corner, float fraction) - => this.Prepend(size => TransformUtilities.CreateTaperMatrix(size, side, corner, fraction)); + => this.Prepend(size => TransformUtils.CreateTaperMatrix(size, side, corner, fraction)); /// /// Appends a matrix that performs a tapering projective transform. @@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.Processing /// The amount to taper. /// The . public ProjectiveTransformBuilder AppendTaper(TaperSide side, TaperCorner corner, float fraction) - => this.Append(size => TransformUtilities.CreateTaperMatrix(size, side, corner, fraction)); + => this.Append(size => TransformUtils.CreateTaperMatrix(size, side, corner, fraction)); /// /// Prepends a centered rotation matrix using the given rotation in degrees. @@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Processing /// The amount of rotation, in radians. /// The . public ProjectiveTransformBuilder PrependRotationRadians(float radians) - => this.Prepend(size => new Matrix4x4(TransformUtilities.CreateRotationMatrixRadians(radians, size))); + => this.Prepend(size => new Matrix4x4(TransformUtils.CreateRotationMatrixRadians(radians, size))); /// /// Prepends a centered rotation matrix using the given rotation in degrees at the given origin. @@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp.Processing /// The amount of rotation, in radians. /// The . public ProjectiveTransformBuilder AppendRotationRadians(float radians) - => this.Append(size => new Matrix4x4(TransformUtilities.CreateRotationMatrixRadians(radians, size))); + => this.Append(size => new Matrix4x4(TransformUtils.CreateRotationMatrixRadians(radians, size))); /// /// Appends a centered rotation matrix using the given rotation in degrees at the given origin. @@ -168,7 +168,7 @@ namespace SixLabors.ImageSharp.Processing /// The Y angle, in radians. /// The . public ProjectiveTransformBuilder PrependSkewRadians(float radiansX, float radiansY) - => this.Prepend(size => new Matrix4x4(TransformUtilities.CreateSkewMatrixRadians(radiansX, radiansY, size))); + => this.Prepend(size => new Matrix4x4(TransformUtils.CreateSkewMatrixRadians(radiansX, radiansY, size))); /// /// Prepends a skew matrix using the given angles in degrees at the given origin. @@ -206,7 +206,7 @@ namespace SixLabors.ImageSharp.Processing /// The Y angle, in radians. /// The . public ProjectiveTransformBuilder AppendSkewRadians(float radiansX, float radiansY) - => this.Append(size => new Matrix4x4(TransformUtilities.CreateSkewMatrixRadians(radiansX, radiansY, size))); + => this.Append(size => new Matrix4x4(TransformUtils.CreateSkewMatrixRadians(radiansX, radiansY, size))); /// /// Appends a skew matrix using the given angles in degrees at the given origin. @@ -332,7 +332,7 @@ namespace SixLabors.ImageSharp.Processing private static void CheckDegenerate(Matrix4x4 matrix) { - if (TransformUtilities.IsDegenerate(matrix)) + if (TransformUtils.IsDegenerate(matrix)) { throw new DegenerateTransformException("Matrix is degenerate. Check input values."); } diff --git a/src/ImageSharp/Processing/ResizeOptions.cs b/src/ImageSharp/Processing/ResizeOptions.cs index bad8bd4554..4b31998da4 100644 --- a/src/ImageSharp/Processing/ResizeOptions.cs +++ b/src/ImageSharp/Processing/ResizeOptions.cs @@ -45,5 +45,11 @@ namespace SixLabors.ImageSharp.Processing /// Gets or sets the target rectangle to resize into. /// public Rectangle? TargetRectangle { get; set; } + + /// + /// Gets or sets a value indicating whether to premultiply + /// the alpha (if it exists) during the resize operation. + /// + public bool PremultiplyAlpha { get; set; } = true; } } diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props index 23a69362b0..ac5b635962 100644 --- a/tests/Directory.Build.props +++ b/tests/Directory.Build.props @@ -5,34 +5,20 @@ Directory.Build.props is automatically picked up and imported by Microsoft.Common.props. This file needs to exist, even if empty so that files in the parent directory tree, with the same name, are not imported - instead. The import fairly early and only Sdk.props will have been + instead. They import fairly early and only Sdk.props will have been imported beforehand. We also don't need to add ourselves to MSBuildAllProjects, as that is done by the file that imports us. --> - - $(MSBuildAllProjects);$(MSBuildThisFileDirectory)..\Directory.Build.props - tests - false - - - - $(MSBuildThisFileDirectory)..\shared-infrastructure\SixLabors.Tests.ruleset - - $(NoWarn);CS0618 - + + + - - - - - - - - - + + ..\ImageSharp.Tests.ruleset + diff --git a/tests/Directory.Build.targets b/tests/Directory.Build.targets index e9e93a855f..af86f49b09 100644 --- a/tests/Directory.Build.targets +++ b/tests/Directory.Build.targets @@ -5,39 +5,30 @@ Directory.Build.targets is automatically picked up and imported by Microsoft.Common.targets. This file needs to exist, even if empty so that files in the parent directory tree, with the same name, are not imported - instead. The import fairly late and most other props/targets will have + instead. They import fairly late and most other props/targets will have been imported beforehand. We also don't need to add ourselves to MSBuildAllProjects, as that is done by the file that imports us. --> - - $(MSBuildAllProjects);$(MSBuildThisFileDirectory)..\Directory.Build.targets - + + + - - - - - - - - + - + - - - - - + + + + - + + - - diff --git a/tests/ImageSharp.Benchmarks/BenchmarkBase.cs b/tests/ImageSharp.Benchmarks/BenchmarkBase.cs deleted file mode 100644 index 5573b1382b..0000000000 --- a/tests/ImageSharp.Benchmarks/BenchmarkBase.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.Benchmarks -{ - /// - /// The image benchmark base class. - /// - public abstract class BenchmarkBase - { - /// - /// Initializes a new instance of the class. - /// - protected BenchmarkBase() - { - // Add Image Formats - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/Codecs/DecodeBmp.cs b/tests/ImageSharp.Benchmarks/Codecs/DecodeBmp.cs index 58a97b65eb..338f221567 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/DecodeBmp.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/DecodeBmp.cs @@ -10,12 +10,13 @@ using SDSize = System.Drawing.Size; namespace SixLabors.ImageSharp.Benchmarks.Codecs { - [Config(typeof(Config.ShortClr))] - public class DecodeBmp : BenchmarkBase + [Config(typeof(Config.ShortMultiFramework))] + public class DecodeBmp { private byte[] bmpBytes; - private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage); + private string TestImageFullPath + => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage); [GlobalSetup] public void ReadImages() @@ -32,25 +33,17 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs [Benchmark(Baseline = true, Description = "System.Drawing Bmp")] public SDSize BmpSystemDrawing() { - using (var memoryStream = new MemoryStream(this.bmpBytes)) - { - using (var image = SDImage.FromStream(memoryStream)) - { - return image.Size; - } - } + using var memoryStream = new MemoryStream(this.bmpBytes); + using var image = SDImage.FromStream(memoryStream); + return image.Size; } [Benchmark(Description = "ImageSharp Bmp")] - public Size BmpCore() + public Size BmpImageSharp() { - using (var memoryStream = new MemoryStream(this.bmpBytes)) - { - using (var image = Image.Load(memoryStream)) - { - return new Size(image.Width, image.Height); - } - } + using var memoryStream = new MemoryStream(this.bmpBytes); + using var image = Image.Load(memoryStream); + return new Size(image.Width, image.Height); } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/DecodeFilteredPng.cs b/tests/ImageSharp.Benchmarks/Codecs/DecodeFilteredPng.cs index 3488d4405c..6517bf3c48 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/DecodeFilteredPng.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/DecodeFilteredPng.cs @@ -6,12 +6,11 @@ using System.Runtime.CompilerServices; using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tests; -using CoreSize = SixLabors.ImageSharp.Size; namespace SixLabors.ImageSharp.Benchmarks.Codecs { - [Config(typeof(Config.ShortClr))] - public class DecodeFilteredPng : BenchmarkBase + [Config(typeof(Config.ShortMultiFramework))] + public class DecodeFilteredPng { private byte[] filter0; private byte[] filter1; @@ -30,44 +29,33 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs } [Benchmark(Baseline = true, Description = "None-filtered PNG file")] - public CoreSize PngFilter0() - { - return LoadPng(this.filter0); - } + public Size PngFilter0() + => LoadPng(this.filter0); [Benchmark(Description = "Sub-filtered PNG file")] - public CoreSize PngFilter1() - { - return LoadPng(this.filter1); - } + public Size PngFilter1() + => LoadPng(this.filter1); [Benchmark(Description = "Up-filtered PNG file")] - public CoreSize PngFilter2() - { - return LoadPng(this.filter2); - } + public Size PngFilter2() + => LoadPng(this.filter2); [Benchmark(Description = "Average-filtered PNG file")] - public CoreSize PngFilter3() - { - return LoadPng(this.filter3); - } + public Size PngFilter3() + => LoadPng(this.filter3); [Benchmark(Description = "Paeth-filtered PNG file")] - public CoreSize PngFilter4() - { - return LoadPng(this.filter4); - } + public Size PngFilter4() + => LoadPng(this.filter4); [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static CoreSize LoadPng(byte[] bytes) + private static Size LoadPng(byte[] bytes) { - using (var image = Image.Load(bytes)) - { - return image.Size(); - } + using var image = Image.Load(bytes); + return image.Size(); } - private static string TestImageFullPath(string path) => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, path); + private static string TestImageFullPath(string path) + => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, path); } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Benchmarks/Codecs/DecodeGif.cs b/tests/ImageSharp.Benchmarks/Codecs/DecodeGif.cs index f4cfddd885..3add96a68b 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/DecodeGif.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/DecodeGif.cs @@ -10,12 +10,13 @@ using SDSize = System.Drawing.Size; namespace SixLabors.ImageSharp.Benchmarks.Codecs { - [Config(typeof(Config.ShortClr))] - public class DecodeGif : BenchmarkBase + [Config(typeof(Config.ShortMultiFramework))] + public class DecodeGif { private byte[] gifBytes; - private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage); + private string TestImageFullPath + => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage); [GlobalSetup] public void ReadImages() @@ -32,25 +33,17 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs [Benchmark(Baseline = true, Description = "System.Drawing Gif")] public SDSize GifSystemDrawing() { - using (var memoryStream = new MemoryStream(this.gifBytes)) - { - using (var image = SDImage.FromStream(memoryStream)) - { - return image.Size; - } - } + using var memoryStream = new MemoryStream(this.gifBytes); + using var image = SDImage.FromStream(memoryStream); + return image.Size; } [Benchmark(Description = "ImageSharp Gif")] - public Size GifCore() + public Size GifImageSharp() { - using (var memoryStream = new MemoryStream(this.gifBytes)) - { - using (var image = Image.Load(memoryStream)) - { - return new Size(image.Width, image.Height); - } - } + using var memoryStream = new MemoryStream(this.gifBytes); + using var image = Image.Load(memoryStream); + return new Size(image.Width, image.Height); } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/DecodePng.cs b/tests/ImageSharp.Benchmarks/Codecs/DecodePng.cs index 57ee308e7c..66feb801fc 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/DecodePng.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/DecodePng.cs @@ -10,12 +10,13 @@ using SDSize = System.Drawing.Size; namespace SixLabors.ImageSharp.Benchmarks.Codecs { - [Config(typeof(Config.ShortClr))] - public class DecodePng : BenchmarkBase + [Config(typeof(Config.ShortMultiFramework))] + public class DecodePng { private byte[] pngBytes; - private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage); + private string TestImageFullPath + => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage); [Params(TestImages.Png.Splash)] public string TestImage { get; set; } @@ -32,25 +33,17 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs [Benchmark(Baseline = true, Description = "System.Drawing Png")] public SDSize PngSystemDrawing() { - using (var memoryStream = new MemoryStream(this.pngBytes)) - { - using (var image = SDImage.FromStream(memoryStream)) - { - return image.Size; - } - } + using var memoryStream = new MemoryStream(this.pngBytes); + using var image = SDImage.FromStream(memoryStream); + return image.Size; } [Benchmark(Description = "ImageSharp Png")] - public Size PngCore() + public Size PngImageSharp() { - using (var memoryStream = new MemoryStream(this.pngBytes)) - { - using (var image = Image.Load(memoryStream)) - { - return image.Size(); - } - } + using var memoryStream = new MemoryStream(this.pngBytes); + using var image = Image.Load(memoryStream); + return image.Size(); } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/DecodeTga.cs b/tests/ImageSharp.Benchmarks/Codecs/DecodeTga.cs index 4695d7ca49..c73fcc17bf 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/DecodeTga.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/DecodeTga.cs @@ -5,7 +5,6 @@ using System.Buffers; using System.IO; using System.Threading; using BenchmarkDotNet.Attributes; - using ImageMagick; using Pfim; using SixLabors.ImageSharp.Formats.Tga; @@ -14,8 +13,8 @@ using SixLabors.ImageSharp.Tests; namespace SixLabors.ImageSharp.Benchmarks.Codecs { - [Config(typeof(Config.ShortClr))] - public class DecodeTga : BenchmarkBase + [Config(typeof(Config.ShortMultiFramework))] + public class DecodeTga { private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage); @@ -28,36 +27,28 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs [GlobalSetup] public void SetupData() - { - this.data = File.ReadAllBytes(this.TestImageFullPath); - } + => this.data = File.ReadAllBytes(this.TestImageFullPath); [Benchmark(Baseline = true, Description = "ImageMagick Tga")] public int TgaImageMagick() { var settings = new MagickReadSettings { Format = MagickFormat.Tga }; - using (var image = new MagickImage(new MemoryStream(this.data), settings)) - { - return image.Width; - } + using var image = new MagickImage(new MemoryStream(this.data), settings); + return image.Width; } [Benchmark(Description = "ImageSharp Tga")] - public int TgaCore() + public int TgaImageSharp() { - using (var image = Image.Load(this.data, new TgaDecoder())) - { - return image.Width; - } + using var image = Image.Load(this.data, new TgaDecoder()); + return image.Width; } [Benchmark(Description = "Pfim Tga")] public int TgaPfim() { - using (var image = Targa.Create(this.data, this.pfimConfig)) - { - return image.Width; - } + using var image = Targa.Create(this.data, this.pfimConfig); + return image.Width; } private class PfimAllocator : IImageAllocator @@ -65,10 +56,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs private int rented; private readonly ArrayPool shared = ArrayPool.Shared; - public byte[] Rent(int size) - { - return this.shared.Rent(size); - } + public byte[] Rent(int size) => this.shared.Rent(size); public void Return(byte[] data) { diff --git a/tests/ImageSharp.Benchmarks/Codecs/EncodeBmp.cs b/tests/ImageSharp.Benchmarks/Codecs/EncodeBmp.cs index c816aee2e9..c9665457f6 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/EncodeBmp.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/EncodeBmp.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System.Drawing.Imaging; @@ -10,8 +10,8 @@ using SDImage = System.Drawing.Image; namespace SixLabors.ImageSharp.Benchmarks.Codecs { - [Config(typeof(Config.ShortClr))] - public class EncodeBmp : BenchmarkBase + [Config(typeof(Config.ShortMultiFramework))] + public class EncodeBmp { private Stream bmpStream; private SDImage bmpDrawing; @@ -33,6 +33,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs public void Cleanup() { this.bmpStream.Dispose(); + this.bmpStream = null; this.bmpCore.Dispose(); this.bmpDrawing.Dispose(); } @@ -40,19 +41,15 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs [Benchmark(Baseline = true, Description = "System.Drawing Bmp")] public void BmpSystemDrawing() { - using (var memoryStream = new MemoryStream()) - { - this.bmpDrawing.Save(memoryStream, ImageFormat.Bmp); - } + using var memoryStream = new MemoryStream(); + this.bmpDrawing.Save(memoryStream, ImageFormat.Bmp); } [Benchmark(Description = "ImageSharp Bmp")] - public void BmpCore() + public void BmpImageSharp() { - using (var memoryStream = new MemoryStream()) - { - this.bmpCore.SaveAsBmp(memoryStream); - } + using var memoryStream = new MemoryStream(); + this.bmpCore.SaveAsBmp(memoryStream); } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Benchmarks/Codecs/EncodeBmpMultiple.cs b/tests/ImageSharp.Benchmarks/Codecs/EncodeBmpMultiple.cs index a7ffbe46ee..60dbdd666f 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/EncodeBmpMultiple.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/EncodeBmpMultiple.cs @@ -8,29 +8,25 @@ using SixLabors.ImageSharp.Formats.Bmp; namespace SixLabors.ImageSharp.Benchmarks.Codecs { - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.ShortMultiFramework))] public class EncodeBmpMultiple : MultiImageBenchmarkBase.WithImagesPreloaded { protected override IEnumerable InputImageSubfoldersOrFiles => new[] { "Bmp/", "Jpg/baseline" }; [Benchmark(Description = "EncodeBmpMultiple - ImageSharp")] public void EncodeBmpImageSharp() - { - this.ForEachImageSharpImage((img, ms) => + => this.ForEachImageSharpImage((img, ms) => { img.Save(ms, new BmpEncoder()); return null; }); - } [Benchmark(Baseline = true, Description = "EncodeBmpMultiple - System.Drawing")] public void EncodeBmpSystemDrawing() - { - this.ForEachSystemDrawingImage((img, ms) => + => this.ForEachSystemDrawingImage((img, ms) => { img.Save(ms, ImageFormat.Bmp); return null; }); - } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/EncodeGif.cs b/tests/ImageSharp.Benchmarks/Codecs/EncodeGif.cs index b6ce67bfdd..26d5c4bc10 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/EncodeGif.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/EncodeGif.cs @@ -13,8 +13,8 @@ using SDImage = System.Drawing.Image; namespace SixLabors.ImageSharp.Benchmarks.Codecs { - [Config(typeof(Config.ShortClr))] - public class EncodeGif : BenchmarkBase + [Config(typeof(Config.ShortMultiFramework))] + public class EncodeGif { // System.Drawing needs this. private Stream bmpStream; @@ -46,6 +46,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs public void Cleanup() { this.bmpStream.Dispose(); + this.bmpStream = null; this.bmpCore.Dispose(); this.bmpDrawing.Dispose(); } @@ -53,19 +54,15 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs [Benchmark(Baseline = true, Description = "System.Drawing Gif")] public void GifSystemDrawing() { - using (var memoryStream = new MemoryStream()) - { - this.bmpDrawing.Save(memoryStream, ImageFormat.Gif); - } + using var memoryStream = new MemoryStream(); + this.bmpDrawing.Save(memoryStream, ImageFormat.Gif); } [Benchmark(Description = "ImageSharp Gif")] - public void GifCore() + public void GifImageSharp() { - using (var memoryStream = new MemoryStream()) - { - this.bmpCore.SaveAsGif(memoryStream, this.encoder); - } + using var memoryStream = new MemoryStream(); + this.bmpCore.SaveAsGif(memoryStream, this.encoder); } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/EncodeGifMultiple.cs b/tests/ImageSharp.Benchmarks/Codecs/EncodeGifMultiple.cs index 179e6946a8..6fea9315a4 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/EncodeGifMultiple.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/EncodeGifMultiple.cs @@ -10,7 +10,7 @@ using SixLabors.ImageSharp.Processing.Processors.Quantization; namespace SixLabors.ImageSharp.Benchmarks.Codecs { - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.ShortMultiFramework))] public class EncodeGifMultiple : MultiImageBenchmarkBase.WithImagesPreloaded { [Params(InputImageCategory.AllImages)] @@ -20,8 +20,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs [Benchmark(Description = "EncodeGifMultiple - ImageSharp")] public void EncodeGifImageSharp() - { - this.ForEachImageSharpImage((img, ms) => + => this.ForEachImageSharpImage((img, ms) => { // Try to get as close to System.Drawing's output as possible var options = new GifEncoder @@ -32,16 +31,13 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs img.Save(ms, options); return null; }); - } [Benchmark(Baseline = true, Description = "EncodeGifMultiple - System.Drawing")] public void EncodeGifSystemDrawing() - { - this.ForEachSystemDrawingImage((img, ms) => + => this.ForEachSystemDrawingImage((img, ms) => { img.Save(ms, ImageFormat.Gif); return null; }); - } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/EncodeIndexedPng.cs b/tests/ImageSharp.Benchmarks/Codecs/EncodeIndexedPng.cs index b3113e6d78..de8d412029 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/EncodeIndexedPng.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/EncodeIndexedPng.cs @@ -8,15 +8,15 @@ using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Quantization; using SixLabors.ImageSharp.Tests; -using CoreImage = SixLabors.ImageSharp.Image; namespace SixLabors.ImageSharp.Benchmarks.Codecs { /// - /// Benchmarks saving png files using different quantizers. System.Drawing cannot save indexed png files so we cannot compare. + /// Benchmarks saving png files using different quantizers. + /// System.Drawing cannot save indexed png files so we cannot compare. /// - [Config(typeof(Config.ShortClr))] - public class EncodeIndexedPng : BenchmarkBase + [Config(typeof(Config.ShortMultiFramework))] + public class EncodeIndexedPng { // System.Drawing needs this. private Stream bmpStream; @@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs if (this.bmpStream == null) { this.bmpStream = File.OpenRead(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Bmp.Car)); - this.bmpCore = CoreImage.Load(this.bmpStream); + this.bmpCore = Image.Load(this.bmpStream); this.bmpStream.Position = 0; } } @@ -37,67 +37,56 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs public void Cleanup() { this.bmpStream.Dispose(); + this.bmpStream = null; this.bmpCore.Dispose(); } [Benchmark(Baseline = true, Description = "ImageSharp Octree Png")] public void PngCoreOctree() { - using (var memoryStream = new MemoryStream()) - { - var options = new PngEncoder { Quantizer = KnownQuantizers.Octree }; - this.bmpCore.SaveAsPng(memoryStream, options); - } + using var memoryStream = new MemoryStream(); + var options = new PngEncoder { Quantizer = KnownQuantizers.Octree }; + this.bmpCore.SaveAsPng(memoryStream, options); } [Benchmark(Description = "ImageSharp Octree NoDither Png")] public void PngCoreOctreeNoDither() { - using (var memoryStream = new MemoryStream()) - { - var options = new PngEncoder { Quantizer = new OctreeQuantizer(new QuantizerOptions { Dither = null }) }; - this.bmpCore.SaveAsPng(memoryStream, options); - } + using var memoryStream = new MemoryStream(); + var options = new PngEncoder { Quantizer = new OctreeQuantizer(new QuantizerOptions { Dither = null }) }; + this.bmpCore.SaveAsPng(memoryStream, options); } [Benchmark(Description = "ImageSharp Palette Png")] public void PngCorePalette() { - using (var memoryStream = new MemoryStream()) - { - var options = new PngEncoder { Quantizer = KnownQuantizers.WebSafe }; - this.bmpCore.SaveAsPng(memoryStream, options); - } + using var memoryStream = new MemoryStream(); + var options = new PngEncoder { Quantizer = KnownQuantizers.WebSafe }; + this.bmpCore.SaveAsPng(memoryStream, options); } [Benchmark(Description = "ImageSharp Palette NoDither Png")] public void PngCorePaletteNoDither() { - using (var memoryStream = new MemoryStream()) - { - var options = new PngEncoder { Quantizer = new WebSafePaletteQuantizer(new QuantizerOptions { Dither = null }) }; - this.bmpCore.SaveAsPng(memoryStream, options); - } + using var memoryStream = new MemoryStream(); + var options = new PngEncoder { Quantizer = new WebSafePaletteQuantizer(new QuantizerOptions { Dither = null }) }; + this.bmpCore.SaveAsPng(memoryStream, options); } [Benchmark(Description = "ImageSharp Wu Png")] public void PngCoreWu() { - using (var memoryStream = new MemoryStream()) - { - var options = new PngEncoder { Quantizer = KnownQuantizers.Wu }; - this.bmpCore.SaveAsPng(memoryStream, options); - } + using var memoryStream = new MemoryStream(); + var options = new PngEncoder { Quantizer = KnownQuantizers.Wu }; + this.bmpCore.SaveAsPng(memoryStream, options); } [Benchmark(Description = "ImageSharp Wu NoDither Png")] public void PngCoreWuNoDither() { - using (var memoryStream = new MemoryStream()) - { - var options = new PngEncoder { Quantizer = new WuQuantizer(new QuantizerOptions { Dither = null }) }; - this.bmpCore.SaveAsPng(memoryStream, options); - } + using var memoryStream = new MemoryStream(); + var options = new PngEncoder { Quantizer = new WuQuantizer(new QuantizerOptions { Dither = null }) }; + this.bmpCore.SaveAsPng(memoryStream, options); } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/EncodePng.cs b/tests/ImageSharp.Benchmarks/Codecs/EncodePng.cs index 81b884b754..c628b71096 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/EncodePng.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/EncodePng.cs @@ -11,8 +11,8 @@ using SDImage = System.Drawing.Image; namespace SixLabors.ImageSharp.Benchmarks.Codecs { - [Config(typeof(Config.ShortClr))] - public class EncodePng : BenchmarkBase + [Config(typeof(Config.ShortMultiFramework))] + public class EncodePng { // System.Drawing needs this. private Stream bmpStream; @@ -39,6 +39,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs public void Cleanup() { this.bmpStream.Dispose(); + this.bmpStream = null; this.bmpCore.Dispose(); this.bmpDrawing.Dispose(); } @@ -46,20 +47,16 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs [Benchmark(Baseline = true, Description = "System.Drawing Png")] public void PngSystemDrawing() { - using (var memoryStream = new MemoryStream()) - { - this.bmpDrawing.Save(memoryStream, ImageFormat.Png); - } + using var memoryStream = new MemoryStream(); + this.bmpDrawing.Save(memoryStream, ImageFormat.Png); } [Benchmark(Description = "ImageSharp Png")] public void PngCore() { - using (var memoryStream = new MemoryStream()) - { - var encoder = new PngEncoder { FilterMethod = PngFilterMethod.None }; - this.bmpCore.SaveAsPng(memoryStream, encoder); - } + using var memoryStream = new MemoryStream(); + var encoder = new PngEncoder { FilterMethod = PngFilterMethod.None }; + this.bmpCore.SaveAsPng(memoryStream, encoder); } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/EncodeTga.cs b/tests/ImageSharp.Benchmarks/Codecs/EncodeTga.cs index 37cfa314c9..bcb015e570 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/EncodeTga.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/EncodeTga.cs @@ -2,23 +2,21 @@ // Licensed under the Apache License, Version 2.0. using System.IO; - using BenchmarkDotNet.Attributes; - using ImageMagick; - using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tests; namespace SixLabors.ImageSharp.Benchmarks.Codecs { - [Config(typeof(Config.ShortClr))] - public class EncodeTga : BenchmarkBase + [Config(typeof(Config.ShortMultiFramework))] + public class EncodeTga { private MagickImage tgaMagick; private Image tgaCore; - private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage); + private string TestImageFullPath + => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage); [Params(TestImages.Tga.Bit24BottomLeft)] public string TestImage { get; set; } @@ -33,22 +31,26 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs } } + [GlobalCleanup] + public void Cleanup() + { + this.tgaCore.Dispose(); + this.tgaCore = null; + this.tgaMagick.Dispose(); + } + [Benchmark(Baseline = true, Description = "Magick Tga")] - public void BmpSystemDrawing() + public void BmpImageMagick() { - using (var memoryStream = new MemoryStream()) - { - this.tgaMagick.Write(memoryStream, MagickFormat.Tga); - } + using var memoryStream = new MemoryStream(); + this.tgaMagick.Write(memoryStream, MagickFormat.Tga); } [Benchmark(Description = "ImageSharp Tga")] - public void BmpCore() + public void BmpImageSharp() { - using (var memoryStream = new MemoryStream()) - { - this.tgaCore.SaveAsBmp(memoryStream); - } + using var memoryStream = new MemoryStream(); + this.tgaCore.SaveAsBmp(memoryStream); } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/GetSetPixel.cs b/tests/ImageSharp.Benchmarks/Codecs/GetSetPixel.cs deleted file mode 100644 index 197f0804d2..0000000000 --- a/tests/ImageSharp.Benchmarks/Codecs/GetSetPixel.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using System.Drawing; -using BenchmarkDotNet.Attributes; -using SixLabors.ImageSharp.PixelFormats; - -namespace SixLabors.ImageSharp.Benchmarks.Codecs -{ - public class GetSetPixel : BenchmarkBase - { - [Benchmark(Baseline = true, Description = "System.Drawing GetSet pixel")] - public System.Drawing.Color ResizeSystemDrawing() - { - using (var source = new Bitmap(400, 400)) - { - source.SetPixel(200, 200, System.Drawing.Color.White); - return source.GetPixel(200, 200); - } - } - - [Benchmark(Description = "ImageSharp GetSet pixel")] - public Rgba32 ResizeCore() - { - using (var image = new Image(400, 400)) - { - image[200, 200] = Color.White; - return image[200, 200]; - } - } - } -} diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_AddInPlace.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_AddInPlace.cs new file mode 100644 index 0000000000..61fb2745b9 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_AddInPlace.cs @@ -0,0 +1,21 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.Formats.Jpeg.Components; + +namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations +{ + [Config(typeof(Config.HwIntrinsics_SSE_AVX))] + public class Block8x8F_AddInPlace + { + [Benchmark] + public float AddInplace() + { + float f = 42F; + Block8x8F b = default; + b.AddInPlace(f); + return f; + } + } +} diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs new file mode 100644 index 0000000000..0d1e67112f --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs @@ -0,0 +1,37 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.Formats.Jpeg.Components; + +namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations +{ + [Config(typeof(Config.HwIntrinsics_SSE_AVX))] + public class Block8x8F_MultiplyInPlaceBlock + { + private static readonly Block8x8F Source = Create8x8FloatData(); + + [Benchmark] + public void MultiplyInPlaceBlock() + { + Block8x8F dest = default; + Source.MultiplyInPlace(ref dest); + } + + private static Block8x8F Create8x8FloatData() + { + var result = new float[64]; + for (int i = 0; i < 8; i++) + { + for (int j = 0; j < 8; j++) + { + result[(i * 8) + j] = (i * 10) + j; + } + } + + var source = default(Block8x8F); + source.LoadFrom(result); + return source; + } + } +} diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceScalar.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceScalar.cs new file mode 100644 index 0000000000..31a6ca713f --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceScalar.cs @@ -0,0 +1,21 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.Formats.Jpeg.Components; + +namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations +{ + [Config(typeof(Config.HwIntrinsics_SSE_AVX))] + public class Block8x8F_MultiplyInPlaceScalar + { + [Benchmark] + public float MultiplyInPlaceScalar() + { + float f = 42F; + Block8x8F b = default; + b.MultiplyInPlace(f); + return f; + } + } +} diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Scale16X16To8X8.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Scale16X16To8X8.cs new file mode 100644 index 0000000000..ebd3e40130 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Scale16X16To8X8.cs @@ -0,0 +1,38 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.Formats.Jpeg.Components; + +namespace SixLabors.ImageSharp.Benchmarks.Format.Jpeg.Components +{ + [Config(typeof(Config.HwIntrinsics_SSE_AVX))] + public class Block8x8F_Scale16X16To8X8 + { + private Block8x8F source; + private readonly Block8x8F[] target = new Block8x8F[4]; + + [GlobalSetup] + public void Setup() + { + var random = new Random(); + + float[] f = new float[8 * 8]; + for (int i = 0; i < f.Length; i++) + { + f[i] = (float)random.NextDouble(); + } + + for (int i = 0; i < 4; i++) + { + this.target[i] = Block8x8F.Load(f); + } + + this.source = Block8x8F.Load(f); + } + + [Benchmark] + public void Scale16X16To8X8() => Block8x8F.Scale16X16To8X8(ref this.source, this.target); + } +} diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Transpose.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Transpose.cs new file mode 100644 index 0000000000..1d103cd1a0 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_Transpose.cs @@ -0,0 +1,37 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.Formats.Jpeg.Components; + +namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations +{ + [Config(typeof(Config.HwIntrinsics_SSE_AVX))] + public class Block8x8F_Transpose + { + private static readonly Block8x8F Source = Create8x8FloatData(); + + [Benchmark] + public void TransposeInto() + { + var dest = default(Block8x8F); + Source.TransposeInto(ref dest); + } + + private static Block8x8F Create8x8FloatData() + { + var result = new float[64]; + for (int i = 0; i < 8; i++) + { + for (int j = 0; j < 8; j++) + { + result[(i * 8) + j] = (i * 10) + j; + } + } + + var source = default(Block8x8F); + source.LoadFrom(result); + return source; + } + } +} diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/CmykColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/CmykColorConversion.cs new file mode 100644 index 0000000000..d17882adf6 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/CmykColorConversion.cs @@ -0,0 +1,41 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters; + +namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg +{ + [Config(typeof(Config.ShortMultiFramework))] + public class CmykColorConversion : ColorConversionBenchmark + { + public CmykColorConversion() + : base(4) + { + } + + [Benchmark(Baseline = true)] + public void Scalar() + { + var values = new JpegColorConverter.ComponentValues(this.Input, 0); + + new JpegColorConverter.FromCmykBasic(8).ConvertToRgba(values, this.Output); + } + + [Benchmark] + public void SimdVector8() + { + var values = new JpegColorConverter.ComponentValues(this.Input, 0); + + new JpegColorConverter.FromCmykVector8(8).ConvertToRgba(values, this.Output); + } + + [Benchmark] + public void SimdVectorAvx2() + { + var values = new JpegColorConverter.ComponentValues(this.Input, 0); + + new JpegColorConverter.FromCmykAvx2(8).ConvertToRgba(values, this.Output); + } + } +} diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversionBenchmark.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversionBenchmark.cs new file mode 100644 index 0000000000..e93ad474b7 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversionBenchmark.cs @@ -0,0 +1,64 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.Memory; + +namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg +{ + public abstract class ColorConversionBenchmark + { + private readonly int componentCount; + + public const int Count = 128; + + protected ColorConversionBenchmark(int componentCount) + => this.componentCount = componentCount; + + protected Buffer2D[] Input { get; private set; } + + protected Vector4[] Output { get; private set; } + + [GlobalSetup] + public void Setup() + { + this.Input = CreateRandomValues(this.componentCount, Count); + this.Output = new Vector4[Count]; + } + + [GlobalCleanup] + public void Cleanup() + { + foreach (Buffer2D buffer in this.Input) + { + buffer.Dispose(); + } + } + + private static Buffer2D[] CreateRandomValues( + int componentCount, + int inputBufferLength, + float minVal = 0f, + float maxVal = 255f) + { + var rnd = new Random(42); + var buffers = new Buffer2D[componentCount]; + for (int i = 0; i < componentCount; i++) + { + var values = new float[inputBufferLength]; + + for (int j = 0; j < inputBufferLength; j++) + { + values[j] = ((float)rnd.NextDouble() * (maxVal - minVal)) + minVal; + } + + // no need to dispose when buffer is not array owner + buffers[i] = Configuration.Default.MemoryAllocator.Allocate2D(values.Length, 1); + } + + return buffers; + } + } +} diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs index 0e68af87a9..68a102e3ce 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpegParseStreamOnly.cs @@ -3,7 +3,6 @@ using System.IO; using BenchmarkDotNet.Attributes; - using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Tests; @@ -11,7 +10,7 @@ using SDSize = System.Drawing.Size; namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.ShortMultiFramework))] public class DecodeJpegParseStreamOnly { [Params(TestImages.Jpeg.BenchmarkSuite.Lake_Small444YCbCr)] @@ -23,9 +22,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg [GlobalSetup] public void Setup() - { - this.jpegBytes = File.ReadAllBytes(this.TestImageFullPath); - } + => this.jpegBytes = File.ReadAllBytes(this.TestImageFullPath); [Benchmark(Baseline = true, Description = "System.Drawing FULL")] public SDSize JpegSystemDrawing() diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_Aggregate.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_Aggregate.cs index b92a66ebd2..cabc0ed917 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_Aggregate.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_Aggregate.cs @@ -2,22 +2,20 @@ // Licensed under the Apache License, Version 2.0. using System.Collections.Generic; - using BenchmarkDotNet.Attributes; - using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tests; - using SDImage = System.Drawing.Image; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { /// - /// An expensive Jpeg benchmark, running on a wide range of input images, showing aggregate results. + /// An expensive Jpeg benchmark, running on a wide range of input images, + /// showing aggregate results. /// - [Config(typeof(MultiImageBenchmarkBase.Config))] + [Config(typeof(Config.ShortMultiFramework))] public class DecodeJpeg_Aggregate : MultiImageBenchmarkBase { protected override IEnumerable InputImageSubfoldersOrFiles => @@ -35,14 +33,10 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg [Benchmark] public void ImageSharp() - { - this.ForEachStream(ms => Image.Load(ms, new JpegDecoder())); - } + => this.ForEachStream(ms => Image.Load(ms, new JpegDecoder())); [Benchmark(Baseline = true)] public void SystemDrawing() - { - this.ForEachStream(SDImage.FromStream); - } + => this.ForEachStream(SDImage.FromStream); } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs index 4b1ee81a4c..b0ac1c0fc0 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs @@ -3,11 +3,6 @@ using System.IO; using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Configs; -using BenchmarkDotNet.Diagnosers; -using BenchmarkDotNet.Environments; -using BenchmarkDotNet.Jobs; - using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tests; @@ -20,26 +15,9 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg /// /// Image-specific Jpeg benchmarks /// - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.ShortMultiFramework))] public class DecodeJpeg_ImageSpecific { - public class Config : ManualConfig - { - public Config() - { - this.Add(MemoryDiagnoser.Default); - } - - public class ShortClr : Benchmarks.Config - { - public ShortClr() - { - // Job.Default.With(ClrRuntime.Net472).WithLaunchCount(1).WithWarmupCount(2).WithIterationCount(3), - this.Add(Job.Default.With(CoreRuntime.Core31).WithLaunchCount(1).WithWarmupCount(2).WithIterationCount(3)); - } - } - } - private byte[] jpegBytes; private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage); diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpeg.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpeg.cs index 4c326fb3ac..5a9ceea946 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpeg.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpeg.cs @@ -1,35 +1,35 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. +using System.Drawing.Imaging; +using System.IO; using BenchmarkDotNet.Attributes; - using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests; +using SDImage = System.Drawing.Image; namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { - using System.Drawing; - using System.Drawing.Imaging; - using System.IO; - using SixLabors.ImageSharp.Tests; - using CoreImage = SixLabors.ImageSharp.Image; - - public class EncodeJpeg : BenchmarkBase + public class EncodeJpeg { // System.Drawing needs this. private Stream bmpStream; - private Image bmpDrawing; + private SDImage bmpDrawing; private Image bmpCore; + private MemoryStream destinationStream; [GlobalSetup] public void ReadImages() { if (this.bmpStream == null) { - const string TestImage = TestImages.Bmp.Car; + const string TestImage = TestImages.Jpeg.BenchmarkSuite.Jpeg420Exif_MidSizeYCbCr; this.bmpStream = File.OpenRead(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImage)); - this.bmpCore = CoreImage.Load(this.bmpStream); + this.bmpCore = Image.Load(this.bmpStream); + this.bmpCore.Metadata.ExifProfile = null; this.bmpStream.Position = 0; - this.bmpDrawing = Image.FromStream(this.bmpStream); + this.bmpDrawing = SDImage.FromStream(this.bmpStream); + this.destinationStream = new MemoryStream(); } } @@ -37,6 +37,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg public void Cleanup() { this.bmpStream.Dispose(); + this.bmpStream = null; this.bmpCore.Dispose(); this.bmpDrawing.Dispose(); } @@ -44,19 +45,15 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg [Benchmark(Baseline = true, Description = "System.Drawing Jpeg")] public void JpegSystemDrawing() { - using (var stream = new MemoryStream()) - { - this.bmpDrawing.Save(stream, ImageFormat.Jpeg); - } + this.bmpDrawing.Save(this.destinationStream, ImageFormat.Jpeg); + this.destinationStream.Seek(0, SeekOrigin.Begin); } [Benchmark(Description = "ImageSharp Jpeg")] public void JpegCore() { - using (var stream = new MemoryStream()) - { - this.bmpCore.SaveAsJpeg(stream); - } + this.bmpCore.SaveAsJpeg(this.destinationStream); + this.destinationStream.Seek(0, SeekOrigin.Begin); } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpegMultiple.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpegMultiple.cs index 14b240339e..71276597a7 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpegMultiple.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/EncodeJpegMultiple.cs @@ -8,7 +8,7 @@ using SixLabors.ImageSharp.Formats.Jpeg; namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { - [Config(typeof(Config.ShortClr))] // It's long enough to iterate through multiple files + [Config(typeof(Config.ShortMultiFramework))] public class EncodeJpegMultiple : MultiImageBenchmarkBase.WithImagesPreloaded { protected override IEnumerable InputImageSubfoldersOrFiles => new[] { "Bmp/", "Jpg/baseline" }; @@ -17,22 +17,18 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg [Benchmark(Description = "EncodeJpegMultiple - ImageSharp")] public void EncodeJpegImageSharp() - { - this.ForEachImageSharpImage((img, ms) => + => this.ForEachImageSharpImage((img, ms) => { img.Save(ms, new JpegEncoder()); return null; }); - } [Benchmark(Baseline = true, Description = "EncodeJpegMultiple - System.Drawing")] public void EncodeJpegSystemDrawing() - { - this.ForEachSystemDrawingImage((img, ms) => + => this.ForEachSystemDrawingImage((img, ms) => { img.Save(ms, ImageFormat.Jpeg); return null; }); - } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/GrayscaleColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/GrayscaleColorConversion.cs new file mode 100644 index 0000000000..1eba1571da --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/GrayscaleColorConversion.cs @@ -0,0 +1,33 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters; + +namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg +{ + [Config(typeof(Config.ShortMultiFramework))] + public class GrayscaleColorConversion : ColorConversionBenchmark + { + public GrayscaleColorConversion() + : base(1) + { + } + + [Benchmark(Baseline = true)] + public void Scalar() + { + var values = new JpegColorConverter.ComponentValues(this.Input, 0); + + new JpegColorConverter.FromGrayscaleBasic(8).ConvertToRgba(values, this.Output); + } + + [Benchmark] + public void SimdVectorAvx2() + { + var values = new JpegColorConverter.ComponentValues(this.Input, 0); + + new JpegColorConverter.FromGrayscaleAvx2(8).ConvertToRgba(values, this.Output); + } + } +} diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs index 43d4ccf07b..aae144ce02 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/IdentifyJpeg.cs @@ -1,15 +1,14 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System.IO; using BenchmarkDotNet.Attributes; - using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Tests; namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.ShortMultiFramework))] public class IdentifyJpeg { private byte[] jpegBytes; @@ -31,11 +30,9 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg [Benchmark] public IImageInfo Identify() { - using (var memoryStream = new MemoryStream(this.jpegBytes)) - { - var decoder = new JpegDecoder(); - return decoder.Identify(Configuration.Default, memoryStream); - } + using var memoryStream = new MemoryStream(this.jpegBytes); + var decoder = new JpegDecoder(); + return decoder.Identify(Configuration.Default, memoryStream); } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/LoadResizeSave_Aggregate.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/LoadResizeSave_Aggregate.cs index 2edc3e7afc..731850c435 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/LoadResizeSave_Aggregate.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/LoadResizeSave_Aggregate.cs @@ -6,9 +6,7 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; - using BenchmarkDotNet.Attributes; - using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; @@ -17,7 +15,7 @@ using SixLabors.ImageSharp.Tests; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { - [Config(typeof(MultiImageBenchmarkBase.Config))] + [Config(typeof(Config.ShortMultiFramework))] public class LoadResizeSave_Aggregate : MultiImageBenchmarkBase { protected override IEnumerable InputImageSubfoldersOrFiles => @@ -48,49 +46,43 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg [Benchmark(Baseline = true)] public void SystemDrawing() - { - this.ForEachStream( + => this.ForEachStream( sourceStream => + { + using (var destStream = new MemoryStream(this.destBytes)) + using (var source = System.Drawing.Image.FromStream(sourceStream)) + using (var destination = new Bitmap(source.Width / 4, source.Height / 4)) { - using (var destStream = new MemoryStream(this.destBytes)) - using (var source = System.Drawing.Image.FromStream(sourceStream)) - using (var destination = new Bitmap(source.Width / 4, source.Height / 4)) + using (var g = Graphics.FromImage(destination)) { - using (var g = Graphics.FromImage(destination)) - { - g.InterpolationMode = InterpolationMode.HighQualityBicubic; - g.PixelOffsetMode = PixelOffsetMode.HighQuality; - g.CompositingQuality = CompositingQuality.HighQuality; - g.DrawImage(source, 0, 0, 400, 400); - } - - destination.Save(destStream, ImageFormat.Jpeg); + g.InterpolationMode = InterpolationMode.HighQualityBicubic; + g.PixelOffsetMode = PixelOffsetMode.HighQuality; + g.CompositingQuality = CompositingQuality.HighQuality; + g.DrawImage(source, 0, 0, 400, 400); } - return null; - }); - } + destination.Save(destStream, ImageFormat.Jpeg); + } + + return null; + }); [Benchmark] public void ImageSharp() - { - this.ForEachStream( + => this.ForEachStream( sourceStream => + { + using (var source = Image.Load( + this.configuration, + sourceStream, + new JpegDecoder { IgnoreMetadata = true })) { - using (var source = Image.Load( - this.configuration, - sourceStream, - new JpegDecoder { IgnoreMetadata = true })) - { - using (var destStream = new MemoryStream(this.destBytes)) - { - source.Mutate(c => c.Resize(source.Width / 4, source.Height / 4)); - source.SaveAsJpeg(destStream); - } - } + using var destStream = new MemoryStream(this.destBytes); + source.Mutate(c => c.Resize(source.Width / 4, source.Height / 4)); + source.SaveAsJpeg(destStream); + } - return null; - }); - } + return null; + }); } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/LoadResizeSave_ImageSpecific.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/LoadResizeSave_ImageSpecific.cs index b46e747779..cfa39bd5ae 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/LoadResizeSave_ImageSpecific.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/LoadResizeSave_ImageSpecific.cs @@ -7,17 +7,15 @@ using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; using BenchmarkDotNet.Attributes; - using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Tests; - using SDImage = System.Drawing.Image; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.ShortMultiFramework))] public class LoadResizeSave_ImageSpecific { private readonly Configuration configuration = new Configuration(new JpegConfigurationModule()); @@ -32,6 +30,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg TestImages.Jpeg.BenchmarkSuite.Lake_Small444YCbCr, TestImages.Jpeg.BenchmarkSuite.BadRstProgressive518_Large444YCbCr, TestImages.Jpeg.BenchmarkSuite.Jpeg420Exif_MidSizeYCbCr)] + public string TestImage { get; set; } [Params(false, true)] @@ -51,28 +50,25 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg [Benchmark(Baseline = true)] public void SystemDrawing() { - using (var sourceStream = new MemoryStream(this.sourceBytes)) - using (var destStream = new MemoryStream(this.destBytes)) - using (var source = SDImage.FromStream(sourceStream)) - using (var destination = new Bitmap(source.Width / 4, source.Height / 4)) + using var sourceStream = new MemoryStream(this.sourceBytes); + using var destStream = new MemoryStream(this.destBytes); + using var source = SDImage.FromStream(sourceStream); + using var destination = new Bitmap(source.Width / 4, source.Height / 4); + using (var g = Graphics.FromImage(destination)) { - using (var g = Graphics.FromImage(destination)) - { - g.InterpolationMode = InterpolationMode.HighQualityBicubic; - g.PixelOffsetMode = PixelOffsetMode.HighQuality; - g.CompositingQuality = CompositingQuality.HighQuality; - g.DrawImage(source, 0, 0, 400, 400); - } - - destination.Save(destStream, ImageFormat.Jpeg); + g.InterpolationMode = InterpolationMode.HighQualityBicubic; + g.PixelOffsetMode = PixelOffsetMode.HighQuality; + g.CompositingQuality = CompositingQuality.HighQuality; + g.DrawImage(source, 0, 0, 400, 400); } + + destination.Save(destStream, ImageFormat.Jpeg); } [Benchmark] public void ImageSharp() { - var source = Image.Load(this.configuration, this.sourceBytes, new JpegDecoder { IgnoreMetadata = true }); - using (source) + using (var source = Image.Load(this.configuration, this.sourceBytes, new JpegDecoder { IgnoreMetadata = true })) using (var destStream = new MemoryStream(this.destBytes)) { source.Mutate(c => c.Resize(source.Width / 4, source.Height / 4)); diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/RgbColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/RgbColorConversion.cs new file mode 100644 index 0000000000..c1598be043 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/RgbColorConversion.cs @@ -0,0 +1,41 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters; + +namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg +{ + [Config(typeof(Config.ShortMultiFramework))] + public class RgbColorConversion : ColorConversionBenchmark + { + public RgbColorConversion() + : base(3) + { + } + + [Benchmark(Baseline = true)] + public void Scalar() + { + var values = new JpegColorConverter.ComponentValues(this.Input, 0); + + new JpegColorConverter.FromRgbBasic(8).ConvertToRgba(values, this.Output); + } + + [Benchmark] + public void SimdVector8() + { + var values = new JpegColorConverter.ComponentValues(this.Input, 0); + + new JpegColorConverter.FromRgbVector8(8).ConvertToRgba(values, this.Output); + } + + [Benchmark] + public void SimdVectorAvx2() + { + var values = new JpegColorConverter.ComponentValues(this.Input, 0); + + new JpegColorConverter.FromRgbAvx2(8).ConvertToRgba(values, this.Output); + } + } +} diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs index 7b47cf94a9..6c5732c99e 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs @@ -1,87 +1,49 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -using System; -using System.Numerics; - using BenchmarkDotNet.Attributes; - using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters; -using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { - [Config(typeof(Config.ShortClr))] - public class YCbCrColorConversion + [Config(typeof(Config.ShortMultiFramework))] + public class YCbCrColorConversion : ColorConversionBenchmark { - private Buffer2D[] input; - - private Vector4[] output; - - public const int Count = 128; - - [GlobalSetup] - public void Setup() + public YCbCrColorConversion() + : base(3) { - this.input = CreateRandomValues(3, Count); - this.output = new Vector4[Count]; - } - - [GlobalCleanup] - public void Cleanup() - { - foreach (Buffer2D buffer in this.input) - { - buffer.Dispose(); - } } [Benchmark] public void Scalar() { - var values = new JpegColorConverter.ComponentValues(this.input, 0); + var values = new JpegColorConverter.ComponentValues(this.Input, 0); - JpegColorConverter.FromYCbCrBasic.ConvertCore(values, this.output, 255F, 128F); + new JpegColorConverter.FromYCbCrBasic(8).ConvertToRgba(values, this.Output); } [Benchmark(Baseline = true)] - public void SimdVector4() + public void SimdVector() { - var values = new JpegColorConverter.ComponentValues(this.input, 0); + var values = new JpegColorConverter.ComponentValues(this.Input, 0); - JpegColorConverter.FromYCbCrSimd.ConvertCore(values, this.output, 255F, 128F); + new JpegColorConverter.FromYCbCrVector4(8).ConvertToRgba(values, this.Output); } [Benchmark] public void SimdVector8() { - var values = new JpegColorConverter.ComponentValues(this.input, 0); + var values = new JpegColorConverter.ComponentValues(this.Input, 0); - JpegColorConverter.FromYCbCrSimdVector8.ConvertCore(values, this.output, 255F, 128F); + new JpegColorConverter.FromYCbCrVector8(8).ConvertToRgba(values, this.Output); } - private static Buffer2D[] CreateRandomValues( - int componentCount, - int inputBufferLength, - float minVal = 0f, - float maxVal = 255f) + [Benchmark] + public void SimdVectorAvx2() { - var rnd = new Random(42); - var buffers = new Buffer2D[componentCount]; - for (int i = 0; i < componentCount; i++) - { - var values = new float[inputBufferLength]; - - for (int j = 0; j < inputBufferLength; j++) - { - values[j] = ((float)rnd.NextDouble() * (maxVal - minVal)) + minVal; - } - - // no need to dispose when buffer is not array owner - buffers[i] = Configuration.Default.MemoryAllocator.Allocate2D(values.Length, 1); - } + var values = new JpegColorConverter.ComponentValues(this.Input, 0); - return buffers; + new JpegColorConverter.FromYCbCrAvx2(8).ConvertToRgba(values, this.Output); } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YccKColorConverter.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YccKColorConverter.cs new file mode 100644 index 0000000000..0a9bdb8fdd --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YccKColorConverter.cs @@ -0,0 +1,41 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters; + +namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg +{ + [Config(typeof(Config.ShortMultiFramework))] + public class YccKColorConverter : ColorConversionBenchmark + { + public YccKColorConverter() + : base(4) + { + } + + [Benchmark(Baseline = true)] + public void Scalar() + { + var values = new JpegColorConverter.ComponentValues(this.Input, 0); + + new JpegColorConverter.FromYccKBasic(8).ConvertToRgba(values, this.Output); + } + + [Benchmark] + public void SimdVector8() + { + var values = new JpegColorConverter.ComponentValues(this.Input, 0); + + new JpegColorConverter.FromYccKVector8(8).ConvertToRgba(values, this.Output); + } + + [Benchmark] + public void SimdVectorAvx2() + { + var values = new JpegColorConverter.ComponentValues(this.Input, 0); + + new JpegColorConverter.FromYccKAvx2(8).ConvertToRgba(values, this.Output); + } + } +} diff --git a/tests/ImageSharp.Benchmarks/Codecs/MultiImageBenchmarkBase.cs b/tests/ImageSharp.Benchmarks/Codecs/MultiImageBenchmarkBase.cs index 96fb2f4e6b..b7e1e8ddb6 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/MultiImageBenchmarkBase.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/MultiImageBenchmarkBase.cs @@ -1,49 +1,25 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -using BenchmarkDotNet.Configs; -using BenchmarkDotNet.Jobs; - +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Numerics; +using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests; namespace SixLabors.ImageSharp.Benchmarks.Codecs { - using System; - using System.Collections.Generic; - using System.Drawing; - using System.IO; - using System.Linq; - using System.Numerics; - - using BenchmarkDotNet.Attributes; - using BenchmarkDotNet.Diagnosers; - using BenchmarkDotNet.Environments; - using SixLabors.ImageSharp.Tests; - - using CoreImage = SixLabors.ImageSharp.Image; - public abstract class MultiImageBenchmarkBase { - public class Config : ManualConfig - { - public Config() - { - // Uncomment if you want to use any of the diagnoser - this.Add(MemoryDiagnoser.Default); - } + protected Dictionary FileNamesToBytes { get; set; } = new Dictionary(); - public class ShortClr : Benchmarks.Config - { - public ShortClr() - { - this.Add(Job.Default.With(CoreRuntime.Core21).WithLaunchCount(1).WithWarmupCount(1).WithIterationCount(2)); - } - } - } + protected Dictionary> FileNamesToImageSharpImages { get; set; } = new Dictionary>(); - protected Dictionary fileNamesToBytes = new Dictionary(); - protected Dictionary> fileNamesToImageSharpImages = new Dictionary>(); - protected Dictionary fileNamesToSystemDrawingImages = new Dictionary(); + protected Dictionary FileNamesToSystemDrawingImages { get; set; } = new Dictionary(); /// /// The values of this enum separate input files into categories. @@ -81,7 +57,8 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs /// /// Gets folders containing files OR files to be processed by the benchmark. /// - protected IEnumerable AllFoldersOrFiles => this.InputImageSubfoldersOrFiles.Select(f => Path.Combine(this.BaseFolder, f)); + protected IEnumerable AllFoldersOrFiles + => this.InputImageSubfoldersOrFiles.Select(f => Path.Combine(this.BaseFolder, f)); /// /// Gets the large image threshold. @@ -92,24 +69,18 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs protected IEnumerable> EnumeratePairsByBenchmarkSettings( Dictionary input, Predicate checkIfSmall) - { - switch (this.InputCategory) + => this.InputCategory switch { - case InputImageCategory.AllImages: - return input; - case InputImageCategory.SmallImagesOnly: - return input.Where(kv => checkIfSmall(kv.Value)); - case InputImageCategory.LargeImagesOnly: - return input.Where(kv => !checkIfSmall(kv.Value)); - default: - throw new ArgumentOutOfRangeException(); - } - } + InputImageCategory.AllImages => input, + InputImageCategory.SmallImagesOnly => input.Where(kv => checkIfSmall(kv.Value)), + InputImageCategory.LargeImagesOnly => input.Where(kv => !checkIfSmall(kv.Value)), + _ => throw new ArgumentOutOfRangeException(), + }; protected IEnumerable> FileNames2Bytes => this.EnumeratePairsByBenchmarkSettings( - this.fileNamesToBytes, + this.FileNamesToBytes, arr => arr.Length < this.LargeImageThresholdInBytes); protected abstract IEnumerable InputImageSubfoldersOrFiles { get; } @@ -132,7 +103,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs { if (File.Exists(path)) { - this.fileNamesToBytes[path] = File.ReadAllBytes(path); + this.FileNamesToBytes[path] = File.ReadAllBytes(path); continue; } @@ -146,7 +117,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs foreach (string fn in allFiles) { - this.fileNamesToBytes[fn] = File.ReadAllBytes(fn); + this.FileNamesToBytes[fn] = File.ReadAllBytes(fn); } } } @@ -159,17 +130,15 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs { foreach (KeyValuePair kv in this.FileNames2Bytes) { - using (var memoryStream = new MemoryStream(kv.Value)) + using var memoryStream = new MemoryStream(kv.Value); + try { - try - { - object obj = operation(memoryStream); - (obj as IDisposable)?.Dispose(); - } - catch (Exception ex) - { - Console.WriteLine($"Operation on {kv.Key} failed with {ex.Message}"); - } + object obj = operation(memoryStream); + (obj as IDisposable)?.Dispose(); + } + catch (Exception ex) + { + Console.WriteLine($"Operation on {kv.Key} failed with {ex.Message}"); } } } @@ -180,30 +149,30 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs { base.ReadFilesImpl(); - foreach (KeyValuePair kv in this.fileNamesToBytes) + foreach (KeyValuePair kv in this.FileNamesToBytes) { byte[] bytes = kv.Value; string fn = kv.Key; using (var ms1 = new MemoryStream(bytes)) { - this.fileNamesToImageSharpImages[fn] = CoreImage.Load(ms1); + this.FileNamesToImageSharpImages[fn] = Image.Load(ms1); } - this.fileNamesToSystemDrawingImages[fn] = new Bitmap(new MemoryStream(bytes)); + this.FileNamesToSystemDrawingImages[fn] = new Bitmap(new MemoryStream(bytes)); } } protected IEnumerable>> FileNames2ImageSharpImages => this.EnumeratePairsByBenchmarkSettings( - this.fileNamesToImageSharpImages, + this.FileNamesToImageSharpImages, img => img.Width * img.Height < this.LargeImageThresholdInPixels); - protected IEnumerable> FileNames2SystemDrawingImages + protected IEnumerable> FileNames2SystemDrawingImages => this.EnumeratePairsByBenchmarkSettings( - this.fileNamesToSystemDrawingImages, + this.FileNamesToSystemDrawingImages, img => img.Width * img.Height < this.LargeImageThresholdInPixels); protected virtual int LargeImageThresholdInPixels => 700000; @@ -226,22 +195,20 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs protected void ForEachImageSharpImage(Func, MemoryStream, object> operation) { - using (var workStream = new MemoryStream()) - { - this.ForEachImageSharpImage( - img => - { - // ReSharper disable AccessToDisposedClosure - object result = operation(img, workStream); - workStream.Seek(0, SeekOrigin.Begin); - - // ReSharper restore AccessToDisposedClosure - return result; - }); - } + using var workStream = new MemoryStream(); + this.ForEachImageSharpImage( + img => + { + // ReSharper disable AccessToDisposedClosure + object result = operation(img, workStream); + workStream.Seek(0, SeekOrigin.Begin); + + // ReSharper restore AccessToDisposedClosure + return result; + }); } - protected void ForEachSystemDrawingImage(Func operation) + protected void ForEachSystemDrawingImage(Func operation) { foreach (KeyValuePair kv in this.FileNames2SystemDrawingImages) { @@ -257,21 +224,19 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs } } - protected void ForEachSystemDrawingImage(Func operation) + protected void ForEachSystemDrawingImage(Func operation) { - using (var workStream = new MemoryStream()) - { - this.ForEachSystemDrawingImage( - img => - { - // ReSharper disable AccessToDisposedClosure - object result = operation(img, workStream); - workStream.Seek(0, SeekOrigin.Begin); - - // ReSharper restore AccessToDisposedClosure - return result; - }); - } + using var workStream = new MemoryStream(); + this.ForEachSystemDrawingImage( + img => + { + // ReSharper disable AccessToDisposedClosure + object result = operation(img, workStream); + workStream.Seek(0, SeekOrigin.Begin); + + // ReSharper restore AccessToDisposedClosure + return result; + }); } } } diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs index da15da24c7..04ca8cd652 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs @@ -13,15 +13,13 @@ using System.Runtime.Intrinsics.X86; #endif using BenchmarkDotNet.Attributes; -using BenchmarkDotNet.Environments; -using BenchmarkDotNet.Jobs; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk { - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.ShortCore31))] public abstract class FromVector4 where TPixel : unmanaged, IPixel { @@ -32,7 +30,7 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk protected Configuration Configuration => Configuration.Default; // [Params(64, 2048)] - [Params(1024)] + [Params(64, 256, 2048)] public int Count { get; set; } [GlobalSetup] @@ -60,7 +58,7 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk } } - [Benchmark] + [Benchmark(Baseline = true)] public void PixelOperations_Base() { new PixelOperations().FromVector4Destructive(this.Configuration, this.source.GetSpan(), this.destination.GetSpan()); @@ -93,7 +91,7 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk SimdUtils.BasicIntrinsics256.NormalizedFloatToByteSaturate(sBytes, dFloats); } - [Benchmark(Baseline = true)] + [Benchmark] public void ExtendedIntrinsic() { Span sBytes = MemoryMarshal.Cast(this.source.GetSpan()); @@ -104,12 +102,12 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk #if SUPPORTS_RUNTIME_INTRINSICS [Benchmark] - public void UseAvx2() + public void UseHwIntrinsics() { Span sBytes = MemoryMarshal.Cast(this.source.GetSpan()); Span dFloats = MemoryMarshal.Cast(this.destination.GetSpan()); - SimdUtils.Avx2Intrinsics.NormalizedFloatToByteSaturate(sBytes, dFloats); + SimdUtils.HwIntrinsics.NormalizedFloatToByteSaturate(sBytes, dFloats); } private static ReadOnlySpan PermuteMaskDeinterleave8x32 => new byte[] { 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 7, 0, 0, 0 }; diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4_Rgb24.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4_Rgb24.cs new file mode 100644 index 0000000000..ff55cc5d01 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4_Rgb24.cs @@ -0,0 +1,55 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk +{ + [Config(typeof(Config.ShortMultiFramework))] + public class FromVector4_Rgb24 : FromVector4 + { + } +} + +// 2020-11-02 +// ########## +// +// BenchmarkDotNet = v0.12.1, OS = Windows 10.0.19041.572(2004 /?/ 20H1) +// Intel Core i7-8650U CPU 1.90GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores +// .NET Core SDK=3.1.403 +// [Host] : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT +// Job-XYEQXL : .NET Framework 4.8 (4.8.4250.0), X64 RyuJIT +// Job-HSXNJV : .NET Core 2.1.23 (CoreCLR 4.6.29321.03, CoreFX 4.6.29321.01), X64 RyuJIT +// Job-YUREJO : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT +// +// IterationCount=3 LaunchCount=1 WarmupCount=3 +// +// | Method | Job | Runtime | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | +// |---------------------------- |----------- |-------------- |------ |-----------:|------------:|----------:|------:|--------:|-------:|------:|------:|----------:| +// | PixelOperations_Base | Job-XYEQXL | .NET 4.7.2 | 64 | 343.2 ns | 305.91 ns | 16.77 ns | 1.00 | 0.00 | 0.0057 | - | - | 24 B | +// | PixelOperations_Specialized | Job-XYEQXL | .NET 4.7.2 | 64 | 320.8 ns | 19.93 ns | 1.09 ns | 0.94 | 0.05 | - | - | - | - | +// | | | | | | | | | | | | | | +// | PixelOperations_Base | Job-HSXNJV | .NET Core 2.1 | 64 | 234.3 ns | 17.98 ns | 0.99 ns | 1.00 | 0.00 | 0.0052 | - | - | 24 B | +// | PixelOperations_Specialized | Job-HSXNJV | .NET Core 2.1 | 64 | 246.0 ns | 82.34 ns | 4.51 ns | 1.05 | 0.02 | - | - | - | - | +// | | | | | | | | | | | | | | +// | PixelOperations_Base | Job-YUREJO | .NET Core 3.1 | 64 | 222.3 ns | 39.46 ns | 2.16 ns | 1.00 | 0.00 | 0.0057 | - | - | 24 B | +// | PixelOperations_Specialized | Job-YUREJO | .NET Core 3.1 | 64 | 243.4 ns | 33.58 ns | 1.84 ns | 1.09 | 0.01 | - | - | - | - | +// | | | | | | | | | | | | | | +// | PixelOperations_Base | Job-XYEQXL | .NET 4.7.2 | 256 | 824.9 ns | 32.77 ns | 1.80 ns | 1.00 | 0.00 | 0.0057 | - | - | 24 B | +// | PixelOperations_Specialized | Job-XYEQXL | .NET 4.7.2 | 256 | 967.0 ns | 39.09 ns | 2.14 ns | 1.17 | 0.01 | 0.0172 | - | - | 72 B | +// | | | | | | | | | | | | | | +// | PixelOperations_Base | Job-HSXNJV | .NET Core 2.1 | 256 | 756.9 ns | 94.43 ns | 5.18 ns | 1.00 | 0.00 | 0.0048 | - | - | 24 B | +// | PixelOperations_Specialized | Job-HSXNJV | .NET Core 2.1 | 256 | 1,003.3 ns | 3,192.09 ns | 174.97 ns | 1.32 | 0.22 | 0.0172 | - | - | 72 B | +// | | | | | | | | | | | | | | +// | PixelOperations_Base | Job-YUREJO | .NET Core 3.1 | 256 | 748.6 ns | 248.03 ns | 13.60 ns | 1.00 | 0.00 | 0.0057 | - | - | 24 B | +// | PixelOperations_Specialized | Job-YUREJO | .NET Core 3.1 | 256 | 437.0 ns | 36.48 ns | 2.00 ns | 0.58 | 0.01 | 0.0172 | - | - | 72 B | +// | | | | | | | | | | | | | | +// | PixelOperations_Base | Job-XYEQXL | .NET 4.7.2 | 2048 | 5,751.6 ns | 704.24 ns | 38.60 ns | 1.00 | 0.00 | - | - | - | 24 B | +// | PixelOperations_Specialized | Job-XYEQXL | .NET 4.7.2 | 2048 | 4,391.6 ns | 718.17 ns | 39.37 ns | 0.76 | 0.00 | 0.0153 | - | - | 72 B | +// | | | | | | | | | | | | | | +// | PixelOperations_Base | Job-HSXNJV | .NET Core 2.1 | 2048 | 6,202.0 ns | 1,815.18 ns | 99.50 ns | 1.00 | 0.00 | - | - | - | 24 B | +// | PixelOperations_Specialized | Job-HSXNJV | .NET Core 2.1 | 2048 | 4,225.6 ns | 1,004.03 ns | 55.03 ns | 0.68 | 0.01 | 0.0153 | - | - | 72 B | +// | | | | | | | | | | | | | | +// | PixelOperations_Base | Job-YUREJO | .NET Core 3.1 | 2048 | 6,157.1 ns | 2,516.98 ns | 137.96 ns | 1.00 | 0.00 | - | - | - | 24 B | +// | PixelOperations_Specialized | Job-YUREJO | .NET Core 3.1 | 2048 | 1,822.7 ns | 1,764.43 ns | 96.71 ns | 0.30 | 0.02 | 0.0172 | - | - | 72 B | diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/Pad3Shuffle4Channel.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/Pad3Shuffle4Channel.cs new file mode 100644 index 0000000000..4af0286054 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/Pad3Shuffle4Channel.cs @@ -0,0 +1,87 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using BenchmarkDotNet.Attributes; + +namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk +{ + [Config(typeof(Config.HwIntrinsics_SSE_AVX))] + public class Pad3Shuffle4Channel + { + private static readonly DefaultPad3Shuffle4 Control = new DefaultPad3Shuffle4(1, 0, 3, 2); + private static readonly XYZWPad3Shuffle4 ControlFast = default; + private byte[] source; + private byte[] destination; + + [GlobalSetup] + public void Setup() + { + this.source = new byte[this.Count]; + new Random(this.Count).NextBytes(this.source); + this.destination = new byte[this.Count * 4 / 3]; + } + + [Params(96, 384, 768, 1536)] + public int Count { get; set; } + + [Benchmark] + public void Pad3Shuffle4() + { + SimdUtils.Pad3Shuffle4(this.source, this.destination, Control); + } + + [Benchmark] + public void Pad3Shuffle4FastFallback() + { + SimdUtils.Pad3Shuffle4(this.source, this.destination, ControlFast); + } + } + + // 2020-10-30 + // ########## + // + // BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.572 (2004/?/20H1) + // Intel Core i7-8650U CPU 1.90GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores + // .NET Core SDK=3.1.403 + // [Host] : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // 1. No HwIntrinsics : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // 2. AVX : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // 3. SSE : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // + // Runtime=.NET Core 3.1 + // + // | Method | Job | EnvironmentVariables | Count | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | + // |------------------------- |------------------- |-------------------------------------------------- |------ |------------:|----------:|----------:|------------:|------:|--------:|------:|------:|------:|----------:| + // | Pad3Shuffle4 | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 96 | 120.64 ns | 7.190 ns | 21.200 ns | 114.26 ns | 1.00 | 0.00 | - | - | - | - | + // | Pad3Shuffle4 | 2. AVX | Empty | 96 | 23.63 ns | 0.175 ns | 0.155 ns | 23.65 ns | 0.15 | 0.01 | - | - | - | - | + // | Pad3Shuffle4 | 3. SSE | COMPlus_EnableAVX=0 | 96 | 25.25 ns | 0.356 ns | 0.298 ns | 25.27 ns | 0.17 | 0.01 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Pad3Shuffle4FastFallback | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 96 | 14.80 ns | 0.358 ns | 1.032 ns | 14.64 ns | 1.00 | 0.00 | - | - | - | - | + // | Pad3Shuffle4FastFallback | 2. AVX | Empty | 96 | 24.84 ns | 0.376 ns | 0.333 ns | 24.74 ns | 1.57 | 0.06 | - | - | - | - | + // | Pad3Shuffle4FastFallback | 3. SSE | COMPlus_EnableAVX=0 | 96 | 24.58 ns | 0.471 ns | 0.704 ns | 24.38 ns | 1.60 | 0.09 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Pad3Shuffle4 | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 384 | 258.92 ns | 4.873 ns | 4.069 ns | 257.95 ns | 1.00 | 0.00 | - | - | - | - | + // | Pad3Shuffle4 | 2. AVX | Empty | 384 | 41.41 ns | 0.859 ns | 1.204 ns | 41.33 ns | 0.16 | 0.00 | - | - | - | - | + // | Pad3Shuffle4 | 3. SSE | COMPlus_EnableAVX=0 | 384 | 40.74 ns | 0.848 ns | 0.793 ns | 40.48 ns | 0.16 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Pad3Shuffle4FastFallback | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 384 | 74.50 ns | 0.490 ns | 0.383 ns | 74.49 ns | 1.00 | 0.00 | - | - | - | - | + // | Pad3Shuffle4FastFallback | 2. AVX | Empty | 384 | 40.74 ns | 0.624 ns | 0.584 ns | 40.72 ns | 0.55 | 0.01 | - | - | - | - | + // | Pad3Shuffle4FastFallback | 3. SSE | COMPlus_EnableAVX=0 | 384 | 38.28 ns | 0.534 ns | 0.417 ns | 38.22 ns | 0.51 | 0.01 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Pad3Shuffle4 | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 768 | 503.91 ns | 6.466 ns | 6.048 ns | 501.58 ns | 1.00 | 0.00 | - | - | - | - | + // | Pad3Shuffle4 | 2. AVX | Empty | 768 | 62.86 ns | 0.332 ns | 0.277 ns | 62.80 ns | 0.12 | 0.00 | - | - | - | - | + // | Pad3Shuffle4 | 3. SSE | COMPlus_EnableAVX=0 | 768 | 64.59 ns | 0.469 ns | 0.415 ns | 64.62 ns | 0.13 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Pad3Shuffle4FastFallback | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 768 | 110.51 ns | 0.592 ns | 0.554 ns | 110.33 ns | 1.00 | 0.00 | - | - | - | - | + // | Pad3Shuffle4FastFallback | 2. AVX | Empty | 768 | 64.72 ns | 1.306 ns | 1.090 ns | 64.51 ns | 0.59 | 0.01 | - | - | - | - | + // | Pad3Shuffle4FastFallback | 3. SSE | COMPlus_EnableAVX=0 | 768 | 62.11 ns | 0.816 ns | 0.682 ns | 61.98 ns | 0.56 | 0.01 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Pad3Shuffle4 | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 1536 | 1,005.84 ns | 13.176 ns | 12.325 ns | 1,004.70 ns | 1.00 | 0.00 | - | - | - | - | + // | Pad3Shuffle4 | 2. AVX | Empty | 1536 | 110.05 ns | 0.256 ns | 0.214 ns | 110.04 ns | 0.11 | 0.00 | - | - | - | - | + // | Pad3Shuffle4 | 3. SSE | COMPlus_EnableAVX=0 | 1536 | 110.23 ns | 0.545 ns | 0.483 ns | 110.09 ns | 0.11 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Pad3Shuffle4FastFallback | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 1536 | 220.37 ns | 1.601 ns | 1.419 ns | 220.13 ns | 1.00 | 0.00 | - | - | - | - | + // | Pad3Shuffle4FastFallback | 2. AVX | Empty | 1536 | 111.54 ns | 2.173 ns | 2.901 ns | 111.27 ns | 0.51 | 0.01 | - | - | - | - | + // | Pad3Shuffle4FastFallback | 3. SSE | COMPlus_EnableAVX=0 | 1536 | 110.23 ns | 0.456 ns | 0.427 ns | 110.25 ns | 0.50 | 0.00 | - | - | - | - | +} diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/PremultiplyVector4.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/PremultiplyVector4.cs new file mode 100644 index 0000000000..b88f5090ba --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/PremultiplyVector4.cs @@ -0,0 +1,68 @@ +// 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; +using BenchmarkDotNet.Attributes; + +namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk +{ + [Config(typeof(Config.ShortCore31))] + public class PremultiplyVector4 + { + private static readonly Vector4[] Vectors = CreateVectors(); + + [Benchmark(Baseline = true)] + public void PremultiplyBaseline() + { + 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); + } + } + + [Benchmark] + public void Premultiply() + { + Numerics.Premultiply(Vectors); + } + + [MethodImpl(InliningOptions.ShortMethod)] + private static void Premultiply(ref Vector4 source) + { + float w = source.W; + source *= w; + source.W = w; + } + + private static Vector4[] CreateVectors() + { + var rnd = new Random(42); + return GenerateRandomVectorArray(rnd, 2048, 0, 1); + } + + private static Vector4[] GenerateRandomVectorArray(Random rnd, int length, float minVal, float maxVal) + { + var values = new Vector4[length]; + + for (int i = 0; i < length; i++) + { + ref Vector4 v = ref values[i]; + v.X = GetRandomFloat(rnd, minVal, maxVal); + v.Y = GetRandomFloat(rnd, minVal, maxVal); + v.Z = GetRandomFloat(rnd, minVal, maxVal); + v.W = GetRandomFloat(rnd, minVal, maxVal); + } + + return values; + } + + private static float GetRandomFloat(Random rnd, float minVal, float maxVal) + => ((float)rnd.NextDouble() * (maxVal - minVal)) + minVal; + } +} diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/Shuffle3Channel.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/Shuffle3Channel.cs new file mode 100644 index 0000000000..3667b973ef --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/Shuffle3Channel.cs @@ -0,0 +1,64 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using BenchmarkDotNet.Attributes; + +namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk +{ + [Config(typeof(Config.HwIntrinsics_SSE_AVX))] + public class Shuffle3Channel + { + private static readonly DefaultShuffle3 Control = new DefaultShuffle3(1, 0, 2); + private byte[] source; + private byte[] destination; + + [GlobalSetup] + public void Setup() + { + this.source = new byte[this.Count]; + new Random(this.Count).NextBytes(this.source); + this.destination = new byte[this.Count]; + } + + [Params(96, 384, 768, 1536)] + public int Count { get; set; } + + [Benchmark] + public void Shuffle3() + { + SimdUtils.Shuffle3(this.source, this.destination, Control); + } + } + + // 2020-11-02 + // ########## + // + // BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.572 (2004/?/20H1) + // Intel Core i7-8650U CPU 1.90GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores + // .NET Core SDK=3.1.403 + // [Host] : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // 1. No HwIntrinsics : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // 2. AVX : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // 3. SSE : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // + // Runtime=.NET Core 3.1 + // + // | Method | Job | EnvironmentVariables | Count | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | + // |--------------------- |------------------- |-------------------------------------------------- |------ |----------:|---------:|---------:|----------:|------:|--------:|------:|------:|------:|----------:| + // | Shuffle3 | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 96 | 48.46 ns | 1.034 ns | 2.438 ns | 47.46 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle3 | 2. AVX | Empty | 96 | 32.42 ns | 0.537 ns | 0.476 ns | 32.34 ns | 0.66 | 0.04 | - | - | - | - | + // | Shuffle3 | 3. SSE | COMPlus_EnableAVX=0 | 96 | 32.51 ns | 0.373 ns | 0.349 ns | 32.56 ns | 0.66 | 0.03 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Shuffle3 | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 384 | 199.04 ns | 1.512 ns | 1.180 ns | 199.17 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle3 | 2. AVX | Empty | 384 | 71.20 ns | 2.654 ns | 7.784 ns | 69.60 ns | 0.41 | 0.02 | - | - | - | - | + // | Shuffle3 | 3. SSE | COMPlus_EnableAVX=0 | 384 | 63.23 ns | 0.569 ns | 0.505 ns | 63.21 ns | 0.32 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Shuffle3 | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 768 | 391.28 ns | 5.087 ns | 3.972 ns | 391.22 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle3 | 2. AVX | Empty | 768 | 109.12 ns | 2.149 ns | 2.010 ns | 108.66 ns | 0.28 | 0.01 | - | - | - | - | + // | Shuffle3 | 3. SSE | COMPlus_EnableAVX=0 | 768 | 106.51 ns | 0.734 ns | 0.613 ns | 106.56 ns | 0.27 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Shuffle3 | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 1536 | 773.70 ns | 5.516 ns | 4.890 ns | 772.96 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle3 | 2. AVX | Empty | 1536 | 190.41 ns | 1.090 ns | 0.851 ns | 190.38 ns | 0.25 | 0.00 | - | - | - | - | + // | Shuffle3 | 3. SSE | COMPlus_EnableAVX=0 | 1536 | 190.94 ns | 0.985 ns | 0.769 ns | 190.85 ns | 0.25 | 0.00 | - | - | - | - | +} diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/Shuffle4Slice3Channel.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/Shuffle4Slice3Channel.cs new file mode 100644 index 0000000000..9cf24ccd69 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/Shuffle4Slice3Channel.cs @@ -0,0 +1,95 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using BenchmarkDotNet.Attributes; + +namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk +{ + [Config(typeof(Config.HwIntrinsics_SSE_AVX))] + public class Shuffle4Slice3Channel + { + private static readonly DefaultShuffle4Slice3 Control = new DefaultShuffle4Slice3(1, 0, 3, 2); + private static readonly XYZWShuffle4Slice3 ControlFast = default; + private byte[] source; + private byte[] destination; + + [GlobalSetup] + public void Setup() + { + this.source = new byte[this.Count]; + new Random(this.Count).NextBytes(this.source); + this.destination = new byte[(int)(this.Count * (3 / 4F))]; + } + + [Params(128, 256, 512, 1024, 2048)] + public int Count { get; set; } + + [Benchmark] + public void Shuffle4Slice3() + { + SimdUtils.Shuffle4Slice3(this.source, this.destination, Control); + } + + [Benchmark] + public void Shuffle4Slice3FastFallback() + { + SimdUtils.Shuffle4Slice3(this.source, this.destination, ControlFast); + } + } + + // 2020-10-29 + // ########## + // + // BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.572 (2004/?/20H1) + // Intel Core i7-8650U CPU 1.90GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores + // .NET Core SDK=3.1.403 + // [Host] : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // 1. No HwIntrinsics : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // 2. AVX : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // 3. SSE : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // + // Runtime=.NET Core 3.1 + // + // | Method | Job | EnvironmentVariables | Count | Mean | Error | StdDev | Median | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | + // |--------------------------- |------------------- |-------------------------------------------------- |------ |----------:|---------:|---------:|----------:|------:|--------:|------:|------:|------:|----------:| + // | Shuffle4Slice3 | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 128 | 56.44 ns | 2.843 ns | 8.382 ns | 56.70 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle4Slice3 | 2. AVX | Empty | 128 | 27.15 ns | 0.556 ns | 0.762 ns | 27.34 ns | 0.41 | 0.03 | - | - | - | - | + // | Shuffle4Slice3 | 3. SSE | COMPlus_EnableAVX=0 | 128 | 26.36 ns | 0.321 ns | 0.268 ns | 26.26 ns | 0.38 | 0.02 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Shuffle4Slice3FastFallback | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 128 | 25.85 ns | 0.494 ns | 0.462 ns | 25.84 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle4Slice3FastFallback | 2. AVX | Empty | 128 | 26.15 ns | 0.113 ns | 0.106 ns | 26.16 ns | 1.01 | 0.02 | - | - | - | - | + // | Shuffle4Slice3FastFallback | 3. SSE | COMPlus_EnableAVX=0 | 128 | 25.57 ns | 0.078 ns | 0.061 ns | 25.56 ns | 0.99 | 0.02 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Shuffle4Slice3 | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 256 | 97.47 ns | 0.327 ns | 0.289 ns | 97.35 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle4Slice3 | 2. AVX | Empty | 256 | 32.61 ns | 0.107 ns | 0.095 ns | 32.62 ns | 0.33 | 0.00 | - | - | - | - | + // | Shuffle4Slice3 | 3. SSE | COMPlus_EnableAVX=0 | 256 | 33.21 ns | 0.169 ns | 0.150 ns | 33.15 ns | 0.34 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Shuffle4Slice3FastFallback | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 256 | 52.34 ns | 0.779 ns | 0.729 ns | 51.94 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle4Slice3FastFallback | 2. AVX | Empty | 256 | 32.16 ns | 0.111 ns | 0.104 ns | 32.16 ns | 0.61 | 0.01 | - | - | - | - | + // | Shuffle4Slice3FastFallback | 3. SSE | COMPlus_EnableAVX=0 | 256 | 33.61 ns | 0.342 ns | 0.319 ns | 33.62 ns | 0.64 | 0.01 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Shuffle4Slice3 | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 512 | 210.74 ns | 3.825 ns | 5.956 ns | 207.70 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle4Slice3 | 2. AVX | Empty | 512 | 51.03 ns | 0.535 ns | 0.501 ns | 51.18 ns | 0.24 | 0.01 | - | - | - | - | + // | Shuffle4Slice3 | 3. SSE | COMPlus_EnableAVX=0 | 512 | 66.60 ns | 1.313 ns | 1.613 ns | 65.93 ns | 0.31 | 0.01 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Shuffle4Slice3FastFallback | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 512 | 119.12 ns | 1.905 ns | 1.689 ns | 118.52 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle4Slice3FastFallback | 2. AVX | Empty | 512 | 50.33 ns | 0.382 ns | 0.339 ns | 50.41 ns | 0.42 | 0.01 | - | - | - | - | + // | Shuffle4Slice3FastFallback | 3. SSE | COMPlus_EnableAVX=0 | 512 | 49.25 ns | 0.555 ns | 0.492 ns | 49.26 ns | 0.41 | 0.01 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Shuffle4Slice3 | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 1024 | 423.55 ns | 4.891 ns | 4.336 ns | 423.27 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle4Slice3 | 2. AVX | Empty | 1024 | 77.13 ns | 1.355 ns | 2.264 ns | 76.19 ns | 0.19 | 0.01 | - | - | - | - | + // | Shuffle4Slice3 | 3. SSE | COMPlus_EnableAVX=0 | 1024 | 79.39 ns | 0.103 ns | 0.086 ns | 79.37 ns | 0.19 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Shuffle4Slice3FastFallback | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 1024 | 226.57 ns | 2.930 ns | 2.598 ns | 226.10 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle4Slice3FastFallback | 2. AVX | Empty | 1024 | 80.25 ns | 1.647 ns | 2.082 ns | 80.98 ns | 0.35 | 0.01 | - | - | - | - | + // | Shuffle4Slice3FastFallback | 3. SSE | COMPlus_EnableAVX=0 | 1024 | 84.99 ns | 1.234 ns | 1.155 ns | 85.60 ns | 0.38 | 0.01 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Shuffle4Slice3 | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 2048 | 794.96 ns | 1.735 ns | 1.538 ns | 795.15 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle4Slice3 | 2. AVX | Empty | 2048 | 128.41 ns | 0.417 ns | 0.390 ns | 128.24 ns | 0.16 | 0.00 | - | - | - | - | + // | Shuffle4Slice3 | 3. SSE | COMPlus_EnableAVX=0 | 2048 | 127.24 ns | 0.294 ns | 0.229 ns | 127.23 ns | 0.16 | 0.00 | - | - | - | - | + // | | | | | | | | | | | | | | | + // | Shuffle4Slice3FastFallback | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 2048 | 382.97 ns | 1.064 ns | 0.831 ns | 382.87 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle4Slice3FastFallback | 2. AVX | Empty | 2048 | 126.93 ns | 0.382 ns | 0.339 ns | 126.94 ns | 0.33 | 0.00 | - | - | - | - | + // | Shuffle4Slice3FastFallback | 3. SSE | COMPlus_EnableAVX=0 | 2048 | 149.36 ns | 1.875 ns | 1.754 ns | 149.33 ns | 0.39 | 0.00 | - | - | - | - | +} diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ShuffleByte4Channel.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ShuffleByte4Channel.cs new file mode 100644 index 0000000000..db49470011 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ShuffleByte4Channel.cs @@ -0,0 +1,67 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using BenchmarkDotNet.Attributes; + +namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk +{ + [Config(typeof(Config.HwIntrinsics_SSE_AVX))] + public class ShuffleByte4Channel + { + private byte[] source; + private byte[] destination; + + [GlobalSetup] + public void Setup() + { + this.source = new byte[this.Count]; + new Random(this.Count).NextBytes(this.source); + this.destination = new byte[this.Count]; + } + + [Params(128, 256, 512, 1024, 2048)] + public int Count { get; set; } + + [Benchmark] + public void Shuffle4Channel() + { + SimdUtils.Shuffle4(this.source, this.destination, default); + } + } + + // 2020-10-29 + // ########## + // + // BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.572 (2004/?/20H1) + // Intel Core i7-8650U CPU 1.90GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores + // .NET Core SDK=3.1.403 + // [Host] : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // 1. No HwIntrinsics : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // 2. AVX : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // 3. SSE : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // + // Runtime=.NET Core 3.1 + // + // | Method | Job | EnvironmentVariables | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | + // |---------------- |------------------- |-------------------------------------------------- |------ |----------:|---------:|---------:|------:|--------:|------:|------:|------:|----------:| + // | Shuffle4Channel | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 128 | 17.39 ns | 0.187 ns | 0.175 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle4Channel | 2. AVX | Empty | 128 | 21.72 ns | 0.299 ns | 0.279 ns | 1.25 | 0.02 | - | - | - | - | + // | Shuffle4Channel | 3. SSE | COMPlus_EnableAVX=0 | 128 | 18.10 ns | 0.346 ns | 0.289 ns | 1.04 | 0.02 | - | - | - | - | + // | | | | | | | | | | | | | | + // | Shuffle4Channel | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 256 | 35.51 ns | 0.711 ns | 0.790 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle4Channel | 2. AVX | Empty | 256 | 23.90 ns | 0.508 ns | 0.820 ns | 0.69 | 0.02 | - | - | - | - | + // | Shuffle4Channel | 3. SSE | COMPlus_EnableAVX=0 | 256 | 20.40 ns | 0.133 ns | 0.111 ns | 0.57 | 0.01 | - | - | - | - | + // | | | | | | | | | | | | | | + // | Shuffle4Channel | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 512 | 73.39 ns | 0.310 ns | 0.259 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle4Channel | 2. AVX | Empty | 512 | 26.10 ns | 0.418 ns | 0.391 ns | 0.36 | 0.01 | - | - | - | - | + // | Shuffle4Channel | 3. SSE | COMPlus_EnableAVX=0 | 512 | 27.59 ns | 0.556 ns | 0.571 ns | 0.38 | 0.01 | - | - | - | - | + // | | | | | | | | | | | | | | + // | Shuffle4Channel | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 1024 | 150.64 ns | 2.903 ns | 2.716 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle4Channel | 2. AVX | Empty | 1024 | 38.67 ns | 0.801 ns | 1.889 ns | 0.24 | 0.02 | - | - | - | - | + // | Shuffle4Channel | 3. SSE | COMPlus_EnableAVX=0 | 1024 | 47.13 ns | 0.948 ns | 1.054 ns | 0.31 | 0.01 | - | - | - | - | + // | | | | | | | | | | | | | | + // | Shuffle4Channel | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 2048 | 315.29 ns | 5.206 ns | 6.583 ns | 1.00 | 0.00 | - | - | - | - | + // | Shuffle4Channel | 2. AVX | Empty | 2048 | 57.37 ns | 1.152 ns | 1.078 ns | 0.18 | 0.01 | - | - | - | - | + // | Shuffle4Channel | 3. SSE | COMPlus_EnableAVX=0 | 2048 | 65.75 ns | 1.198 ns | 1.600 ns | 0.21 | 0.01 | - | - | - | - | +} diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ShuffleFloat4Channel.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ShuffleFloat4Channel.cs new file mode 100644 index 0000000000..86b1f766e1 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ShuffleFloat4Channel.cs @@ -0,0 +1,68 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.Tests; + +namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk +{ + [Config(typeof(Config.HwIntrinsics_SSE_AVX))] + public class ShuffleFloat4Channel + { + private static readonly byte Control = default(WXYZShuffle4).Control; + private float[] source; + private float[] destination; + + [GlobalSetup] + public void Setup() + { + this.source = new Random(this.Count).GenerateRandomFloatArray(this.Count, 0, 256); + this.destination = new float[this.Count]; + } + + [Params(128, 256, 512, 1024, 2048)] + public int Count { get; set; } + + [Benchmark] + public void Shuffle4Channel() + { + SimdUtils.Shuffle4(this.source, this.destination, Control); + } + } + + // 2020-10-29 + // ########## + // + // BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.572 (2004/?/20H1) + // Intel Core i7-8650U CPU 1.90GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores + // .NET Core SDK=3.1.403 + // [Host] : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // 1. No HwIntrinsics : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // 2. AVX : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // 3. SSE : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT + // + // Runtime=.NET Core 3.1 + // + // | Method | Job | EnvironmentVariables | Count | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | + // |---------------- |------------------- |-------------------------------------------------- |------ |-----------:|----------:|----------:|------:|------:|------:|------:|----------:| + // | Shuffle4Channel | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 128 | 63.647 ns | 0.5475 ns | 0.4853 ns | 1.00 | - | - | - | - | + // | Shuffle4Channel | 2. AVX | Empty | 128 | 9.818 ns | 0.1457 ns | 0.1292 ns | 0.15 | - | - | - | - | + // | Shuffle4Channel | 3. SSE | COMPlus_EnableAVX=0 | 128 | 15.267 ns | 0.1005 ns | 0.0940 ns | 0.24 | - | - | - | - | + // | | | | | | | | | | | | | + // | Shuffle4Channel | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 256 | 125.586 ns | 1.9312 ns | 1.8064 ns | 1.00 | - | - | - | - | + // | Shuffle4Channel | 2. AVX | Empty | 256 | 15.878 ns | 0.1983 ns | 0.1758 ns | 0.13 | - | - | - | - | + // | Shuffle4Channel | 3. SSE | COMPlus_EnableAVX=0 | 256 | 29.170 ns | 0.2925 ns | 0.2442 ns | 0.23 | - | - | - | - | + // | | | | | | | | | | | | | + // | Shuffle4Channel | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 512 | 263.859 ns | 2.6660 ns | 2.3634 ns | 1.00 | - | - | - | - | + // | Shuffle4Channel | 2. AVX | Empty | 512 | 29.452 ns | 0.3334 ns | 0.3118 ns | 0.11 | - | - | - | - | + // | Shuffle4Channel | 3. SSE | COMPlus_EnableAVX=0 | 512 | 52.912 ns | 0.1932 ns | 0.1713 ns | 0.20 | - | - | - | - | + // | | | | | | | | | | | | | + // | Shuffle4Channel | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 1024 | 495.717 ns | 1.9850 ns | 1.8567 ns | 1.00 | - | - | - | - | + // | Shuffle4Channel | 2. AVX | Empty | 1024 | 53.757 ns | 0.3212 ns | 0.2847 ns | 0.11 | - | - | - | - | + // | Shuffle4Channel | 3. SSE | COMPlus_EnableAVX=0 | 1024 | 107.815 ns | 1.6201 ns | 1.3528 ns | 0.22 | - | - | - | - | + // | | | | | | | | | | | | | + // | Shuffle4Channel | 1. No HwIntrinsics | COMPlus_EnableHWIntrinsic=0,COMPlus_FeatureSIMD=0 | 2048 | 980.134 ns | 3.7407 ns | 3.1237 ns | 1.00 | - | - | - | - | + // | Shuffle4Channel | 2. AVX | Empty | 2048 | 105.120 ns | 0.6140 ns | 0.5443 ns | 0.11 | - | - | - | - | + // | Shuffle4Channel | 3. SSE | COMPlus_EnableAVX=0 | 2048 | 216.473 ns | 2.3268 ns | 2.0627 ns | 0.22 | - | - | - | - | +} diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Bgra32.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Bgra32.cs index b090c7dc21..0426dcf096 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Bgra32.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Bgra32.cs @@ -8,7 +8,7 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk { - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.ShortMultiFramework))] public class ToVector4_Bgra32 : ToVector4 { [Benchmark(Baseline = true)] diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgb24.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgb24.cs new file mode 100644 index 0000000000..63a3148aad --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgb24.cs @@ -0,0 +1,65 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using BenchmarkDotNet.Attributes; + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk +{ + [Config(typeof(Config.ShortMultiFramework))] + public class ToVector4_Rgb24 : ToVector4 + { + [Benchmark(Baseline = true)] + public void PixelOperations_Base() + { + new PixelOperations().ToVector4( + this.Configuration, + this.source.GetSpan(), + this.destination.GetSpan()); + } + } +} + +// 2020-11-02 +// ########## +// +// BenchmarkDotNet = v0.12.1, OS = Windows 10.0.19041.572(2004 /?/ 20H1) +// Intel Core i7-8650U CPU 1.90GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores +// .NET Core SDK=3.1.403 +// [Host] : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT +// Job-XYEQXL : .NET Framework 4.8 (4.8.4250.0), X64 RyuJIT +// Job-HSXNJV : .NET Core 2.1.23 (CoreCLR 4.6.29321.03, CoreFX 4.6.29321.01), X64 RyuJIT +// Job-YUREJO : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT +// +// IterationCount=3 LaunchCount=1 WarmupCount=3 +// +// | Method | Job | Runtime | Count | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | +// |---------------------------- |----------- |-------------- |------ |-----------:|------------:|----------:|------:|--------:|-------:|------:|------:|----------:| +// | PixelOperations_Base | Job-OIBEDX | .NET 4.7.2 | 64 | 298.4 ns | 33.63 ns | 1.84 ns | 1.00 | 0.00 | 0.0057 | - | - | 24 B | +// | PixelOperations_Specialized | Job-OIBEDX | .NET 4.7.2 | 64 | 355.5 ns | 908.51 ns | 49.80 ns | 1.19 | 0.17 | - | - | - | - | +// | | | | | | | | | | | | | | +// | PixelOperations_Base | Job-OPAORC | .NET Core 2.1 | 64 | 220.1 ns | 13.77 ns | 0.75 ns | 1.00 | 0.00 | 0.0055 | - | - | 24 B | +// | PixelOperations_Specialized | Job-OPAORC | .NET Core 2.1 | 64 | 228.5 ns | 41.41 ns | 2.27 ns | 1.04 | 0.01 | - | - | - | - | +// | | | | | | | | | | | | | | +// | PixelOperations_Base | Job-VPSIRL | .NET Core 3.1 | 64 | 213.6 ns | 12.47 ns | 0.68 ns | 1.00 | 0.00 | 0.0057 | - | - | 24 B | +// | PixelOperations_Specialized | Job-VPSIRL | .NET Core 3.1 | 64 | 217.0 ns | 9.95 ns | 0.55 ns | 1.02 | 0.01 | - | - | - | - | +// | | | | | | | | | | | | | | +// | PixelOperations_Base | Job-OIBEDX | .NET 4.7.2 | 256 | 829.0 ns | 242.93 ns | 13.32 ns | 1.00 | 0.00 | 0.0057 | - | - | 24 B | +// | PixelOperations_Specialized | Job-OIBEDX | .NET 4.7.2 | 256 | 448.9 ns | 4.04 ns | 0.22 ns | 0.54 | 0.01 | - | - | - | - | +// | | | | | | | | | | | | | | +// | PixelOperations_Base | Job-OPAORC | .NET Core 2.1 | 256 | 863.0 ns | 1,253.26 ns | 68.70 ns | 1.00 | 0.00 | 0.0048 | - | - | 24 B | +// | PixelOperations_Specialized | Job-OPAORC | .NET Core 2.1 | 256 | 309.2 ns | 66.16 ns | 3.63 ns | 0.36 | 0.03 | - | - | - | - | +// | | | | | | | | | | | | | | +// | PixelOperations_Base | Job-VPSIRL | .NET Core 3.1 | 256 | 737.0 ns | 253.90 ns | 13.92 ns | 1.00 | 0.00 | 0.0057 | - | - | 24 B | +// | PixelOperations_Specialized | Job-VPSIRL | .NET Core 3.1 | 256 | 212.3 ns | 1.07 ns | 0.06 ns | 0.29 | 0.01 | - | - | - | - | +// | | | | | | | | | | | | | | +// | PixelOperations_Base | Job-OIBEDX | .NET 4.7.2 | 2048 | 5,625.6 ns | 404.35 ns | 22.16 ns | 1.00 | 0.00 | - | - | - | 24 B | +// | PixelOperations_Specialized | Job-OIBEDX | .NET 4.7.2 | 2048 | 1,974.1 ns | 229.84 ns | 12.60 ns | 0.35 | 0.00 | - | - | - | - | +// | | | | | | | | | | | | | | +// | PixelOperations_Base | Job-OPAORC | .NET Core 2.1 | 2048 | 5,467.2 ns | 537.29 ns | 29.45 ns | 1.00 | 0.00 | - | - | - | 24 B | +// | PixelOperations_Specialized | Job-OPAORC | .NET Core 2.1 | 2048 | 1,985.5 ns | 4,714.23 ns | 258.40 ns | 0.36 | 0.05 | - | - | - | - | +// | | | | | | | | | | | | | | +// | PixelOperations_Base | Job-VPSIRL | .NET Core 3.1 | 2048 | 5,888.2 ns | 1,622.23 ns | 88.92 ns | 1.00 | 0.00 | - | - | - | 24 B | +// | PixelOperations_Specialized | Job-VPSIRL | .NET Core 3.1 | 2048 | 1,165.0 ns | 191.71 ns | 10.51 ns | 0.20 | 0.00 | - | - | - | - | diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgba32.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgba32.cs index 145bf9889b..9ae3b073d4 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgba32.cs +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgba32.cs @@ -13,7 +13,7 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk { - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.ShortCore31))] public class ToVector4_Rgba32 : ToVector4 { [Benchmark] @@ -52,6 +52,17 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk SimdUtils.ExtendedIntrinsics.ByteToNormalizedFloat(sBytes, dFloats); } +#if SUPPORTS_RUNTIME_INTRINSICS + [Benchmark] + public void HwIntrinsics() + { + Span sBytes = MemoryMarshal.Cast(this.source.GetSpan()); + Span dFloats = MemoryMarshal.Cast(this.destination.GetSpan()); + + SimdUtils.HwIntrinsics.ByteToNormalizedFloat(sBytes, dFloats); + } +#endif + // [Benchmark] public void ExtendedIntrinsics_BulkConvertByteToNormalizedFloat_2Loops() { diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/UnPremultiplyVector4.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/UnPremultiplyVector4.cs new file mode 100644 index 0000000000..aa73bc3d01 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Color/Bulk/UnPremultiplyVector4.cs @@ -0,0 +1,68 @@ +// 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; +using BenchmarkDotNet.Attributes; + +namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk +{ + [Config(typeof(Config.ShortCore31))] + public class UnPremultiplyVector4 + { + private static readonly Vector4[] Vectors = CreateVectors(); + + [Benchmark(Baseline = true)] + public void UnPremultiplyBaseline() + { + 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); + } + } + + [Benchmark] + public void UnPremultiply() + { + Numerics.UnPremultiply(Vectors); + } + + [MethodImpl(InliningOptions.ShortMethod)] + private static void UnPremultiply(ref Vector4 source) + { + float w = source.W; + source /= w; + source.W = w; + } + + private static Vector4[] CreateVectors() + { + var rnd = new Random(42); + return GenerateRandomVectorArray(rnd, 2048, 0, 1); + } + + private static Vector4[] GenerateRandomVectorArray(Random rnd, int length, float minVal, float maxVal) + { + var values = new Vector4[length]; + + for (int i = 0; i < length; i++) + { + ref Vector4 v = ref values[i]; + v.X = GetRandomFloat(rnd, minVal, maxVal); + v.Y = GetRandomFloat(rnd, minVal, maxVal); + v.Z = GetRandomFloat(rnd, minVal, maxVal); + v.W = GetRandomFloat(rnd, minVal, maxVal); + } + + return values; + } + + private static float GetRandomFloat(Random rnd, float minVal, float maxVal) + => ((float)rnd.NextDouble() * (maxVal - minVal)) + minVal; + } +} diff --git a/tests/ImageSharp.Benchmarks/Color/YcbCrToRgb.cs b/tests/ImageSharp.Benchmarks/Color/YcbCrToRgb.cs index c962886d1c..07707029a0 100644 --- a/tests/ImageSharp.Benchmarks/Color/YcbCrToRgb.cs +++ b/tests/ImageSharp.Benchmarks/Color/YcbCrToRgb.cs @@ -1,12 +1,11 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. +using System.Numerics; +using BenchmarkDotNet.Attributes; + namespace SixLabors.ImageSharp.Benchmarks { - using System.Numerics; - - using BenchmarkDotNet.Attributes; - public class YcbCrToRgb { [Benchmark(Baseline = true, Description = "Floating Point Conversion")] @@ -19,9 +18,9 @@ namespace SixLabors.ImageSharp.Benchmarks int ccb = cb - 128; int ccr = cr - 128; - byte r = (byte)(y + (1.402F * ccr)).Clamp(0, 255); - byte g = (byte)(y - (0.34414F * ccb) - (0.71414F * ccr)).Clamp(0, 255); - byte b = (byte)(y + (1.772F * ccb)).Clamp(0, 255); + byte r = (byte)Numerics.Clamp(y + (1.402F * ccr), 0, 255); + byte g = (byte)Numerics.Clamp(y - (0.34414F * ccb) - (0.71414F * ccr), 0, 255); + byte b = (byte)Numerics.Clamp(y + (1.772F * ccb), 0, 255); return new Vector3(r, g, b); } @@ -42,9 +41,9 @@ namespace SixLabors.ImageSharp.Benchmarks int g1 = 731 * ccr; // (0.71414F * 1024) + .5F int b0 = 1815 * ccb; // (1.772F * 1024) + .5F - byte r = (byte)(y + (r0 >> 10)).Clamp(0, 255); - byte g = (byte)(y - (g0 >> 10) - (g1 >> 10)).Clamp(0, 255); - byte b = (byte)(y + (b0 >> 10)).Clamp(0, 255); + byte r = (byte)Numerics.Clamp(y + (r0 >> 10), 0, 255); + byte g = (byte)Numerics.Clamp(y - (g0 >> 10) - (g1 >> 10), 0, 255); + byte b = (byte)Numerics.Clamp(y + (b0 >> 10), 0, 255); return new Vector3(r, g, b); } diff --git a/tests/ImageSharp.Benchmarks/Config.HwIntrinsics.cs b/tests/ImageSharp.Benchmarks/Config.HwIntrinsics.cs new file mode 100644 index 0000000000..5ceb4c8a00 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Config.HwIntrinsics.cs @@ -0,0 +1,84 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +#if SUPPORTS_RUNTIME_INTRINSICS +using System.Runtime.Intrinsics.X86; +#endif +using BenchmarkDotNet.Environments; +using BenchmarkDotNet.Jobs; + +namespace SixLabors.ImageSharp.Benchmarks +{ + public partial class Config + { + private const string On = "1"; + private const string Off = "0"; + + // See https://github.com/SixLabors/ImageSharp/pull/1229#discussion_r440477861 + // * EnableHWIntrinsic + // * EnableSSE + // * EnableSSE2 + // * EnableAES + // * EnablePCLMULQDQ + // * EnableSSE3 + // * EnableSSSE3 + // * EnableSSE41 + // * EnableSSE42 + // * EnablePOPCNT + // * EnableAVX + // * EnableFMA + // * EnableAVX2 + // * EnableBMI1 + // * EnableBMI2 + // * EnableLZCNT + // + // `FeatureSIMD` ends up impacting all SIMD support(including `System.Numerics`) but not things + // like `LZCNT`, `BMI1`, or `BMI2` + // `EnableSSE3_4` is a legacy switch that exists for compat and is basically the same as `EnableSSE3` + private const string EnableAES = "COMPlus_EnableAES"; + private const string EnableAVX = "COMPlus_EnableAVX"; + private const string EnableAVX2 = "COMPlus_EnableAVX2"; + private const string EnableBMI1 = "COMPlus_EnableBMI1"; + private const string EnableBMI2 = "COMPlus_EnableBMI2"; + private const string EnableFMA = "COMPlus_EnableFMA"; + private const string EnableHWIntrinsic = "COMPlus_EnableHWIntrinsic"; + private const string EnableLZCNT = "COMPlus_EnableLZCNT"; + private const string EnablePCLMULQDQ = "COMPlus_EnablePCLMULQDQ"; + private const string EnablePOPCNT = "COMPlus_EnablePOPCNT"; + private const string EnableSSE = "COMPlus_EnableSSE"; + private const string EnableSSE2 = "COMPlus_EnableSSE2"; + private const string EnableSSE3 = "COMPlus_EnableSSE3"; + private const string EnableSSE3_4 = "COMPlus_EnableSSE3_4"; + private const string EnableSSE41 = "COMPlus_EnableSSE41"; + private const string EnableSSE42 = "COMPlus_EnableSSE42"; + private const string EnableSSSE3 = "COMPlus_EnableSSSE3"; + private const string FeatureSIMD = "COMPlus_FeatureSIMD"; + + public class HwIntrinsics_SSE_AVX : Config + { + public HwIntrinsics_SSE_AVX() + { + this.AddJob(Job.Default.WithRuntime(CoreRuntime.Core31) + .WithEnvironmentVariables( + new EnvironmentVariable(EnableHWIntrinsic, Off), + new EnvironmentVariable(FeatureSIMD, Off)) + .WithId("1. No HwIntrinsics").AsBaseline()); + +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx.IsSupported) + { + this.AddJob(Job.Default.WithRuntime(CoreRuntime.Core31) + .WithId("2. AVX")); + } + + if (Sse.IsSupported) + { + this.AddJob(Job.Default.WithRuntime(CoreRuntime.Core31) + .WithEnvironmentVariables(new EnvironmentVariable(EnableAVX, Off)) + .WithId("3. SSE")); + } +#endif + } + } + } +} diff --git a/tests/ImageSharp.Benchmarks/Config.cs b/tests/ImageSharp.Benchmarks/Config.cs index f9240779b9..0c40b482ad 100644 --- a/tests/ImageSharp.Benchmarks/Config.cs +++ b/tests/ImageSharp.Benchmarks/Config.cs @@ -1,7 +1,7 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -#if Windows_NT +#if OS_WINDOWS using System.Security.Principal; using BenchmarkDotNet.Diagnostics.Windows; #endif @@ -12,48 +12,45 @@ using BenchmarkDotNet.Jobs; namespace SixLabors.ImageSharp.Benchmarks { - public class Config : ManualConfig + public partial class Config : ManualConfig { public Config() { - this.Add(MemoryDiagnoser.Default); + this.AddDiagnoser(MemoryDiagnoser.Default); -#if Windows_NT +#if OS_WINDOWS if (this.IsElevated) { - this.Add(new NativeMemoryProfiler()); + this.AddDiagnoser(new NativeMemoryProfiler()); } #endif } - public class ShortClr : Config + public class MultiFramework : Config { - public ShortClr() - { - this.Add( - Job.Default.With(ClrRuntime.Net472).WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3), - Job.Default.With(CoreRuntime.Core31).WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3), - Job.Default.With(CoreRuntime.Core21).WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3)); - } + public MultiFramework() => this.AddJob( + Job.Default.WithRuntime(ClrRuntime.Net472), + Job.Default.WithRuntime(CoreRuntime.Core21), + Job.Default.WithRuntime(CoreRuntime.Core31)); } - public class ShortCore31 : Config + public class ShortMultiFramework : Config { - public ShortCore31() - { - this.Add(Job.Default.With(CoreRuntime.Core31).WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3)); - } + public ShortMultiFramework() => this.AddJob( + Job.Default.WithRuntime(ClrRuntime.Net472).WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3), + Job.Default.WithRuntime(CoreRuntime.Core21).WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3), + Job.Default.WithRuntime(CoreRuntime.Core31).WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3)); } -#if Windows_NT - private bool IsElevated + public class ShortCore31 : Config { - get - { - return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator); - } + public ShortCore31() + => this.AddJob(Job.Default.WithRuntime(CoreRuntime.Core31).WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3)); } + +#if OS_WINDOWS + private bool IsElevated => new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator); #endif } } diff --git a/tests/ImageSharp.Benchmarks/Format/Jpeg/Components/Encoder/YCbCrForwardConverterBenchmark.cs b/tests/ImageSharp.Benchmarks/Format/Jpeg/Components/Encoder/YCbCrForwardConverterBenchmark.cs new file mode 100644 index 0000000000..1db4072932 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Format/Jpeg/Components/Encoder/YCbCrForwardConverterBenchmark.cs @@ -0,0 +1,56 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.Formats.Jpeg.Components; +using SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Benchmarks.Format.Jpeg.Components.Encoder +{ + public class YCbCrForwardConverterBenchmark + { + private RgbToYCbCrConverterLut converter; + private Rgb24[] data; + + [GlobalSetup] + public void Setup() + { + this.converter = RgbToYCbCrConverterLut.Create(); + + var r = new Random(42); + this.data = new Rgb24[64]; + + var d = new byte[3]; + for (int i = 0; i < this.data.Length; i++) + { + r.NextBytes(d); + this.data[i] = new Rgb24(d[0], d[1], d[2]); + } + } + + [Benchmark(Baseline = true)] + public void ConvertLut() + { + Block8x8F y = default; + Block8x8F cb = default; + Block8x8F cr = default; + + this.converter.Convert(this.data.AsSpan(), ref y, ref cb, ref cr); + } + + [Benchmark] + public void ConvertVectorized() + { + Block8x8F y = default; + Block8x8F cb = default; + Block8x8F cr = default; + + if (RgbToYCbCrConverterVectorized.IsSupported) + { + RgbToYCbCrConverterVectorized.Convert(this.data.AsSpan(), ref y, ref cb, ref cr); + } + } + } +} diff --git a/tests/ImageSharp.Benchmarks/General/Adler32Benchmark.cs b/tests/ImageSharp.Benchmarks/General/Adler32Benchmark.cs index eba4bcbb43..2d0fce0a01 100644 --- a/tests/ImageSharp.Benchmarks/General/Adler32Benchmark.cs +++ b/tests/ImageSharp.Benchmarks/General/Adler32Benchmark.cs @@ -8,7 +8,7 @@ using SharpAdler32 = ICSharpCode.SharpZipLib.Checksum.Adler32; namespace SixLabors.ImageSharp.Benchmarks.General { - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.ShortMultiFramework))] public class Adler32Benchmark { private byte[] data; diff --git a/tests/ImageSharp.Benchmarks/General/BasicMath/ClampSpan.cs b/tests/ImageSharp.Benchmarks/General/BasicMath/ClampSpan.cs new file mode 100644 index 0000000000..59e2d68c9d --- /dev/null +++ b/tests/ImageSharp.Benchmarks/General/BasicMath/ClampSpan.cs @@ -0,0 +1,57 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using BenchmarkDotNet.Attributes; + +namespace SixLabors.ImageSharp.Benchmarks.General.BasicMath +{ + public class ClampSpan + { + private static readonly int[] A = new int[2048]; + private static readonly int[] B = new int[2048]; + + public void Setup() + { + var r = new Random(); + + for (int i = 0; i < A.Length; i++) + { + int x = r.Next(); + A[i] = x; + B[i] = x; + } + } + + [Benchmark(Baseline = true)] + public void ClampNoIntrinsics() + { + for (int i = 0; i < A.Length; i++) + { + ref int x = ref A[i]; + x = Numerics.Clamp(x, 64, 128); + } + } + + [Benchmark] + public void ClampVectorIntrinsics() + { + Numerics.Clamp(B, 64, 128); + } + } +} + +// 23-11-2020 +// ########## +// +// BenchmarkDotNet = v0.12.1, OS = Windows 10.0.19041.630(2004 /?/ 20H1) +// Intel Core i7-8650U CPU 1.90GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores +// .NET Core SDK=5.0.100 +// [Host] : .NET Core 3.1.10 (CoreCLR 4.700.20.51601, CoreFX 4.700.20.51901), X64 RyuJIT +// DefaultJob : .NET Core 3.1.10 (CoreCLR 4.700.20.51601, CoreFX 4.700.20.51901), X64 RyuJIT +// +// +// | Method | Mean | Error | StdDev | Ratio | +// |---------------------- |-----------:| ---------:| ----------:| ------:| +// | ClampNoIntrinsics | 3,629.9 ns | 70.80 ns | 129.47 ns | 1.00 | +// | ClampVectorIntrinsics | 131.9 ns | 2.68 ns | 6.66 ns | 0.04 | diff --git a/tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoConstant.cs b/tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoConstant.cs index 55e26372b0..27ae787bca 100644 --- a/tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoConstant.cs +++ b/tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoConstant.cs @@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.BasicMath [Benchmark] public int Bitwise() { - return ImageMaths.Modulo8(this.value); + return Numerics.Modulo8(this.value); } } } diff --git a/tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoVariable.cs b/tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoVariable.cs index 9da7b9fdf3..d336015a0a 100644 --- a/tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoVariable.cs +++ b/tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoVariable.cs @@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.BasicMath [Benchmark] public int Bitwise() { - return ImageMaths.ModuloP2(this.value, this.m); + return Numerics.ModuloP2(this.value, this.m); } // RESULTS: diff --git a/tests/ImageSharp.Benchmarks/General/CopyBuffers.cs b/tests/ImageSharp.Benchmarks/General/CopyBuffers.cs index 96a95942cb..d21e44a1cd 100644 --- a/tests/ImageSharp.Benchmarks/General/CopyBuffers.cs +++ b/tests/ImageSharp.Benchmarks/General/CopyBuffers.cs @@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General /// - Span.CopyTo() has terrible performance on classic .NET Framework /// - Buffer.MemoryCopy() performance is good enough for all sizes (but needs pinning) /// - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.ShortMultiFramework))] public class CopyBuffers { private byte[] destArray; diff --git a/tests/ImageSharp.Benchmarks/General/Crc32Benchmark.cs b/tests/ImageSharp.Benchmarks/General/Crc32Benchmark.cs index 2dcf036278..0153ca8b1e 100644 --- a/tests/ImageSharp.Benchmarks/General/Crc32Benchmark.cs +++ b/tests/ImageSharp.Benchmarks/General/Crc32Benchmark.cs @@ -8,7 +8,7 @@ using SharpCrc32 = ICSharpCode.SharpZipLib.Checksum.Crc32; namespace SixLabors.ImageSharp.Benchmarks.General { - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.ShortMultiFramework))] public class Crc32Benchmark { private byte[] data; diff --git a/tests/ImageSharp.Benchmarks/General/GetSetPixel.cs b/tests/ImageSharp.Benchmarks/General/GetSetPixel.cs new file mode 100644 index 0000000000..6bb269e4ce --- /dev/null +++ b/tests/ImageSharp.Benchmarks/General/GetSetPixel.cs @@ -0,0 +1,28 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System.Drawing; +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Benchmarks +{ + public class GetSetPixel + { + [Benchmark(Baseline = true, Description = "System.Drawing GetSet pixel")] + public System.Drawing.Color GetSetSystemDrawing() + { + using var source = new Bitmap(400, 400); + source.SetPixel(200, 200, System.Drawing.Color.White); + return source.GetPixel(200, 200); + } + + [Benchmark(Description = "ImageSharp GetSet pixel")] + public Rgba32 GetSetImageSharp() + { + using var image = new Image(400, 400); + image[200, 200] = Color.White; + return image[200, 200]; + } + } +} diff --git a/tests/ImageSharp.Benchmarks/General/IO/BufferedStreams.cs b/tests/ImageSharp.Benchmarks/General/IO/BufferedStreams.cs index f2ff49d4e9..f5cf5211ed 100644 --- a/tests/ImageSharp.Benchmarks/General/IO/BufferedStreams.cs +++ b/tests/ImageSharp.Benchmarks/General/IO/BufferedStreams.cs @@ -8,7 +8,7 @@ using SixLabors.ImageSharp.IO; namespace SixLabors.ImageSharp.Benchmarks.IO { - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.ShortMultiFramework))] public class BufferedStreams { private readonly byte[] buffer = CreateTestBytes(); diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs index 7d6c2efedf..a933f890fc 100644 --- a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs @@ -168,49 +168,27 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion [Benchmark] public void PixelConverter_Rgba32_ToArgb32() { - ref uint sBase = ref Unsafe.As(ref this.PermutedRunnerRgbaToArgb.Source[0]); - ref uint dBase = ref Unsafe.As(ref this.PermutedRunnerRgbaToArgb.Dest[0]); + Span source = MemoryMarshal.Cast(this.PermutedRunnerRgbaToArgb.Source); + Span dest = MemoryMarshal.Cast(this.PermutedRunnerRgbaToArgb.Dest); - for (int i = 0; i < this.Count; i++) - { - uint s = Unsafe.Add(ref sBase, i); - Unsafe.Add(ref dBase, i) = PixelConverter.FromRgba32.ToArgb32(s); - } - } - - [Benchmark] - public void PixelConverter_Rgba32_ToArgb32_CopyThenWorkOnSingleBuffer() - { - Span source = MemoryMarshal.Cast(this.PermutedRunnerRgbaToArgb.Source); - Span dest = MemoryMarshal.Cast(this.PermutedRunnerRgbaToArgb.Dest); - source.CopyTo(dest); - - ref uint dBase = ref MemoryMarshal.GetReference(dest); - - for (int i = 0; i < this.Count; i++) - { - uint s = Unsafe.Add(ref dBase, i); - Unsafe.Add(ref dBase, i) = PixelConverter.FromRgba32.ToArgb32(s); - } + PixelConverter.FromRgba32.ToArgb32(source, dest); } /* RESULTS: - Method | Count | Mean | Error | StdDev | Scaled | ScaledSD | - ---------------------------------------------------------- |------ |-----------:|-----------:|-----------:|-------:|---------:| - ByRef | 256 | 328.7 ns | 6.6141 ns | 6.1868 ns | 1.00 | 0.00 | - ByVal | 256 | 322.0 ns | 4.3541 ns | 4.0728 ns | 0.98 | 0.02 | - FromBytes | 256 | 321.5 ns | 3.3499 ns | 3.1335 ns | 0.98 | 0.02 | - InlineShuffle | 256 | 330.7 ns | 4.2525 ns | 3.9778 ns | 1.01 | 0.02 | - PixelConverter_Rgba32_ToArgb32 | 256 | 167.4 ns | 0.6357 ns | 0.5309 ns | 0.51 | 0.01 | - PixelConverter_Rgba32_ToArgb32_CopyThenWorkOnSingleBuffer | 256 | 196.6 ns | 0.8929 ns | 0.7915 ns | 0.60 | 0.01 | - | | | | | | | - ByRef | 2048 | 2,534.4 ns | 8.2947 ns | 6.9265 ns | 1.00 | 0.00 | - ByVal | 2048 | 2,638.5 ns | 52.6843 ns | 70.3320 ns | 1.04 | 0.03 | - FromBytes | 2048 | 2,517.2 ns | 40.8055 ns | 38.1695 ns | 0.99 | 0.01 | - InlineShuffle | 2048 | 2,546.5 ns | 21.2506 ns | 19.8778 ns | 1.00 | 0.01 | - PixelConverter_Rgba32_ToArgb32 | 2048 | 1,265.7 ns | 5.1397 ns | 4.5562 ns | 0.50 | 0.00 | - PixelConverter_Rgba32_ToArgb32_CopyThenWorkOnSingleBuffer | 2048 | 1,410.3 ns | 11.1939 ns | 9.9231 ns | 0.56 | 0.00 | - */ + | Method | Count | Mean | Error | StdDev | Median | Ratio | RatioSD | + |------------------------------- |------ |------------:|----------:|----------:|------------:|------:|--------:| + | ByRef | 256 | 288.84 ns | 19.601 ns | 52.319 ns | 268.10 ns | 1.00 | 0.00 | + | ByVal | 256 | 267.97 ns | 1.831 ns | 1.713 ns | 267.85 ns | 0.77 | 0.18 | + | FromBytes | 256 | 266.81 ns | 2.427 ns | 2.270 ns | 266.47 ns | 0.76 | 0.18 | + | InlineShuffle | 256 | 291.41 ns | 5.820 ns | 5.444 ns | 290.17 ns | 0.83 | 0.19 | + | PixelConverter_Rgba32_ToArgb32 | 256 | 38.62 ns | 0.431 ns | 0.403 ns | 38.68 ns | 0.11 | 0.03 | + | | | | | | | | | + | ByRef | 2048 | 2,197.69 ns | 15.826 ns | 14.804 ns | 2,197.25 ns | 1.00 | 0.00 | + | ByVal | 2048 | 2,226.81 ns | 44.266 ns | 62.054 ns | 2,197.17 ns | 1.03 | 0.04 | + | FromBytes | 2048 | 2,181.35 ns | 18.033 ns | 16.868 ns | 2,185.97 ns | 0.99 | 0.01 | + | InlineShuffle | 2048 | 2,233.10 ns | 27.673 ns | 24.531 ns | 2,229.78 ns | 1.02 | 0.01 | + | PixelConverter_Rgba32_ToArgb32 | 2048 | 139.90 ns | 2.152 ns | 3.825 ns | 138.70 ns | 0.06 | 0.00 | + */ } } diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_PackFromRgbPlanes.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_PackFromRgbPlanes.cs new file mode 100644 index 0000000000..eade8e0c43 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_PackFromRgbPlanes.cs @@ -0,0 +1,286 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +#if SUPPORTS_RUNTIME_INTRINSICS +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +#endif +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.PixelFormats; + +namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion +{ + public unsafe class PixelConversion_PackFromRgbPlanes + { + private byte[] rBuf; + private byte[] gBuf; + private byte[] bBuf; + private Rgb24[] rgbBuf; + private Rgba32[] rgbaBuf; + + private float[] rFloat; + private float[] gFloat; + private float[] bFloat; + + private float[] rgbaFloat; + + [Params(1024)] + public int Count { get; set; } + + [GlobalSetup] + public void Setup() + { + this.rBuf = new byte[this.Count]; + this.gBuf = new byte[this.Count]; + this.bBuf = new byte[this.Count]; + this.rgbBuf = new Rgb24[this.Count + 3]; // padded + this.rgbaBuf = new Rgba32[this.Count]; + + this.rFloat = new float[this.Count]; + this.gFloat = new float[this.Count]; + this.bFloat = new float[this.Count]; + + this.rgbaFloat = new float[this.Count * 4]; + } + + // [Benchmark] + public void Rgb24_Scalar_PerElement_Pinned() + { + fixed (byte* r = &this.rBuf[0]) + fixed (byte* g = &this.gBuf[0]) + fixed (byte* b = &this.bBuf[0]) + fixed (Rgb24* rgb = &this.rgbBuf[0]) + { + for (int i = 0; i < this.Count; i++) + { + Rgb24* d = rgb + i; + d->R = r[i]; + d->G = g[i]; + d->B = b[i]; + } + } + } + + [Benchmark] + public void Rgb24_Scalar_PerElement_Span() + { + Span r = this.rBuf; + Span g = this.rBuf; + Span b = this.rBuf; + Span rgb = this.rgbBuf; + + for (int i = 0; i < r.Length; i++) + { + ref Rgb24 d = ref rgb[i]; + d.R = r[i]; + d.G = g[i]; + d.B = b[i]; + } + } + + [Benchmark] + public void Rgb24_Scalar_PerElement_Unsafe() + { + ref byte r = ref this.rBuf[0]; + ref byte g = ref this.rBuf[0]; + ref byte b = ref this.rBuf[0]; + ref Rgb24 rgb = ref this.rgbBuf[0]; + + for (int i = 0; i < this.Count; i++) + { + ref Rgb24 d = ref Unsafe.Add(ref rgb, i); + d.R = Unsafe.Add(ref r, i); + d.G = Unsafe.Add(ref g, i); + d.B = Unsafe.Add(ref b, i); + } + } + + [Benchmark] + public void Rgb24_Scalar_PerElement_Batched8() + { + ref Byte8 r = ref Unsafe.As(ref this.rBuf[0]); + ref Byte8 g = ref Unsafe.As(ref this.rBuf[0]); + ref Byte8 b = ref Unsafe.As(ref this.rBuf[0]); + ref Rgb24 rgb = ref this.rgbBuf[0]; + + int count = this.Count / 8; + for (int i = 0; i < count; i++) + { + ref Rgb24 d0 = ref Unsafe.Add(ref rgb, i * 8); + ref Rgb24 d1 = ref Unsafe.Add(ref d0, 1); + ref Rgb24 d2 = ref Unsafe.Add(ref d0, 2); + ref Rgb24 d3 = ref Unsafe.Add(ref d0, 3); + ref Rgb24 d4 = ref Unsafe.Add(ref d0, 4); + ref Rgb24 d5 = ref Unsafe.Add(ref d0, 5); + ref Rgb24 d6 = ref Unsafe.Add(ref d0, 6); + ref Rgb24 d7 = ref Unsafe.Add(ref d0, 7); + + ref Byte8 rr = ref Unsafe.Add(ref r, i); + ref Byte8 gg = ref Unsafe.Add(ref g, i); + ref Byte8 bb = ref Unsafe.Add(ref b, i); + + d0.R = rr.V0; + d0.G = gg.V0; + d0.B = bb.V0; + + d1.R = rr.V1; + d1.G = gg.V1; + d1.B = bb.V1; + + d2.R = rr.V2; + d2.G = gg.V2; + d2.B = bb.V2; + + d3.R = rr.V3; + d3.G = gg.V3; + d3.B = bb.V3; + + d4.R = rr.V4; + d4.G = gg.V4; + d4.B = bb.V4; + + d5.R = rr.V5; + d5.G = gg.V5; + d5.B = bb.V5; + + d6.R = rr.V6; + d6.G = gg.V6; + d6.B = bb.V6; + + d7.R = rr.V7; + d7.G = gg.V7; + d7.B = bb.V7; + } + } + + [Benchmark] + public void Rgb24_Scalar_PerElement_Batched4() + { + ref Byte4 r = ref Unsafe.As(ref this.rBuf[0]); + ref Byte4 g = ref Unsafe.As(ref this.rBuf[0]); + ref Byte4 b = ref Unsafe.As(ref this.rBuf[0]); + ref Rgb24 rgb = ref this.rgbBuf[0]; + + int count = this.Count / 4; + for (int i = 0; i < count; i++) + { + ref Rgb24 d0 = ref Unsafe.Add(ref rgb, i * 4); + ref Rgb24 d1 = ref Unsafe.Add(ref d0, 1); + ref Rgb24 d2 = ref Unsafe.Add(ref d0, 2); + ref Rgb24 d3 = ref Unsafe.Add(ref d0, 3); + + ref Byte4 rr = ref Unsafe.Add(ref r, i); + ref Byte4 gg = ref Unsafe.Add(ref g, i); + ref Byte4 bb = ref Unsafe.Add(ref b, i); + + d0.R = rr.V0; + d0.G = gg.V0; + d0.B = bb.V0; + + d1.R = rr.V1; + d1.G = gg.V1; + d1.B = bb.V1; + + d2.R = rr.V2; + d2.G = gg.V2; + d2.B = bb.V2; + + d3.R = rr.V3; + d3.G = gg.V3; + d3.B = bb.V3; + } + } + +#if SUPPORTS_RUNTIME_INTRINSICS + [Benchmark(Baseline = true)] + public void Rgba32_Avx2_Float() + { + ref Vector256 rBase = ref Unsafe.As>(ref this.rFloat[0]); + ref Vector256 gBase = ref Unsafe.As>(ref this.gFloat[0]); + ref Vector256 bBase = ref Unsafe.As>(ref this.bFloat[0]); + ref Vector256 resultBase = ref Unsafe.As>(ref this.rgbaFloat[0]); + + int count = this.Count / Vector256.Count; + + ref byte control = ref MemoryMarshal.GetReference(SimdUtils.HwIntrinsics.PermuteMaskEvenOdd8x32); + Vector256 vcontrol = Unsafe.As>(ref control); + + var va = Vector256.Create(1F); + + for (int i = 0; i < count; i++) + { + Vector256 r = Unsafe.Add(ref rBase, i); + Vector256 g = Unsafe.Add(ref gBase, i); + Vector256 b = Unsafe.Add(ref bBase, i); + + r = Avx2.PermuteVar8x32(r, vcontrol); + g = Avx2.PermuteVar8x32(g, vcontrol); + b = Avx2.PermuteVar8x32(b, vcontrol); + + Vector256 vte = Avx.UnpackLow(r, b); + Vector256 vto = Avx.UnpackLow(g, va); + + ref Vector256 destination = ref Unsafe.Add(ref resultBase, i * 4); + + destination = Avx.UnpackLow(vte, vto); + Unsafe.Add(ref destination, 1) = Avx.UnpackHigh(vte, vto); + + vte = Avx.UnpackHigh(r, b); + vto = Avx.UnpackHigh(g, va); + + Unsafe.Add(ref destination, 2) = Avx.UnpackLow(vte, vto); + Unsafe.Add(ref destination, 3) = Avx.UnpackHigh(vte, vto); + } + } + + [Benchmark] + public void Rgb24_Avx2_Bytes() + { + ReadOnlySpan r = this.rBuf; + ReadOnlySpan g = this.rBuf; + ReadOnlySpan b = this.rBuf; + Span rgb = this.rgbBuf; + SimdUtils.HwIntrinsics.PackFromRgbPlanesAvx2Reduce(ref r, ref g, ref b, ref rgb); + } + + [Benchmark] + public void Rgba32_Avx2_Bytes() + { + ReadOnlySpan r = this.rBuf; + ReadOnlySpan g = this.rBuf; + ReadOnlySpan b = this.rBuf; + Span rgb = this.rgbaBuf; + SimdUtils.HwIntrinsics.PackFromRgbPlanesAvx2Reduce(ref r, ref g, ref b, ref rgb); + } +#endif + +#pragma warning disable SA1132 + private struct Byte8 + { + public byte V0, V1, V2, V3, V4, V5, V6, V7; + } + + private struct Byte4 + { + public byte V0, V1, V2, V3; + } +#pragma warning restore + + // Results @ Anton's PC, 2020 Dec 05 + // .NET Core 3.1.1 + // Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores + // + // | Method | Count | Mean | Error | StdDev | Ratio | RatioSD | + // |--------------------------------- |------ |-----------:|---------:|---------:|------:|--------:| + // | Rgb24_Scalar_PerElement_Span | 1024 | 1,634.6 ns | 26.56 ns | 24.84 ns | 3.12 | 0.05 | + // | Rgb24_Scalar_PerElement_Unsafe | 1024 | 1,284.7 ns | 4.70 ns | 4.16 ns | 2.46 | 0.01 | + // | Rgb24_Scalar_PerElement_Batched8 | 1024 | 1,182.3 ns | 5.12 ns | 4.27 ns | 2.26 | 0.01 | + // | Rgb24_Scalar_PerElement_Batched4 | 1024 | 1,146.2 ns | 16.38 ns | 14.52 ns | 2.19 | 0.02 | + // | Rgba32_Avx2_Float | 1024 | 522.7 ns | 1.78 ns | 1.39 ns | 1.00 | 0.00 | + // | Rgb24_Avx2_Bytes | 1024 | 243.3 ns | 1.56 ns | 1.30 ns | 0.47 | 0.00 | + // | Rgba32_Avx2_Bytes | 1024 | 146.0 ns | 2.48 ns | 2.32 ns | 0.28 | 0.01 | + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Benchmarks/General/Vectorization/UInt32ToSingle.cs b/tests/ImageSharp.Benchmarks/General/Vectorization/UInt32ToSingle.cs index 15c4b8c054..5ec5f1d18b 100644 --- a/tests/ImageSharp.Benchmarks/General/Vectorization/UInt32ToSingle.cs +++ b/tests/ImageSharp.Benchmarks/General/Vectorization/UInt32ToSingle.cs @@ -8,7 +8,7 @@ using BenchmarkDotNet.Attributes; namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization { - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.ShortMultiFramework))] public class UInt32ToSingle { private float[] data; diff --git a/tests/ImageSharp.Benchmarks/General/Vectorization/WidenBytesToUInt32.cs b/tests/ImageSharp.Benchmarks/General/Vectorization/WidenBytesToUInt32.cs index a0049f9848..20d3bd9d66 100644 --- a/tests/ImageSharp.Benchmarks/General/Vectorization/WidenBytesToUInt32.cs +++ b/tests/ImageSharp.Benchmarks/General/Vectorization/WidenBytesToUInt32.cs @@ -10,7 +10,7 @@ using SixLabors.ImageSharp.Tuples; namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization { - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.ShortMultiFramework))] public class WidenBytesToUInt32 { private byte[] source; diff --git a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj index eaab162ff2..d89cf79fc9 100644 --- a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj +++ b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj @@ -5,7 +5,7 @@ ImageSharp.Benchmarks Exe SixLabors.ImageSharp.Benchmarks - netcoreapp3.1;netcoreapp2.1;net472 + net5.0;netcoreapp3.1;netcoreapp2.1;net472 false false @@ -17,6 +17,7 @@ + @@ -25,7 +26,7 @@ - + @@ -42,7 +43,7 @@ - + diff --git a/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs b/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs index 2b6657a22c..cf78078376 100644 --- a/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs +++ b/tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs @@ -1,21 +1,17 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System; using System.Buffers; using System.Numerics; - using BenchmarkDotNet.Attributes; - using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats.PixelBlenders; namespace SixLabors.ImageSharp.Benchmarks { - using CoreSize = SixLabors.ImageSharp.Size; - - public class PorterDuffBulkVsPixel : BenchmarkBase + public class PorterDuffBulkVsPixel { private Configuration Configuration => Configuration.Default; @@ -30,23 +26,21 @@ namespace SixLabors.ImageSharp.Benchmarks Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); - using (IMemoryOwner buffer = - Configuration.Default.MemoryAllocator.Allocate(destination.Length * 3)) - { - Span destinationSpan = buffer.Slice(0, destination.Length); - Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); - Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); + using IMemoryOwner buffer = + Configuration.Default.MemoryAllocator.Allocate(destination.Length * 3); + Span destinationSpan = buffer.Slice(0, destination.Length); + Span backgroundSpan = buffer.Slice(destination.Length, destination.Length); + Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); - PixelOperations.Instance.ToVector4(this.Configuration, background, backgroundSpan); - PixelOperations.Instance.ToVector4(this.Configuration, source, sourceSpan); + PixelOperations.Instance.ToVector4(this.Configuration, background, backgroundSpan); + PixelOperations.Instance.ToVector4(this.Configuration, source, sourceSpan); - for (int i = 0; i < destination.Length; i++) - { - destinationSpan[i] = PorterDuffFunctions.NormalSrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); - } - - PixelOperations.Instance.FromVector4Destructive(this.Configuration, destinationSpan, destination); + for (int i = 0; i < destination.Length; i++) + { + destinationSpan[i] = PorterDuffFunctions.NormalSrcOver(backgroundSpan[i], sourceSpan[i], amount[i]); } + + PixelOperations.Instance.FromVector4Destructive(this.Configuration, destinationSpan, destination); } private void BulkPixelConvert( @@ -67,44 +61,36 @@ namespace SixLabors.ImageSharp.Benchmarks } [Benchmark(Description = "ImageSharp BulkVectorConvert")] - public CoreSize BulkVectorConvert() + public Size BulkVectorConvert() { - using (var image = new Image(800, 800)) - { - using (IMemoryOwner amounts = Configuration.Default.MemoryAllocator.Allocate(image.Width)) - { - amounts.GetSpan().Fill(1); + using var image = new Image(800, 800); + using IMemoryOwner amounts = Configuration.Default.MemoryAllocator.Allocate(image.Width); + amounts.GetSpan().Fill(1); - Buffer2D pixels = image.GetRootFramePixelBuffer(); - for (int y = 0; y < image.Height; y++) - { - Span span = pixels.GetRowSpan(y); - this.BulkVectorConvert(span, span, span, amounts.GetSpan()); - } - - return new CoreSize(image.Width, image.Height); - } + Buffer2D pixels = image.GetRootFramePixelBuffer(); + for (int y = 0; y < image.Height; y++) + { + Span span = pixels.GetRowSpan(y); + this.BulkVectorConvert(span, span, span, amounts.GetSpan()); } + + return new Size(image.Width, image.Height); } [Benchmark(Description = "ImageSharp BulkPixelConvert")] - public CoreSize BulkPixelConvert() + public Size BulkPixelConvert() { - using (var image = new Image(800, 800)) + using var image = new Image(800, 800); + using IMemoryOwner amounts = Configuration.Default.MemoryAllocator.Allocate(image.Width); + amounts.GetSpan().Fill(1); + Buffer2D pixels = image.GetRootFramePixelBuffer(); + for (int y = 0; y < image.Height; y++) { - using (IMemoryOwner amounts = Configuration.Default.MemoryAllocator.Allocate(image.Width)) - { - amounts.GetSpan().Fill(1); - Buffer2D pixels = image.GetRootFramePixelBuffer(); - for (int y = 0; y < image.Height; y++) - { - Span span = pixels.GetRowSpan(y); - this.BulkPixelConvert(span, span, span, amounts.GetSpan()); - } - - return new CoreSize(image.Width, image.Height); - } + Span span = pixels.GetRowSpan(y); + this.BulkPixelConvert(span, span, span, amounts.GetSpan()); } + + return new Size(image.Width, image.Height); } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Benchmarks/Processing/BokehBlur.cs b/tests/ImageSharp.Benchmarks/Processing/BokehBlur.cs new file mode 100644 index 0000000000..7a1c7260eb --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Processing/BokehBlur.cs @@ -0,0 +1,20 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; + +namespace SixLabors.ImageSharp.Benchmarks.Processing +{ + [Config(typeof(Config.MultiFramework))] + public class BokehBlur + { + [Benchmark] + public void Blur() + { + using var image = new Image(Configuration.Default, 400, 400, Color.White); + image.Mutate(c => c.BokehBlur()); + } + } +} diff --git a/tests/ImageSharp.Benchmarks/Processing/Crop.cs b/tests/ImageSharp.Benchmarks/Processing/Crop.cs new file mode 100644 index 0000000000..9f08adc9dd --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Processing/Crop.cs @@ -0,0 +1,40 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System.Drawing; +using System.Drawing.Drawing2D; +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SDRectangle = System.Drawing.Rectangle; +using SDSize = System.Drawing.Size; + +namespace SixLabors.ImageSharp.Benchmarks.Processing +{ + [Config(typeof(Config.MultiFramework))] + public class Crop + { + [Benchmark(Baseline = true, Description = "System.Drawing Crop")] + public SDSize CropSystemDrawing() + { + using var source = new Bitmap(800, 800); + using var destination = new Bitmap(100, 100); + using var graphics = Graphics.FromImage(destination); + + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.DrawImage(source, new SDRectangle(0, 0, 100, 100), 0, 0, 100, 100, GraphicsUnit.Pixel); + + return destination.Size; + } + + [Benchmark(Description = "ImageSharp Crop")] + public Size CropImageSharp() + { + using var image = new Image(800, 800); + image.Mutate(x => x.Crop(100, 100)); + return new Size(image.Width, image.Height); + } + } +} diff --git a/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs b/tests/ImageSharp.Benchmarks/Processing/DetectEdges.cs similarity index 79% rename from tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs rename to tests/ImageSharp.Benchmarks/Processing/DetectEdges.cs index ce2fa988c7..f3d6d03afb 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/DetectEdges.cs +++ b/tests/ImageSharp.Benchmarks/Processing/DetectEdges.cs @@ -1,18 +1,16 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. +using System.IO; +using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Tests; namespace SixLabors.ImageSharp.Benchmarks { - using System.IO; - - using BenchmarkDotNet.Attributes; - - using SixLabors.ImageSharp.Processing; - using CoreImage = SixLabors.ImageSharp.Image; - - public class DetectEdges : BenchmarkBase + [Config(typeof(Config.MultiFramework))] + public class DetectEdges { private Image image; @@ -21,10 +19,7 @@ namespace SixLabors.ImageSharp.Benchmarks { if (this.image == null) { - using (FileStream stream = File.OpenRead("../ImageSharp.Tests/TestImages/Formats/Bmp/Car.bmp")) - { - this.image = CoreImage.Load(stream); - } + this.image = Image.Load(File.OpenRead(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Bmp.Car))); } } @@ -32,6 +27,7 @@ namespace SixLabors.ImageSharp.Benchmarks public void Cleanup() { this.image.Dispose(); + this.image = null; } [Benchmark(Description = "ImageSharp DetectEdges")] diff --git a/tests/ImageSharp.Benchmarks/Samplers/Diffuse.cs b/tests/ImageSharp.Benchmarks/Processing/Diffuse.cs similarity index 76% rename from tests/ImageSharp.Benchmarks/Samplers/Diffuse.cs rename to tests/ImageSharp.Benchmarks/Processing/Diffuse.cs index 354d105e6e..d706938c80 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Diffuse.cs +++ b/tests/ImageSharp.Benchmarks/Processing/Diffuse.cs @@ -5,31 +5,27 @@ using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; -namespace SixLabors.ImageSharp.Benchmarks.Samplers +namespace SixLabors.ImageSharp.Benchmarks.Processing { - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.MultiFramework))] public class Diffuse { [Benchmark] public Size DoDiffuse() { - using (var image = new Image(Configuration.Default, 800, 800, Color.BlanchedAlmond)) - { - image.Mutate(x => x.Dither(KnownDitherings.FloydSteinberg)); + using var image = new Image(Configuration.Default, 800, 800, Color.BlanchedAlmond); + image.Mutate(x => x.Dither(KnownDitherings.FloydSteinberg)); - return image.Size(); - } + return image.Size(); } [Benchmark] public Size DoDither() { - using (var image = new Image(Configuration.Default, 800, 800, Color.BlanchedAlmond)) - { - image.Mutate(x => x.Dither()); + using var image = new Image(Configuration.Default, 800, 800, Color.BlanchedAlmond); + image.Mutate(x => x.Dither()); - return image.Size(); - } + return image.Size(); } } } diff --git a/tests/ImageSharp.Benchmarks/Samplers/GaussianBlur.cs b/tests/ImageSharp.Benchmarks/Processing/GaussianBlur.cs similarity index 62% rename from tests/ImageSharp.Benchmarks/Samplers/GaussianBlur.cs rename to tests/ImageSharp.Benchmarks/Processing/GaussianBlur.cs index 62d5806037..8a4ab8747c 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/GaussianBlur.cs +++ b/tests/ImageSharp.Benchmarks/Processing/GaussianBlur.cs @@ -7,16 +7,14 @@ using SixLabors.ImageSharp.Processing; namespace SixLabors.ImageSharp.Benchmarks.Samplers { - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.MultiFramework))] public class GaussianBlur { [Benchmark] public void Blur() { - using (var image = new Image(Configuration.Default, 400, 400, Color.White)) - { - image.Mutate(c => c.GaussianBlur()); - } + using var image = new Image(Configuration.Default, 400, 400, Color.White); + image.Mutate(c => c.GaussianBlur()); } } } diff --git a/tests/ImageSharp.Benchmarks/Processing/HistogramEqualization.cs b/tests/ImageSharp.Benchmarks/Processing/HistogramEqualization.cs new file mode 100644 index 0000000000..cfcb69a0a9 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Processing/HistogramEqualization.cs @@ -0,0 +1,52 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System.IO; +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Normalization; +using SixLabors.ImageSharp.Tests; + +namespace SixLabors.ImageSharp.Benchmarks.Processing +{ + [Config(typeof(Config.MultiFramework))] + public class HistogramEqualization + { + private Image image; + + [GlobalSetup] + public void ReadImages() + { + if (this.image == null) + { + this.image = Image.Load(File.OpenRead(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Jpeg.Baseline.HistogramEqImage))); + } + } + + [GlobalCleanup] + public void Cleanup() + { + this.image.Dispose(); + this.image = null; + } + + [Benchmark(Description = "Global Histogram Equalization")] + public void GlobalHistogramEqualization() + => this.image.Mutate(img => img.HistogramEqualization( + new HistogramEqualizationOptions() + { + LuminanceLevels = 256, + Method = HistogramEqualizationMethod.Global + })); + + [Benchmark(Description = "AdaptiveHistogramEqualization (Tile interpolation)")] + public void AdaptiveHistogramEqualization() + => this.image.Mutate(img => img.HistogramEqualization( + new HistogramEqualizationOptions() + { + LuminanceLevels = 256, + Method = HistogramEqualizationMethod.AdaptiveTileInterpolation + })); + } +} diff --git a/tests/ImageSharp.Benchmarks/Samplers/Resize.cs b/tests/ImageSharp.Benchmarks/Processing/Resize.cs similarity index 87% rename from tests/ImageSharp.Benchmarks/Samplers/Resize.cs rename to tests/ImageSharp.Benchmarks/Processing/Resize.cs index 63a85c757d..571c92cc87 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Resize.cs +++ b/tests/ImageSharp.Benchmarks/Processing/Resize.cs @@ -4,47 +4,49 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Globalization; - +using System.IO; using BenchmarkDotNet.Attributes; - using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Tests; +using SDImage = System.Drawing.Image; namespace SixLabors.ImageSharp.Benchmarks { - [Config(typeof(Config.ShortClr))] -#pragma warning disable SA1649 // File name should match first type name - public abstract class ResizeBenchmarkBase -#pragma warning restore SA1649 // File name should match first type name + [Config(typeof(Config.MultiFramework))] + public abstract class Resize where TPixel : unmanaged, IPixel { - protected readonly Configuration Configuration = new Configuration(new JpegConfigurationModule()); + private byte[] bytes = null; private Image sourceImage; - private Bitmap sourceBitmap; + private SDImage sourceBitmap; - [Params("3032-400")] - public virtual string SourceToDest { get; set; } - - protected int SourceSize { get; private set; } + protected Configuration Configuration { get; } = new Configuration(new JpegConfigurationModule()); protected int DestSize { get; private set; } [GlobalSetup] public virtual void Setup() { - string[] stuff = this.SourceToDest.Split('-'); - this.SourceSize = int.Parse(stuff[0], CultureInfo.InvariantCulture); - this.DestSize = int.Parse(stuff[1], CultureInfo.InvariantCulture); - this.sourceImage = new Image(this.Configuration, this.SourceSize, this.SourceSize); - this.sourceBitmap = new Bitmap(this.SourceSize, this.SourceSize); + if (this.bytes is null) + { + this.bytes = File.ReadAllBytes(Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Jpeg.Baseline.Snake)); + + this.sourceImage = Image.Load(this.bytes); + + var ms1 = new MemoryStream(this.bytes); + this.sourceBitmap = SDImage.FromStream(ms1); + this.DestSize = this.sourceBitmap.Width / 2; + } } [GlobalCleanup] public void Cleanup() { + this.bytes = null; this.sourceImage.Dispose(); this.sourceBitmap.Dispose(); } @@ -96,12 +98,10 @@ namespace SixLabors.ImageSharp.Benchmarks protected abstract void ExecuteResizeOperation(IImageProcessingContext ctx); } - public class Resize_Bicubic_Rgba32 : ResizeBenchmarkBase + public class Resize_Bicubic_Rgba32 : Resize { protected override void ExecuteResizeOperation(IImageProcessingContext ctx) - { - ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); - } + => ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); // RESULTS - 2019 April - ResizeWorker: // @@ -133,9 +133,6 @@ namespace SixLabors.ImageSharp.Benchmarks [Params(128, 512, 1024, 8 * 1024)] public int WorkingBufferSizeHintInKilobytes { get; set; } - [Params("3032-400", "4000-300")] - public override string SourceToDest { get; set; } - public override void Setup() { this.Configuration.WorkingBufferSizeHintInBytes = this.WorkingBufferSizeHintInKilobytes * 1024; @@ -143,12 +140,10 @@ namespace SixLabors.ImageSharp.Benchmarks } } - public class Resize_Bicubic_Bgra32 : ResizeBenchmarkBase + public class Resize_Bicubic_Bgra32 : Resize { protected override void ExecuteResizeOperation(IImageProcessingContext ctx) - { - ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); - } + => ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); // RESULTS (2019 April): // @@ -171,12 +166,10 @@ namespace SixLabors.ImageSharp.Benchmarks // 'ImageSharp, MaxDegreeOfParallelism = 1' | Core | Core | 3032 | 400 | 96.96 ms | 7.899 ms | 0.4329 ms | 0.80 | - | - | - | 44512 B | } - public class Resize_Bicubic_Rgb24 : ResizeBenchmarkBase + public class Resize_Bicubic_Rgb24 : Resize { protected override void ExecuteResizeOperation(IImageProcessingContext ctx) - { - ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); - } + => ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic); // RESULTS (2019 April): // @@ -197,12 +190,10 @@ namespace SixLabors.ImageSharp.Benchmarks // 'ImageSharp, MaxDegreeOfParallelism = 1' | Core | Core | 3032 | 400 | 92.47 ms | 5.683 ms | 0.3115 ms | 0.78 | 0.01 | - | - | - | 44512 B | } - public class Resize_BicubicCompand_Rgba32 : ResizeBenchmarkBase + public class Resize_BicubicCompand_Rgba32 : Resize { protected override void ExecuteResizeOperation(IImageProcessingContext ctx) - { - ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic, true); - } + => ctx.Resize(this.DestSize, this.DestSize, KnownResamplers.Bicubic, true); // RESULTS (2019 April): // diff --git a/tests/ImageSharp.Benchmarks/Samplers/Rotate.cs b/tests/ImageSharp.Benchmarks/Processing/Rotate.cs similarity index 81% rename from tests/ImageSharp.Benchmarks/Samplers/Rotate.cs rename to tests/ImageSharp.Benchmarks/Processing/Rotate.cs index 94594c7875..107c47f062 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Rotate.cs +++ b/tests/ImageSharp.Benchmarks/Processing/Rotate.cs @@ -5,20 +5,18 @@ using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; -namespace SixLabors.ImageSharp.Benchmarks.Samplers +namespace SixLabors.ImageSharp.Benchmarks.Processing { - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.MultiFramework))] public class Rotate { [Benchmark] public Size DoRotate() { - using (var image = new Image(Configuration.Default, 400, 400, Color.BlanchedAlmond)) - { - image.Mutate(x => x.Rotate(37.5F)); + using var image = new Image(Configuration.Default, 400, 400, Color.BlanchedAlmond); + image.Mutate(x => x.Rotate(37.5F)); - return image.Size(); - } + return image.Size(); } } } diff --git a/tests/ImageSharp.Benchmarks/Samplers/Skew.cs b/tests/ImageSharp.Benchmarks/Processing/Skew.cs similarity index 81% rename from tests/ImageSharp.Benchmarks/Samplers/Skew.cs rename to tests/ImageSharp.Benchmarks/Processing/Skew.cs index 2758bed7a5..b77f0dcd6b 100644 --- a/tests/ImageSharp.Benchmarks/Samplers/Skew.cs +++ b/tests/ImageSharp.Benchmarks/Processing/Skew.cs @@ -5,20 +5,18 @@ using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; -namespace SixLabors.ImageSharp.Benchmarks.Samplers +namespace SixLabors.ImageSharp.Benchmarks.Processing { - [Config(typeof(Config.ShortClr))] + [Config(typeof(Config.MultiFramework))] public class Skew { [Benchmark] public Size DoSkew() { - using (var image = new Image(Configuration.Default, 400, 400, Color.BlanchedAlmond)) - { - image.Mutate(x => x.Skew(20, 10)); + using var image = new Image(Configuration.Default, 400, 400, Color.BlanchedAlmond); + image.Mutate(x => x.Skew(20, 10)); - return image.Size(); - } + return image.Size(); } } } diff --git a/tests/ImageSharp.Benchmarks/Samplers/Crop.cs b/tests/ImageSharp.Benchmarks/Samplers/Crop.cs deleted file mode 100644 index a62b68557c..0000000000 --- a/tests/ImageSharp.Benchmarks/Samplers/Crop.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using System.Drawing; -using System.Drawing.Drawing2D; -using BenchmarkDotNet.Attributes; - -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; - -using SDRectangle = System.Drawing.Rectangle; -using SDSize = System.Drawing.Size; - -namespace SixLabors.ImageSharp.Benchmarks -{ - [Config(typeof(Config.ShortClr))] - public class Crop : BenchmarkBase - { - [Benchmark(Baseline = true, Description = "System.Drawing Crop")] - public SDSize CropSystemDrawing() - { - using (var source = new Bitmap(800, 800)) - using (var destination = new Bitmap(100, 100)) - using (var graphics = Graphics.FromImage(destination)) - { - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.DrawImage(source, new SDRectangle(0, 0, 100, 100), 0, 0, 100, 100, GraphicsUnit.Pixel); - - return destination.Size; - } - } - - [Benchmark(Description = "ImageSharp Crop")] - public Size CropResizeCore() - { - using (var image = new Image(800, 800)) - { - image.Mutate(x => x.Crop(100, 100)); - return new Size(image.Width, image.Height); - } - } - } -} diff --git a/tests/ImageSharp.Tests.ProfilingSandbox/ImageSharp.Tests.ProfilingSandbox.csproj b/tests/ImageSharp.Tests.ProfilingSandbox/ImageSharp.Tests.ProfilingSandbox.csproj index 7c80316930..220780c58e 100644 --- a/tests/ImageSharp.Tests.ProfilingSandbox/ImageSharp.Tests.ProfilingSandbox.csproj +++ b/tests/ImageSharp.Tests.ProfilingSandbox/ImageSharp.Tests.ProfilingSandbox.csproj @@ -8,10 +8,11 @@ false SixLabors.ImageSharp.Tests.ProfilingSandbox win7-x64 - netcoreapp3.1;netcoreapp2.1;net472 + net5.0;netcoreapp3.1;netcoreapp2.1;net472 SixLabors.ImageSharp.Tests.ProfilingSandbox.Program false + false diff --git a/tests/ImageSharp.Tests.ProfilingSandbox/Program.cs b/tests/ImageSharp.Tests.ProfilingSandbox/Program.cs index 8155c6a584..50a930b6f1 100644 --- a/tests/ImageSharp.Tests.ProfilingSandbox/Program.cs +++ b/tests/ImageSharp.Tests.ProfilingSandbox/Program.cs @@ -31,14 +31,21 @@ namespace SixLabors.ImageSharp.Tests.ProfilingSandbox /// public static void Main(string[] args) { + RunJpegEncoderProfilingTests(); // RunJpegColorProfilingTests(); - RunDecodeJpegProfilingTests(); + // RunDecodeJpegProfilingTests(); // RunToVector4ProfilingTest(); // RunResizeProfilingTest(); Console.ReadLine(); } + private static void RunJpegEncoderProfilingTests() + { + var benchmarks = new JpegProfilingBenchmarks(new ConsoleOutput()); + benchmarks.EncodeJpeg_SingleMidSize(); + } + private static void RunJpegColorProfilingTests() { new JpegColorConverterTests(new ConsoleOutput()).BenchmarkYCbCr(false); @@ -53,7 +60,7 @@ namespace SixLabors.ImageSharp.Tests.ProfilingSandbox private static void RunToVector4ProfilingTest() { - var tests = new PixelOperationsTests.Rgba32OperationsTests(new ConsoleOutput()); + var tests = new PixelOperationsTests.Rgba32_OperationsTests(new ConsoleOutput()); tests.Benchmark_ToVector4(); } diff --git a/tests/ImageSharp.Tests.ruleset b/tests/ImageSharp.Tests.ruleset new file mode 100644 index 0000000000..673f005170 --- /dev/null +++ b/tests/ImageSharp.Tests.ruleset @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Common/SimdUtilsTests.Shuffle.cs b/tests/ImageSharp.Tests/Common/SimdUtilsTests.Shuffle.cs new file mode 100644 index 0000000000..f1bfaa4ad4 --- /dev/null +++ b/tests/ImageSharp.Tests/Common/SimdUtilsTests.Shuffle.cs @@ -0,0 +1,399 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using SixLabors.ImageSharp.Tests.TestUtilities; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Common +{ + public partial class SimdUtilsTests + { + [Theory] + [MemberData(nameof(ArraySizesDivisibleBy4))] + public void BulkShuffleFloat4Channel(int count) + { + static void RunTest(string serialized) + { + // No need to test multiple shuffle controls as the + // pipeline is always the same. + int size = FeatureTestRunner.Deserialize(serialized); + byte control = default(WZYXShuffle4).Control; + + TestShuffleFloat4Channel( + size, + (s, d) => SimdUtils.Shuffle4(s.Span, d.Span, control), + control); + } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, + count, + HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX | HwIntrinsics.DisableSSE); + } + + [Theory] + [MemberData(nameof(ArraySizesDivisibleBy4))] + public void BulkShuffleByte4Channel(int count) + { + static void RunTest(string serialized) + { + int size = FeatureTestRunner.Deserialize(serialized); + + // These cannot be expressed as a theory as you cannot + // use RemoteExecutor within generic methods nor pass + // IShuffle4 to the generic utils method. + WXYZShuffle4 wxyz = default; + TestShuffleByte4Channel( + size, + (s, d) => SimdUtils.Shuffle4(s.Span, d.Span, wxyz), + wxyz.Control); + + WZYXShuffle4 wzyx = default; + TestShuffleByte4Channel( + size, + (s, d) => SimdUtils.Shuffle4(s.Span, d.Span, wzyx), + wzyx.Control); + + YZWXShuffle4 yzwx = default; + TestShuffleByte4Channel( + size, + (s, d) => SimdUtils.Shuffle4(s.Span, d.Span, yzwx), + yzwx.Control); + + ZYXWShuffle4 zyxw = default; + TestShuffleByte4Channel( + size, + (s, d) => SimdUtils.Shuffle4(s.Span, d.Span, zyxw), + zyxw.Control); + + var xwyz = new DefaultShuffle4(2, 1, 3, 0); + TestShuffleByte4Channel( + size, + (s, d) => SimdUtils.Shuffle4(s.Span, d.Span, xwyz), + xwyz.Control); + + var yyyy = new DefaultShuffle4(1, 1, 1, 1); + TestShuffleByte4Channel( + size, + (s, d) => SimdUtils.Shuffle4(s.Span, d.Span, yyyy), + yyyy.Control); + + var wwww = new DefaultShuffle4(3, 3, 3, 3); + TestShuffleByte4Channel( + size, + (s, d) => SimdUtils.Shuffle4(s.Span, d.Span, wwww), + wwww.Control); + } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, + count, + HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableSSE); + } + + [Theory] + [MemberData(nameof(ArraySizesDivisibleBy3))] + public void BulkShuffleByte3Channel(int count) + { + static void RunTest(string serialized) + { + int size = FeatureTestRunner.Deserialize(serialized); + + // These cannot be expressed as a theory as you cannot + // use RemoteExecutor within generic methods nor pass + // IShuffle3 to the generic utils method. + var zyx = new DefaultShuffle3(0, 1, 2); + TestShuffleByte3Channel( + size, + (s, d) => SimdUtils.Shuffle3(s.Span, d.Span, zyx), + zyx.Control); + + var xyz = new DefaultShuffle3(2, 1, 0); + TestShuffleByte3Channel( + size, + (s, d) => SimdUtils.Shuffle3(s.Span, d.Span, xyz), + xyz.Control); + + var yyy = new DefaultShuffle3(1, 1, 1); + TestShuffleByte3Channel( + size, + (s, d) => SimdUtils.Shuffle3(s.Span, d.Span, yyy), + yyy.Control); + + var zzz = new DefaultShuffle3(2, 2, 2); + TestShuffleByte3Channel( + size, + (s, d) => SimdUtils.Shuffle3(s.Span, d.Span, zzz), + zzz.Control); + } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, + count, + HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableSSE); + } + + [Theory] + [MemberData(nameof(ArraySizesDivisibleBy3))] + public void BulkPad3Shuffle4Channel(int count) + { + static void RunTest(string serialized) + { + int size = FeatureTestRunner.Deserialize(serialized); + + // These cannot be expressed as a theory as you cannot + // use RemoteExecutor within generic methods nor pass + // IPad3Shuffle4 to the generic utils method. + XYZWPad3Shuffle4 xyzw = default; + TestPad3Shuffle4Channel( + size, + (s, d) => SimdUtils.Pad3Shuffle4(s.Span, d.Span, xyzw), + xyzw.Control); + + var xwyz = new DefaultPad3Shuffle4(2, 1, 3, 0); + TestPad3Shuffle4Channel( + size, + (s, d) => SimdUtils.Pad3Shuffle4(s.Span, d.Span, xwyz), + xwyz.Control); + + var yyyy = new DefaultPad3Shuffle4(1, 1, 1, 1); + TestPad3Shuffle4Channel( + size, + (s, d) => SimdUtils.Pad3Shuffle4(s.Span, d.Span, yyyy), + yyyy.Control); + + var wwww = new DefaultPad3Shuffle4(3, 3, 3, 3); + TestPad3Shuffle4Channel( + size, + (s, d) => SimdUtils.Pad3Shuffle4(s.Span, d.Span, wwww), + wwww.Control); + } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, + count, + HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableSSE); + } + + [Theory] + [MemberData(nameof(ArraySizesDivisibleBy4))] + public void BulkShuffle4Slice3Channel(int count) + { + static void RunTest(string serialized) + { + int size = FeatureTestRunner.Deserialize(serialized); + + // These cannot be expressed as a theory as you cannot + // use RemoteExecutor within generic methods nor pass + // IShuffle4Slice3 to the generic utils method. + XYZWShuffle4Slice3 xyzw = default; + TestShuffle4Slice3Channel( + size, + (s, d) => SimdUtils.Shuffle4Slice3(s.Span, d.Span, xyzw), + xyzw.Control); + + var xwyz = new DefaultShuffle4Slice3(2, 1, 3, 0); + TestShuffle4Slice3Channel( + size, + (s, d) => SimdUtils.Shuffle4Slice3(s.Span, d.Span, xwyz), + xwyz.Control); + + var yyyy = new DefaultShuffle4Slice3(1, 1, 1, 1); + TestShuffle4Slice3Channel( + size, + (s, d) => SimdUtils.Shuffle4Slice3(s.Span, d.Span, yyyy), + yyyy.Control); + + var wwww = new DefaultShuffle4Slice3(3, 3, 3, 3); + TestShuffle4Slice3Channel( + size, + (s, d) => SimdUtils.Shuffle4Slice3(s.Span, d.Span, wwww), + wwww.Control); + } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, + count, + HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX | HwIntrinsics.DisableSSE); + } + + private static void TestShuffleFloat4Channel( + int count, + Action, Memory> convert, + byte control) + { + float[] source = new Random(count).GenerateRandomFloatArray(count, 0, 256); + var result = new float[count]; + + float[] expected = new float[count]; + + SimdUtils.Shuffle.InverseMmShuffle( + control, + out int p3, + out int p2, + out int p1, + out int p0); + + for (int i = 0; i < expected.Length; i += 4) + { + expected[i] = source[p0 + i]; + expected[i + 1] = source[p1 + i]; + expected[i + 2] = source[p2 + i]; + expected[i + 3] = source[p3 + i]; + } + + convert(source, result); + + Assert.Equal(expected, result, new ApproximateFloatComparer(1e-5F)); + } + + private static void TestShuffleByte4Channel( + int count, + Action, Memory> convert, + byte control) + { + byte[] source = new byte[count]; + new Random(count).NextBytes(source); + var result = new byte[count]; + + byte[] expected = new byte[count]; + + SimdUtils.Shuffle.InverseMmShuffle( + control, + out int p3, + out int p2, + out int p1, + out int p0); + + for (int i = 0; i < expected.Length; i += 4) + { + expected[i] = source[p0 + i]; + expected[i + 1] = source[p1 + i]; + expected[i + 2] = source[p2 + i]; + expected[i + 3] = source[p3 + i]; + } + + convert(source, result); + + Assert.Equal(expected, result); + } + + private static void TestShuffleByte3Channel( + int count, + Action, Memory> convert, + byte control) + { + byte[] source = new byte[count]; + new Random(count).NextBytes(source); + var result = new byte[count]; + + byte[] expected = new byte[count]; + + SimdUtils.Shuffle.InverseMmShuffle( + control, + out int _, + out int p2, + out int p1, + out int p0); + + for (int i = 0; i < expected.Length; i += 3) + { + expected[i] = source[p0 + i]; + expected[i + 1] = source[p1 + i]; + expected[i + 2] = source[p2 + i]; + } + + convert(source, result); + + Assert.Equal(expected, result); + } + + private static void TestPad3Shuffle4Channel( + int count, + Action, Memory> convert, + byte control) + { + byte[] source = new byte[count]; + new Random(count).NextBytes(source); + + var result = new byte[count * 4 / 3]; + + byte[] expected = new byte[result.Length]; + + SimdUtils.Shuffle.InverseMmShuffle( + control, + out int p3, + out int p2, + out int p1, + out int p0); + + for (int i = 0, j = 0; i < expected.Length; i += 4, j += 3) + { + expected[p0 + i] = source[j]; + expected[p1 + i] = source[j + 1]; + expected[p2 + i] = source[j + 2]; + expected[p3 + i] = byte.MaxValue; + } + + Span temp = stackalloc byte[4]; + for (int i = 0, j = 0; i < expected.Length; i += 4, j += 3) + { + temp[0] = source[j]; + temp[1] = source[j + 1]; + temp[2] = source[j + 2]; + temp[3] = byte.MaxValue; + + expected[i] = temp[p0]; + expected[i + 1] = temp[p1]; + expected[i + 2] = temp[p2]; + expected[i + 3] = temp[p3]; + } + + convert(source, result); + + for (int i = 0; i < expected.Length; i++) + { + Assert.Equal(expected[i], result[i]); + } + + Assert.Equal(expected, result); + } + + private static void TestShuffle4Slice3Channel( + int count, + Action, Memory> convert, + byte control) + { + byte[] source = new byte[count]; + new Random(count).NextBytes(source); + + var result = new byte[count * 3 / 4]; + + byte[] expected = new byte[result.Length]; + + SimdUtils.Shuffle.InverseMmShuffle( + control, + out int _, + out int p2, + out int p1, + out int p0); + + for (int i = 0, j = 0; i < expected.Length; i += 3, j += 4) + { + expected[i] = source[p0 + j]; + expected[i + 1] = source[p1 + j]; + expected[i + 2] = source[p2 + j]; + } + + convert(source, result); + + for (int i = 0; i < expected.Length; i++) + { + Assert.Equal(expected[i], result[i]); + } + + Assert.Equal(expected, result); + } + } +} diff --git a/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs b/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs index 6dce489353..1f680aa6cc 100644 --- a/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs +++ b/tests/ImageSharp.Tests/Common/SimdUtilsTests.cs @@ -5,15 +5,17 @@ using System; using System.Linq; using System.Numerics; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using SixLabors.ImageSharp.Common.Tuples; - +#if SUPPORTS_RUNTIME_INTRINSICS +using System.Runtime.Intrinsics.X86; +#endif +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.TestUtilities; using Xunit; using Xunit.Abstractions; namespace SixLabors.ImageSharp.Tests.Common { - public class SimdUtilsTests + public partial class SimdUtilsTests { private ITestOutputHelper Output { get; } @@ -163,13 +165,13 @@ namespace SixLabors.ImageSharp.Tests.Common public static readonly TheoryData ArraySizesDivisibleBy8 = new TheoryData { 0, 8, 16, 1024 }; public static readonly TheoryData ArraySizesDivisibleBy4 = new TheoryData { 0, 4, 8, 28, 1020 }; - + public static readonly TheoryData ArraySizesDivisibleBy3 = new TheoryData { 0, 3, 9, 36, 957 }; public static readonly TheoryData ArraySizesDivisibleBy32 = new TheoryData { 0, 32, 512 }; public static readonly TheoryData ArbitraryArraySizes = new TheoryData { - 0, 1, 2, 3, 4, 7, 8, 9, 15, 16, 17, 63, 64, 255, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 520, + 0, 1, 2, 3, 4, 7, 8, 9, 15, 16, 17, 63, 64, 255, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, }; [Theory] @@ -204,6 +206,25 @@ namespace SixLabors.ImageSharp.Tests.Common (s, d) => SimdUtils.ExtendedIntrinsics.ByteToNormalizedFloat(s.Span, d.Span)); } +#if SUPPORTS_RUNTIME_INTRINSICS + [Theory] + [MemberData(nameof(ArraySizesDivisibleBy32))] + public void HwIntrinsics_BulkConvertByteToNormalizedFloat(int count) + { + static void RunTest(string serialized) + { + TestImpl_BulkConvertByteToNormalizedFloat( + FeatureTestRunner.Deserialize(serialized), + (s, d) => SimdUtils.HwIntrinsics.ByteToNormalizedFloat(s.Span, d.Span)); + } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, + count, + HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableSSE41); + } +#endif + [Theory] [MemberData(nameof(ArbitraryArraySizes))] public void BulkConvertByteToNormalizedFloat(int count) @@ -281,16 +302,19 @@ namespace SixLabors.ImageSharp.Tests.Common [Theory] [MemberData(nameof(ArraySizesDivisibleBy32))] - public void Avx2_BulkConvertNormalizedFloatToByteClampOverflows(int count) + public void HwIntrinsics_BulkConvertNormalizedFloatToByteClampOverflows(int count) { - if (!System.Runtime.Intrinsics.X86.Avx2.IsSupported) + static void RunTest(string serialized) { - return; + TestImpl_BulkConvertNormalizedFloatToByteClampOverflows( + FeatureTestRunner.Deserialize(serialized), + (s, d) => SimdUtils.HwIntrinsics.NormalizedFloatToByteSaturate(s.Span, d.Span)); } - TestImpl_BulkConvertNormalizedFloatToByteClampOverflows( + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, count, - (s, d) => SimdUtils.Avx2Intrinsics.NormalizedFloatToByteSaturate(s.Span, d.Span)); + HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2); } #endif @@ -314,90 +338,135 @@ namespace SixLabors.ImageSharp.Tests.Common } } - private static void TestImpl_BulkConvertNormalizedFloatToByteClampOverflows( - int count, - Action, - Memory> convert, - int seed = -1) + [Theory] + [MemberData(nameof(ArbitraryArraySizes))] + public void PackFromRgbPlanes_Rgb24(int count) { - seed = seed > 0 ? seed : count; - float[] source = new Random(seed).GenerateRandomFloatArray(count, -0.2f, 1.2f); - byte[] expected = source.Select(NormalizedFloatToByte).ToArray(); - var actual = new byte[count]; - - convert(source, actual); - - Assert.Equal(expected, actual); + TestPackFromRgbPlanes( + count, + (r, g, b, actual) => + SimdUtils.PackFromRgbPlanes(Configuration.Default, r, g, b, actual)); } - private static byte NormalizedFloatToByte(float f) => (byte)Math.Min(255f, Math.Max(0f, (f * 255f) + 0.5f)); - [Theory] - [InlineData(0)] - [InlineData(7)] - [InlineData(42)] - [InlineData(255)] - [InlineData(256)] - [InlineData(257)] - private void MagicConvertToByte(float value) + [MemberData(nameof(ArbitraryArraySizes))] + public void PackFromRgbPlanes_Rgba32(int count) { - byte actual = MagicConvert(value / 256f); - var expected = (byte)value; - - Assert.Equal(expected, actual); + TestPackFromRgbPlanes( + count, + (r, g, b, actual) => + SimdUtils.PackFromRgbPlanes(Configuration.Default, r, g, b, actual)); } +#if SUPPORTS_RUNTIME_INTRINSICS [Fact] - private void BulkConvertNormalizedFloatToByte_Step() + public void PackFromRgbPlanesAvx2Reduce_Rgb24() { - if (this.SkipOnNonAvx2()) + if (!Avx2.IsSupported) { return; } - float[] source = { 0, 7, 42, 255, 0.5f, 1.1f, 2.6f, 16f }; + byte[] r = Enumerable.Range(0, 32).Select(x => (byte)x).ToArray(); + byte[] g = Enumerable.Range(100, 32).Select(x => (byte)x).ToArray(); + byte[] b = Enumerable.Range(200, 32).Select(x => (byte)x).ToArray(); + const int padding = 4; + Rgb24[] d = new Rgb24[32 + padding]; - byte[] expected = source.Select(f => (byte)Math.Round(f)).ToArray(); + ReadOnlySpan rr = r.AsSpan(); + ReadOnlySpan gg = g.AsSpan(); + ReadOnlySpan bb = b.AsSpan(); + Span dd = d.AsSpan(); - source = source.Select(f => f / 255f).ToArray(); + SimdUtils.HwIntrinsics.PackFromRgbPlanesAvx2Reduce(ref rr, ref gg, ref bb, ref dd); - Span dest = stackalloc byte[8]; - - this.MagicConvert(source, dest); + for (int i = 0; i < 32; i++) + { + Assert.Equal(i, d[i].R); + Assert.Equal(i + 100, d[i].G); + Assert.Equal(i + 200, d[i].B); + } - Assert.True(dest.SequenceEqual(expected)); + Assert.Equal(0, rr.Length); + Assert.Equal(0, gg.Length); + Assert.Equal(0, bb.Length); + Assert.Equal(padding, dd.Length); } - private static byte MagicConvert(float x) + [Fact] + public void PackFromRgbPlanesAvx2Reduce_Rgba32() { - float f = 32768.0f + x; - uint i = Unsafe.As(ref f); - return (byte)i; - } + if (!Avx2.IsSupported) + { + return; + } - private void MagicConvert(Span source, Span dest) - { - var magick = new Vector(32768.0f); + byte[] r = Enumerable.Range(0, 32).Select(x => (byte)x).ToArray(); + byte[] g = Enumerable.Range(100, 32).Select(x => (byte)x).ToArray(); + byte[] b = Enumerable.Range(200, 32).Select(x => (byte)x).ToArray(); + + Rgba32[] d = new Rgba32[32]; + + ReadOnlySpan rr = r.AsSpan(); + ReadOnlySpan gg = g.AsSpan(); + ReadOnlySpan bb = b.AsSpan(); + Span dd = d.AsSpan(); + + SimdUtils.HwIntrinsics.PackFromRgbPlanesAvx2Reduce(ref rr, ref gg, ref bb, ref dd); - var scale = new Vector(255f) / new Vector(256f); + for (int i = 0; i < 32; i++) + { + Assert.Equal(i, d[i].R); + Assert.Equal(i + 100, d[i].G); + Assert.Equal(i + 200, d[i].B); + Assert.Equal(255, d[i].A); + } + + Assert.Equal(0, rr.Length); + Assert.Equal(0, gg.Length); + Assert.Equal(0, bb.Length); + Assert.Equal(0, dd.Length); + } +#endif - Vector x = MemoryMarshal.Cast>(source)[0]; + internal static void TestPackFromRgbPlanes(int count, Action packMethod) + where TPixel : unmanaged, IPixel + { + Random rnd = new Random(42); + byte[] r = rnd.GenerateRandomByteArray(count); + byte[] g = rnd.GenerateRandomByteArray(count); + byte[] b = rnd.GenerateRandomByteArray(count); - x = (x * scale) + magick; + TPixel[] expected = new TPixel[count]; + for (int i = 0; i < count; i++) + { + expected[i].FromRgb24(new Rgb24(r[i], g[i], b[i])); + } - Tuple8.OfUInt32 ii = default; + TPixel[] actual = new TPixel[count + 3]; // padding for Rgb24 AVX2 + packMethod(r, g, b, actual); - ref Vector iiRef = ref Unsafe.As>(ref ii); + Assert.True(expected.AsSpan().SequenceEqual(actual.AsSpan().Slice(0, count))); + } - iiRef = x; + private static void TestImpl_BulkConvertNormalizedFloatToByteClampOverflows( + int count, + Action, + Memory> convert, + int seed = -1) + { + seed = seed > 0 ? seed : count; + float[] source = new Random(seed).GenerateRandomFloatArray(count, -0.2f, 1.2f); + byte[] expected = source.Select(NormalizedFloatToByte).ToArray(); + var actual = new byte[count]; - ref Tuple8.OfByte d = ref MemoryMarshal.Cast(dest)[0]; - d.LoadFrom(ref ii); + convert(source, actual); - this.Output.WriteLine(ii.ToString()); - this.Output.WriteLine(d.ToString()); + Assert.Equal(expected, actual); } + private static byte NormalizedFloatToByte(float f) => (byte)Math.Min(255f, Math.Max(0f, (f * 255f) + 0.5f)); + private static void AssertEvenRoundIsCorrect(Vector r, Vector v) { for (int i = 0; i < Vector.Count; i++) diff --git a/tests/ImageSharp.Tests/FileTestBase.cs b/tests/ImageSharp.Tests/FileTestBase.cs deleted file mode 100644 index 93024197b3..0000000000 --- a/tests/ImageSharp.Tests/FileTestBase.cs +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Collections.Generic; - -namespace SixLabors.ImageSharp.Tests -{ - /// - /// The test base class for reading and writing to files. - /// - [Obsolete("See: https://github.com/SixLabors/ImageSharp/issues/868")] - public abstract class FileTestBase - { - /// - /// TODO: We really should not depend on this! Let's use well defined, test-case specific inputs everywhere! - /// A collection made up of one file for each image format - /// - public static IEnumerable DefaultFiles = - new[] - { - TestImages.Bmp.Car, - TestImages.Jpeg.Baseline.Calliphora, - TestImages.Png.Splash, - TestImages.Gif.Trans - }; - - /// - /// A collection of all the bmp test images - /// - public static IEnumerable AllBmpFiles = TestImages.Bmp.Benchmark; - - /// - /// A collection of all the jpeg test images - /// - public static IEnumerable AllJpegFiles = TestImages.Jpeg.All; - - /// - /// A collection of all the png test images - /// - public static IEnumerable AllPngFiles = TestImages.Png.All; - - /// - /// A collection of all the gif test images - /// - public static IEnumerable AllGifFiles = TestImages.Gif.All; - - /// - /// The standard pixel format enumeration - /// - public const PixelTypes DefaultPixelType = PixelTypes.Rgba32; - - /// - /// A few other pixel types to prove that a processor is not bound to a single one. - /// - public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.RgbaVector; - - public static class Extensions - { - public const string Bmp = "bmp"; - - public const string Jpeg = "jpg"; - - public const string Png = "png"; - - public const string Gif = "gif"; - } - - /// - /// The collection of image files to test against. - /// - protected static readonly List Files = new List - { -#pragma warning disable SA1515 // Single-line comment should be preceded by blank line - TestFile.Create(TestImages.Jpeg.Baseline.Calliphora), - // TestFile.Create(TestImages.Jpeg.Baseline.Turtle), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Jpeg.Baseline.Ycck), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Jpeg.Baseline.Cmyk), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Jpeg.Baseline.Floorplan), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Jpeg.Progressive.Festzug), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Jpeg.Baseline.Bad.BadEOF), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Jpeg.Baseline.Bad.ExifUndefType), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Jpeg.Progressive.Fb), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Jpeg.Progressive.Progress), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Jpeg.Baseline.GammaDalaiLamaGray), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Jpeg.Progressive.Bad.BadEOF), // Perf: Enable for local testing only - TestFile.Create(TestImages.Bmp.Car), - // TestFile.Create(TestImages.Bmp.NegHeight), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Bmp.CoreHeader), // Perf: Enable for local testing only - TestFile.Create(TestImages.Png.Splash), - // TestFile.Create(TestImages.Png.SnakeGame), - // TestFile.Create(TestImages.Png.Cross), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Png.Bad.ChunkLength1), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Png.Bad.ChunkLength2), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Png.Powerpoint), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Png.Blur), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Png.Indexed), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Png.SplashInterlaced), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Png.Interlaced), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Png.Filter0), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Png.Filter1), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Png.Filter2), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Png.Filter3), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Png.Filter4), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Png.FilterVar), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Png.P1), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Png.Pd), // Perf: Enable for local testing only - TestFile.Create(TestImages.Gif.Rings), - // TestFile.Create(TestImages.Gif.Trans), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Gif.Cheers), // Perf: Enable for local testing only - // TestFile.Create(TestImages.Gif.Giphy) // Perf: Enable for local testing only - }; -#pragma warning restore SA1515 // Single-line comment should be preceded by blank line - } -} diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs index 3f767620a6..ef245d4d0d 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs @@ -7,6 +7,7 @@ using Microsoft.DotNet.RemoteExecutor; using SixLabors.ImageSharp.Formats.Bmp; using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tests.TestUtilities; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; @@ -14,12 +15,12 @@ using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; using Xunit; +using static SixLabors.ImageSharp.Tests.TestImages.Bmp; + // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Bmp { - using SixLabors.ImageSharp.Metadata; - using static TestImages.Bmp; - + [Trait("Format", "Bmp")] public class BmpDecoderTests { public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.RgbaVector; @@ -39,22 +40,32 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp }; [Theory] - [WithFileCollection(nameof(MiscBmpFiles), PixelTypes.Rgba32, false)] - [WithFileCollection(nameof(MiscBmpFiles), PixelTypes.Rgba32, true)] - public void BmpDecoder_CanDecode_MiscellaneousBitmaps(TestImageProvider provider, bool enforceDiscontiguousBuffers) + [WithFileCollection(nameof(MiscBmpFiles), PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_MiscellaneousBitmaps(TestImageProvider provider) where TPixel : unmanaged, IPixel + { + using Image image = provider.GetImage(BmpDecoder); + image.DebugSave(provider); + + if (TestEnvironment.IsWindows) + { + image.CompareToOriginal(provider); + } + } + + [Theory] + [WithFileCollection(nameof(MiscBmpFiles), PixelTypes.Rgba32)] + public void BmpDecoder_CanDecode_MiscellaneousBitmaps_WithLimitedAllocatorBufferCapacity( + TestImageProvider provider) { static void RunTest(string providerDump, string nonContiguousBuffersStr) { - TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); + TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); - if (!string.IsNullOrEmpty(nonContiguousBuffersStr)) - { - provider.LimitAllocatorBufferCapacity().InPixelsSqrt(100); - } + provider.LimitAllocatorBufferCapacity().InPixelsSqrt(100); - using Image image = provider.GetImage(BmpDecoder); - image.DebugSave(provider, testOutputDetails: nonContiguousBuffersStr); + using Image image = provider.GetImage(BmpDecoder); + image.DebugSave(provider, nonContiguousBuffersStr); if (TestEnvironment.IsWindows) { @@ -66,7 +77,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp RemoteExecutor.Invoke( RunTest, providerDump, - enforceDiscontiguousBuffers ? "Disco" : string.Empty) + "Disco") .Dispose(); } @@ -348,7 +359,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp using (Image image = provider.GetImage(BmpDecoder)) { image.DebugSave(provider); - image.CompareToOriginal(provider); + + // Do not validate. Reference files will fail validation. + image.CompareToOriginal(provider, new MagickReferenceDecoder(false)); } } diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs index b05486e356..fa63642bd2 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpEncoderTests.cs @@ -10,15 +10,17 @@ using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Quantization; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; +using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; using Xunit; using Xunit.Abstractions; +using static SixLabors.ImageSharp.Tests.TestImages.Bmp; + // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Bmp { - using static TestImages.Bmp; - + [Trait("Format", "Bmp")] public class BmpEncoderTests { public static readonly TheoryData BitsPerPixel = @@ -200,10 +202,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp Quantizer = new WuQuantizer() }; string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "bmp", encoder, appendPixelTypeToFileName: false); + + // Use the default decoder to test our encoded image. This verifies the content. + // We do not verify the reference image though as some are invalid. IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); using (var referenceImage = Image.Load(actualOutputFile, referenceDecoder)) { - referenceImage.CompareToReferenceOutput(ImageComparer.TolerantPercentage(0.01f), provider, extension: "bmp", appendPixelTypeToFileName: false); + referenceImage.CompareToReferenceOutput( + ImageComparer.TolerantPercentage(0.01f), + provider, + extension: "bmp", + appendPixelTypeToFileName: false, + decoder: new MagickReferenceDecoder(false)); } } } @@ -226,10 +236,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp Quantizer = new OctreeQuantizer() }; string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "bmp", encoder, appendPixelTypeToFileName: false); + + // Use the default decoder to test our encoded image. This verifies the content. + // We do not verify the reference image though as some are invalid. IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); using (var referenceImage = Image.Load(actualOutputFile, referenceDecoder)) { - referenceImage.CompareToReferenceOutput(ImageComparer.TolerantPercentage(0.01f), provider, extension: "bmp", appendPixelTypeToFileName: false); + referenceImage.CompareToReferenceOutput( + ImageComparer.TolerantPercentage(0.01f), + provider, + extension: "bmp", + appendPixelTypeToFileName: false, + decoder: new MagickReferenceDecoder(false)); } } } diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpFileHeaderTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpFileHeaderTests.cs index 125e40194f..c0c03201fa 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpFileHeaderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpFileHeaderTests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Bmp { + [Trait("Format", "Bmp")] public class BmpFileHeaderTests { [Fact] diff --git a/tests/ImageSharp.Tests/Formats/Bmp/BmpMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Bmp/BmpMetadataTests.cs index b149563793..44a6b17a66 100644 --- a/tests/ImageSharp.Tests/Formats/Bmp/BmpMetadataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Bmp/BmpMetadataTests.cs @@ -4,13 +4,15 @@ using System.IO; using SixLabors.ImageSharp.Formats.Bmp; + using Xunit; +using static SixLabors.ImageSharp.Tests.TestImages.Bmp; + // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Bmp { - using static TestImages.Bmp; - + [Trait("Format", "Bmp")] public class BmpMetadataTests { [Fact] diff --git a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs index c10cd8d298..a171d6d523 100644 --- a/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs +++ b/tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs @@ -2,25 +2,47 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; - using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Quantization; - using Xunit; namespace SixLabors.ImageSharp.Tests.Formats { - public class GeneralFormatTests : FileTestBase + public class GeneralFormatTests { + /// + /// A collection made up of one file for each image format + /// + public static readonly IEnumerable DefaultFiles = + new[] + { + TestImages.Bmp.Car, + TestImages.Jpeg.Baseline.Calliphora, + TestImages.Png.Splash, + TestImages.Gif.Trans + }; + + /// + /// The collection of image files to test against. + /// + protected static readonly List Files = new List + { + TestFile.Create(TestImages.Jpeg.Baseline.Calliphora), + TestFile.Create(TestImages.Bmp.Car), + TestFile.Create(TestImages.Png.Splash), + TestFile.Create(TestImages.Gif.Rings), + }; + [Theory] - [WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] + [WithFileCollection(nameof(DefaultFiles), PixelTypes.Rgba32)] public void ResolutionShouldChange(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -200,7 +222,7 @@ namespace SixLabors.ImageSharp.Tests.Formats [Fact] public void IdentifyReturnsNullWithInvalidStream() { - byte[] invalid = new byte[10]; + var invalid = new byte[10]; using (var memoryStream = new MemoryStream(invalid)) { @@ -212,8 +234,7 @@ namespace SixLabors.ImageSharp.Tests.Formats } private static IImageFormat GetFormat(string format) - { - return Configuration.Default.ImageFormats.FirstOrDefault(x => x.FileExtensions.Contains(format)); - } + => Configuration.Default.ImageFormats + .FirstOrDefault(x => x.FileExtensions.Contains(format)); } } diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs index 63aae5c559..446f1e9d47 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifDecoderTests.cs @@ -17,6 +17,7 @@ using Xunit; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Gif { + [Trait("Format", "Gif")] public class GifDecoderTests { private const PixelTypes TestPixelTypes = PixelTypes.Rgba32 | PixelTypes.RgbaVector | PixelTypes.Argb32; @@ -154,9 +155,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif [Fact] public void CanDecodeIntermingledImages() { - using (var kumin1 = Image.Load(TestFile.Create(TestImages.Gif.Kumin).Bytes)) + using (var kumin1 = Image.Load(TestFile.Create(TestImages.Gif.Kumin).Bytes)) using (Image.Load(TestFile.Create(TestImages.Png.Icon).Bytes)) - using (var kumin2 = Image.Load(TestFile.Create(TestImages.Gif.Kumin).Bytes)) + using (var kumin2 = Image.Load(TestFile.Create(TestImages.Gif.Kumin).Bytes)) { for (int i = 0; i < kumin1.Frames.Count; i++) { @@ -170,6 +171,17 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif } } + // https://github.com/SixLabors/ImageSharp/issues/1503 + [Theory] + [WithFile(TestImages.Gif.Issues.Issue1530, PixelTypes.Rgba32)] + public void Issue1530_BadDescriptorDimensions(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + using Image image = provider.GetImage(); + image.DebugSaveMultiFrame(provider); + image.CompareToReferenceOutputMultiFrame(provider, ImageComparer.Exact); + } + // https://github.com/SixLabors/ImageSharp/issues/405 [Theory] [WithFile(TestImages.Gif.Issues.BadAppExtLength, PixelTypes.Rgba32)] @@ -180,6 +192,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif using (Image image = provider.GetImage()) { image.DebugSave(provider); + image.CompareFirstFrameToReferenceOutput(ImageComparer.Exact, provider); } } @@ -198,17 +211,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Gif [Theory] [WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32)] [WithFile(TestImages.Gif.Kumin, PixelTypes.Rgba32)] - public void GifDecoder_CanDecode_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) - where TPixel : unmanaged, IPixel + public void GifDecoder_CanDecode_WithLimitedAllocatorBufferCapacity( + TestImageProvider provider) { static void RunTest(string providerDump, string nonContiguousBuffersStr) { - TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); + TestImageProvider provider + = BasicSerializer.Deserialize>(providerDump); provider.LimitAllocatorBufferCapacity().InPixelsSqrt(100); - using Image image = provider.GetImage(GifDecoder); - image.DebugSave(provider); + using Image image = provider.GetImage(GifDecoder); + image.DebugSave(provider, nonContiguousBuffersStr); image.CompareToOriginal(provider); } diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs index f8efe700f6..3a0f188ce3 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifEncoderTests.cs @@ -2,17 +2,19 @@ // Licensed under the Apache License, Version 2.0. using System.IO; -using SixLabors.ImageSharp.Formats; + using SixLabors.ImageSharp.Formats.Gif; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Quantization; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; + using Xunit; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Gif { + [Trait("Format", "Gif")] public class GifEncoderTests { private const PixelTypes TestPixelTypes = PixelTypes.Rgba32 | PixelTypes.RgbaVector | PixelTypes.Argb32; diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifFrameMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifFrameMetadataTests.cs index 61caaad66d..144bfae213 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifFrameMetadataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifFrameMetadataTests.cs @@ -6,6 +6,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Gif { + [Trait("Format", "Gif")] public class GifFrameMetadataTests { [Fact] diff --git a/tests/ImageSharp.Tests/Formats/Gif/GifMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Gif/GifMetadataTests.cs index 533b1ed301..e209586f5f 100644 --- a/tests/ImageSharp.Tests/Formats/Gif/GifMetadataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Gif/GifMetadataTests.cs @@ -13,6 +13,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Gif { + [Trait("Format", "Gif")] public class GifMetadataTests { public static readonly TheoryData RatioFiles = diff --git a/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs b/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs index 98fbac7c04..dea8c62e19 100644 --- a/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs +++ b/tests/ImageSharp.Tests/Formats/ImageFormatManagerTests.cs @@ -46,45 +46,22 @@ namespace SixLabors.ImageSharp.Tests.Formats [Fact] public void AddImageFormatDetectorNullThrows() - { - Assert.Throws(() => - { - this.DefaultFormatsManager.AddImageFormatDetector(null); - }); - } + => Assert.Throws(() => this.DefaultFormatsManager.AddImageFormatDetector(null)); [Fact] public void RegisterNullMimeTypeEncoder() { - Assert.Throws(() => - { - this.DefaultFormatsManager.SetEncoder(null, new Mock().Object); - }); - Assert.Throws(() => - { - this.DefaultFormatsManager.SetEncoder(BmpFormat.Instance, null); - }); - Assert.Throws(() => - { - this.DefaultFormatsManager.SetEncoder(null, null); - }); + Assert.Throws(() => this.DefaultFormatsManager.SetEncoder(null, new Mock().Object)); + Assert.Throws(() => this.DefaultFormatsManager.SetEncoder(BmpFormat.Instance, null)); + Assert.Throws(() => this.DefaultFormatsManager.SetEncoder(null, null)); } [Fact] public void RegisterNullSetDecoder() { - Assert.Throws(() => - { - this.DefaultFormatsManager.SetDecoder(null, new Mock().Object); - }); - Assert.Throws(() => - { - this.DefaultFormatsManager.SetDecoder(BmpFormat.Instance, null); - }); - Assert.Throws(() => - { - this.DefaultFormatsManager.SetDecoder(null, null); - }); + Assert.Throws(() => this.DefaultFormatsManager.SetDecoder(null, new Mock().Object)); + Assert.Throws(() => this.DefaultFormatsManager.SetDecoder(BmpFormat.Instance, null)); + Assert.Throws(() => this.DefaultFormatsManager.SetDecoder(null, null)); } [Fact] @@ -133,11 +110,9 @@ namespace SixLabors.ImageSharp.Tests.Formats byte[] jpegImage; using (var buffer = new MemoryStream()) { - using (var image = new Image(100, 100)) - { - image.SaveAsJpeg(buffer); - jpegImage = buffer.ToArray(); - } + using var image = new Image(100, 100); + image.SaveAsJpeg(buffer); + jpegImage = buffer.ToArray(); } byte[] invalidImage = { 1, 2, 3 }; diff --git a/tests/ImageSharp.Tests/Formats/Jpg/AdobeMarkerTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/AdobeMarkerTests.cs index d033e17ff7..2d149167a0 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/AdobeMarkerTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/AdobeMarkerTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.Formats.Jpeg; @@ -8,6 +8,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public class AdobeMarkerTests { // Taken from actual test image @@ -79,4 +80,4 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg Assert.False(marker.GetHashCode().Equals(marker2.GetHashCode())); } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.CopyToBufferArea.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.CopyToBufferArea.cs index 193fead8e2..cba042fcbd 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.CopyToBufferArea.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.CopyToBufferArea.cs @@ -13,6 +13,7 @@ using Xunit.Abstractions; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public partial class Block8x8FTests { public class CopyToBufferArea : JpegFixture diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs index 722521f98d..4effc52b23 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs @@ -8,12 +8,13 @@ using System.Diagnostics; using SixLabors.ImageSharp.Formats.Jpeg.Components; using SixLabors.ImageSharp.Tests.Formats.Jpg.Utils; - +using SixLabors.ImageSharp.Tests.TestUtilities; using Xunit; using Xunit.Abstractions; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public partial class Block8x8FTests : JpegFixture { #if BENCHMARKING @@ -45,20 +46,20 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg this.Measure( Times, () => + { + var block = default(Block8x8F); + + for (int i = 0; i < Block8x8F.Size; i++) { - var block = default(Block8x8F); - - for (int i = 0; i < Block8x8F.Size; i++) - { - block[i] = i; - } - - sum = 0; - for (int i = 0; i < Block8x8F.Size; i++) - { - sum += block[i]; - } - }); + block[i] = i; + } + + sum = 0; + for (int i = 0; i < Block8x8F.Size; i++) + { + sum += block[i]; + } + }); Assert.Equal(sum, 64f * 63f * 0.5f); } @@ -70,20 +71,20 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg this.Measure( Times, () => + { + // Block8x8F block = new Block8x8F(); + float[] block = new float[64]; + for (int i = 0; i < Block8x8F.Size; i++) { - // Block8x8F block = new Block8x8F(); - float[] block = new float[64]; - for (int i = 0; i < Block8x8F.Size; i++) - { - block[i] = i; - } - - sum = 0; - for (int i = 0; i < Block8x8F.Size; i++) - { - sum += block[i]; - } - }); + block[i] = i; + } + + sum = 0; + for (int i = 0; i < Block8x8F.Size; i++) + { + sum += block[i]; + } + }); Assert.Equal(sum, 64f * 63f * 0.5f); } @@ -101,11 +102,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg this.Measure( Times, () => - { - var b = default(Block8x8F); - b.LoadFrom(data); - b.ScaledCopyTo(mirror); - }); + { + var b = default(Block8x8F); + b.LoadFrom(data); + b.ScaledCopyTo(mirror); + }); Assert.Equal(data, mirror); @@ -126,11 +127,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg this.Measure( Times, () => - { - var b = default(Block8x8F); - Block8x8F.LoadFrom(&b, data); - Block8x8F.ScaledCopyTo(&b, mirror); - }); + { + var b = default(Block8x8F); + Block8x8F.LoadFrom(&b, data); + Block8x8F.ScaledCopyTo(&b, mirror); + }); Assert.Equal(data, mirror); @@ -151,11 +152,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg this.Measure( Times, () => - { - var v = default(Block8x8F); - v.LoadFrom(data); - v.ScaledCopyTo(mirror); - }); + { + var v = default(Block8x8F); + v.LoadFrom(data); + v.ScaledCopyTo(mirror); + }); Assert.Equal(data, mirror); @@ -165,19 +166,26 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [Fact] public void TransposeInto() { - float[] expected = Create8x8FloatData(); - ReferenceImplementations.Transpose8x8(expected); + static void RunTest() + { + float[] expected = Create8x8FloatData(); + ReferenceImplementations.Transpose8x8(expected); - var source = default(Block8x8F); - source.LoadFrom(Create8x8FloatData()); + var source = default(Block8x8F); + source.LoadFrom(Create8x8FloatData()); - var dest = default(Block8x8F); - source.TransposeInto(ref dest); + var dest = default(Block8x8F); + source.TransposeInto(ref dest); - float[] actual = new float[64]; - dest.ScaledCopyTo(actual); + float[] actual = new float[64]; + dest.ScaledCopyTo(actual); - Assert.Equal(expected, actual); + Assert.Equal(expected, actual); + } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, + HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX); } private class BufferHolder @@ -228,7 +236,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg this.PrintLinearData(input); Block8x8F dest = block; - dest.NormalizeColorsInplace(255); + dest.NormalizeColorsInPlace(255); float[] array = new float[64]; dest.ScaledCopyTo(array); @@ -253,11 +261,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg Block8x8F source = CreateRandomFloatBlock(-200, 200, seed); Block8x8F expected = source; - expected.NormalizeColorsInplace(255); - expected.RoundInplace(); + expected.NormalizeColorsInPlace(255); + expected.RoundInPlace(); Block8x8F actual = source; - actual.NormalizeColorsAndRoundInplaceVector8(255); + actual.NormalizeColorsAndRoundInPlaceVector8(255); this.Output.WriteLine(expected.ToString()); this.Output.WriteLine(actual.ToString()); @@ -318,12 +326,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [InlineData(1)] [InlineData(2)] [InlineData(3)] - public void RoundInplaceSlow(int seed) + public void RoundInPlaceSlow(int seed) { Block8x8F s = CreateRandomFloatBlock(-500, 500, seed); Block8x8F d = s; - d.RoundInplace(); + d.RoundInPlace(); this.Output.WriteLine(s.ToString()); this.Output.WriteLine(d.ToString()); @@ -338,19 +346,26 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg } [Fact] - public void MultiplyInplace_ByOtherBlock() + public void MultiplyInPlace_ByOtherBlock() { - Block8x8F original = CreateRandomFloatBlock(-500, 500, 42); - Block8x8F m = CreateRandomFloatBlock(-500, 500, 42); + static void RunTest() + { + Block8x8F original = CreateRandomFloatBlock(-500, 500, 42); + Block8x8F m = CreateRandomFloatBlock(-500, 500, 42); - Block8x8F actual = original; + Block8x8F actual = original; - actual.MultiplyInplace(ref m); + actual.MultiplyInPlace(ref m); - for (int i = 0; i < Block8x8F.Size; i++) - { - Assert.Equal(original[i] * m[i], actual[i]); + for (int i = 0; i < Block8x8F.Size; i++) + { + Assert.Equal(original[i] * m[i], actual[i]); + } } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, + HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX); } [Theory] @@ -390,23 +405,51 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg ReferenceImplementations.DequantizeBlock(&expected, &qt, unzig.Data); - actual.MultiplyInplace(ref zigQt); + actual.MultiplyInPlace(ref zigQt); this.CompareBlocks(expected, actual, 0); } [Fact] - public void MultiplyInplace_ByScalar() + public void AddToAllInPlace() { - Block8x8F original = CreateRandomFloatBlock(-500, 500); + static void RunTest() + { + Block8x8F original = CreateRandomFloatBlock(-500, 500); - Block8x8F actual = original; - actual.MultiplyInplace(42f); + Block8x8F actual = original; + actual.AddInPlace(42f); - for (int i = 0; i < 64; i++) + for (int i = 0; i < 64; i++) + { + Assert.Equal(original[i] + 42f, actual[i]); + } + } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, + HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX); + } + + [Fact] + public void MultiplyInPlace_ByScalar() + { + static void RunTest() { - Assert.Equal(original[i] * 42f, actual[i]); + Block8x8F original = CreateRandomFloatBlock(-500, 500); + + Block8x8F actual = original; + actual.MultiplyInPlace(42f); + + for (int i = 0; i < 64; i++) + { + Assert.Equal(original[i] * 42f, actual[i]); + } } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, + HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX); } [Fact] diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs index c22db3a1ce..9195f09157 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs @@ -9,6 +9,7 @@ using Xunit.Abstractions; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public class Block8x8Tests : JpegFixture { public Block8x8Tests(ITestOutputHelper output) diff --git a/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs index 2c1239883d..75ad5427c7 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs @@ -12,6 +12,7 @@ using Xunit.Abstractions; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public static class DCTTests { public class FastFloatingPoint : JpegFixture diff --git a/tests/ImageSharp.Tests/Formats/Jpg/GenericBlock8x8Tests.cs b/tests/ImageSharp.Tests/Formats/Jpg/GenericBlock8x8Tests.cs index bb857f1eda..c0f3b6a6a4 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/GenericBlock8x8Tests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/GenericBlock8x8Tests.cs @@ -11,6 +11,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public class GenericBlock8x8Tests { public static Image CreateTestImage() @@ -41,8 +42,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg using (Image s = provider.GetImage()) { var d = default(GenericBlock8x8); - var rowOctet = new RowOctet(s.GetRootFramePixelBuffer(), 0); - d.LoadAndStretchEdges(s.Frames.RootFrame.PixelBuffer, 0, 0, rowOctet); + RowOctet rowOctet = default; + rowOctet.Update(s.GetRootFramePixelBuffer(), 0); + d.LoadAndStretchEdges(s.Frames.RootFrame.PixelBuffer, 0, 0, ref rowOctet); TPixel a = s.Frames.RootFrame[0, 0]; TPixel b = d[0, 0]; @@ -66,8 +68,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg using (Image s = provider.GetImage()) { var d = default(GenericBlock8x8); - var rowOctet = new RowOctet(s.GetRootFramePixelBuffer(), 7); - d.LoadAndStretchEdges(s.Frames.RootFrame.PixelBuffer, 6, 7, rowOctet); + RowOctet rowOctet = default; + rowOctet.Update(s.GetRootFramePixelBuffer(), 7); + + d.LoadAndStretchEdges(s.Frames.RootFrame.PixelBuffer, 6, 7, ref rowOctet); Assert.Equal(s[6, 7], d[0, 0]); Assert.Equal(s[6, 8], d[0, 1]); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/ImageExtensionsTest.cs b/tests/ImageSharp.Tests/Formats/Jpg/ImageExtensionsTest.cs index 9b67bcd1eb..1b3e9882ee 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/ImageExtensionsTest.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/ImageExtensionsTest.cs @@ -10,6 +10,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public class ImageExtensionsTest { [Fact] diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs index 0f25d11d4f..1f2e88e67b 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JFifMarkerTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder; @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public class JFifMarkerTests { // Taken from actual test image @@ -91,4 +92,4 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg Assert.False(marker.GetHashCode().Equals(marker2.GetHashCode())); } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs index 860f9c396c..5f05621466 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs @@ -16,12 +16,14 @@ using Xunit.Abstractions; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public class JpegColorConverterTests { private const float Precision = 0.1F / 255; private static readonly ApproximateColorSpaceComparer ColorSpaceComparer = new ApproximateColorSpaceComparer(Precision); + // int inputBufferLength, int resultBufferLength, int seed public static readonly TheoryData CommonConversionData = new TheoryData { @@ -41,9 +43,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [Theory] [MemberData(nameof(CommonConversionData))] - public void ConvertFromYCbCrBasic(int inputBufferLength, int resultBufferLength, int seed) + public void FromYCbCrBasic(int inputBufferLength, int resultBufferLength, int seed) { - ValidateRgbToYCbCrConversion( + ValidateConversion( new JpegColorConverter.FromYCbCrBasic(8), 3, inputBufferLength, @@ -51,44 +53,36 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg seed); } - private static void ValidateYCbCr(in JpegColorConverter.ComponentValues values, Vector4[] result, int i) - { - float y = values.Component0[i]; - float cb = values.Component1[i]; - float cr = values.Component2[i]; - var ycbcr = new YCbCr(y, cb, cr); - - Vector4 rgba = result[i]; - var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); - var expected = ColorSpaceConverter.ToRgb(ycbcr); - - Assert.Equal(expected, actual, ColorSpaceComparer); - Assert.Equal(1, rgba.W); - } - [Theory] - [InlineData(64, 1)] - [InlineData(16, 2)] - [InlineData(8, 3)] - public void FromYCbCrSimd_ConvertCore(int size, int seed) + [MemberData(nameof(CommonConversionData))] + public void FromYCbCrVector4(int inputBufferLength, int resultBufferLength, int seed) { - JpegColorConverter.ComponentValues values = CreateRandomValues(3, size, seed); - var result = new Vector4[size]; - - JpegColorConverter.FromYCbCrSimd.ConvertCore(values, result, 255, 128); - - for (int i = 0; i < size; i++) + if (!SimdUtils.HasVector4) { - ValidateYCbCr(values, result, i); + this.Output.WriteLine("No SSE present, skipping test!"); + return; } + + ValidateConversion( + new JpegColorConverter.FromYCbCrVector4(8), + 3, + inputBufferLength, + resultBufferLength, + seed); } [Theory] [MemberData(nameof(CommonConversionData))] - public void FromYCbCrSimd(int inputBufferLength, int resultBufferLength, int seed) + public void FromYCbCrVector8(int inputBufferLength, int resultBufferLength, int seed) { - ValidateRgbToYCbCrConversion( - new JpegColorConverter.FromYCbCrSimd(8), + if (!SimdUtils.HasVector8) + { + this.Output.WriteLine("No AVX2 present, skipping test!"); + return; + } + + ValidateConversion( + new JpegColorConverter.FromYCbCrVector8(8), 3, inputBufferLength, resultBufferLength, @@ -97,17 +91,16 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [Theory] [MemberData(nameof(CommonConversionData))] - public void FromYCbCrSimdAvx2(int inputBufferLength, int resultBufferLength, int seed) + public void FromYCbCrAvx2(int inputBufferLength, int resultBufferLength, int seed) { - if (!SimdUtils.HasVector8) + if (!SimdUtils.HasAvx2) { this.Output.WriteLine("No AVX2 present, skipping test!"); return; } - // JpegColorConverter.FromYCbCrSimdAvx2.LogPlz = s => this.Output.WriteLine(s); - ValidateRgbToYCbCrConversion( - new JpegColorConverter.FromYCbCrSimdVector8(8), + ValidateConversion( + new JpegColorConverter.FromYCbCrAvx2(8), 3, inputBufferLength, resultBufferLength, @@ -116,7 +109,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [Theory] [MemberData(nameof(CommonConversionData))] - public void ConvertFromYCbCr_WithDefaultConverter(int inputBufferLength, int resultBufferLength, int seed) + public void FromYCbCr_WithDefaultConverter(int inputBufferLength, int resultBufferLength, int seed) { ValidateConversion( JpegColorSpace.YCbCr, @@ -126,149 +119,251 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg seed); } - // Benchmark, for local execution only - // [Theory] - // [InlineData(false)] - // [InlineData(true)] - public void BenchmarkYCbCr(bool simd) + [Theory] + [MemberData(nameof(CommonConversionData))] + public void FromCmykBasic(int inputBufferLength, int resultBufferLength, int seed) { - int count = 2053; - int times = 50000; - - JpegColorConverter.ComponentValues values = CreateRandomValues(3, count, 1); - var result = new Vector4[count]; + ValidateConversion( + new JpegColorConverter.FromCmykBasic(8), + 4, + inputBufferLength, + resultBufferLength, + seed); + } - JpegColorConverter converter = simd ? (JpegColorConverter)new JpegColorConverter.FromYCbCrSimd(8) : new JpegColorConverter.FromYCbCrBasic(8); + [Theory] + [MemberData(nameof(CommonConversionData))] + public void FromCmykVector8(int inputBufferLength, int resultBufferLength, int seed) + { + if (!SimdUtils.HasVector8) + { + this.Output.WriteLine("No AVX2 present, skipping test!"); + return; + } - // Warm up: - converter.ConvertToRgba(values, result); + ValidateConversion( + new JpegColorConverter.FromCmykVector8(8), + 4, + inputBufferLength, + resultBufferLength, + seed); + } - using (new MeasureGuard(this.Output, $"{converter.GetType().Name} x {times}")) + [Theory] + [MemberData(nameof(CommonConversionData))] + public void FromCmykAvx2(int inputBufferLength, int resultBufferLength, int seed) + { + if (!SimdUtils.HasAvx2) { - for (int i = 0; i < times; i++) - { - converter.ConvertToRgba(values, result); - } + this.Output.WriteLine("No AVX2 present, skipping test!"); + return; } + + ValidateConversion( + new JpegColorConverter.FromCmykAvx2(8), + 4, + inputBufferLength, + resultBufferLength, + seed); } [Theory] [MemberData(nameof(CommonConversionData))] - public void ConvertFromCmyk(int inputBufferLength, int resultBufferLength, int seed) + public void FromCmyk_WithDefaultConverter(int inputBufferLength, int resultBufferLength, int seed) { - var v = new Vector4(0, 0, 0, 1F); - var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); - - var converter = JpegColorConverter.GetConverter(JpegColorSpace.Cmyk, 8); - JpegColorConverter.ComponentValues values = CreateRandomValues(4, inputBufferLength, seed); - var result = new Vector4[resultBufferLength]; + ValidateConversion( + JpegColorSpace.Cmyk, + 4, + inputBufferLength, + resultBufferLength, + seed); + } - converter.ConvertToRgba(values, result); + [Theory] + [MemberData(nameof(CommonConversionData))] + public void FromGrayscaleBasic(int inputBufferLength, int resultBufferLength, int seed) + { + ValidateConversion( + new JpegColorConverter.FromGrayscaleBasic(8), + 1, + inputBufferLength, + resultBufferLength, + seed); + } - for (int i = 0; i < resultBufferLength; i++) + [Theory] + [MemberData(nameof(CommonConversionData))] + public void FromGrayscaleAvx2(int inputBufferLength, int resultBufferLength, int seed) + { + if (!SimdUtils.HasAvx2) { - float c = values.Component0[i]; - float m = values.Component1[i]; - float y = values.Component2[i]; - float k = values.Component3[i] / 255F; + this.Output.WriteLine("No AVX2 present, skipping test!"); + return; + } - v.X = c * k; - v.Y = m * k; - v.Z = y * k; - v.W = 1F; + ValidateConversion( + new JpegColorConverter.FromGrayscaleAvx2(8), + 1, + inputBufferLength, + resultBufferLength, + seed); + } - v *= scale; + [Theory] + [MemberData(nameof(CommonConversionData))] + public void FromGraysacle_WithDefaultConverter(int inputBufferLength, int resultBufferLength, int seed) + { + ValidateConversion( + JpegColorSpace.Grayscale, + 1, + inputBufferLength, + resultBufferLength, + seed); + } - Vector4 rgba = result[i]; - var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); - var expected = new Rgb(v.X, v.Y, v.Z); + [Theory] + [MemberData(nameof(CommonConversionData))] + public void FromRgbBasic(int inputBufferLength, int resultBufferLength, int seed) + { + ValidateConversion( + new JpegColorConverter.FromRgbBasic(8), + 3, + inputBufferLength, + resultBufferLength, + seed); + } - Assert.Equal(expected, actual); - Assert.Equal(1, rgba.W); + [Theory] + [MemberData(nameof(CommonConversionData))] + public void FromRgbVector8(int inputBufferLength, int resultBufferLength, int seed) + { + if (!SimdUtils.HasVector8) + { + this.Output.WriteLine("No AVX2 present, skipping test!"); + return; } + + ValidateConversion( + new JpegColorConverter.FromRgbVector8(8), + 3, + inputBufferLength, + resultBufferLength, + seed); } [Theory] [MemberData(nameof(CommonConversionData))] - public void ConvertFromGrayScale(int inputBufferLength, int resultBufferLength, int seed) + public void FromRgbAvx2(int inputBufferLength, int resultBufferLength, int seed) { - var converter = JpegColorConverter.GetConverter(JpegColorSpace.Grayscale, 8); - JpegColorConverter.ComponentValues values = CreateRandomValues(1, inputBufferLength, seed); - var result = new Vector4[resultBufferLength]; + if (!SimdUtils.HasAvx2) + { + this.Output.WriteLine("No AVX2 present, skipping test!"); + return; + } - converter.ConvertToRgba(values, result); + ValidateConversion( + new JpegColorConverter.FromRgbAvx2(8), + 3, + inputBufferLength, + resultBufferLength, + seed); + } - for (int i = 0; i < resultBufferLength; i++) - { - float y = values.Component0[i]; - Vector4 rgba = result[i]; - var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); - var expected = new Rgb(y / 255F, y / 255F, y / 255F); + [Theory] + [MemberData(nameof(CommonConversionData))] + public void FromRgb_WithDefaultConverter(int inputBufferLength, int resultBufferLength, int seed) + { + ValidateConversion( + JpegColorSpace.RGB, + 3, + inputBufferLength, + resultBufferLength, + seed); + } - Assert.Equal(expected, actual, ColorSpaceComparer); - Assert.Equal(1, rgba.W); - } + [Theory] + [MemberData(nameof(CommonConversionData))] + public void FromYccKBasic(int inputBufferLength, int resultBufferLength, int seed) + { + ValidateConversion( + new JpegColorConverter.FromYccKBasic(8), + 4, + inputBufferLength, + resultBufferLength, + seed); } [Theory] [MemberData(nameof(CommonConversionData))] - public void ConvertFromRgb(int inputBufferLength, int resultBufferLength, int seed) + public void FromYccKVector8(int inputBufferLength, int resultBufferLength, int seed) { - var converter = JpegColorConverter.GetConverter(JpegColorSpace.RGB, 8); - JpegColorConverter.ComponentValues values = CreateRandomValues(3, inputBufferLength, seed); - var result = new Vector4[resultBufferLength]; + if (!SimdUtils.HasVector8) + { + this.Output.WriteLine("No AVX2 present, skipping test!"); + return; + } - converter.ConvertToRgba(values, result); + ValidateConversion( + new JpegColorConverter.FromYccKVector8(8), + 4, + inputBufferLength, + resultBufferLength, + seed); + } - for (int i = 0; i < resultBufferLength; i++) + [Theory] + [MemberData(nameof(CommonConversionData))] + public void FromYccKAvx2(int inputBufferLength, int resultBufferLength, int seed) + { + if (!SimdUtils.HasAvx2) { - float r = values.Component0[i]; - float g = values.Component1[i]; - float b = values.Component2[i]; - Vector4 rgba = result[i]; - var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); - var expected = new Rgb(r / 255F, g / 255F, b / 255F); - - Assert.Equal(expected, actual, ColorSpaceComparer); - Assert.Equal(1, rgba.W); + this.Output.WriteLine("No AVX2 present, skipping test!"); + return; } + + ValidateConversion( + new JpegColorConverter.FromYccKAvx2(8), + 4, + inputBufferLength, + resultBufferLength, + seed); } [Theory] [MemberData(nameof(CommonConversionData))] - public void ConvertFromYcck(int inputBufferLength, int resultBufferLength, int seed) + public void FromYcck_WithDefaultConverter(int inputBufferLength, int resultBufferLength, int seed) { - var v = new Vector4(0, 0, 0, 1F); - var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); + ValidateConversion( + JpegColorSpace.Ycck, + 4, + inputBufferLength, + resultBufferLength, + seed); + } - var converter = JpegColorConverter.GetConverter(JpegColorSpace.Ycck, 8); - JpegColorConverter.ComponentValues values = CreateRandomValues(4, inputBufferLength, seed); - var result = new Vector4[resultBufferLength]; + // Benchmark, for local execution only + // [Theory] + // [InlineData(false)] + // [InlineData(true)] + public void BenchmarkYCbCr(bool simd) + { + int count = 2053; + int times = 50000; + + JpegColorConverter.ComponentValues values = CreateRandomValues(3, count, 1); + var result = new Vector4[count]; + JpegColorConverter converter = simd ? (JpegColorConverter)new JpegColorConverter.FromYCbCrVector4(8) : new JpegColorConverter.FromYCbCrBasic(8); + + // Warm up: converter.ConvertToRgba(values, result); - for (int i = 0; i < resultBufferLength; i++) + using (new MeasureGuard(this.Output, $"{converter.GetType().Name} x {times}")) { - float y = values.Component0[i]; - float cb = values.Component1[i] - 128F; - float cr = values.Component2[i] - 128F; - float k = values.Component3[i] / 255F; - - v.X = (255F - (float)Math.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * k; - v.Y = (255F - (float)Math.Round( - y - (0.344136F * cb) - (0.714136F * cr), - MidpointRounding.AwayFromZero)) * k; - v.Z = (255F - (float)Math.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * k; - v.W = 1F; - - v *= scale; - - Vector4 rgba = result[i]; - var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); - var expected = new Rgb(v.X, v.Y, v.Z); - - Assert.Equal(expected, actual, ColorSpaceComparer); - Assert.Equal(1, rgba.W); + for (int i = 0; i < times; i++) + { + converter.ConvertToRgba(values, result); + } } } @@ -283,7 +378,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg var buffers = new Buffer2D[componentCount]; for (int i = 0; i < componentCount; i++) { - float[] values = new float[inputBufferLength]; + var values = new float[inputBufferLength]; for (int j = 0; j < inputBufferLength; j++) { @@ -306,7 +401,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg int resultBufferLength, int seed) { - ValidateRgbToYCbCrConversion( + ValidateConversion( JpegColorConverter.GetConverter(colorSpace, 8), componentCount, inputBufferLength, @@ -314,7 +409,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg seed); } - private static void ValidateRgbToYCbCrConversion( + private static void ValidateConversion( JpegColorConverter converter, int componentCount, int inputBufferLength, @@ -328,8 +423,128 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg for (int i = 0; i < resultBufferLength; i++) { - ValidateYCbCr(values, result, i); + Validate(converter.ColorSpace, values, result, i); } } + + private static void Validate( + JpegColorSpace colorSpace, + in JpegColorConverter.ComponentValues values, + Vector4[] result, + int i) + { + switch (colorSpace) + { + case JpegColorSpace.Grayscale: + ValidateGrayScale(values, result, i); + break; + case JpegColorSpace.Ycck: + ValidateCyyK(values, result, i); + break; + case JpegColorSpace.Cmyk: + ValidateCmyk(values, result, i); + break; + case JpegColorSpace.RGB: + ValidateRgb(values, result, i); + break; + case JpegColorSpace.YCbCr: + ValidateYCbCr(values, result, i); + break; + default: + Assert.True(false, $"Colorspace {colorSpace} not supported!"); + break; + } + } + + private static void ValidateYCbCr(in JpegColorConverter.ComponentValues values, Vector4[] result, int i) + { + float y = values.Component0[i]; + float cb = values.Component1[i]; + float cr = values.Component2[i]; + var ycbcr = new YCbCr(y, cb, cr); + + Vector4 rgba = result[i]; + var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); + var expected = ColorSpaceConverter.ToRgb(ycbcr); + + Assert.Equal(expected, actual, ColorSpaceComparer); + Assert.Equal(1, rgba.W); + } + + private static void ValidateCyyK(in JpegColorConverter.ComponentValues values, Vector4[] result, int i) + { + var v = new Vector4(0, 0, 0, 1F); + var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); + + float y = values.Component0[i]; + float cb = values.Component1[i] - 128F; + float cr = values.Component2[i] - 128F; + float k = values.Component3[i] / 255F; + + v.X = (255F - (float)Math.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * k; + v.Y = (255F - (float)Math.Round( + y - (0.344136F * cb) - (0.714136F * cr), + MidpointRounding.AwayFromZero)) * k; + v.Z = (255F - (float)Math.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * k; + v.W = 1F; + + v *= scale; + + Vector4 rgba = result[i]; + var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); + var expected = new Rgb(v.X, v.Y, v.Z); + + Assert.Equal(expected, actual, ColorSpaceComparer); + Assert.Equal(1, rgba.W); + } + + private static void ValidateRgb(in JpegColorConverter.ComponentValues values, Vector4[] result, int i) + { + float r = values.Component0[i]; + float g = values.Component1[i]; + float b = values.Component2[i]; + Vector4 rgba = result[i]; + var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); + var expected = new Rgb(r / 255F, g / 255F, b / 255F); + + Assert.Equal(expected, actual, ColorSpaceComparer); + Assert.Equal(1, rgba.W); + } + + private static void ValidateGrayScale(in JpegColorConverter.ComponentValues values, Vector4[] result, int i) + { + float y = values.Component0[i]; + Vector4 rgba = result[i]; + var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); + var expected = new Rgb(y / 255F, y / 255F, y / 255F); + + Assert.Equal(expected, actual, ColorSpaceComparer); + Assert.Equal(1, rgba.W); + } + + private static void ValidateCmyk(in JpegColorConverter.ComponentValues values, Vector4[] result, int i) + { + var v = new Vector4(0, 0, 0, 1F); + var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); + + float c = values.Component0[i]; + float m = values.Component1[i]; + float y = values.Component2[i]; + float k = values.Component3[i] / 255F; + + v.X = c * k; + v.Y = m * k; + v.Z = y * k; + v.W = 1F; + + v *= scale; + + Vector4 rgba = result[i]; + var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); + var expected = new Rgb(v.X, v.Y, v.Z); + + Assert.Equal(expected, actual, ColorSpaceComparer); + Assert.Equal(1, rgba.W); + } } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs index f0a64e6af5..7002bfd65e 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs @@ -1,16 +1,15 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -using Microsoft.DotNet.RemoteExecutor; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tests.TestUtilities; -using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; + using Xunit; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public partial class JpegDecoderTests { [Theory] diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs index c91aad7e74..2faea2611e 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs @@ -2,9 +2,11 @@ // Licensed under the Apache License, Version 2.0. using System.Collections.Generic; +using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public partial class JpegDecoderTests { public static string[] BaselineTestJpegs = diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs index e37b26cdbf..f47ae55220 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs @@ -1,22 +1,23 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. +using System; using System.IO; +using System.Runtime.CompilerServices; + using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Jpeg; +using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.Metadata.Profiles.Icc; using SixLabors.ImageSharp.PixelFormats; + using Xunit; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Jpg { - using System; - using System.Runtime.CompilerServices; - - using SixLabors.ImageSharp.Formats.Jpeg; - using SixLabors.ImageSharp.Metadata; - + [Trait("Format", "Jpg")] public partial class JpegDecoderTests { // TODO: A JPEGsnoop & metadata expert should review if the Exif/Icc expectations are correct. diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs index e29d8f158b..9beb8358c6 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs @@ -9,27 +9,38 @@ using Xunit; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public partial class JpegDecoderTests { public const string DecodeProgressiveJpegOutputName = "DecodeProgressiveJpeg"; [Theory] - [WithFileCollection(nameof(ProgressiveTestJpegs), PixelTypes.Rgba32, false)] - [WithFile(TestImages.Jpeg.Progressive.Progress, PixelTypes.Rgba32, true)] - public void DecodeProgressiveJpeg(TestImageProvider provider, bool enforceDiscontiguousBuffers) + [WithFileCollection(nameof(ProgressiveTestJpegs), PixelTypes.Rgba32)] + public void DecodeProgressiveJpeg(TestImageProvider provider) where TPixel : unmanaged, IPixel + { + using Image image = provider.GetImage(JpegDecoder); + image.DebugSave(provider); + + provider.Utility.TestName = DecodeProgressiveJpegOutputName; + image.CompareToReferenceOutput( + GetImageComparer(provider), + provider, + appendPixelTypeToFileName: false); + } + + [Theory] + [WithFile(TestImages.Jpeg.Progressive.Progress, PixelTypes.Rgba32)] + public void DecodeProgressiveJpeg_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) { static void RunTest(string providerDump, string nonContiguousBuffersStr) { - TestImageProvider provider = - BasicSerializer.Deserialize>(providerDump); + TestImageProvider provider = + BasicSerializer.Deserialize>(providerDump); - if (!string.IsNullOrEmpty(nonContiguousBuffersStr)) - { - provider.LimitAllocatorBufferCapacity().InBytesSqrt(200); - } + provider.LimitAllocatorBufferCapacity().InBytesSqrt(200); - using Image image = provider.GetImage(JpegDecoder); + using Image image = provider.GetImage(JpegDecoder); image.DebugSave(provider, nonContiguousBuffersStr); provider.Utility.TestName = DecodeProgressiveJpegOutputName; @@ -44,8 +55,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg RemoteExecutor.Invoke( RunTest, providerDump, - enforceDiscontiguousBuffers ? "Disco" : string.Empty) - .Dispose(); + "Disco").Dispose(); } } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs index 78218aec90..3910b2c498 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs @@ -6,13 +6,12 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using Microsoft.DotNet.RemoteExecutor; + using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tests.Formats.Jpg.Utils; -using SixLabors.ImageSharp.Tests.TestUtilities; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using Xunit; @@ -22,6 +21,7 @@ using Xunit.Abstractions; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { // TODO: Scatter test cases into multiple test classes + [Trait("Format", "Jpg")] public partial class JpegDecoderTests { public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Argb32 | PixelTypes.RgbaVector; @@ -129,10 +129,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [Theory] [InlineData(TestImages.Jpeg.Baseline.Jpeg420Small, 0)] [InlineData(TestImages.Jpeg.Issues.ExifGetString750Transform, 1)] - [InlineData(TestImages.Jpeg.Issues.ExifGetString750Transform, 10)] + [InlineData(TestImages.Jpeg.Issues.ExifGetString750Transform, 15)] [InlineData(TestImages.Jpeg.Issues.ExifGetString750Transform, 30)] [InlineData(TestImages.Jpeg.Issues.BadRstProgressive518, 1)] - [InlineData(TestImages.Jpeg.Issues.BadRstProgressive518, 10)] + [InlineData(TestImages.Jpeg.Issues.BadRstProgressive518, 15)] [InlineData(TestImages.Jpeg.Issues.BadRstProgressive518, 30)] public async Task Decode_IsCancellable(string fileName, int cancellationDelayMs) { @@ -141,17 +141,32 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg TestEnvironment.InputImagesDirectoryFullPath, fileName); - var cts = new CancellationTokenSource(); - if (cancellationDelayMs == 0) - { - cts.Cancel(); - } - else + const int NumberOfRuns = 5; + + for (int i = 0; i < NumberOfRuns; i++) { - cts.CancelAfter(cancellationDelayMs); + var cts = new CancellationTokenSource(); + if (cancellationDelayMs == 0) + { + cts.Cancel(); + } + else + { + cts.CancelAfter(cancellationDelayMs); + } + + try + { + using var image = await Image.LoadAsync(hugeFile, cts.Token); + } + catch (TaskCanceledException) + { + // Succesfully observed a cancellation + return; + } } - await Assert.ThrowsAsync(() => Image.LoadAsync(hugeFile, cts.Token)); + throw new Exception($"No cancellation happened out of {NumberOfRuns} runs!"); } [Theory(Skip = "Identify is too fast, doesn't work reliably.")] diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs index 981270a5fb..6481c711ff 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs @@ -1,13 +1,12 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -using System; using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; + using SixLabors.ImageSharp.Formats.Jpeg; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Metadata; using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.Metadata.Profiles.Icc; @@ -20,6 +19,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public class JpegEncoderTests { public static readonly TheoryData QualityFiles = diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegFileMarkerTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegFileMarkerTests.cs index 79e3c448f1..6295122581 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegFileMarkerTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegFileMarkerTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.Formats.Jpeg; @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public class JpegFileMarkerTests { [Fact] diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegImagePostProcessorTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegImagePostProcessorTests.cs index 0dd2abcc1f..93d9aee923 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegImagePostProcessorTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegImagePostProcessorTests.cs @@ -12,6 +12,7 @@ using Xunit.Abstractions; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public class JpegImagePostProcessorTests { public static string[] BaselineTestJpegs = diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegMetadataTests.cs index 98558a7265..e14ec81c67 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegMetadataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegMetadataTests.cs @@ -6,6 +6,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public class JpegMetadataTests { [Fact] diff --git a/tests/ImageSharp.Tests/Formats/Jpg/LibJpegToolsTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/LibJpegToolsTests.cs index a267d437bc..1703d007f7 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/LibJpegToolsTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/LibJpegToolsTests.cs @@ -10,6 +10,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public class LibJpegToolsTests { [Fact] diff --git a/tests/ImageSharp.Tests/Formats/Jpg/ParseStreamTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/ParseStreamTests.cs index 94e3af3a97..de8103d639 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/ParseStreamTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/ParseStreamTests.cs @@ -13,6 +13,7 @@ using Xunit.Abstractions; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public class ParseStreamTests { private ITestOutputHelper Output { get; } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/ProfileResolverTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/ProfileResolverTests.cs index 0c17ac7dbe..8d2328a3a1 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/ProfileResolverTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/ProfileResolverTests.cs @@ -9,6 +9,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public class ProfileResolverTests { private static readonly byte[] JFifMarker = Encoding.ASCII.GetBytes("JFIF\0"); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.AccurateDCT.cs b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.AccurateDCT.cs index bfa0966af4..9f17985d2b 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.AccurateDCT.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.AccurateDCT.cs @@ -9,6 +9,7 @@ using Xunit.Abstractions; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public partial class ReferenceImplementationsTests { public class AccurateDCT : JpegFixture diff --git a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs index 770f0cbf71..8920d42d48 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs @@ -10,6 +10,7 @@ using Xunit.Abstractions; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public partial class ReferenceImplementationsTests { public class FastFloatingPointDCT : JpegFixture diff --git a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.StandardIntegerDCT.cs b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.StandardIntegerDCT.cs index 8bf1d7155c..c7bf9d1b6c 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.StandardIntegerDCT.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.StandardIntegerDCT.cs @@ -12,6 +12,7 @@ using Xunit.Abstractions; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public partial class ReferenceImplementationsTests { public class StandardIntegerDCT : JpegFixture diff --git a/tests/ImageSharp.Tests/Formats/Jpg/RgbToYCbCrConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/RgbToYCbCrConverterTests.cs new file mode 100644 index 0000000000..9a6fc8d6fd --- /dev/null +++ b/tests/ImageSharp.Tests/Formats/Jpg/RgbToYCbCrConverterTests.cs @@ -0,0 +1,91 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using SixLabors.ImageSharp.ColorSpaces; +using SixLabors.ImageSharp.Formats.Jpeg.Components; +using SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.Colorspaces.Conversion; +using Xunit; +using Xunit.Abstractions; + +// ReSharper disable InconsistentNaming +namespace SixLabors.ImageSharp.Tests.Formats.Jpg +{ + public class RgbToYCbCrConverterTests + { + public RgbToYCbCrConverterTests(ITestOutputHelper output) + { + this.Output = output; + } + + private ITestOutputHelper Output { get; } + + [Fact] + public void TestLutConverter() + { + Rgb24[] data = CreateTestData(); + var target = RgbToYCbCrConverterLut.Create(); + + Block8x8F y = default; + Block8x8F cb = default; + Block8x8F cr = default; + + target.Convert(data.AsSpan(), ref y, ref cb, ref cr); + + Verify(data, ref y, ref cb, ref cr, new ApproximateColorSpaceComparer(1F)); + } + + [Fact] + public void TestVectorizedConverter() + { + if (!RgbToYCbCrConverterVectorized.IsSupported) + { + this.Output.WriteLine("No AVX and/or FMA present, skipping test!"); + return; + } + + Rgb24[] data = CreateTestData(); + + Block8x8F y = default; + Block8x8F cb = default; + Block8x8F cr = default; + + RgbToYCbCrConverterVectorized.Convert(data.AsSpan(), ref y, ref cb, ref cr); + + Verify(data, ref y, ref cb, ref cr, new ApproximateColorSpaceComparer(0.0001F)); + } + + private static void Verify(ReadOnlySpan data, ref Block8x8F yResult, ref Block8x8F cbResult, ref Block8x8F crResult, ApproximateColorSpaceComparer comparer) + { + for (int i = 0; i < data.Length; i++) + { + int r = data[i].R; + int g = data[i].G; + int b = data[i].B; + + float y = (0.299F * r) + (0.587F * g) + (0.114F * b); + float cb = 128F + ((-0.168736F * r) - (0.331264F * g) + (0.5F * b)); + float cr = 128F + ((0.5F * r) - (0.418688F * g) - (0.081312F * b)); + + Assert.True(comparer.Equals(new YCbCr(y, cb, cr), new YCbCr(yResult[i], cbResult[i], crResult[i])), $"Pos {i}, Expected {y} == {yResult[i]}, {cb} == {cbResult[i]}, {cr} == {crResult[i]}"); + } + } + + private static Rgb24[] CreateTestData() + { + var data = new Rgb24[64]; + var r = new Random(); + + var random = new byte[3]; + for (int i = 0; i < data.Length; i++) + { + r.NextBytes(random); + data[i] = new Rgb24(random[0], random[1], random[2]); + } + + return data; + } + } +} diff --git a/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs index 662ea9e330..4d6de7e279 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs @@ -7,7 +7,6 @@ using System.Linq; using SixLabors.ImageSharp.Formats.Jpeg; using SixLabors.ImageSharp.IO; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Tests.Formats.Jpg.Utils; @@ -17,6 +16,7 @@ using Xunit.Abstractions; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public class SpectralJpegTests { public SpectralJpegTests(ITestOutputHelper output) diff --git a/tests/ImageSharp.Tests/Formats/Jpg/ZigZagTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/ZigZagTests.cs index cf50ba0b35..e03cf9958f 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/ZigZagTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/ZigZagTests.cs @@ -6,6 +6,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Jpg { + [Trait("Format", "Jpg")] public class ZigZagTests { [Fact] diff --git a/tests/ImageSharp.Tests/Formats/Png/Adler32Tests.cs b/tests/ImageSharp.Tests/Formats/Png/Adler32Tests.cs index 26fbe57c3a..aadd30f2bc 100644 --- a/tests/ImageSharp.Tests/Formats/Png/Adler32Tests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/Adler32Tests.cs @@ -8,6 +8,7 @@ using SharpAdler32 = ICSharpCode.SharpZipLib.Checksum.Adler32; namespace SixLabors.ImageSharp.Tests.Formats.Png { + [Trait("Format", "Png")] public class Adler32Tests { [Theory] diff --git a/tests/ImageSharp.Tests/Formats/Png/Crc32Tests.cs b/tests/ImageSharp.Tests/Formats/Png/Crc32Tests.cs index a9a4ba3182..1ae21e7715 100644 --- a/tests/ImageSharp.Tests/Formats/Png/Crc32Tests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/Crc32Tests.cs @@ -8,6 +8,7 @@ using SharpCrc32 = ICSharpCode.SharpZipLib.Checksum.Crc32; namespace SixLabors.ImageSharp.Tests.Formats.Png { + [Trait("Format", "Png")] public class Crc32Tests { [Theory] diff --git a/tests/ImageSharp.Tests/Formats/Png/ImageExtensionsTest.cs b/tests/ImageSharp.Tests/Formats/Png/ImageExtensionsTest.cs index f0493f1767..4c94ce4e49 100644 --- a/tests/ImageSharp.Tests/Formats/Png/ImageExtensionsTest.cs +++ b/tests/ImageSharp.Tests/Formats/Png/ImageExtensionsTest.cs @@ -10,6 +10,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Png { + [Trait("Format", "Png")] public class ImageExtensionsTest { [Fact] diff --git a/tests/ImageSharp.Tests/Formats/Png/PngChunkTypeTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngChunkTypeTests.cs index 34014e9777..37734a6716 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngChunkTypeTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngChunkTypeTests.cs @@ -8,6 +8,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Png { + [Trait("Format", "Png")] public class PngChunkTypeTests { [Fact] diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs index 1ec7e24486..150b3bd0a7 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs @@ -1,13 +1,11 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -using System; using System.Buffers.Binary; using System.IO; using System.Text; using SixLabors.ImageSharp.Formats.Png; -using SixLabors.ImageSharp.Formats.Png.Zlib; using SixLabors.ImageSharp.PixelFormats; using Xunit; @@ -15,6 +13,7 @@ using Xunit; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Png { + [Trait("Format", "Png")] public partial class PngDecoderTests { // Represents ASCII string of "123456789" diff --git a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs index 5b6adfe1af..7147f82d68 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs @@ -16,6 +16,7 @@ using Xunit; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Png { + [Trait("Format", "Png")] public partial class PngDecoderTests { private const PixelTypes PixelTypes = Tests.PixelTypes.Rgba32 | Tests.PixelTypes.RgbaVector | Tests.PixelTypes.Argb32; @@ -404,16 +405,15 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png [Theory] [WithFile(TestImages.Png.Splash, PixelTypes.Rgba32)] [WithFile(TestImages.Png.Bike, PixelTypes.Rgba32)] - public void PngDecoder_CanDecode_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) - where TPixel : unmanaged, IPixel + public void PngDecoder_CanDecode_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) { static void RunTest(string providerDump, string nonContiguousBuffersStr) { - TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); + TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); provider.LimitAllocatorBufferCapacity().InPixelsSqrt(100); - using Image image = provider.GetImage(PngDecoder); + using Image image = provider.GetImage(PngDecoder); image.DebugSave(provider, testOutputDetails: nonContiguousBuffersStr); image.CompareToOriginal(provider); } diff --git a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.Chunks.cs b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.Chunks.cs index 31fd676012..06cde65f8b 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.Chunks.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.Chunks.cs @@ -4,15 +4,17 @@ using System; using System.Buffers.Binary; using System.Collections.Generic; -using System.ComponentModel; using System.IO; + using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.PixelFormats; + using Xunit; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Png { + [Trait("Format", "Png")] public partial class PngEncoderTests { [Fact] diff --git a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs index b9f5f16fa5..58d733c4f0 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs @@ -2,13 +2,8 @@ // Licensed under the Apache License, Version 2.0. // ReSharper disable InconsistentNaming -using System.Diagnostics; using System.IO; using System.Linq; -#if SUPPORTS_RUNTIME_INTRINSICS -using System.Runtime.Intrinsics.X86; -#endif -using Microsoft.DotNet.RemoteExecutor; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Metadata; @@ -16,11 +11,11 @@ using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors.Quantization; using SixLabors.ImageSharp.Tests.TestUtilities; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; - using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Png { + [Trait("Format", "Png")] public partial class PngEncoderTests { private static PngEncoder PngEncoder => new PngEncoder(); @@ -441,7 +436,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png Rgba32 expectedColor = Color.Blue; if (colorType == PngColorType.Grayscale || colorType == PngColorType.GrayscaleWithAlpha) { - var luminance = ImageMaths.Get8BitBT709Luminance(expectedColor.R, expectedColor.G, expectedColor.B); + var luminance = ColorNumerics.Get8BitBT709Luminance(expectedColor.R, expectedColor.G, expectedColor.B); expectedColor = new Rgba32(luminance, luminance, luminance); } @@ -536,16 +531,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png [Theory] [WithTestPatternImages(100, 100, PixelTypes.Rgba32)] - public void EncodeWorksWithoutSsse3Intrinsics(TestImageProvider provider) - where TPixel : unmanaged, IPixel + public void EncodeWorksWithoutSsse3Intrinsics(TestImageProvider provider) { - static void RunTest(string providerDump) + static void RunTest(string serialized) { - TestImageProvider provider = - BasicSerializer.Deserialize>(providerDump); -#if SUPPORTS_RUNTIME_INTRINSICS - Assert.False(Ssse3.IsSupported); -#endif + TestImageProvider provider = + FeatureTestRunner.DeserializeForXunit>(serialized); foreach (PngInterlaceMode interlaceMode in InterlaceMode) { @@ -560,19 +551,21 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png } } - string providerDump = BasicSerializer.Serialize(provider); + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, + HwIntrinsics.DisableSSSE3, + provider); + } - var processStartInfo = new ProcessStartInfo(); - processStartInfo.Environment[TestEnvironment.Features.EnableSSE3] = TestEnvironment.Features.Off; + [Fact] + public void EncodeFixesInvalidOptions() + { + // https://github.com/SixLabors/ImageSharp/issues/935 + using var ms = new MemoryStream(); + var testFile = TestFile.Create(TestImages.Png.Issue935); + using Image image = testFile.CreateRgba32Image(new PngDecoder()); - RemoteExecutor.Invoke( - RunTest, - providerDump, - new RemoteInvokeOptions - { - StartInfo = processStartInfo - }) - .Dispose(); + image.Save(ms, new PngEncoder { ColorType = PngColorType.RgbWithAlpha }); } private static void TestPngEncoderCore( diff --git a/tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs index bea116b2bf..f9ff41df1e 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngMetadataTests.cs @@ -12,6 +12,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Png { + [Trait("Format", "Png")] public class PngMetadataTests { public static readonly TheoryData RatioFiles = diff --git a/tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs index f1fdd83326..a2ede61091 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs @@ -10,6 +10,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Png { + [Trait("Format", "Png")] public class PngSmokeTests { [Theory] diff --git a/tests/ImageSharp.Tests/Formats/Png/PngTextDataTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngTextDataTests.cs index 5080b0b121..1acd9dbd39 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngTextDataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngTextDataTests.cs @@ -10,6 +10,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png /// /// Tests the class. /// + [Trait("Format", "Png")] public class PngTextDataTests { /// diff --git a/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs index 5fb15541ec..2a7aca8820 100644 --- a/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs @@ -6,16 +6,17 @@ using Microsoft.DotNet.RemoteExecutor; using SixLabors.ImageSharp.Formats.Tga; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Tests.TestUtilities; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; + using Xunit; +using static SixLabors.ImageSharp.Tests.TestImages.Tga; + // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Tga { - using static TestImages.Tga; - + [Trait("Format", "Tga")] public class TgaDecoderTests { private static TgaDecoder TgaDecoder => new TgaDecoder(); @@ -747,16 +748,15 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga [Theory] [WithFile(Bit24BottomLeft, PixelTypes.Rgba32)] [WithFile(Bit32BottomLeft, PixelTypes.Rgba32)] - public void TgaDecoder_CanDecode_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) - where TPixel : unmanaged, IPixel + public void TgaDecoder_CanDecode_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) { static void RunTest(string providerDump, string nonContiguousBuffersStr) { - TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); + TestImageProvider provider = BasicSerializer.Deserialize>(providerDump); provider.LimitAllocatorBufferCapacity().InPixelsSqrt(100); - using Image image = provider.GetImage(TgaDecoder); + using Image image = provider.GetImage(TgaDecoder); image.DebugSave(provider, testOutputDetails: nonContiguousBuffersStr); if (TestEnvironment.IsWindows) diff --git a/tests/ImageSharp.Tests/Formats/Tga/TgaEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Tga/TgaEncoderTests.cs index 22c5d20b31..d6eb333a20 100644 --- a/tests/ImageSharp.Tests/Formats/Tga/TgaEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tga/TgaEncoderTests.cs @@ -8,11 +8,12 @@ using SixLabors.ImageSharp.PixelFormats; using Xunit; +using static SixLabors.ImageSharp.Tests.TestImages.Tga; + // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Formats.Tga { - using static TestImages.Tga; - + [Trait("Format", "Tga")] public class TgaEncoderTests { public static readonly TheoryData BitsPerPixel = diff --git a/tests/ImageSharp.Tests/Formats/Tga/TgaFileHeaderTests.cs b/tests/ImageSharp.Tests/Formats/Tga/TgaFileHeaderTests.cs index beec043c78..61ddf37b70 100644 --- a/tests/ImageSharp.Tests/Formats/Tga/TgaFileHeaderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tga/TgaFileHeaderTests.cs @@ -1,15 +1,16 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -using System.Collections.Generic; using System.IO; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Tga; + using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.Tga { + [Trait("Format", "Tga")] public class TgaFileHeaderTests { [Theory] diff --git a/tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs b/tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs index 0f76d99317..58ed31e610 100644 --- a/tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs +++ b/tests/ImageSharp.Tests/Formats/Tga/TgaTestUtils.cs @@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga Image image, bool useExactComparer = true, float compareTolerance = 0.01f) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { string path = TestImageProvider.GetFilePathOrNull(provider); if (path == null) @@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga } public static Image DecodeWithMagick(Configuration configuration, FileInfo fileInfo) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { using (var magickImage = new MagickImage(fileInfo)) { @@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga Assert.True(result.TryGetSinglePixelSpan(out Span resultPixels)); - using (IPixelCollection pixels = magickImage.GetPixelsUnsafe()) + using (IUnsafePixelCollection pixels = magickImage.GetPixelsUnsafe()) { byte[] data = pixels.ToByteArray(PixelMapping.RGBA); diff --git a/tests/ImageSharp.Tests/GlobalSuppressions.cs b/tests/ImageSharp.Tests/GlobalSuppressions.cs deleted file mode 100644 index 0411ce883f..0000000000 --- a/tests/ImageSharp.Tests/GlobalSuppressions.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -// This file is used by Code Analysis to maintain SuppressMessage -// attributes that are applied to this project. -// Project-level suppressions either have no target or are given -// a specific target and scoped to a namespace, type, member, etc. -#pragma warning disable SA1404 // Code analysis suppression should have justification -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "xUnit1026:Theory methods should use all of their parameters")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "xUnit1013:Public method should be marked as test")] -[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Assertions", "xUnit2013:Do not use equality check to check for collection size.")] -#pragma warning restore SA1404 // Code analysis suppression should have justification diff --git a/tests/ImageSharp.Tests/Helpers/ColorNumericsTests.cs b/tests/ImageSharp.Tests/Helpers/ColorNumericsTests.cs new file mode 100644 index 0000000000..7d7f5f15ac --- /dev/null +++ b/tests/ImageSharp.Tests/Helpers/ColorNumericsTests.cs @@ -0,0 +1,31 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System.Numerics; + +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Helpers +{ + public class ColorNumericsTests + { + [Theory] + [InlineData(0.2f, 0.7f, 0.1f, 256, 140)] + [InlineData(0.5f, 0.5f, 0.5f, 256, 128)] + [InlineData(0.5f, 0.5f, 0.5f, 65536, 32768)] + [InlineData(0.2f, 0.7f, 0.1f, 65536, 36069)] + public void GetBT709Luminance_WithVector4(float x, float y, float z, int luminanceLevels, int expected) + { + // arrange + var vector = new Vector4(x, y, z, 0.0f); + + // act + int actual = ColorNumerics.GetBT709Luminance(ref vector, luminanceLevels); + + // assert + Assert.Equal(expected, actual); + } + + // TODO: We need to test all ColorNumerics methods! + } +} diff --git a/tests/ImageSharp.Tests/Helpers/ImageMathsTests.cs b/tests/ImageSharp.Tests/Helpers/ImageMathsTests.cs deleted file mode 100644 index 27689f6813..0000000000 --- a/tests/ImageSharp.Tests/Helpers/ImageMathsTests.cs +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Numerics; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Helpers -{ - public class ImageMathsTests - { - [Theory] - [InlineData(0)] - [InlineData(1)] - [InlineData(2)] - [InlineData(3)] - [InlineData(4)] - [InlineData(100)] - [InlineData(123)] - [InlineData(53436353)] - public void Modulo4(int x) - { - int actual = ImageMaths.Modulo4(x); - Assert.Equal(x % 4, actual); - } - - [Theory] - [InlineData(0)] - [InlineData(1)] - [InlineData(2)] - [InlineData(6)] - [InlineData(7)] - [InlineData(8)] - [InlineData(100)] - [InlineData(123)] - [InlineData(53436353)] - [InlineData(975)] - public void Modulo8(int x) - { - int actual = ImageMaths.Modulo8(x); - Assert.Equal(x % 8, actual); - } - - [Theory] - [InlineData(0, 2)] - [InlineData(1, 2)] - [InlineData(2, 2)] - [InlineData(0, 4)] - [InlineData(3, 4)] - [InlineData(5, 4)] - [InlineData(5, 8)] - [InlineData(8, 8)] - [InlineData(8, 16)] - [InlineData(15, 16)] - [InlineData(17, 16)] - [InlineData(17, 32)] - [InlineData(31, 32)] - [InlineData(32, 32)] - [InlineData(33, 32)] - public void Modulo2P(int x, int m) - { - int actual = ImageMaths.ModuloP2(x, m); - Assert.Equal(x % m, actual); - } - - [Theory] - [InlineData(0, 0, 0, 0)] - [InlineData(0.5f, 0, 1, 0.5f)] - [InlineData(-0.5f, -0.1f, 10, -0.1f)] - [InlineData(-0.05f, -0.1f, 10, -0.05f)] - [InlineData(9.9f, -0.1f, 10, 9.9f)] - [InlineData(10f, -0.1f, 10, 10f)] - [InlineData(10.1f, -0.1f, 10, 10f)] - public void Clamp(float x, float min, float max, float expected) - { - float actual = x.Clamp(min, max); - Assert.Equal(expected, actual); - } - - [Fact] - public void FasAbsResultMatchesMath() - { - const int X = -33; - int expected = Math.Abs(X); - - Assert.Equal(expected, ImageMaths.FastAbs(X)); - } - - [Fact] - public void Pow2ResultMatchesMath() - { - const float X = -33; - float expected = (float)Math.Pow(X, 2); - - Assert.Equal(expected, ImageMaths.Pow2(X)); - } - - [Fact] - public void Pow3ResultMatchesMath() - { - const float X = -33; - float expected = (float)Math.Pow(X, 3); - - Assert.Equal(expected, ImageMaths.Pow3(X)); - } - - [Theory] - [InlineData(1, 1, 1)] - [InlineData(1, 42, 1)] - [InlineData(10, 8, 2)] - [InlineData(12, 18, 6)] - [InlineData(4536, 1000, 8)] - [InlineData(1600, 1024, 64)] - public void GreatestCommonDivisor(int a, int b, int expected) - { - int actual = ImageMaths.GreatestCommonDivisor(a, b); - - Assert.Equal(expected, actual); - } - - [Theory] - [InlineData(1, 1, 1)] - [InlineData(1, 42, 42)] - [InlineData(3, 4, 12)] - [InlineData(6, 4, 12)] - [InlineData(1600, 1024, 25600)] - [InlineData(3264, 100, 81600)] - public void LeastCommonMultiple(int a, int b, int expected) - { - int actual = ImageMaths.LeastCommonMultiple(a, b); - - Assert.Equal(expected, actual); - } - - [Theory] - [InlineData(0.2f, 0.7f, 0.1f, 256, 140)] - [InlineData(0.5f, 0.5f, 0.5f, 256, 128)] - [InlineData(0.5f, 0.5f, 0.5f, 65536, 32768)] - [InlineData(0.2f, 0.7f, 0.1f, 65536, 36069)] - public void GetBT709Luminance_WithVector4(float x, float y, float z, int luminanceLevels, int expected) - { - // arrange - var vector = new Vector4(x, y, z, 0.0f); - - // act - int actual = ImageMaths.GetBT709Luminance(ref vector, luminanceLevels); - - // assert - Assert.Equal(expected, actual); - } - - // TODO: We need to test all ImageMaths methods! - } -} diff --git a/tests/ImageSharp.Tests/Helpers/NumericsTests.cs b/tests/ImageSharp.Tests/Helpers/NumericsTests.cs new file mode 100644 index 0000000000..98363b7515 --- /dev/null +++ b/tests/ImageSharp.Tests/Helpers/NumericsTests.cs @@ -0,0 +1,309 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Linq; +using System.Numerics; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Helpers +{ + public class NumericsTests + { + private delegate void SpanAction(Span span, TArg arg, TArg1 arg1); + + private readonly ApproximateFloatComparer approximateFloatComparer = new ApproximateFloatComparer(1e-6f); + + [Theory] + [InlineData(0)] + [InlineData(1)] + [InlineData(2)] + [InlineData(3)] + [InlineData(4)] + [InlineData(100)] + [InlineData(123)] + [InlineData(53436353)] + public void Modulo2(int x) + { + int actual = Numerics.Modulo2(x); + Assert.Equal(x % 2, actual); + } + + [Theory] + [InlineData(0)] + [InlineData(1)] + [InlineData(2)] + [InlineData(3)] + [InlineData(4)] + [InlineData(100)] + [InlineData(123)] + [InlineData(53436353)] + public void Modulo4(int x) + { + int actual = Numerics.Modulo4(x); + Assert.Equal(x % 4, actual); + } + + [Theory] + [InlineData(0)] + [InlineData(1)] + [InlineData(2)] + [InlineData(6)] + [InlineData(7)] + [InlineData(8)] + [InlineData(100)] + [InlineData(123)] + [InlineData(53436353)] + [InlineData(975)] + public void Modulo8(int x) + { + int actual = Numerics.Modulo8(x); + Assert.Equal(x % 8, actual); + } + + [Theory] + [InlineData(0, 2)] + [InlineData(1, 2)] + [InlineData(2, 2)] + [InlineData(0, 4)] + [InlineData(3, 4)] + [InlineData(5, 4)] + [InlineData(5, 8)] + [InlineData(8, 8)] + [InlineData(8, 16)] + [InlineData(15, 16)] + [InlineData(17, 16)] + [InlineData(17, 32)] + [InlineData(31, 32)] + [InlineData(32, 32)] + [InlineData(33, 32)] + public void Modulo2P(int x, int m) + { + int actual = Numerics.ModuloP2(x, m); + Assert.Equal(x % m, actual); + } + + [Theory] + [InlineData(-5)] + [InlineData(-17)] + [InlineData(-12856)] + [InlineData(-32)] + [InlineData(-7425)] + [InlineData(5)] + [InlineData(17)] + [InlineData(12856)] + [InlineData(32)] + [InlineData(7425)] + public void Abs(int x) + { + int expected = Math.Abs(x); + Assert.Equal(expected, Numerics.Abs(x)); + } + + [Theory] + [InlineData(-5)] + [InlineData(-17)] + [InlineData(-12856)] + [InlineData(-32)] + [InlineData(-7425)] + [InlineData(5)] + [InlineData(17)] + [InlineData(12856)] + [InlineData(32)] + [InlineData(7425)] + public void Pow2(float x) + { + float expected = (float)Math.Pow(x, 2); + Assert.Equal(expected, Numerics.Pow2(x)); + } + + [Theory] + [InlineData(-5)] + [InlineData(-17)] + [InlineData(-12856)] + [InlineData(-32)] + [InlineData(5)] + [InlineData(17)] + [InlineData(12856)] + [InlineData(32)] + public void Pow3(float x) + { + float expected = (float)Math.Pow(x, 3); + Assert.Equal(expected, Numerics.Pow3(x)); + } + + [Theory] + [InlineData(1, 1, 1)] + [InlineData(1, 42, 1)] + [InlineData(10, 8, 2)] + [InlineData(12, 18, 6)] + [InlineData(4536, 1000, 8)] + [InlineData(1600, 1024, 64)] + public void GreatestCommonDivisor(int a, int b, int expected) + { + int actual = Numerics.GreatestCommonDivisor(a, b); + Assert.Equal(expected, actual); + } + + [Theory] + [InlineData(1, 1, 1)] + [InlineData(1, 42, 42)] + [InlineData(3, 4, 12)] + [InlineData(6, 4, 12)] + [InlineData(1600, 1024, 25600)] + [InlineData(3264, 100, 81600)] + public void LeastCommonMultiple(int a, int b, int expected) + { + int actual = Numerics.LeastCommonMultiple(a, b); + Assert.Equal(expected, actual); + } + + [Theory] + [InlineData(0)] + [InlineData(1)] + [InlineData(30)] + [InlineData(63)] + public void PremultiplyVectorSpan(int length) + { + var rnd = new Random(42); + Vector4[] source = rnd.GenerateRandomVectorArray(length, 0, 1); + Vector4[] expected = source.Select(v => + { + Numerics.Premultiply(ref v); + return v; + }).ToArray(); + + Numerics.Premultiply(source); + + Assert.Equal(expected, source, this.approximateFloatComparer); + } + + [Theory] + [InlineData(0)] + [InlineData(1)] + [InlineData(30)] + [InlineData(63)] + public void UnPremultiplyVectorSpan(int length) + { + var rnd = new Random(42); + Vector4[] source = rnd.GenerateRandomVectorArray(length, 0, 1); + Vector4[] expected = source.Select(v => + { + Numerics.UnPremultiply(ref v); + return v; + }).ToArray(); + + Numerics.UnPremultiply(source); + + Assert.Equal(expected, source, this.approximateFloatComparer); + } + + [Theory] + [InlineData(64, 36, 96)] + [InlineData(128, 16, 196)] + [InlineData(567, 18, 142)] + [InlineData(1024, 0, 255)] + public void ClampByte(int length, byte min, byte max) + { + TestClampSpan( + length, + min, + max, + (s, m1, m2) => Numerics.Clamp(s, m1, m2), + (v, m1, m2) => Numerics.Clamp(v, m1, m2)); + } + + [Theory] + [InlineData(64, 36, 96)] + [InlineData(128, 16, 196)] + [InlineData(567, 18, 142)] + [InlineData(1024, 0, 255)] + public void ClampInt(int length, int min, int max) + { + TestClampSpan( + length, + min, + max, + (s, m1, m2) => Numerics.Clamp(s, m1, m2), + (v, m1, m2) => Numerics.Clamp(v, m1, m2)); + } + + [Theory] + [InlineData(64, 36, 96)] + [InlineData(128, 16, 196)] + [InlineData(567, 18, 142)] + [InlineData(1024, 0, 255)] + public void ClampUInt(int length, uint min, uint max) + { + TestClampSpan( + length, + min, + max, + (s, m1, m2) => Numerics.Clamp(s, m1, m2), + (v, m1, m2) => Numerics.Clamp(v, m1, m2)); + } + + [Theory] + [InlineData(64, 36, 96)] + [InlineData(128, 16, 196)] + [InlineData(567, 18, 142)] + [InlineData(1024, 0, 255)] + public void ClampFloat(int length, float min, float max) + { + TestClampSpan( + length, + min, + max, + (s, m1, m2) => Numerics.Clamp(s, m1, m2), + (v, m1, m2) => Numerics.Clamp(v, m1, m2)); + } + + [Theory] + [InlineData(64, 36, 96)] + [InlineData(128, 16, 196)] + [InlineData(567, 18, 142)] + [InlineData(1024, 0, 255)] + public void ClampDouble(int length, double min, double max) + { + TestClampSpan( + length, + min, + max, + (s, m1, m2) => Numerics.Clamp(s, m1, m2), + (v, m1, m2) => Numerics.Clamp(v, m1, m2)); + } + + private static void TestClampSpan( + int length, + T min, + T max, + SpanAction clampAction, + Func refClampFunc) + where T : unmanaged, IComparable + { + Span actual = new T[length]; + + var r = new Random(); + for (int i = 0; i < length; i++) + { + actual[i] = (T)Convert.ChangeType(r.Next(byte.MinValue, byte.MaxValue), typeof(T)); + } + + Span expected = new T[length]; + actual.CopyTo(expected); + + for (int i = 0; i < expected.Length; i++) + { + ref T v = ref expected[i]; + v = refClampFunc(v, min, max); + } + + clampAction(actual, min, max); + + for (int i = 0; i < expected.Length; i++) + { + Assert.Equal(expected[i], actual[i]); + } + } + } +} diff --git a/tests/ImageSharp.Tests/Helpers/Vector4UtilsTests.cs b/tests/ImageSharp.Tests/Helpers/Vector4UtilsTests.cs deleted file mode 100644 index c3b8e79ee2..0000000000 --- a/tests/ImageSharp.Tests/Helpers/Vector4UtilsTests.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Linq; -using System.Numerics; - -using Xunit; - -namespace SixLabors.ImageSharp.Tests.Helpers -{ - public class Vector4UtilsTests - { - private readonly ApproximateFloatComparer approximateFloatComparer = new ApproximateFloatComparer(1e-6f); - - [Theory] - [InlineData(0)] - [InlineData(1)] - [InlineData(30)] - public void Premultiply_VectorSpan(int length) - { - var rnd = new Random(42); - Vector4[] source = rnd.GenerateRandomVectorArray(length, 0, 1); - Vector4[] expected = source.Select(v => - { - Vector4Utilities.Premultiply(ref v); - return v; - }).ToArray(); - - Vector4Utilities.Premultiply(source); - - Assert.Equal(expected, source, this.approximateFloatComparer); - } - - [Theory] - [InlineData(0)] - [InlineData(1)] - [InlineData(30)] - public void UnPremultiply_VectorSpan(int length) - { - var rnd = new Random(42); - Vector4[] source = rnd.GenerateRandomVectorArray(length, 0, 1); - Vector4[] expected = source.Select(v => - { - Vector4Utilities.UnPremultiply(ref v); - return v; - }).ToArray(); - - Vector4Utilities.UnPremultiply(source); - - Assert.Equal(expected, source, this.approximateFloatComparer); - } - } -} diff --git a/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs b/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs index 7dc7dbb30c..17c73cc834 100644 --- a/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs +++ b/tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs @@ -282,11 +282,79 @@ namespace SixLabors.ImageSharp.Tests } } + [Fact] + public unsafe void WrapMemory_FromPointer_CreatedImageIsCorrect() + { + var cfg = Configuration.CreateDefaultInstance(); + var metaData = new ImageMetadata(); + + var array = new Rgba32[25]; + + fixed (void* ptr = array) + { + using (var image = Image.WrapMemory(cfg, ptr, 5, 5, metaData)) + { + Assert.True(image.TryGetSinglePixelSpan(out Span imageSpan)); + ref Rgba32 pixel0 = ref imageSpan[0]; + Assert.True(Unsafe.AreSame(ref array[0], ref pixel0)); + ref Rgba32 pixel_1 = ref imageSpan[imageSpan.Length - 1]; + Assert.True(Unsafe.AreSame(ref array[array.Length - 1], ref pixel_1)); + + Assert.Equal(cfg, image.GetConfiguration()); + Assert.Equal(metaData, image.Metadata); + } + } + } + + [Fact] + public unsafe void WrapSystemDrawingBitmap_FromPointer() + { + if (ShouldSkipBitmapTest) + { + return; + } + + using (var bmp = new Bitmap(51, 23)) + { + using (var memoryManager = new BitmapMemoryManager(bmp)) + { + Memory pixelMemory = memoryManager.Memory; + Bgra32 bg = Color.Red; + Bgra32 fg = Color.Green; + + fixed (void* p = pixelMemory.Span) + { + using (var image = Image.WrapMemory(p, bmp.Width, bmp.Height)) + { + Span pixelSpan = pixelMemory.Span; + Span imageSpan = image.GetRootFramePixelBuffer().GetSingleMemory().Span; + + Assert.Equal(pixelSpan.Length, imageSpan.Length); + Assert.True(Unsafe.AreSame(ref pixelSpan.GetPinnableReference(), ref imageSpan.GetPinnableReference())); + + Assert.True(image.TryGetSinglePixelSpan(out imageSpan)); + imageSpan.Fill(bg); + for (var i = 10; i < 20; i++) + { + image.GetPixelRowSpan(i).Slice(10, 10).Fill(fg); + } + } + + Assert.False(memoryManager.IsDisposed); + } + } + + string fn = System.IO.Path.Combine( + TestEnvironment.ActualOutputDirectoryFullPath, + $"{nameof(this.WrapSystemDrawingBitmap_WhenObserved)}.bmp"); + + bmp.Save(fn, ImageFormat.Bmp); + } + } + [Theory] [InlineData(0, 5, 5)] [InlineData(20, 5, 5)] - [InlineData(26, 5, 5)] - [InlineData(2, 1, 1)] [InlineData(1023, 32, 32)] public void WrapMemory_MemoryOfT_InvalidSize(int size, int height, int width) { @@ -296,6 +364,20 @@ namespace SixLabors.ImageSharp.Tests Assert.Throws(() => Image.WrapMemory(memory, height, width)); } + [Theory] + [InlineData(25, 5, 5)] + [InlineData(26, 5, 5)] + [InlineData(2, 1, 1)] + [InlineData(1024, 32, 32)] + [InlineData(2048, 32, 32)] + public void WrapMemory_MemoryOfT_ValidSize(int size, int height, int width) + { + var array = new Rgba32[size]; + var memory = new Memory(array); + + Image.WrapMemory(memory, height, width); + } + private class TestMemoryOwner : IMemoryOwner { public Memory Memory { get; set; } @@ -308,8 +390,6 @@ namespace SixLabors.ImageSharp.Tests [Theory] [InlineData(0, 5, 5)] [InlineData(20, 5, 5)] - [InlineData(26, 5, 5)] - [InlineData(2, 1, 1)] [InlineData(1023, 32, 32)] public void WrapMemory_IMemoryOwnerOfT_InvalidSize(int size, int height, int width) { @@ -320,10 +400,22 @@ namespace SixLabors.ImageSharp.Tests } [Theory] - [InlineData(0, 5, 5)] - [InlineData(20, 5, 5)] + [InlineData(25, 5, 5)] [InlineData(26, 5, 5)] [InlineData(2, 1, 1)] + [InlineData(1024, 32, 32)] + [InlineData(2048, 32, 32)] + public void WrapMemory_IMemoryOwnerOfT_ValidSize(int size, int height, int width) + { + var array = new Rgba32[size]; + var memory = new TestMemoryOwner { Memory = array }; + + Image.WrapMemory(memory, height, width); + } + + [Theory] + [InlineData(0, 5, 5)] + [InlineData(20, 5, 5)] [InlineData(1023, 32, 32)] public void WrapMemory_MemoryOfByte_InvalidSize(int size, int height, int width) { @@ -333,6 +425,31 @@ namespace SixLabors.ImageSharp.Tests Assert.Throws(() => Image.WrapMemory(memory, height, width)); } + [Theory] + [InlineData(25, 5, 5)] + [InlineData(26, 5, 5)] + [InlineData(2, 1, 1)] + [InlineData(1024, 32, 32)] + [InlineData(2048, 32, 32)] + public void WrapMemory_MemoryOfByte_ValidSize(int size, int height, int width) + { + var array = new byte[size * Unsafe.SizeOf()]; + var memory = new Memory(array); + + Image.WrapMemory(memory, height, width); + } + + [Theory] + [InlineData(0, 5, 5)] + [InlineData(20, 5, 5)] + [InlineData(26, 5, 5)] + [InlineData(2, 1, 1)] + [InlineData(1023, 32, 32)] + public unsafe void WrapMemory_Pointer_Null(int size, int height, int width) + { + Assert.Throws(() => Image.WrapMemory((void*)null, height, width)); + } + private static bool ShouldSkipBitmapTest => !TestEnvironment.Is64BitProcess || (TestHelpers.ImageSharpBuiltAgainst != "netcoreapp3.1" && TestHelpers.ImageSharpBuiltAgainst != "netcoreapp2.1"); } diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index ba849ab251..ebbe2cbdfa 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -2,30 +2,39 @@ - netcoreapp3.1;netcoreapp2.1;net472 - True + net5.0;netcoreapp3.1;netcoreapp2.1;net472 True SixLabors.ImageSharp.Tests AnyCPU;x64;x86 SixLabors.ImageSharp.Tests - - true - + + + True + True + PixelOperationsTests.Specialized.Generated.tt + + + + + + TextTemplatingFileGenerator + PixelOperationsTests.Specialized.Generated.cs + PreserveNewest @@ -37,5 +46,17 @@ + + + True + True + PixelOperationsTests.Specialized.Generated.tt + + + + + + + diff --git a/tests/ImageSharp.Tests/PixelFormats/A8Tests.cs b/tests/ImageSharp.Tests/PixelFormats/A8Tests.cs index 784f9821fa..2c6b0fa48b 100644 --- a/tests/ImageSharp.Tests/PixelFormats/A8Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/A8Tests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System.Numerics; @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class A8Tests { [Fact] diff --git a/tests/ImageSharp.Tests/PixelFormats/Argb32Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Argb32Tests.cs index c8cf0cf111..e0c1dc9a84 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Argb32Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Argb32Tests.cs @@ -8,6 +8,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class Argb32Tests { /// diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs index 110bdc2f0c..f6a6d44bb4 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class Bgr24Tests { [Fact] diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs index 8c53e117fd..9f409bc982 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class Bgr565Tests { /// diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs index 195f92b0e2..b7fbdde714 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class Bgra32Tests { /// diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgra4444Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgra4444Tests.cs index 776f5cdc6c..9145a2ecf9 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgra4444Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgra4444Tests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System.Numerics; @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class Bgra4444Tests { /// diff --git a/tests/ImageSharp.Tests/PixelFormats/Bgra5551Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Bgra5551Tests.cs index cdc03b292d..85e8bbb3e6 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Bgra5551Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Bgra5551Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class Bgra5551Tests { /// diff --git a/tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs index bb7e82e50e..68cf1aea77 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class Byte4Tests { /// diff --git a/tests/ImageSharp.Tests/PixelFormats/HalfSingleTests.cs b/tests/ImageSharp.Tests/PixelFormats/HalfSingleTests.cs index e59cb33444..c1ad06c669 100644 --- a/tests/ImageSharp.Tests/PixelFormats/HalfSingleTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/HalfSingleTests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class HalfSingleTests { [Fact] diff --git a/tests/ImageSharp.Tests/PixelFormats/HalfVector2Tests.cs b/tests/ImageSharp.Tests/PixelFormats/HalfVector2Tests.cs index b59e598b44..394a0e2668 100644 --- a/tests/ImageSharp.Tests/PixelFormats/HalfVector2Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/HalfVector2Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class HalfVector2Tests { [Fact] diff --git a/tests/ImageSharp.Tests/PixelFormats/HalfVector4Tests.cs b/tests/ImageSharp.Tests/PixelFormats/HalfVector4Tests.cs index 27726e9a33..bda46df9c3 100644 --- a/tests/ImageSharp.Tests/PixelFormats/HalfVector4Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/HalfVector4Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class HalfVector4Tests { [Fact] diff --git a/tests/ImageSharp.Tests/PixelFormats/L16Tests.cs b/tests/ImageSharp.Tests/PixelFormats/L16Tests.cs index 4204fc2f70..bef3463436 100644 --- a/tests/ImageSharp.Tests/PixelFormats/L16Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/L16Tests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System.Numerics; @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class L16Tests { [Fact] @@ -113,8 +114,8 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // Arrange L16 gray = default; const byte rgb = 128; - ushort scaledRgb = ImageMaths.UpscaleFrom8BitTo16Bit(rgb); - ushort expected = ImageMaths.Get16BitBT709Luminance(scaledRgb, scaledRgb, scaledRgb); + ushort scaledRgb = ColorNumerics.UpscaleFrom8BitTo16Bit(rgb); + ushort expected = ColorNumerics.Get16BitBT709Luminance(scaledRgb, scaledRgb, scaledRgb); // Act gray.FromRgba32(new Rgba32(rgb, rgb, rgb)); @@ -131,7 +132,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats public void L16_ToRgba32(ushort input) { // Arrange - ushort expected = ImageMaths.DownScaleFrom16BitTo8Bit(input); + ushort expected = ColorNumerics.DownScaleFrom16BitTo8Bit(input); var gray = new L16(input); // Act diff --git a/tests/ImageSharp.Tests/PixelFormats/L8Tests.cs b/tests/ImageSharp.Tests/PixelFormats/L8Tests.cs index 09d67ab9ab..4986068819 100644 --- a/tests/ImageSharp.Tests/PixelFormats/L8Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/L8Tests.cs @@ -9,6 +9,7 @@ using Xunit; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class L8Tests { public static readonly TheoryData LuminanceData @@ -136,7 +137,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { // Arrange L8 gray = default; - byte expected = ImageMaths.Get8BitBT709Luminance(rgb, rgb, rgb); + byte expected = ColorNumerics.Get8BitBT709Luminance(rgb, rgb, rgb); // Act gray.FromRgba32(new Rgba32(rgb, rgb, rgb)); diff --git a/tests/ImageSharp.Tests/PixelFormats/La16Tests.cs b/tests/ImageSharp.Tests/PixelFormats/La16Tests.cs index f36d9765c9..5dec524d5f 100644 --- a/tests/ImageSharp.Tests/PixelFormats/La16Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/La16Tests.cs @@ -9,6 +9,7 @@ using Xunit; // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class La16Tests { public static readonly TheoryData LuminanceData @@ -138,7 +139,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats { // Arrange La16 gray = default; - byte expected = ImageMaths.Get8BitBT709Luminance(rgb, rgb, rgb); + byte expected = ColorNumerics.Get8BitBT709Luminance(rgb, rgb, rgb); // Act gray.FromRgba32(new Rgba32(rgb, rgb, rgb)); diff --git a/tests/ImageSharp.Tests/PixelFormats/La32Tests.cs b/tests/ImageSharp.Tests/PixelFormats/La32Tests.cs index d3fdbd085d..8d86003087 100644 --- a/tests/ImageSharp.Tests/PixelFormats/La32Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/La32Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class La32Tests { [Fact] @@ -117,8 +118,8 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats // Arrange La32 gray = default; const byte rgb = 128; - ushort scaledRgb = ImageMaths.UpscaleFrom8BitTo16Bit(rgb); - ushort expected = ImageMaths.Get16BitBT709Luminance(scaledRgb, scaledRgb, scaledRgb); + ushort scaledRgb = ColorNumerics.UpscaleFrom8BitTo16Bit(rgb); + ushort expected = ColorNumerics.Get16BitBT709Luminance(scaledRgb, scaledRgb, scaledRgb); // Act gray.FromRgba32(new Rgba32(rgb, rgb, rgb)); @@ -136,7 +137,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats public void La32_ToRgba32(ushort input) { // Arrange - ushort expected = ImageMaths.DownScaleFrom16BitTo8Bit(input); + ushort expected = ColorNumerics.DownScaleFrom16BitTo8Bit(input); var gray = new La32(input, ushort.MaxValue); // Act diff --git a/tests/ImageSharp.Tests/PixelFormats/NormalizedByte2Tests.cs b/tests/ImageSharp.Tests/PixelFormats/NormalizedByte2Tests.cs index 9278a8a48a..165c19acf6 100644 --- a/tests/ImageSharp.Tests/PixelFormats/NormalizedByte2Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/NormalizedByte2Tests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System.Numerics; @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class NormalizedByte2Tests { [Fact] diff --git a/tests/ImageSharp.Tests/PixelFormats/NormalizedByte4Tests.cs b/tests/ImageSharp.Tests/PixelFormats/NormalizedByte4Tests.cs index 9b754ecc2f..1235562f6c 100644 --- a/tests/ImageSharp.Tests/PixelFormats/NormalizedByte4Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/NormalizedByte4Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class NormalizedByte4Tests { /// diff --git a/tests/ImageSharp.Tests/PixelFormats/NormalizedShort2Tests.cs b/tests/ImageSharp.Tests/PixelFormats/NormalizedShort2Tests.cs index 0b346b256f..3fbf784311 100644 --- a/tests/ImageSharp.Tests/PixelFormats/NormalizedShort2Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/NormalizedShort2Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class NormalizedShort2Tests { [Fact] diff --git a/tests/ImageSharp.Tests/PixelFormats/NormalizedShort4Tests.cs b/tests/ImageSharp.Tests/PixelFormats/NormalizedShort4Tests.cs index 8166421a19..cdfbcfe83f 100644 --- a/tests/ImageSharp.Tests/PixelFormats/NormalizedShort4Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/NormalizedShort4Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class NormalizedShort4Tests { /// diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelBlenderTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelBlenderTests.cs index 548e2f4d89..78aa382aa2 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelBlenderTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelBlenderTests.cs @@ -10,6 +10,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class PixelBlenderTests { public static TheoryData BlenderMappings = new TheoryData diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.ReferenceImplementations.cs b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.ReferenceImplementations.cs index 6fda9dbbad..b0e152b9f8 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.ReferenceImplementations.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.ReferenceImplementations.cs @@ -7,40 +7,58 @@ using System.Runtime.InteropServices; using SixLabors.ImageSharp.PixelFormats; +using Xunit; + namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public abstract partial class PixelConverterTests { public static class ReferenceImplementations { - public static Rgba32 MakeRgba32(byte r, byte g, byte b, byte a) + public static byte[] MakeRgba32ByteArray(byte r, byte g, byte b, byte a) { - Rgba32 d = default; - d.R = r; - d.G = g; - d.B = b; - d.A = a; - return d; + var buffer = new byte[256]; + + for (int i = 0; i < buffer.Length; i += 4) + { + buffer[i] = r; + buffer[i + 1] = g; + buffer[i + 2] = b; + buffer[i + 3] = a; + } + + return buffer; } - public static Argb32 MakeArgb32(byte r, byte g, byte b, byte a) + public static byte[] MakeArgb32ByteArray(byte r, byte g, byte b, byte a) { - Argb32 d = default; - d.R = r; - d.G = g; - d.B = b; - d.A = a; - return d; + var buffer = new byte[256]; + + for (int i = 0; i < buffer.Length; i += 4) + { + buffer[i] = a; + buffer[i + 1] = r; + buffer[i + 2] = g; + buffer[i + 3] = b; + } + + return buffer; } - public static Bgra32 MakeBgra32(byte r, byte g, byte b, byte a) + public static byte[] MakeBgra32ByteArray(byte r, byte g, byte b, byte a) { - Bgra32 d = default; - d.R = r; - d.G = g; - d.B = b; - d.A = a; - return d; + var buffer = new byte[256]; + + for (int i = 0; i < buffer.Length; i += 4) + { + buffer[i] = b; + buffer[i + 1] = g; + buffer[i + 2] = r; + buffer[i + 3] = a; + } + + return buffer; } internal static void To( @@ -83,8 +101,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats if (typeof(TDestinationPixel) == typeof(L8)) { - ref L8 l8Ref = ref MemoryMarshal.GetReference( - MemoryMarshal.Cast(destinationPixels)); + ref L8 l8Ref = ref MemoryMarshal.GetReference(MemoryMarshal.Cast(destinationPixels)); for (int i = 0; i < count; i++) { ref TSourcePixel sp = ref Unsafe.Add(ref sourceRef, i); diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs index 3de6804dcf..ec53629a80 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs @@ -1,13 +1,13 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats.Utils; using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public abstract partial class PixelConverterTests { public static readonly TheoryData RgbaData = @@ -33,30 +33,28 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats [MemberData(nameof(RgbaData))] public void ToArgb32(byte r, byte g, byte b, byte a) { - Rgba32 s = ReferenceImplementations.MakeRgba32(r, g, b, a); + byte[] source = ReferenceImplementations.MakeRgba32ByteArray(r, g, b, a); + var actual = new byte[source.Length]; - // Act: - uint actualPacked = PixelConverter.FromRgba32.ToArgb32(s.PackedValue); + PixelConverter.FromRgba32.ToArgb32(source, actual); - // Assert: - uint expectedPacked = ReferenceImplementations.MakeArgb32(r, g, b, a).PackedValue; + byte[] expected = ReferenceImplementations.MakeArgb32ByteArray(r, g, b, a); - Assert.Equal(expectedPacked, actualPacked); + Assert.Equal(expected, actual); } [Theory] [MemberData(nameof(RgbaData))] public void ToBgra32(byte r, byte g, byte b, byte a) { - Rgba32 s = ReferenceImplementations.MakeRgba32(r, g, b, a); + byte[] source = ReferenceImplementations.MakeRgba32ByteArray(r, g, b, a); + var actual = new byte[source.Length]; - // Act: - uint actualPacked = PixelConverter.FromRgba32.ToBgra32(s.PackedValue); + PixelConverter.FromRgba32.ToBgra32(source, actual); - // Assert: - uint expectedPacked = ReferenceImplementations.MakeBgra32(r, g, b, a).PackedValue; + byte[] expected = ReferenceImplementations.MakeBgra32ByteArray(r, g, b, a); - Assert.Equal(expectedPacked, actualPacked); + Assert.Equal(expected, actual); } } @@ -66,30 +64,28 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats [MemberData(nameof(RgbaData))] public void ToRgba32(byte r, byte g, byte b, byte a) { - Argb32 s = ReferenceImplementations.MakeArgb32(r, g, b, a); + byte[] source = ReferenceImplementations.MakeArgb32ByteArray(r, g, b, a); + var actual = new byte[source.Length]; - // Act: - uint actualPacked = PixelConverter.FromArgb32.ToRgba32(s.PackedValue); + PixelConverter.FromArgb32.ToRgba32(source, actual); - // Assert: - uint expectedPacked = ReferenceImplementations.MakeRgba32(r, g, b, a).PackedValue; + byte[] expected = ReferenceImplementations.MakeRgba32ByteArray(r, g, b, a); - Assert.Equal(expectedPacked, actualPacked); + Assert.Equal(expected, actual); } [Theory] [MemberData(nameof(RgbaData))] public void ToBgra32(byte r, byte g, byte b, byte a) { - Argb32 s = ReferenceImplementations.MakeArgb32(r, g, b, a); + byte[] source = ReferenceImplementations.MakeArgb32ByteArray(r, g, b, a); + var actual = new byte[source.Length]; - // Act: - uint actualPacked = PixelConverter.FromArgb32.ToBgra32(s.PackedValue); + PixelConverter.FromArgb32.ToBgra32(source, actual); - // Assert: - uint expectedPacked = ReferenceImplementations.MakeBgra32(r, g, b, a).PackedValue; + byte[] expected = ReferenceImplementations.MakeBgra32ByteArray(r, g, b, a); - Assert.Equal(expectedPacked, actualPacked); + Assert.Equal(expected, actual); } } @@ -99,30 +95,28 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats [MemberData(nameof(RgbaData))] public void ToArgb32(byte r, byte g, byte b, byte a) { - Bgra32 s = ReferenceImplementations.MakeBgra32(r, g, b, a); + byte[] source = ReferenceImplementations.MakeBgra32ByteArray(r, g, b, a); + var actual = new byte[source.Length]; - // Act: - uint actualPacked = PixelConverter.FromBgra32.ToArgb32(s.PackedValue); + PixelConverter.FromBgra32.ToArgb32(source, actual); - // Assert: - uint expectedPacked = ReferenceImplementations.MakeArgb32(r, g, b, a).PackedValue; + byte[] expected = ReferenceImplementations.MakeArgb32ByteArray(r, g, b, a); - Assert.Equal(expectedPacked, actualPacked); + Assert.Equal(expected, actual); } [Theory] [MemberData(nameof(RgbaData))] public void ToRgba32(byte r, byte g, byte b, byte a) { - Bgra32 s = ReferenceImplementations.MakeBgra32(r, g, b, a); + byte[] source = ReferenceImplementations.MakeBgra32ByteArray(r, g, b, a); + var actual = new byte[source.Length]; - // Act: - uint actualPacked = PixelConverter.FromBgra32.ToRgba32(s.PackedValue); + PixelConverter.FromBgra32.ToRgba32(source, actual); - // Assert: - uint expectedPacked = ReferenceImplementations.MakeRgba32(r, g, b, a).PackedValue; + byte[] expected = ReferenceImplementations.MakeRgba32ByteArray(r, g, b, a); - Assert.Equal(expectedPacked, actualPacked); + Assert.Equal(expected, actual); } } } diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/Generated/PixelOperationsTests.Specialized.Generated.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/Generated/PixelOperationsTests.Specialized.Generated.cs new file mode 100644 index 0000000000..1069eb9aca --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/Generated/PixelOperationsTests.Specialized.Generated.cs @@ -0,0 +1,577 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +// + +using SixLabors.ImageSharp.PixelFormats; +using Xunit; +using Xunit.Abstractions; + + +namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations +{ + public partial class PixelOperationsTests + { + + public partial class A8_OperationsTests : PixelOperationsTests + { + public A8_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => A8.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.Unassociated, alphaRepresentation); + } + } + + public partial class Argb32_OperationsTests : PixelOperationsTests + { + public Argb32_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => Argb32.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.Unassociated, alphaRepresentation); + } + } + + public partial class Bgr24_OperationsTests : PixelOperationsTests + { + public Bgr24_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => Bgr24.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.None, alphaRepresentation); + } + } + + public partial class Bgr565_OperationsTests : PixelOperationsTests + { + public Bgr565_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => Bgr565.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.None, alphaRepresentation); + } + } + + public partial class Bgra32_OperationsTests : PixelOperationsTests + { + public Bgra32_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => Bgra32.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.Unassociated, alphaRepresentation); + } + } + + public partial class Bgra4444_OperationsTests : PixelOperationsTests + { + public Bgra4444_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => Bgra4444.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.Unassociated, alphaRepresentation); + } + } + + public partial class Bgra5551_OperationsTests : PixelOperationsTests + { + public Bgra5551_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => Bgra5551.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.Unassociated, alphaRepresentation); + } + } + + public partial class Byte4_OperationsTests : PixelOperationsTests + { + public Byte4_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => Byte4.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.Unassociated, alphaRepresentation); + } + } + + public partial class HalfSingle_OperationsTests : PixelOperationsTests + { + public HalfSingle_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => HalfSingle.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.None, alphaRepresentation); + } + } + + public partial class HalfVector2_OperationsTests : PixelOperationsTests + { + public HalfVector2_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => HalfVector2.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.None, alphaRepresentation); + } + } + + public partial class HalfVector4_OperationsTests : PixelOperationsTests + { + public HalfVector4_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => HalfVector4.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.Unassociated, alphaRepresentation); + } + } + + public partial class L16_OperationsTests : PixelOperationsTests + { + public L16_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => L16.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.None, alphaRepresentation); + } + } + + public partial class L8_OperationsTests : PixelOperationsTests + { + public L8_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => L8.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.None, alphaRepresentation); + } + } + + public partial class La16_OperationsTests : PixelOperationsTests + { + public La16_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => La16.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.Unassociated, alphaRepresentation); + } + } + + public partial class La32_OperationsTests : PixelOperationsTests + { + public La32_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => La32.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.Unassociated, alphaRepresentation); + } + } + + public partial class NormalizedByte2_OperationsTests : PixelOperationsTests + { + public NormalizedByte2_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => NormalizedByte2.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.None, alphaRepresentation); + } + } + + public partial class NormalizedByte4_OperationsTests : PixelOperationsTests + { + public NormalizedByte4_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => NormalizedByte4.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.Unassociated, alphaRepresentation); + } + } + + public partial class NormalizedShort2_OperationsTests : PixelOperationsTests + { + public NormalizedShort2_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => NormalizedShort2.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.None, alphaRepresentation); + } + } + + public partial class NormalizedShort4_OperationsTests : PixelOperationsTests + { + public NormalizedShort4_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => NormalizedShort4.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.Unassociated, alphaRepresentation); + } + } + + public partial class Rg32_OperationsTests : PixelOperationsTests + { + public Rg32_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => Rg32.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.None, alphaRepresentation); + } + } + + public partial class Rgb24_OperationsTests : PixelOperationsTests + { + public Rgb24_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => Rgb24.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.None, alphaRepresentation); + } + } + + public partial class Rgb48_OperationsTests : PixelOperationsTests + { + public Rgb48_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => Rgb48.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.None, alphaRepresentation); + } + } + + public partial class Rgba1010102_OperationsTests : PixelOperationsTests + { + public Rgba1010102_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => Rgba1010102.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.Unassociated, alphaRepresentation); + } + } + + public partial class Rgba32_OperationsTests : PixelOperationsTests + { + public Rgba32_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => Rgba32.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.Unassociated, alphaRepresentation); + } + } + + public partial class Rgba64_OperationsTests : PixelOperationsTests + { + public Rgba64_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => Rgba64.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.Unassociated, alphaRepresentation); + } + } + + public partial class RgbaVector_OperationsTests : PixelOperationsTests + { + public RgbaVector_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => RgbaVector.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.Unassociated, alphaRepresentation); + } + } + + public partial class Short2_OperationsTests : PixelOperationsTests + { + public Short2_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => Short2.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.None, alphaRepresentation); + } + } + + public partial class Short4_OperationsTests : PixelOperationsTests + { + public Short4_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations Operations => Short4.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(PixelAlphaRepresentation.Unassociated, alphaRepresentation); + } + } + } +} + diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/Generated/PixelOperationsTests.Specialized.Generated.tt b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/Generated/PixelOperationsTests.Specialized.Generated.tt new file mode 100644 index 0000000000..502b66fb51 --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/Generated/PixelOperationsTests.Specialized.Generated.tt @@ -0,0 +1,11 @@ +<#@include file="_Common.ttinclude" #> +<#@ output extension=".cs" #> + +namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations +{ + public partial class PixelOperationsTests + { + <# GenerateAllSpecializedClasses(); #> + } +} + diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/Generated/_Common.ttinclude b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/Generated/_Common.ttinclude new file mode 100644 index 0000000000..8c436eecca --- /dev/null +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/Generated/_Common.ttinclude @@ -0,0 +1,111 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +// + +using SixLabors.ImageSharp.PixelFormats; +using Xunit; +using Xunit.Abstractions; +<#+ + private static readonly string[] UnassociatedAlphaPixelTypes = + { + "A8", + "Argb32", + "Bgra32", + "Bgra4444", + "Bgra5551", + "Byte4", + "HalfVector4", + "La16", + "La32", + "NormalizedByte4", + "NormalizedShort4", + "Rgba1010102", + "Rgba32", + "Rgba64", + "RgbaVector", + "Short4" + }; + + private static readonly string[] AssociatedAlphaPixelTypes = Array.Empty(); + + private static readonly string[] CommonPixelTypes = + { + "A8", + "Argb32", + "Bgr24", + "Bgr565", + "Bgra32", + "Bgra4444", + "Bgra5551", + "Byte4", + "HalfSingle", + "HalfVector2", + "HalfVector4", + "L16", + "L8", + "La16", + "La32", + "NormalizedByte2", + "NormalizedByte4", + "NormalizedShort2", + "NormalizedShort4", + "Rg32", + "Rgb24", + "Rgb48", + "Rgba1010102", + "Rgba32", + "Rgba64", + "RgbaVector", + "Short2", + "Short4", + }; + + void GenerateSpecializedClass(string pixelType, string alpha) + { +#> + public partial class <#=pixelType#>_OperationsTests : PixelOperationsTests<<#=pixelType#>> + { + public <#=pixelType#>_OperationsTests(ITestOutputHelper output) + : base(output) + { + } + + protected override PixelOperations<<#=pixelType#>> Operations => <#=pixelType#>.PixelOperations.Instance; + + [Fact] + public void IsSpecialImplementation() => Assert.IsType<<#=pixelType#>.PixelOperations>(PixelOperations<<#=pixelType#>>.Instance); + + [Fact] + public void PixelTypeInfoHasCorrectAlphaRepresentation() + { + var alphaRepresentation = this.Operations.GetPixelTypeInfo().AlphaRepresentation; + Assert.Equal(<#=alpha#>, alphaRepresentation); + } + } +<#+ + } + + void GenerateAllSpecializedClasses() + { + foreach (string pixelType in CommonPixelTypes) + { + string alpha = "PixelAlphaRepresentation.None"; + if (AssociatedAlphaPixelTypes.Contains(pixelType)) + { + alpha = "PixelAlphaRepresentation.Associated"; + } + else if (UnassociatedAlphaPixelTypes.Contains(pixelType)) + { + alpha = "PixelAlphaRepresentation.Unassociated"; + } + + GenerateSpecializedClass(pixelType, alpha); + } + } +#> diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelConversionModifiersExtensionsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelConversionModifiersExtensionsTests.cs index aa39588f94..6555ed8671 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelConversionModifiersExtensionsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelConversionModifiersExtensionsTests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations { + [Trait("Category", "PixelFormats")] public class PixelConversionModifiersExtensionsTests { [Theory] diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Argb32OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Argb32OperationsTests.cs deleted file mode 100644 index 1d4d583411..0000000000 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Argb32OperationsTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; - -using Xunit; -using Xunit.Abstractions; - -namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations -{ - public partial class PixelOperationsTests - { - public class Argb32OperationsTests : PixelOperationsTests - { - public Argb32OperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - } - } -} diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgr24OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgr24OperationsTests.cs deleted file mode 100644 index 712b1495ba..0000000000 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgr24OperationsTests.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; - -using Xunit; -using Xunit.Abstractions; - -namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations -{ - public partial class PixelOperationsTests - { - public class Bgr24OperationsTests : PixelOperationsTests - { - public Bgr24OperationsTests(ITestOutputHelper output) - : base(output) - { - this.HasAlpha = false; - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra32OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra32OperationsTests.cs deleted file mode 100644 index 7f248b682d..0000000000 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra32OperationsTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; - -using Xunit; -using Xunit.Abstractions; - -namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations -{ - public partial class PixelOperationsTests - { - public class Bgra32OperationsTests : PixelOperationsTests - { - public Bgra32OperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra5551OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra5551OperationsTests.cs deleted file mode 100644 index 9a0e51563a..0000000000 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Bgra5551OperationsTests.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; - -using Xunit.Abstractions; - -namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations -{ - public partial class PixelOperationsTests - { - public class Bgra5551OperationsTests : PixelOperationsTests - { - public Bgra5551OperationsTests(ITestOutputHelper output) - : base(output) - { - } - } - } -} diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.L16OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.L16OperationsTests.cs deleted file mode 100644 index 6acd439f21..0000000000 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.L16OperationsTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; - -using Xunit; -using Xunit.Abstractions; - -namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations -{ - public partial class PixelOperationsTests - { - public class L16OperationsTests : PixelOperationsTests - { - public L16OperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - } - } -} diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.L8OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.L8OperationsTests.cs deleted file mode 100644 index a16f8c66d2..0000000000 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.L8OperationsTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; - -using Xunit; -using Xunit.Abstractions; - -namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations -{ - public partial class PixelOperationsTests - { - public class L8OperationsTests : PixelOperationsTests - { - public L8OperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - } - } -} diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.La16OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.La16OperationsTests.cs deleted file mode 100644 index 07ec79777c..0000000000 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.La16OperationsTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; - -using Xunit; -using Xunit.Abstractions; - -namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations -{ - public partial class PixelOperationsTests - { - public class La16OperationsTests : PixelOperationsTests - { - public La16OperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - } - } -} diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.La32OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.La32OperationsTests.cs deleted file mode 100644 index bd8bb40da2..0000000000 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.La32OperationsTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; - -using Xunit; -using Xunit.Abstractions; - -namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations -{ - public partial class PixelOperationsTests - { - public class La32OperationsTests : PixelOperationsTests - { - public La32OperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - } - } -} diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb24OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb24OperationsTests.cs deleted file mode 100644 index 07bf838eee..0000000000 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb24OperationsTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; -using Xunit; -using Xunit.Abstractions; - -namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations -{ - public partial class PixelOperationsTests - { - public class Rgb24OperationsTests : PixelOperationsTests - { - public Rgb24OperationsTests(ITestOutputHelper output) - : base(output) - { - this.HasAlpha = false; - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - } - } -} diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb48OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb48OperationsTests.cs deleted file mode 100644 index 7ab6777664..0000000000 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgb48OperationsTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; - -using Xunit; -using Xunit.Abstractions; - -namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations -{ - public partial class PixelOperationsTests - { - public class Rgb48OperationsTests : PixelOperationsTests - { - public Rgb48OperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba32OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba32OperationsTests.cs index e4f1fa4624..9f4f1636b0 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba32OperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba32OperationsTests.cs @@ -1,29 +1,19 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System.Buffers; using System.Numerics; - using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; - using Xunit; -using Xunit.Abstractions; namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations { + [Trait("Category", "PixelFormats")] public partial class PixelOperationsTests { - public class Rgba32OperationsTests : PixelOperationsTests + public partial class Rgba32_OperationsTests : PixelOperationsTests { - public Rgba32OperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - [Fact(Skip = SkipProfilingBenchmarks)] public void Benchmark_ToVector4() { @@ -43,4 +33,4 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations } } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba64OperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba64OperationsTests.cs deleted file mode 100644 index a0ef2f765f..0000000000 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.Rgba64OperationsTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; - -using Xunit; -using Xunit.Abstractions; - -namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations -{ - public partial class PixelOperationsTests - { - public class Rgba64OperationsTests : PixelOperationsTests - { - public Rgba64OperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.RgbaVectorOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.RgbaVectorOperationsTests.cs deleted file mode 100644 index c552fb3592..0000000000 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.RgbaVectorOperationsTests.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.PixelFormats; - -using Xunit; -using Xunit.Abstractions; - -namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations -{ - public partial class PixelOperationsTests - { - public class RgbaVectorOperationsTests : PixelOperationsTests - { - public RgbaVectorOperationsTests(ITestOutputHelper output) - : base(output) - { - } - - [Fact] - public void IsSpecialImplementation() => Assert.IsType(PixelOperations.Instance); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs index 3c4b9dc795..cc7f32bef7 100644 --- a/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperations/PixelOperationsTests.cs @@ -10,12 +10,14 @@ using System.Runtime.InteropServices; using SixLabors.ImageSharp.ColorSpaces.Companding; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Tests.Common; using SixLabors.ImageSharp.Tests.TestUtilities; using Xunit; using Xunit.Abstractions; namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations { + [Trait("Category", "PixelFormats")] public partial class PixelOperationsTests { #pragma warning disable SA1313 // Parameter names should begin with lower-case letter @@ -36,8 +38,6 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations null; #endif - protected bool HasAlpha { get; set; } = true; - protected PixelOperationsTests(ITestOutputHelper output) : base(output) { @@ -73,7 +73,9 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations protected Configuration Configuration => Configuration.Default; - internal static PixelOperations Operations => PixelOperations.Instance; + protected virtual PixelOperations Operations { get; } = PixelOperations.Instance; + + protected bool HasUnassociatedAlpha => this.Operations.GetPixelTypeInfo().AlphaRepresentation == PixelAlphaRepresentation.Unassociated; internal static TPixel[] CreateExpectedPixelData(Vector4[] source, RefAction vectorModifier = null) { @@ -105,6 +107,33 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations return expected; } + [Fact] + public void PixelTypeInfoHasCorrectBitsPerPixel() + { + var bits = this.Operations.GetPixelTypeInfo().BitsPerPixel; + Assert.Equal(Unsafe.SizeOf() * 8, bits); + } + + [Fact] + public void PixelAlphaRepresentation_DefinesPresenceOfAlphaChannel() + { + // We use 0 - 255 as we have pixel formats that store + // the alpha component in less than 8 bits. + const byte Alpha = byte.MinValue; + const byte NoAlpha = byte.MaxValue; + + TPixel pixel = default; + pixel.FromRgba32(new Rgba32(0, 0, 0, Alpha)); + + Rgba32 dest = default; + pixel.ToRgba32(ref dest); + + bool hasAlpha = this.Operations.GetPixelTypeInfo().AlphaRepresentation != PixelAlphaRepresentation.None; + + byte expectedAlpha = hasAlpha ? Alpha : NoAlpha; + Assert.Equal(expectedAlpha, dest.A); + } + [Theory] [MemberData(nameof(ArraySizesData))] public void FromVector4(int count) @@ -115,7 +144,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromVector4Destructive(this.Configuration, s, d.GetSpan())); + (s, d) => this.Operations.FromVector4Destructive(this.Configuration, s, d.GetSpan())); } [Theory] @@ -131,7 +160,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations (s, d) => { Span destPixels = d.GetSpan(); - Operations.FromVector4Destructive(this.Configuration, (Span)s, destPixels, PixelConversionModifiers.Scale); + this.Operations.FromVector4Destructive(this.Configuration, s, destPixels, PixelConversionModifiers.Scale); }); } @@ -139,15 +168,9 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations [MemberData(nameof(ArraySizesData))] public void FromCompandedScaledVector4(int count) { - void SourceAction(ref Vector4 v) - { - SRgbCompanding.Expand(ref v); - } + void SourceAction(ref Vector4 v) => SRgbCompanding.Expand(ref v); - void ExpectedAction(ref Vector4 v) - { - SRgbCompanding.Compress(ref v); - } + void ExpectedAction(ref Vector4 v) => SRgbCompanding.Compress(ref v); Vector4[] source = CreateVector4TestData(count, (ref Vector4 v) => SourceAction(ref v)); TPixel[] expected = CreateScaledExpectedPixelData(source, (ref Vector4 v) => ExpectedAction(ref v)); @@ -155,11 +178,12 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromVector4Destructive( + (s, d) => this.Operations.FromVector4Destructive( this.Configuration, s, d.GetSpan(), - PixelConversionModifiers.SRgbCompand | PixelConversionModifiers.Scale)); + PixelConversionModifiers.SRgbCompand | PixelConversionModifiers.Scale), + false); } [Theory] @@ -168,17 +192,17 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations { void SourceAction(ref Vector4 v) { - if (this.HasAlpha) + if (this.HasUnassociatedAlpha) { - Vector4Utilities.Premultiply(ref v); + Numerics.Premultiply(ref v); } } void ExpectedAction(ref Vector4 v) { - if (this.HasAlpha) + if (this.HasUnassociatedAlpha) { - Vector4Utilities.UnPremultiply(ref v); + Numerics.UnPremultiply(ref v); } } @@ -188,7 +212,14 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromVector4Destructive(this.Configuration, s, d.GetSpan(), PixelConversionModifiers.Premultiply)); + (s, d) => + { + PixelConversionModifiers modifiers = this.HasUnassociatedAlpha + ? PixelConversionModifiers.Premultiply + : PixelConversionModifiers.None; + + this.Operations.FromVector4Destructive(this.Configuration, s, d.GetSpan(), modifiers); + }); } [Theory] @@ -197,17 +228,17 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations { void SourceAction(ref Vector4 v) { - if (this.HasAlpha) + if (this.HasUnassociatedAlpha) { - Vector4Utilities.Premultiply(ref v); + Numerics.Premultiply(ref v); } } void ExpectedAction(ref Vector4 v) { - if (this.HasAlpha) + if (this.HasUnassociatedAlpha) { - Vector4Utilities.UnPremultiply(ref v); + Numerics.UnPremultiply(ref v); } } @@ -217,11 +248,18 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromVector4Destructive( - this.Configuration, - s, - d.GetSpan(), - PixelConversionModifiers.Premultiply | PixelConversionModifiers.Scale)); + (s, d) => + { + PixelConversionModifiers modifiers = this.HasUnassociatedAlpha + ? PixelConversionModifiers.Premultiply + : PixelConversionModifiers.None; + + this.Operations.FromVector4Destructive( + this.Configuration, + s, + d.GetSpan(), + modifiers | PixelConversionModifiers.Scale); + }); } [Theory] @@ -232,17 +270,17 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations { SRgbCompanding.Expand(ref v); - if (this.HasAlpha) + if (this.HasUnassociatedAlpha) { - Vector4Utilities.Premultiply(ref v); + Numerics.Premultiply(ref v); } } void ExpectedAction(ref Vector4 v) { - if (this.HasAlpha) + if (this.HasUnassociatedAlpha) { - Vector4Utilities.UnPremultiply(ref v); + Numerics.UnPremultiply(ref v); } SRgbCompanding.Compress(ref v); @@ -254,11 +292,19 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromVector4Destructive( - this.Configuration, - s, - d.GetSpan(), - PixelConversionModifiers.SRgbCompand | PixelConversionModifiers.Premultiply | PixelConversionModifiers.Scale)); + (s, d) => + { + PixelConversionModifiers modifiers = this.HasUnassociatedAlpha + ? PixelConversionModifiers.Premultiply + : PixelConversionModifiers.None; + + this.Operations.FromVector4Destructive( + this.Configuration, + s, + d.GetSpan(), + modifiers | PixelConversionModifiers.SRgbCompand | PixelConversionModifiers.Scale); + }, + false); } [Theory] @@ -271,7 +317,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToVector4(this.Configuration, s, d.GetSpan())); + (s, d) => this.Operations.ToVector4(this.Configuration, s, d.GetSpan())); } public static readonly TheoryData Generic_To_Data = new TheoryData @@ -296,7 +342,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations PixelConverterTests.ReferenceImplementations.To(this.Configuration, source, expected); - TestOperation(source, expected, (s, d) => Operations.To(this.Configuration, (ReadOnlySpan)s, d.GetSpan())); + TestOperation(source, expected, (s, d) => this.Operations.To(this.Configuration, s, d.GetSpan())); } [Theory] @@ -309,11 +355,11 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => - { - Span destVectors = d.GetSpan(); - Operations.ToVector4(this.Configuration, (ReadOnlySpan)s, destVectors, PixelConversionModifiers.Scale); - }); + (s, d) => this.Operations.ToVector4( + this.Configuration, + s, + d.GetSpan(), + PixelConversionModifiers.Scale)); } [Theory] @@ -322,13 +368,9 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations { void SourceAction(ref Vector4 v) { - SRgbCompanding.Compress(ref v); } - void ExpectedAction(ref Vector4 v) - { - SRgbCompanding.Expand(ref v); - } + void ExpectedAction(ref Vector4 v) => SRgbCompanding.Expand(ref v); TPixel[] source = CreateScaledPixelTestData(count, (ref Vector4 v) => SourceAction(ref v)); Vector4[] expected = CreateExpectedScaledVector4Data(source, (ref Vector4 v) => ExpectedAction(ref v)); @@ -336,7 +378,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToVector4( + (s, d) => this.Operations.ToVector4( this.Configuration, s, d.GetSpan(), @@ -349,13 +391,9 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations { void SourceAction(ref Vector4 v) { - Vector4Utilities.UnPremultiply(ref v); } - void ExpectedAction(ref Vector4 v) - { - Vector4Utilities.Premultiply(ref v); - } + void ExpectedAction(ref Vector4 v) => Numerics.Premultiply(ref v); TPixel[] source = CreatePixelTestData(count, (ref Vector4 v) => SourceAction(ref v)); Vector4[] expected = CreateExpectedVector4Data(source, (ref Vector4 v) => ExpectedAction(ref v)); @@ -363,7 +401,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToVector4(this.Configuration, s, d.GetSpan(), PixelConversionModifiers.Premultiply)); + (s, d) => this.Operations.ToVector4(this.Configuration, s, d.GetSpan(), PixelConversionModifiers.Premultiply)); } [Theory] @@ -372,13 +410,9 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations { void SourceAction(ref Vector4 v) { - Vector4Utilities.UnPremultiply(ref v); } - void ExpectedAction(ref Vector4 v) - { - Vector4Utilities.Premultiply(ref v); - } + void ExpectedAction(ref Vector4 v) => Numerics.Premultiply(ref v); TPixel[] source = CreateScaledPixelTestData(count, (ref Vector4 v) => SourceAction(ref v)); Vector4[] expected = CreateExpectedScaledVector4Data(source, (ref Vector4 v) => ExpectedAction(ref v)); @@ -386,7 +420,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToVector4( + (s, d) => this.Operations.ToVector4( this.Configuration, s, d.GetSpan(), @@ -399,14 +433,12 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations { void SourceAction(ref Vector4 v) { - Vector4Utilities.UnPremultiply(ref v); - SRgbCompanding.Compress(ref v); } void ExpectedAction(ref Vector4 v) { SRgbCompanding.Expand(ref v); - Vector4Utilities.Premultiply(ref v); + Numerics.Premultiply(ref v); } TPixel[] source = CreateScaledPixelTestData(count, (ref Vector4 v) => SourceAction(ref v)); @@ -415,7 +447,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToVector4( + (s, d) => this.Operations.ToVector4( this.Configuration, s, d.GetSpan(), @@ -439,7 +471,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromArgb32Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.FromArgb32Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -464,7 +496,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToArgb32Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.ToArgb32Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -484,7 +516,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromBgr24Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.FromBgr24Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -507,7 +539,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToBgr24Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.ToBgr24Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -527,7 +559,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromBgra32Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.FromBgra32Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -551,7 +583,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToBgra32Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.ToBgra32Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -573,7 +605,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromBgra5551Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.FromBgra5551Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -597,7 +629,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToBgra5551Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.ToBgra5551Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -616,7 +648,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromL8(this.Configuration, s, d.GetSpan())); + (s, d) => this.Operations.FromL8(this.Configuration, s, d.GetSpan())); } [Theory] @@ -634,7 +666,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToL8(this.Configuration, s, d.GetSpan())); + (s, d) => this.Operations.ToL8(this.Configuration, s, d.GetSpan())); } [Theory] @@ -658,7 +690,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromL16(this.Configuration, s, d.GetSpan())); + (s, d) => this.Operations.FromL16(this.Configuration, s, d.GetSpan())); } [Theory] @@ -676,7 +708,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToL16(this.Configuration, s, d.GetSpan())); + (s, d) => this.Operations.ToL16(this.Configuration, s, d.GetSpan())); } [Theory] @@ -698,7 +730,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromLa16Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.FromLa16Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -722,7 +754,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToLa16Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.ToLa16Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -744,7 +776,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromLa32Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.FromLa32Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -770,7 +802,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToLa32Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.ToLa32Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -790,7 +822,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromRgb24Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.FromRgb24Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -813,7 +845,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToRgb24Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.ToRgb24Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -833,7 +865,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromRgba32Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.FromRgba32Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -857,7 +889,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToRgba32Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.ToRgba32Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -877,7 +909,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromRgb48Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.FromRgb48Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -904,7 +936,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToRgb48Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.ToRgb48Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -924,7 +956,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.FromRgba64Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.FromRgba64Bytes(this.Configuration, s, d.GetSpan(), count)); } [Theory] @@ -953,9 +985,16 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations TestOperation( source, expected, - (s, d) => Operations.ToRgba64Bytes(this.Configuration, s, d.GetSpan(), count)); + (s, d) => this.Operations.ToRgba64Bytes(this.Configuration, s, d.GetSpan(), count)); } + [Theory] + [MemberData(nameof(ArraySizesData))] + public void PackFromRgbPlanes(int count) + => SimdUtilsTests.TestPackFromRgbPlanes( + count, + (r, g, b, actual) => PixelOperations.Instance.PackFromRgbPlanes(this.Configuration, r, g, b, actual)); + public delegate void RefAction(ref T1 arg1); internal static Vector4[] CreateExpectedVector4Data(TPixel[] source, RefAction vectorModifier = null) @@ -993,11 +1032,12 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations internal static void TestOperation( TSource[] source, TDest[] expected, - Action> action) + Action> action, + bool preferExactComparison = true) where TSource : struct where TDest : struct { - using (var buffers = new TestBuffers(source, expected)) + using (var buffers = new TestBuffers(source, expected, preferExactComparison)) { action(buffers.SourceBuffer, buffers.ActualDestBuffer); buffers.Verify(); @@ -1011,7 +1051,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations for (int i = 0; i < result.Length; i++) { - Vector4 v = GetVector(rnd); + Vector4 v = GetScaledVector(rnd); vectorModifier?.Invoke(ref v); result[i] = v; @@ -1028,7 +1068,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations for (int i = 0; i < result.Length; i++) { - Vector4 v = GetVector(rnd); + Vector4 v = GetScaledVector(rnd); vectorModifier?.Invoke(ref v); @@ -1046,7 +1086,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations for (int i = 0; i < result.Length; i++) { - Vector4 v = GetVector(rnd); + Vector4 v = GetScaledVector(rnd); vectorModifier?.Invoke(ref v); @@ -1056,10 +1096,10 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations return result; } - internal static byte[] CreateByteTestData(int length) + internal static byte[] CreateByteTestData(int length, int seed = 42) { byte[] result = new byte[length]; - var rnd = new Random(42); // Deterministic random values + var rnd = new Random(seed); // Deterministic random values for (int i = 0; i < result.Length; i++) { @@ -1069,10 +1109,8 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations return result; } - internal static Vector4 GetVector(Random rnd) - { - return new Vector4((float)rnd.NextDouble(), (float)rnd.NextDouble(), (float)rnd.NextDouble(), (float)rnd.NextDouble()); - } + internal static Vector4 GetScaledVector(Random rnd) + => new Vector4((float)rnd.NextDouble(), (float)rnd.NextDouble(), (float)rnd.NextDouble(), (float)rnd.NextDouble()); [StructLayout(LayoutKind.Sequential)] internal unsafe struct OctetBytes @@ -1100,11 +1138,14 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations public TDest[] ExpectedDestBuffer { get; } - public TestBuffers(TSource[] source, TDest[] expectedDest) + public bool PreferExactComparison { get; } + + public TestBuffers(TSource[] source, TDest[] expectedDest, bool preferExactComparison = true) { this.SourceBuffer = source; this.ExpectedDestBuffer = expectedDest; this.ActualDestBuffer = Configuration.Default.MemoryAllocator.Allocate(expectedDest.Length); + this.PreferExactComparison = preferExactComparison; } public void Dispose() => this.ActualDestBuffer.Dispose(); @@ -1117,26 +1158,54 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats.PixelOperations { Span expected = MemoryMarshal.Cast(this.ExpectedDestBuffer.AsSpan()); Span actual = MemoryMarshal.Cast(this.ActualDestBuffer.GetSpan()); + var comparer = new ApproximateFloatComparer(TestEnvironment.Is64BitProcess ? 0.0001F : 0.001F); - var comparer = new ApproximateFloatComparer(0.001f); for (int i = 0; i < count; i++) { - // ReSharper disable PossibleNullReferenceException Assert.Equal(expected[i], actual[i], comparer); + } + } + else if (!this.PreferExactComparison && typeof(IPixel).IsAssignableFrom(typeof(TDest)) && IsComplexPixel()) + { + Span expected = this.ExpectedDestBuffer.AsSpan(); + Span actual = this.ActualDestBuffer.GetSpan(); + var comparer = new ApproximateFloatComparer(TestEnvironment.Is64BitProcess ? 0.0001F : 0.001F); - // ReSharper restore PossibleNullReferenceException + for (int i = 0; i < count; i++) + { + Assert.Equal((IPixel)expected[i], (IPixel)actual[i], comparer); } } else { Span expected = this.ExpectedDestBuffer.AsSpan(); Span actual = this.ActualDestBuffer.GetSpan(); + for (int i = 0; i < count; i++) { Assert.Equal(expected[i], actual[i]); } } } + + // TODO: We really need a PixelTypeInfo.BitsPerComponent property!! + private static bool IsComplexPixel() + { + switch (default(TDest)) + { + case HalfSingle _: + case HalfVector2 _: + case L16 _: + case La32 _: + case NormalizedShort2 _: + case Rg32 _: + case Short2 _: + return true; + + default: + return Unsafe.SizeOf() > sizeof(int); + } + } } } } diff --git a/tests/ImageSharp.Tests/PixelFormats/Rg32Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rg32Tests.cs index e3e65798a3..a39fa51666 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rg32Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rg32Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class Rg32Tests { [Fact] diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs index 926f820c73..4d4f8c9fb9 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class Rgb24Tests { public static readonly TheoryData ColorData = diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgb48Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgb48Tests.cs index 835779e684..928998579e 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgb48Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgb48Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class Rgb48Tests { [Fact] diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs index ba222c2305..0704c7fdd5 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgba1010102Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class Rgba1010102Tests { /// diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgba32Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgba32Tests.cs index 0eb95d4cbe..bc66d404b6 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgba32Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgba32Tests.cs @@ -11,6 +11,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats /// /// Tests the struct. /// + [Trait("Category", "PixelFormats")] public class Rgba32Tests { /// diff --git a/tests/ImageSharp.Tests/PixelFormats/Rgba64Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Rgba64Tests.cs index 8d29c8e2d4..8daf960d6e 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Rgba64Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Rgba64Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class Rgba64Tests { [Fact] diff --git a/tests/ImageSharp.Tests/PixelFormats/RgbaVectorTests.cs b/tests/ImageSharp.Tests/PixelFormats/RgbaVectorTests.cs index de6cc09de7..438d5f2ed3 100644 --- a/tests/ImageSharp.Tests/PixelFormats/RgbaVectorTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/RgbaVectorTests.cs @@ -11,6 +11,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats /// /// Tests the struct. /// + [Trait("Category", "PixelFormats")] public class RgbaVectorTests { /// diff --git a/tests/ImageSharp.Tests/PixelFormats/Short2Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Short2Tests.cs index b65299cccd..75b1df37d7 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Short2Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Short2Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class Short2Tests { [Fact] diff --git a/tests/ImageSharp.Tests/PixelFormats/Short4Tests.cs b/tests/ImageSharp.Tests/PixelFormats/Short4Tests.cs index 8da95e0f50..3709205ac4 100644 --- a/tests/ImageSharp.Tests/PixelFormats/Short4Tests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/Short4Tests.cs @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.PixelFormats { + [Trait("Category", "PixelFormats")] public class Short4Tests { [Fact] diff --git a/tests/ImageSharp.Tests/PixelFormats/UnPackedPixelTests.cs b/tests/ImageSharp.Tests/PixelFormats/UnPackedPixelTests.cs index b8c7786211..9492fef90b 100644 --- a/tests/ImageSharp.Tests/PixelFormats/UnPackedPixelTests.cs +++ b/tests/ImageSharp.Tests/PixelFormats/UnPackedPixelTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using System.Numerics; @@ -7,6 +7,7 @@ using Xunit; namespace SixLabors.ImageSharp.Tests.Colors { + [Trait("Category", "PixelFormats")] public class UnPackedPixelTests { [Fact] @@ -102,4 +103,4 @@ namespace SixLabors.ImageSharp.Tests.Colors Assert.Equal(color.ToHex(), colorVector.ToHex()); } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/Processing/Binarization/AdaptiveThresholdTests.cs b/tests/ImageSharp.Tests/Processing/Binarization/AdaptiveThresholdTests.cs index 8efac7593d..f4f800107f 100644 --- a/tests/ImageSharp.Tests/Processing/Binarization/AdaptiveThresholdTests.cs +++ b/tests/ImageSharp.Tests/Processing/Binarization/AdaptiveThresholdTests.cs @@ -100,6 +100,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization [Theory] [WithFile(TestImages.Png.Bradley01, PixelTypes.Rgba32)] [WithFile(TestImages.Png.Bradley02, PixelTypes.Rgba32)] + [WithFile(TestImages.Png.Ducky, PixelTypes.Rgba32)] public void AdaptiveThreshold_Works(TestImageProvider provider) where TPixel : unmanaged, IPixel { diff --git a/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs b/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs index 5bdfda02eb..a2fb9f9bad 100644 --- a/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs +++ b/tests/ImageSharp.Tests/Processing/Binarization/BinaryThresholdTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. using SixLabors.ImageSharp.Processing; @@ -16,6 +16,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization this.operations.BinaryThreshold(.23f); BinaryThresholdProcessor p = this.Verify(); Assert.Equal(.23f, p.Threshold); + Assert.Equal(BinaryThresholdMode.Luminance, p.Mode); Assert.Equal(Color.White, p.UpperColor); Assert.Equal(Color.Black, p.LowerColor); } @@ -26,6 +27,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization this.operations.BinaryThreshold(.93f, this.rect); BinaryThresholdProcessor p = this.Verify(this.rect); Assert.Equal(.93f, p.Threshold); + Assert.Equal(BinaryThresholdMode.Luminance, p.Mode); Assert.Equal(Color.White, p.UpperColor); Assert.Equal(Color.Black, p.LowerColor); } @@ -36,6 +38,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization this.operations.BinaryThreshold(.23f, Color.HotPink, Color.Yellow); BinaryThresholdProcessor p = this.Verify(); Assert.Equal(.23f, p.Threshold); + Assert.Equal(BinaryThresholdMode.Luminance, p.Mode); Assert.Equal(Color.HotPink, p.UpperColor); Assert.Equal(Color.Yellow, p.LowerColor); } @@ -45,9 +48,98 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization { this.operations.BinaryThreshold(.93f, Color.HotPink, Color.Yellow, this.rect); BinaryThresholdProcessor p = this.Verify(this.rect); + Assert.Equal(BinaryThresholdMode.Luminance, p.Mode); Assert.Equal(.93f, p.Threshold); Assert.Equal(Color.HotPink, p.UpperColor); Assert.Equal(Color.Yellow, p.LowerColor); } + + [Fact] + public void BinarySaturationThreshold_CorrectProcessor() + { + this.operations.BinaryThreshold(.23f, BinaryThresholdMode.Saturation); + BinaryThresholdProcessor p = this.Verify(); + Assert.Equal(.23f, p.Threshold); + Assert.Equal(BinaryThresholdMode.Saturation, p.Mode); + Assert.Equal(Color.White, p.UpperColor); + Assert.Equal(Color.Black, p.LowerColor); + } + + [Fact] + public void BinarySaturationThreshold_rect_CorrectProcessor() + { + this.operations.BinaryThreshold(.93f, BinaryThresholdMode.Saturation, this.rect); + BinaryThresholdProcessor p = this.Verify(this.rect); + Assert.Equal(.93f, p.Threshold); + Assert.Equal(BinaryThresholdMode.Saturation, p.Mode); + Assert.Equal(Color.White, p.UpperColor); + Assert.Equal(Color.Black, p.LowerColor); + } + + [Fact] + public void BinarySaturationThreshold_CorrectProcessorWithUpperLower() + { + this.operations.BinaryThreshold(.23f, Color.HotPink, Color.Yellow, BinaryThresholdMode.Saturation); + BinaryThresholdProcessor p = this.Verify(); + Assert.Equal(.23f, p.Threshold); + Assert.Equal(BinaryThresholdMode.Saturation, p.Mode); + Assert.Equal(Color.HotPink, p.UpperColor); + Assert.Equal(Color.Yellow, p.LowerColor); + } + + [Fact] + public void BinarySaturationThreshold_rect_CorrectProcessorWithUpperLower() + { + this.operations.BinaryThreshold(.93f, Color.HotPink, Color.Yellow, BinaryThresholdMode.Saturation, this.rect); + BinaryThresholdProcessor p = this.Verify(this.rect); + Assert.Equal(.93f, p.Threshold); + Assert.Equal(BinaryThresholdMode.Saturation, p.Mode); + Assert.Equal(Color.HotPink, p.UpperColor); + Assert.Equal(Color.Yellow, p.LowerColor); + } + + [Fact] + public void BinaryMaxChromaThreshold_CorrectProcessor() + { + this.operations.BinaryThreshold(.23f, BinaryThresholdMode.MaxChroma); + BinaryThresholdProcessor p = this.Verify(); + Assert.Equal(.23f, p.Threshold); + Assert.Equal(BinaryThresholdMode.MaxChroma, p.Mode); + Assert.Equal(Color.White, p.UpperColor); + Assert.Equal(Color.Black, p.LowerColor); + } + + [Fact] + public void BinaryMaxChromaThreshold_rect_CorrectProcessor() + { + this.operations.BinaryThreshold(.93f, BinaryThresholdMode.MaxChroma, this.rect); + BinaryThresholdProcessor p = this.Verify(this.rect); + Assert.Equal(.93f, p.Threshold); + Assert.Equal(BinaryThresholdMode.MaxChroma, p.Mode); + Assert.Equal(Color.White, p.UpperColor); + Assert.Equal(Color.Black, p.LowerColor); + } + + [Fact] + public void BinaryMaxChromaThreshold_CorrectProcessorWithUpperLower() + { + this.operations.BinaryThreshold(.23f, Color.HotPink, Color.Yellow, BinaryThresholdMode.MaxChroma); + BinaryThresholdProcessor p = this.Verify(); + Assert.Equal(.23f, p.Threshold); + Assert.Equal(BinaryThresholdMode.MaxChroma, p.Mode); + Assert.Equal(Color.HotPink, p.UpperColor); + Assert.Equal(Color.Yellow, p.LowerColor); + } + + [Fact] + public void BinaryMaxChromaThreshold_rect_CorrectProcessorWithUpperLower() + { + this.operations.BinaryThreshold(.93f, Color.HotPink, Color.Yellow, BinaryThresholdMode.MaxChroma, this.rect); + BinaryThresholdProcessor p = this.Verify(this.rect); + Assert.Equal(.93f, p.Threshold); + Assert.Equal(BinaryThresholdMode.MaxChroma, p.Mode); + Assert.Equal(Color.HotPink, p.UpperColor); + Assert.Equal(Color.Yellow, p.LowerColor); + } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/Processing/Filters/BrightnessTest.cs b/tests/ImageSharp.Tests/Processing/Filters/BrightnessTest.cs index 75a9072c59..680a6afdce 100644 --- a/tests/ImageSharp.Tests/Processing/Filters/BrightnessTest.cs +++ b/tests/ImageSharp.Tests/Processing/Filters/BrightnessTest.cs @@ -1,6 +1,7 @@ -// Copyright (c) Six Labors. +// Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. +using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Filters; using Xunit; @@ -26,5 +27,33 @@ namespace SixLabors.ImageSharp.Tests.Processing.Effects Assert.Equal(1.5F, processor.Amount); } + + [Fact] + public void Brightness_scaled_vector() + { + var rgbImage = new Image(Configuration.Default, 100, 100, new Rgb24(0, 0, 0)); + + rgbImage.Mutate(x => x.ApplyProcessor(new BrightnessProcessor(2))); + + Assert.Equal(new Rgb24(0, 0, 0), rgbImage[0, 0]); + + rgbImage = new Image(Configuration.Default, 100, 100, new Rgb24(10, 10, 10)); + + rgbImage.Mutate(x => x.ApplyProcessor(new BrightnessProcessor(2))); + + Assert.Equal(new Rgb24(20, 20, 20), rgbImage[0, 0]); + + var halfSingleImage = new Image(Configuration.Default, 100, 100, new HalfSingle(-1)); + + halfSingleImage.Mutate(x => x.ApplyProcessor(new BrightnessProcessor(2))); + + Assert.Equal(new HalfSingle(-1), halfSingleImage[0, 0]); + + halfSingleImage = new Image(Configuration.Default, 100, 100, new HalfSingle(-0.5f)); + + halfSingleImage.Mutate(x => x.ApplyProcessor(new BrightnessProcessor(2))); + + Assert.Equal(new HalfSingle(0), halfSingleImage[0, 0]); + } } -} \ No newline at end of file +} diff --git a/tests/ImageSharp.Tests/Processing/IntegralImageTests.cs b/tests/ImageSharp.Tests/Processing/IntegralImageTests.cs new file mode 100644 index 0000000000..481463f47e --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/IntegralImageTests.cs @@ -0,0 +1,110 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Transforms +{ + public class IntegralImageTests : BaseImageOperationsExtensionTest + { + [Theory] + [WithFile(TestImages.Png.Bradley01, PixelTypes.Rgba32)] + [WithFile(TestImages.Png.Bradley02, PixelTypes.Rgba32)] + [WithFile(TestImages.Png.Ducky, PixelTypes.Rgba32)] + public void CalculateIntegralImage_Rgba32Works(TestImageProvider provider) + { + using Image image = provider.GetImage(); + + // Act: + Buffer2D integralBuffer = image.CalculateIntegralImage(); + + // Assert: + VerifySumValues(provider, integralBuffer, (Rgba32 pixel) => + { + L8 outputPixel = default; + + outputPixel.FromRgba32(pixel); + + return outputPixel.PackedValue; + }); + } + + [Theory] + [WithFile(TestImages.Png.Bradley01, PixelTypes.L8)] + [WithFile(TestImages.Png.Bradley02, PixelTypes.L8)] + public void CalculateIntegralImage_L8Works(TestImageProvider provider) + { + using Image image = provider.GetImage(); + + // Act: + Buffer2D integralBuffer = image.CalculateIntegralImage(); + + // Assert: + VerifySumValues(provider, integralBuffer, (L8 pixel) => { return pixel.PackedValue; }); + } + + private static void VerifySumValues( + TestImageProvider provider, + Buffer2D integralBuffer, + System.Func getPixel) + where TPixel : unmanaged, IPixel + { + Image image = provider.GetImage(); + + // Check top-left corner + Assert.Equal(getPixel(image[0, 0]), integralBuffer[0, 0]); + + ulong pixelValues = 0; + + pixelValues += getPixel(image[0, 0]); + pixelValues += getPixel(image[1, 0]); + pixelValues += getPixel(image[0, 1]); + pixelValues += getPixel(image[1, 1]); + + // Check top-left 2x2 pixels + Assert.Equal(pixelValues, integralBuffer[1, 1]); + + pixelValues = 0; + + pixelValues += getPixel(image[image.Width - 3, 0]); + pixelValues += getPixel(image[image.Width - 2, 0]); + pixelValues += getPixel(image[image.Width - 1, 0]); + pixelValues += getPixel(image[image.Width - 3, 1]); + pixelValues += getPixel(image[image.Width - 2, 1]); + pixelValues += getPixel(image[image.Width - 1, 1]); + + // Check top-right 3x2 pixels + Assert.Equal(pixelValues, integralBuffer[image.Width - 1, 1] + 0 - 0 - integralBuffer[image.Width - 4, 1]); + + pixelValues = 0; + + pixelValues += getPixel(image[0, image.Height - 3]); + pixelValues += getPixel(image[0, image.Height - 2]); + pixelValues += getPixel(image[0, image.Height - 1]); + pixelValues += getPixel(image[1, image.Height - 3]); + pixelValues += getPixel(image[1, image.Height - 2]); + pixelValues += getPixel(image[1, image.Height - 1]); + + // Check bottom-left 2x3 pixels + Assert.Equal(pixelValues, integralBuffer[1, image.Height - 1] + 0 - integralBuffer[1, image.Height - 4] - 0); + + pixelValues = 0; + + pixelValues += getPixel(image[image.Width - 3, image.Height - 3]); + pixelValues += getPixel(image[image.Width - 2, image.Height - 3]); + pixelValues += getPixel(image[image.Width - 1, image.Height - 3]); + pixelValues += getPixel(image[image.Width - 3, image.Height - 2]); + pixelValues += getPixel(image[image.Width - 2, image.Height - 2]); + pixelValues += getPixel(image[image.Width - 1, image.Height - 2]); + pixelValues += getPixel(image[image.Width - 3, image.Height - 1]); + pixelValues += getPixel(image[image.Width - 2, image.Height - 1]); + pixelValues += getPixel(image[image.Width - 1, image.Height - 1]); + + // Check bottom-right 3x3 pixels + Assert.Equal(pixelValues, integralBuffer[image.Width - 1, image.Height - 1] + integralBuffer[image.Width - 4, image.Height - 4] - integralBuffer[image.Width - 1, image.Height - 4] - integralBuffer[image.Width - 4, image.Height - 1]); + } + } +} diff --git a/tests/ImageSharp.Tests/Processing/Normalization/HistogramEqualizationTests.cs b/tests/ImageSharp.Tests/Processing/Normalization/HistogramEqualizationTests.cs index 1c1da6f191..4460f04fb1 100644 --- a/tests/ImageSharp.Tests/Processing/Normalization/HistogramEqualizationTests.cs +++ b/tests/ImageSharp.Tests/Processing/Normalization/HistogramEqualizationTests.cs @@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Normalization [Theory] [InlineData(256)] [InlineData(65536)] - public void HistogramEqualizationTest(int luminanceLevels) + public void GlobalHistogramEqualization_WithDifferentLumanceLevels(int luminanceLevels) { // Arrange var pixels = new byte[] @@ -45,20 +45,21 @@ namespace SixLabors.ImageSharp.Tests.Processing.Normalization var expected = new byte[] { - 0, 12, 53, 32, 146, 53, 174, 53, - 57, 32, 12, 227, 219, 202, 32, 154, - 65, 85, 93, 239, 251, 227, 65, 158, - 73, 146, 146, 247, 255, 235, 154, 130, - 97, 166, 117, 231, 243, 210, 117, 117, - 117, 190, 36, 190, 178, 93, 20, 170, - 130, 202, 73, 20, 12, 53, 85, 194, - 146, 206, 130, 117, 85, 166, 182, 215 + 0, 12, 53, 32, 146, 53, 174, 53, + 57, 32, 12, 227, 219, 202, 32, 154, + 65, 85, 93, 239, 251, 227, 65, 158, + 73, 146, 146, 247, 255, 235, 154, 130, + 97, 166, 117, 231, 243, 210, 117, 117, + 117, 190, 36, 190, 178, 93, 20, 170, + 130, 202, 73, 20, 12, 53, 85, 194, + 146, 206, 130, 117, 85, 166, 182, 215 }; // Act image.Mutate(x => x.HistogramEqualization(new HistogramEqualizationOptions { - LuminanceLevels = luminanceLevels + LuminanceLevels = luminanceLevels, + Method = HistogramEqualizationMethod.Global })); // Assert @@ -75,6 +76,24 @@ namespace SixLabors.ImageSharp.Tests.Processing.Normalization } } + [Theory] + [WithFile(TestImages.Jpeg.Baseline.HistogramEqImage, PixelTypes.Rgba32)] + public void GlobalHistogramEqualization_CompareToReferenceOutput(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + using (Image image = provider.GetImage()) + { + var options = new HistogramEqualizationOptions + { + Method = HistogramEqualizationMethod.Global, + LuminanceLevels = 256, + }; + image.Mutate(x => x.HistogramEqualization(options)); + image.DebugSave(provider); + image.CompareToReferenceOutput(ValidatorComparer, provider, extension: "png"); + } + } + [Theory] [WithFile(TestImages.Jpeg.Baseline.LowContrast, PixelTypes.Rgba32)] public void Adaptive_SlidingWindow_15Tiles_WithClipping(TestImageProvider provider) diff --git a/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs index c5b7808cc2..fd08eb2dea 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Binarization/BinaryThresholdTest.cs @@ -1,14 +1,15 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. +using System.Globalization; using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Processors.Binarization; using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization { - using SixLabors.ImageSharp.Processing; - public class BinaryThresholdTest { public static readonly TheoryData BinaryThresholdValues @@ -19,9 +20,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization }; public static readonly string[] CommonTestImages = - { - TestImages.Png.CalliphoraPartial, TestImages.Png.Bike - }; + { + TestImages.Png.Rgb48Bpp, + TestImages.Png.ColorsSaturationLightness, + }; public const PixelTypes TestPixelTypes = PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Rgb24; @@ -43,9 +45,9 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization where TPixel : unmanaged, IPixel { using (Image source = provider.GetImage()) - using (var image = source.Clone()) + using (Image image = source.Clone()) { - var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); + var bounds = new Rectangle(image.Width / 8, image.Height / 8, 6 * image.Width / 8, 6 * image.Width / 8); image.Mutate(x => x.BinaryThreshold(value, bounds)); image.DebugSave(provider, value); @@ -53,5 +55,81 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); } } + + [Theory] + [WithFileCollection(nameof(CommonTestImages), nameof(BinaryThresholdValues), PixelTypes.Rgba32)] + public void ImageShouldApplyBinarySaturationThresholdFilter(TestImageProvider provider, float value) + where TPixel : unmanaged, IPixel + { + using (Image image = provider.GetImage()) + { + image.Mutate(x => x.BinaryThreshold(value, BinaryThresholdMode.Saturation)); + image.DebugSave(provider, value); + image.CompareToReferenceOutput(ImageComparer.Exact, provider, value.ToString("0.00", NumberFormatInfo.InvariantInfo)); + } + } + + [Theory] + [WithFileCollection(nameof(CommonTestImages), nameof(BinaryThresholdValues), PixelTypes.Rgba32)] + public void ImageShouldApplyBinarySaturationThresholdInBox(TestImageProvider provider, float value) + where TPixel : unmanaged, IPixel + { + using (Image source = provider.GetImage()) + using (Image image = source.Clone()) + { + var bounds = new Rectangle(image.Width / 8, image.Height / 8, 6 * image.Width / 8, 6 * image.Width / 8); + + image.Mutate(x => x.BinaryThreshold(value, BinaryThresholdMode.Saturation, bounds)); + image.DebugSave(provider, value); + image.CompareToReferenceOutput(ImageComparer.Exact, provider, value.ToString("0.00", NumberFormatInfo.InvariantInfo)); + } + } + + [Theory] + [WithFileCollection(nameof(CommonTestImages), nameof(BinaryThresholdValues), PixelTypes.Rgba32)] + public void ImageShouldApplyBinaryMaxChromaThresholdFilter(TestImageProvider provider, float value) + where TPixel : unmanaged, IPixel + { + using (Image image = provider.GetImage()) + { + image.Mutate(x => x.BinaryThreshold(value, BinaryThresholdMode.MaxChroma)); + image.DebugSave(provider, value); + + if (!TestEnvironment.Is64BitProcess && TestEnvironment.IsFramework) + { + var comparer = ImageComparer.TolerantPercentage(0.0004F); + image.CompareToReferenceOutput(comparer, provider, value.ToString("0.00", NumberFormatInfo.InvariantInfo)); + } + else + { + image.CompareToReferenceOutput(ImageComparer.Exact, provider, value.ToString("0.00", NumberFormatInfo.InvariantInfo)); + } + } + } + + [Theory] + [WithFileCollection(nameof(CommonTestImages), nameof(BinaryThresholdValues), PixelTypes.Rgba32)] + public void ImageShouldApplyBinaryMaxChromaThresholdInBox(TestImageProvider provider, float value) + where TPixel : unmanaged, IPixel + { + using (Image source = provider.GetImage()) + using (Image image = source.Clone()) + { + var bounds = new Rectangle(image.Width / 8, image.Height / 8, 6 * image.Width / 8, 6 * image.Width / 8); + + image.Mutate(x => x.BinaryThreshold(value, BinaryThresholdMode.MaxChroma, bounds)); + image.DebugSave(provider, value); + + if (!TestEnvironment.Is64BitProcess && TestEnvironment.IsFramework) + { + var comparer = ImageComparer.TolerantPercentage(0.0004F); + image.CompareToReferenceOutput(comparer, provider, value.ToString("0.00", NumberFormatInfo.InvariantInfo)); + } + else + { + image.CompareToReferenceOutput(ImageComparer.Exact, provider, value.ToString("0.00", NumberFormatInfo.InvariantInfo)); + } + } + } } } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Convolution/BokehBlurTest.cs b/tests/ImageSharp.Tests/Processing/Processors/Convolution/BokehBlurTest.cs index 50b8782e47..dbf59a29ba 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Convolution/BokehBlurTest.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Convolution/BokehBlurTest.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text.RegularExpressions; -using Microsoft.DotNet.RemoteExecutor; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; @@ -44,9 +43,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution [InlineData(20, 4, -10f)] [InlineData(20, 4, 0f)] public void VerifyBokehBlurProcessorArguments_Fail(int radius, int components, float gamma) - { - Assert.Throws(() => new BokehBlurProcessor(radius, components, gamma)); - } + => Assert.Throws( + () => new BokehBlurProcessor(radius, components, gamma)); [Fact] public void VerifyComplexComponents() @@ -137,23 +135,10 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution [WithTestPatternImages(nameof(BokehBlurValues), 30, 20, PixelTypes.Rgba32)] public void BokehBlurFilterProcessor(TestImageProvider provider, BokehBlurInfo value) where TPixel : unmanaged, IPixel - { - static void RunTest(string providerDump, string infoDump) - { - TestImageProvider provider = - BasicSerializer.Deserialize>(providerDump); - BokehBlurInfo value = BasicSerializer.Deserialize(infoDump); - - provider.RunValidatingProcessorTest( - x => x.BokehBlur(value.Radius, value.Components, value.Gamma), - testOutputDetails: value.ToString(), - appendPixelTypeToFileName: false); - } - - RemoteExecutor - .Invoke(RunTest, BasicSerializer.Serialize(provider), BasicSerializer.Serialize(value)) - .Dispose(); - } + => provider.RunValidatingProcessorTest( + x => x.BokehBlur(value.Radius, value.Components, value.Gamma), + testOutputDetails: value.ToString(), + appendPixelTypeToFileName: false); [Theory] /* @@ -163,54 +148,44 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution [WithTestPatternImages(200, 200, PixelTypes.Bgr24 | PixelTypes.Bgra32)] public void BokehBlurFilterProcessor_WorksWithAllPixelTypes(TestImageProvider provider) where TPixel : unmanaged, IPixel - { - static void RunTest(string providerDump) - { - TestImageProvider provider = - BasicSerializer.Deserialize>(providerDump); - provider.RunValidatingProcessorTest( - x => x.BokehBlur(8, 2, 3), - appendSourceFileOrDescription: false); - } - - RemoteExecutor - .Invoke(RunTest, BasicSerializer.Serialize(provider)) - .Dispose(); - } + => provider.RunValidatingProcessorTest( + x => x.BokehBlur(8, 2, 3), + appendSourceFileOrDescription: false); [Theory] [WithFileCollection(nameof(TestFiles), nameof(BokehBlurValues), PixelTypes.Rgba32)] - public void BokehBlurFilterProcessor_Bounded(TestImageProvider provider, BokehBlurInfo value) - where TPixel : unmanaged, IPixel + public void BokehBlurFilterProcessor_Bounded(TestImageProvider provider, BokehBlurInfo value) { - static void RunTest(string providerDump, string infoDump) + static void RunTest(string arg1, string arg2) { - TestImageProvider provider = - BasicSerializer.Deserialize>(providerDump); - BokehBlurInfo value = BasicSerializer.Deserialize(infoDump); + TestImageProvider provider = + FeatureTestRunner.DeserializeForXunit>(arg1); + + BokehBlurInfo value = + FeatureTestRunner.DeserializeForXunit(arg2); provider.RunValidatingProcessorTest( - x => - { - Size size = x.GetCurrentSize(); - var bounds = new Rectangle(10, 10, size.Width / 2, size.Height / 2); - x.BokehBlur(value.Radius, value.Components, value.Gamma, bounds); - }, - testOutputDetails: value.ToString(), - appendPixelTypeToFileName: false); + x => + { + Size size = x.GetCurrentSize(); + var bounds = new Rectangle(10, 10, size.Width / 2, size.Height / 2); + x.BokehBlur(value.Radius, value.Components, value.Gamma, bounds); + }, + testOutputDetails: value.ToString(), + appendPixelTypeToFileName: false); } - RemoteExecutor - .Invoke(RunTest, BasicSerializer.Serialize(provider), BasicSerializer.Serialize(value)) - .Dispose(); + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, + HwIntrinsics.DisableSSE41, + provider, + value); } [Theory] [WithTestPatternImages(100, 300, PixelTypes.Bgr24)] public void WorksWithDiscoBuffers(TestImageProvider provider) where TPixel : unmanaged, IPixel - { - provider.RunBufferCapacityLimitProcessorTest(41, c => c.BokehBlur()); - } + => provider.RunBufferCapacityLimitProcessorTest(260, c => c.BokehBlur()); } } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs index adc3c381a0..5c1b5da7f1 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs @@ -37,6 +37,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization { KnownDitherings.Bayer2x2, nameof(KnownDitherings.Bayer2x2) }, { KnownDitherings.Bayer4x4, nameof(KnownDitherings.Bayer4x4) }, { KnownDitherings.Bayer8x8, nameof(KnownDitherings.Bayer8x8) }, + { KnownDitherings.Bayer16x16, nameof(KnownDitherings.Bayer16x16) }, { KnownDitherings.Ordered3x3, nameof(KnownDitherings.Ordered3x3) } }; diff --git a/tests/ImageSharp.Tests/Processing/Processors/Quantization/QuantizerTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Quantization/QuantizerTests.cs index a25eca5b02..3f4656d411 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Quantization/QuantizerTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Quantization/QuantizerTests.cs @@ -169,8 +169,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Quantization provider.RunRectangleConstrainedValidatingProcessorTest( (x, rect) => x.Quantize(quantizer, rect), - comparer: ValidatorComparer, testOutputDetails: testOutputDetails, + comparer: ValidatorComparer, appendPixelTypeToFileName: false); } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index f40b8d11a0..58b7fd12e8 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -35,7 +35,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms nameof(KnownResamplers.Lanczos5), }; - private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.07F); + private static readonly ImageComparer ValidatorComparer = + ImageComparer.TolerantPercentage(TestEnvironment.IsOSX && TestEnvironment.RunsOnCI ? 0.26F : 0.07F); [Fact] public void Resize_PixelAgnostic() @@ -138,7 +139,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms testOutputDetails: workingBufferLimitInRows, appendPixelTypeToFileName: false); image.CompareToReferenceOutput( - ImageComparer.TolerantPercentage(0.001f), + ImageComparer.TolerantPercentage(0.004f), provider, testOutputDetails: workingBufferLimitInRows, appendPixelTypeToFileName: false); @@ -215,6 +216,32 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms appendSourceFileOrDescription: false); } + [Theory] + [WithFile(TestImages.Png.Kaboom, DefaultPixelType, false)] + [WithFile(TestImages.Png.Kaboom, DefaultPixelType, true)] + public void Resize_PremultiplyAlpha(TestImageProvider provider, bool premultiplyAlpha) + where TPixel : unmanaged, IPixel + { + string details = premultiplyAlpha ? "On" : "Off"; + + provider.RunValidatingProcessorTest( + x => + { + var resizeOptions = new ResizeOptions() + { + Size = x.GetCurrentSize() / 2, + Mode = ResizeMode.Crop, + Sampler = KnownResamplers.Bicubic, + Compand = false, + PremultiplyAlpha = premultiplyAlpha + }; + x.Resize(resizeOptions); + }, + details, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); + } + [Theory] [WithFile(TestImages.Gif.Giphy, DefaultPixelType)] public void Resize_IsAppliedToAllFrames(TestImageProvider provider) diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/SwizzleTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/SwizzleTests.cs new file mode 100644 index 0000000000..f508744fae --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/SwizzleTests.cs @@ -0,0 +1,58 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Processing.Extensions.Transforms; +using SixLabors.ImageSharp.Processing.Processors.Transforms; +using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms +{ + [GroupOutput("Transforms")] + public class SwizzleTests + { + private struct InvertXAndYSwizzler : ISwizzler + { + public InvertXAndYSwizzler(Size sourceSize) + { + this.DestinationSize = new Size(sourceSize.Height, sourceSize.Width); + } + + public Size DestinationSize { get; } + + public Point Transform(Point point) + => new Point(point.Y, point.X); + } + + [Theory] + [WithTestPatternImages(20, 37, PixelTypes.Rgba32)] + [WithTestPatternImages(53, 37, PixelTypes.Byte4)] + [WithTestPatternImages(17, 32, PixelTypes.Rgba32)] + public void InvertXAndYSwizzle(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + using Image expectedImage = provider.GetImage(); + using Image image = provider.GetImage(); + + image.Mutate(ctx => ctx.Swizzle(new InvertXAndYSwizzler(new Size(image.Width, image.Height)))); + + image.DebugSave( + provider, + nameof(InvertXAndYSwizzler), + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: true); + + image.Mutate(ctx => ctx.Swizzle(new InvertXAndYSwizzler(new Size(image.Width, image.Height)))); + + image.DebugSave( + provider, + "Unswizzle", + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: true); + + ImageComparer.Exact.VerifySimilarity(expectedImage, image); + } + } +} diff --git a/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs index bf412739d9..5f426083c2 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs @@ -1,8 +1,10 @@ // Copyright (c) Six Labors. // Licensed under the Apache License, Version 2.0. +using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Transforms; +using SixLabors.ImageSharp.Tests.TestUtilities; using Xunit; namespace SixLabors.ImageSharp.Tests.Processing.Transforms @@ -85,5 +87,24 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms Assert.Equal(compand, resizeOptions.Compand); Assert.Equal(mode, resizeOptions.Mode); } + +#if SUPPORTS_RUNTIME_INTRINSICS + [Fact] + public void HwIntrinsics_Resize() + { + static void RunTest() + { + using var image = new Image(50, 50); + image.Mutate(img => img.Resize(25, 25)); + + Assert.Equal(25, image.Width); + Assert.Equal(25, image.Height); + } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, + HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2 | HwIntrinsics.DisableFMA); + } +#endif } } diff --git a/tests/ImageSharp.Tests/Processing/Transforms/SwizzleTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/SwizzleTests.cs new file mode 100644 index 0000000000..cde6aeca36 --- /dev/null +++ b/tests/ImageSharp.Tests/Processing/Transforms/SwizzleTests.cs @@ -0,0 +1,44 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.Processing.Extensions.Transforms; +using SixLabors.ImageSharp.Processing.Processors.Transforms; +using Xunit; + +namespace SixLabors.ImageSharp.Tests.Processing.Transforms +{ + public class SwizzleTests : BaseImageOperationsExtensionTest + { + private struct InvertXAndYSwizzler : ISwizzler + { + public InvertXAndYSwizzler(Size sourceSize) + { + this.DestinationSize = new Size(sourceSize.Height, sourceSize.Width); + } + + public Size DestinationSize { get; } + + public Point Transform(Point point) + => new Point(point.Y, point.X); + } + + [Fact] + public void InvertXAndYSwizzlerSetsCorrectSizes() + { + int width = 5; + int height = 10; + + this.operations.Swizzle(new InvertXAndYSwizzler(new Size(width, height))); + SwizzleProcessor processor = this.Verify>(); + + Assert.Equal(processor.Swizzler.DestinationSize.Width, height); + Assert.Equal(processor.Swizzler.DestinationSize.Height, width); + + this.operations.Swizzle(new InvertXAndYSwizzler(processor.Swizzler.DestinationSize)); + SwizzleProcessor processor2 = this.Verify>(1); + + Assert.Equal(processor2.Swizzler.DestinationSize.Width, width); + Assert.Equal(processor2.Swizzler.DestinationSize.Height, height); + } + } +} diff --git a/tests/ImageSharp.Tests/Processing/Transforms/TransformBuilderTestBase.cs b/tests/ImageSharp.Tests/Processing/Transforms/TransformBuilderTestBase.cs index 4306732e8a..2e0dfd59e7 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/TransformBuilderTestBase.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/TransformBuilderTestBase.cs @@ -99,7 +99,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms this.AppendRotationDegrees(builder, degrees); // TODO: We should also test CreateRotationMatrixDegrees() (and all TransformUtils stuff!) for correctness - Matrix3x2 matrix = TransformUtilities.CreateRotationMatrixDegrees(degrees, size); + Matrix3x2 matrix = TransformUtils.CreateRotationMatrixDegrees(degrees, size); var position = new Vector2(x, y); var expected = Vector2.Transform(position, matrix); @@ -153,7 +153,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms this.AppendSkewDegrees(builder, degreesX, degreesY); - Matrix3x2 matrix = TransformUtilities.CreateSkewMatrixDegrees(degreesX, degreesY, size); + Matrix3x2 matrix = TransformUtils.CreateSkewMatrixDegrees(degreesX, degreesY, size); var position = new Vector2(x, y); var expected = Vector2.Transform(position, matrix); diff --git a/tests/ImageSharp.Tests/ProfilingBenchmarks/JpegProfilingBenchmarks.cs b/tests/ImageSharp.Tests/ProfilingBenchmarks/JpegProfilingBenchmarks.cs index 78fb99802e..9de3fc8dfe 100644 --- a/tests/ImageSharp.Tests/ProfilingBenchmarks/JpegProfilingBenchmarks.cs +++ b/tests/ImageSharp.Tests/ProfilingBenchmarks/JpegProfilingBenchmarks.cs @@ -75,6 +75,21 @@ namespace SixLabors.ImageSharp.Tests.ProfilingBenchmarks #pragma warning restore SA1515 // Single-line comment should be preceded by blank line } + [Fact(Skip = ProfilingSetup.SkipProfilingTests)] + public void EncodeJpeg_SingleMidSize() + { + string path = TestFile.GetInputFileFullPath(TestImages.Jpeg.BenchmarkSuite.Jpeg420Exif_MidSizeYCbCr); + using var image = Image.Load(path); + image.Metadata.ExifProfile = null; + + using var ms = new MemoryStream(); + for (int i = 0; i < 30; i++) + { + image.SaveAsJpeg(ms); + ms.Seek(0, SeekOrigin.Begin); + } + } + // Benchmark, enable manually! [Theory(Skip = ProfilingSetup.SkipProfilingTests)] [InlineData(1, 75, JpegSubsample.Ratio420)] diff --git a/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs b/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs index 7d57d8c499..6eb0f51a3e 100644 --- a/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs +++ b/tests/ImageSharp.Tests/Quantization/QuantizedImageTests.cs @@ -110,6 +110,21 @@ namespace SixLabors.ImageSharp.Tests } } + // Test case for issue: https://github.com/SixLabors/ImageSharp/issues/1505 + [Theory] + [WithFile(TestImages.Gif.Issues.Issue1505, PixelTypes.Rgba32)] + public void Issue1505(TestImageProvider provider) + where TPixel : unmanaged, IPixel + { + using (Image image = provider.GetImage()) + { + var octreeQuantizer = new OctreeQuantizer(); + IQuantizer quantizer = octreeQuantizer.CreatePixelSpecificQuantizer(Configuration.Default, new QuantizerOptions() { MaxColors = 128 }); + ImageFrame frame = image.Frames[0]; + quantizer.BuildPaletteAndQuantizeFrame(frame, frame.Bounds()); + } + } + private int GetTransparentIndex(IndexedImageFrame quantized) where TPixel : unmanaged, IPixel { diff --git a/tests/ImageSharp.Tests/TestImages.cs b/tests/ImageSharp.Tests/TestImages.cs index fd5296c375..c15327e0de 100644 --- a/tests/ImageSharp.Tests/TestImages.cs +++ b/tests/ImageSharp.Tests/TestImages.cs @@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.Tests { /// /// Class that contains all the relative test image paths in the TestImages/Formats directory. - /// Use with , or . + /// Use with , . /// public static class TestImages { @@ -40,6 +40,7 @@ namespace SixLabors.ImageSharp.Tests public const string Rgb48BppInterlaced = "Png/rgb-48bpp-interlaced.png"; public const string Rgb48BppTrans = "Png/rgb-16-tRNS.png"; public const string Rgba64Bpp = "Png/rgb-16-alpha.png"; + public const string ColorsSaturationLightness = "Png/colors-saturation-lightness.png"; public const string CalliphoraPartial = "Png/CalliphoraPartial.png"; public const string CalliphoraPartialGrayscale = "Png/CalliphoraPartialGrayscale.png"; public const string Bike = "Png/Bike.png"; @@ -107,6 +108,9 @@ namespace SixLabors.ImageSharp.Tests public const string Issue1177_1 = "Png/issues/Issue_1177_1.png"; public const string Issue1177_2 = "Png/issues/Issue_1177_2.png"; + // Issue 935: https://github.com/SixLabors/ImageSharp/issues/935 + public const string Issue935 = "Png/issues/Issue_935.png"; + public static class Bad { public const string MissingDataChunk = "Png/xdtn0g01.png"; @@ -193,6 +197,7 @@ namespace SixLabors.ImageSharp.Tests public const string YcckSubsample1222 = "Jpg/baseline/ycck-subsample-1222.jpg"; public const string Iptc = "Jpg/baseline/iptc.jpg"; public const string App13WithEmptyIptc = "Jpg/baseline/iptc-psAPP13-wIPTCempty.jpg"; + public const string HistogramEqImage = "Jpg/baseline/640px-Unequalized_Hawkes_Bay_NZ.jpg"; public static readonly string[] All = { @@ -411,6 +416,8 @@ namespace SixLabors.ImageSharp.Tests public const string BadAppExtLength = "Gif/issues/issue405_badappextlength252.gif"; public const string BadAppExtLength_2 = "Gif/issues/issue405_badappextlength252-2.gif"; public const string BadDescriptorWidth = "Gif/issues/issue403_baddescriptorwidth.gif"; + public const string Issue1505 = "Gif/issues/issue1505_argumentoutofrange.png"; + public const string Issue1530 = "Gif/issues/issue1530.gif"; } public static readonly string[] All = { Rings, Giphy, Cheers, Trans, Kumin, Leo, Ratio4x1, Ratio1x4 }; diff --git a/tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs b/tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs index b2f390dcdf..2a0ed19b48 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Numerics; +using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Tests { @@ -12,6 +13,7 @@ namespace SixLabors.ImageSharp.Tests internal readonly struct ApproximateFloatComparer : IEqualityComparer, IEqualityComparer, + IEqualityComparer, IEqualityComparer, IEqualityComparer { @@ -32,30 +34,42 @@ namespace SixLabors.ImageSharp.Tests } /// - public int GetHashCode(float obj) => obj.GetHashCode(); + public int GetHashCode(float obj) + => obj.GetHashCode(); /// - public bool Equals(Vector2 x, Vector2 y) => this.Equals(x.X, y.X) && this.Equals(x.Y, y.Y); + public bool Equals(Vector2 x, Vector2 y) + => this.Equals(x.X, y.X) && this.Equals(x.Y, y.Y); /// - public int GetHashCode(Vector2 obj) => obj.GetHashCode(); + public int GetHashCode(Vector2 obj) + => obj.GetHashCode(); /// - public bool Equals(Vector4 x, Vector4 y) => this.Equals(x.X, y.X) && this.Equals(x.Y, y.Y) && this.Equals(x.Z, y.Z) && this.Equals(x.W, y.W); + public bool Equals(IPixel x, IPixel y) + => this.Equals(x.ToScaledVector4(), y.ToScaledVector4()); + + public int GetHashCode(IPixel obj) + => obj.ToScaledVector4().GetHashCode(); + + /// + public bool Equals(Vector4 x, Vector4 y) + => this.Equals(x.X, y.X) + && this.Equals(x.Y, y.Y) + && this.Equals(x.Z, y.Z) + && this.Equals(x.W, y.W); /// - public int GetHashCode(Vector4 obj) => obj.GetHashCode(); + public int GetHashCode(Vector4 obj) + => obj.GetHashCode(); /// public bool Equals(ColorMatrix x, ColorMatrix y) - { - return - this.Equals(x.M11, y.M11) && this.Equals(x.M12, y.M12) && this.Equals(x.M13, y.M13) && this.Equals(x.M14, y.M14) + => this.Equals(x.M11, y.M11) && this.Equals(x.M12, y.M12) && this.Equals(x.M13, y.M13) && this.Equals(x.M14, y.M14) && this.Equals(x.M21, y.M21) && this.Equals(x.M22, y.M22) && this.Equals(x.M23, y.M23) && this.Equals(x.M24, y.M24) && this.Equals(x.M31, y.M31) && this.Equals(x.M32, y.M32) && this.Equals(x.M33, y.M33) && this.Equals(x.M34, y.M34) && this.Equals(x.M41, y.M41) && this.Equals(x.M42, y.M42) && this.Equals(x.M43, y.M43) && this.Equals(x.M44, y.M44) && this.Equals(x.M51, y.M51) && this.Equals(x.M52, y.M52) && this.Equals(x.M53, y.M53) && this.Equals(x.M54, y.M54); - } /// public int GetHashCode(ColorMatrix obj) => obj.GetHashCode(); diff --git a/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs b/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs new file mode 100644 index 0000000000..fa0f02ca1f --- /dev/null +++ b/tests/ImageSharp.Tests/TestUtilities/FeatureTesting/FeatureTestRunner.cs @@ -0,0 +1,366 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using Microsoft.DotNet.RemoteExecutor; +using Xunit.Abstractions; + +namespace SixLabors.ImageSharp.Tests.TestUtilities +{ + /// + /// Allows the testing against specific feature sets. + /// + public static class FeatureTestRunner + { + private static readonly char[] SplitChars = new[] { ',', ' ' }; + + /// + /// Allows the deserialization of parameters passed to the feature test. + /// + /// + /// This is required because does not allow + /// marshalling of fields so we cannot pass a wrapped + /// allowing automatic deserialization. + /// + /// + /// + /// The type to deserialize to. + /// The string value to deserialize. + /// The value. + public static T DeserializeForXunit(string value) + where T : IXunitSerializable + => BasicSerializer.Deserialize(value); + + /// + /// Allows the deserialization of types implementing + /// passed to the feature test. + /// + /// The string value to deserialize. + /// The value. + public static T Deserialize(string value) + where T : IConvertible + => (T)Convert.ChangeType(value, typeof(T)); + + /// + /// Runs the given test within an environment + /// where the given features. + /// + /// The test action to run. + /// The intrinsics features. + public static void RunWithHwIntrinsicsFeature( + Action action, + HwIntrinsics intrinsics) + { + if (!RemoteExecutor.IsSupported) + { + return; + } + + foreach (KeyValuePair intrinsic in intrinsics.ToFeatureKeyValueCollection()) + { + var processStartInfo = new ProcessStartInfo(); + if (intrinsic.Key != HwIntrinsics.AllowAll) + { + processStartInfo.Environment[$"COMPlus_{intrinsic.Value}"] = "0"; + + RemoteExecutor.Invoke( + action, + new RemoteInvokeOptions + { + StartInfo = processStartInfo + }) + .Dispose(); + } + else + { + // Since we are running using the default architecture there is no + // point creating the overhead of running the action in a separate process. + action(); + } + } + } + + /// + /// Runs the given test within an environment + /// where the given features. + /// + /// + /// The test action to run. + /// The parameter passed will be a string representing the currently testing . + /// The intrinsics features. + public static void RunWithHwIntrinsicsFeature( + Action action, + HwIntrinsics intrinsics) + { + if (!RemoteExecutor.IsSupported) + { + return; + } + + foreach (KeyValuePair intrinsic in intrinsics.ToFeatureKeyValueCollection()) + { + var processStartInfo = new ProcessStartInfo(); + if (intrinsic.Key != HwIntrinsics.AllowAll) + { + processStartInfo.Environment[$"COMPlus_{intrinsic.Value}"] = "0"; + + RemoteExecutor.Invoke( + action, + intrinsic.Key.ToString(), + new RemoteInvokeOptions + { + StartInfo = processStartInfo + }) + .Dispose(); + } + else + { + // Since we are running using the default architecture there is no + // point creating the overhead of running the action in a separate process. + action(intrinsic.Key.ToString()); + } + } + } + + /// + /// Runs the given test within an environment + /// where the given features. + /// + /// The test action to run. + /// The intrinsics features. + /// The value to pass as a parameter to the test action. + public static void RunWithHwIntrinsicsFeature( + Action action, + HwIntrinsics intrinsics, + T serializable) + where T : IXunitSerializable + { + if (!RemoteExecutor.IsSupported) + { + return; + } + + foreach (KeyValuePair intrinsic in intrinsics.ToFeatureKeyValueCollection()) + { + var processStartInfo = new ProcessStartInfo(); + if (intrinsic.Key != HwIntrinsics.AllowAll) + { + processStartInfo.Environment[$"COMPlus_{intrinsic.Value}"] = "0"; + + RemoteExecutor.Invoke( + action, + BasicSerializer.Serialize(serializable), + new RemoteInvokeOptions + { + StartInfo = processStartInfo + }) + .Dispose(); + } + else + { + // Since we are running using the default architecture there is no + // point creating the overhead of running the action in a separate process. + action(BasicSerializer.Serialize(serializable)); + } + } + } + + /// + /// Runs the given test within an environment + /// where the given features. + /// + /// The test action to run. + /// The intrinsics features. + /// The value to pass as a parameter to the test action. + public static void RunWithHwIntrinsicsFeature( + Action action, + HwIntrinsics intrinsics, + T serializable) + where T : IXunitSerializable + { + if (!RemoteExecutor.IsSupported) + { + return; + } + + foreach (KeyValuePair intrinsic in intrinsics.ToFeatureKeyValueCollection()) + { + var processStartInfo = new ProcessStartInfo(); + if (intrinsic.Key != HwIntrinsics.AllowAll) + { + processStartInfo.Environment[$"COMPlus_{intrinsic.Value}"] = "0"; + + RemoteExecutor.Invoke( + action, + BasicSerializer.Serialize(serializable), + intrinsic.Key.ToString(), + new RemoteInvokeOptions + { + StartInfo = processStartInfo + }) + .Dispose(); + } + else + { + // Since we are running using the default architecture there is no + // point creating the overhead of running the action in a separate process. + action(BasicSerializer.Serialize(serializable), intrinsic.Key.ToString()); + } + } + } + + /// + /// Runs the given test within an environment + /// where the given features. + /// + /// The test action to run. + /// The intrinsics features. + /// The value to pass as a parameter to the test action. + /// The second value to pass as a parameter to the test action. + public static void RunWithHwIntrinsicsFeature( + Action action, + HwIntrinsics intrinsics, + T arg1, + T2 arg2) + where T : IXunitSerializable + where T2 : IXunitSerializable + { + if (!RemoteExecutor.IsSupported) + { + return; + } + + foreach (KeyValuePair intrinsic in intrinsics.ToFeatureKeyValueCollection()) + { + var processStartInfo = new ProcessStartInfo(); + if (intrinsic.Key != HwIntrinsics.AllowAll) + { + processStartInfo.Environment[$"COMPlus_{intrinsic.Value}"] = "0"; + + RemoteExecutor.Invoke( + action, + BasicSerializer.Serialize(arg1), + BasicSerializer.Serialize(arg2), + new RemoteInvokeOptions + { + StartInfo = processStartInfo + }) + .Dispose(); + } + else + { + // Since we are running using the default architecture there is no + // point creating the overhead of running the action in a separate process. + action(BasicSerializer.Serialize(arg1), BasicSerializer.Serialize(arg2)); + } + } + } + + /// + /// Runs the given test within an environment + /// where the given features. + /// + /// The test action to run. + /// The value to pass as a parameter to the test action. + /// The intrinsics features. + public static void RunWithHwIntrinsicsFeature( + Action action, + T serializable, + HwIntrinsics intrinsics) + where T : IConvertible + { + if (!RemoteExecutor.IsSupported) + { + return; + } + + foreach (KeyValuePair intrinsic in intrinsics.ToFeatureKeyValueCollection()) + { + var processStartInfo = new ProcessStartInfo(); + if (intrinsic.Key != HwIntrinsics.AllowAll) + { + processStartInfo.Environment[$"COMPlus_{intrinsic.Value}"] = "0"; + + RemoteExecutor.Invoke( + action, + serializable.ToString(), + new RemoteInvokeOptions + { + StartInfo = processStartInfo + }) + .Dispose(); + } + else + { + // Since we are running using the default architecture there is no + // point creating the overhead of running the action in a separate process. + action(serializable.ToString()); + } + } + } + + internal static Dictionary ToFeatureKeyValueCollection(this HwIntrinsics intrinsics) + { + // Loop through and translate the given values into COMPlus equivaluents + var features = new Dictionary(); + foreach (string intrinsic in intrinsics.ToString("G").Split(SplitChars, StringSplitOptions.RemoveEmptyEntries)) + { + var key = (HwIntrinsics)Enum.Parse(typeof(HwIntrinsics), intrinsic); + switch (intrinsic) + { + case nameof(HwIntrinsics.DisableSIMD): + features.Add(key, "FeatureSIMD"); + break; + + case nameof(HwIntrinsics.AllowAll): + + // Not a COMPlus value. We filter in calling method. + features.Add(key, nameof(HwIntrinsics.AllowAll)); + break; + + default: + features.Add(key, intrinsic.Replace("Disable", "Enable")); + break; + } + } + + return features; + } + } + + /// + /// See + /// + /// ends up impacting all SIMD support(including System.Numerics) + /// but not things like , , and . + /// + /// + [Flags] +#pragma warning disable RCS1135 // Declare enum member with zero value (when enum has FlagsAttribute). + public enum HwIntrinsics +#pragma warning restore RCS1135 // Declare enum member with zero value (when enum has FlagsAttribute). + { + // Use flags so we can pass multiple values without using params. + // Don't base on 0 or use inverse for All as that doesn't translate to string values. + DisableSIMD = 1 << 0, + DisableHWIntrinsic = 1 << 1, + DisableSSE = 1 << 2, + DisableSSE2 = 1 << 3, + DisableAES = 1 << 4, + DisablePCLMULQDQ = 1 << 5, + DisableSSE3 = 1 << 6, + DisableSSSE3 = 1 << 7, + DisableSSE41 = 1 << 8, + DisableSSE42 = 1 << 9, + DisablePOPCNT = 1 << 10, + DisableAVX = 1 << 11, + DisableFMA = 1 << 12, + DisableAVX2 = 1 << 13, + DisableBMI1 = 1 << 14, + DisableBMI2 = 1 << 15, + DisableLZCNT = 1 << 16, + AllowAll = 1 << 17 + } +} diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs index de8278a33e..163bb84d56 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/MagickReferenceDecoder.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using ImageMagick; +using ImageMagick.Formats; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -15,10 +16,22 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs { public class MagickReferenceDecoder : IImageDecoder { + private readonly bool validate; + + public MagickReferenceDecoder() + : this(true) + { + } + + public MagickReferenceDecoder(bool validate) + { + this.validate = validate; + } + public static MagickReferenceDecoder Instance { get; } = new MagickReferenceDecoder(); private static void FromRgba32Bytes(Configuration configuration, Span rgbaBytes, IMemoryGroup destinationGroup) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { foreach (Memory m in destinationGroup) { @@ -33,7 +46,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs } private static void FromRgba64Bytes(Configuration configuration, Span rgbaBytes, IMemoryGroup destinationGroup) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { foreach (Memory m in destinationGroup) { @@ -48,17 +61,25 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs } public Task> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel => Task.FromResult(this.Decode(configuration, stream)); public Image Decode(Configuration configuration, Stream stream) - where TPixel : unmanaged, IPixel + where TPixel : unmanaged, ImageSharp.PixelFormats.IPixel { - using var magickImage = new MagickImage(stream); + var bmpReadDefines = new BmpReadDefines + { + IgnoreFileSize = !this.validate + }; + + var settings = new MagickReadSettings(); + settings.SetDefines(bmpReadDefines); + + using var magickImage = new MagickImage(stream, settings); var result = new Image(configuration, magickImage.Width, magickImage.Height); MemoryGroup resultPixels = result.GetRootFramePixelBuffer().FastMemoryGroup; - using (IPixelCollection pixels = magickImage.GetPixelsUnsafe()) + using (IUnsafePixelCollection pixels = magickImage.GetPixelsUnsafe()) { if (magickImage.Depth == 8) { diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Features.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Features.cs deleted file mode 100644 index 3568c1e5dc..0000000000 --- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Features.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.Tests -{ - public static partial class TestEnvironment - { - internal static class Features - { - public const string On = "1"; - public const string Off = "0"; - - // See https://github.com/SixLabors/ImageSharp/pull/1229#discussion_r440477861 - // * EnableHWIntrinsic - // * EnableSSE - // * EnableSSE2 - // * EnableAES - // * EnablePCLMULQDQ - // * EnableSSE3 - // * EnableSSSE3 - // * EnableSSE41 - // * EnableSSE42 - // * EnablePOPCNT - // * EnableAVX - // * EnableFMA - // * EnableAVX2 - // * EnableBMI1 - // * EnableBMI2 - // * EnableLZCNT - // - // `FeatureSIMD` ends up impacting all SIMD support(including `System.Numerics`) but not things - // like `LZCNT`, `BMI1`, or `BMI2` - // `EnableSSE3_4` is a legacy switch that exists for compat and is basically the same as `EnableSSE3` - public const string EnableAES = "COMPlus_EnableAES"; - public const string EnableAVX = "COMPlus_EnableAVX"; - public const string EnableAVX2 = "COMPlus_EnableAVX2"; - public const string EnableBMI1 = "COMPlus_EnableBMI1"; - public const string EnableBMI2 = "COMPlus_EnableBMI2"; - public const string EnableFMA = "COMPlus_EnableFMA"; - public const string EnableHWIntrinsic = "COMPlus_EnableHWIntrinsic"; - public const string EnableLZCNT = "COMPlus_EnableLZCNT"; - public const string EnablePCLMULQDQ = "COMPlus_EnablePCLMULQDQ"; - public const string EnablePOPCNT = "COMPlus_EnablePOPCNT"; - public const string EnableSSE = "COMPlus_EnableSSE"; - public const string EnableSSE2 = "COMPlus_EnableSSE2"; - public const string EnableSSE3 = "COMPlus_EnableSSE3"; - public const string EnableSSE3_4 = "COMPlus_EnableSSE3_4"; - public const string EnableSSE41 = "COMPlus_EnableSSE41"; - public const string EnableSSE42 = "COMPlus_EnableSSE42"; - public const string EnableSSSE3 = "COMPlus_EnableSSSE3"; - public const string FeatureSIMD = "COMPlus_FeatureSIMD"; - } - } -} diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs index 1375b5763e..cb8a0df42f 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs @@ -7,7 +7,6 @@ using System.IO; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; -using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.Tests { @@ -25,19 +24,11 @@ namespace SixLabors.ImageSharp.Tests private static readonly Lazy SolutionDirectoryFullPathLazy = new Lazy(GetSolutionDirectoryFullPathImpl); - private static readonly Lazy RunsOnCiLazy = new Lazy( - () => - { - bool isCi; - return bool.TryParse(Environment.GetEnvironmentVariable("CI"), out isCi) && isCi; - }); + private static readonly Lazy RunsOnCiLazy = new Lazy(() => bool.TryParse(Environment.GetEnvironmentVariable("CI"), out bool isCi) && isCi); private static readonly Lazy NetCoreVersionLazy = new Lazy(GetNetCoreVersion); - static TestEnvironment() - { - PrepareRemoteExecutor(); - } + static TestEnvironment() => PrepareRemoteExecutor(); /// /// Gets the .NET Core version, if running on .NET Core, otherwise returns an empty string. @@ -108,6 +99,8 @@ namespace SixLabors.ImageSharp.Tests internal static bool IsLinux => RuntimeInformation.IsOSPlatform(OSPlatform.Linux); + internal static bool IsOSX => RuntimeInformation.IsOSPlatform(OSPlatform.OSX); + internal static bool IsMono => Type.GetType("Mono.Runtime") != null; // https://stackoverflow.com/a/721194 internal static bool IsWindows => RuntimeInformation.IsOSPlatform(OSPlatform.Windows); @@ -170,7 +163,10 @@ namespace SixLabors.ImageSharp.Tests } string testProjectConfigPath = TestAssemblyFile.FullName + ".config"; - File.Copy(testProjectConfigPath, remoteExecutorConfigPath); + if (File.Exists(testProjectConfigPath)) + { + File.Copy(testProjectConfigPath, remoteExecutorConfigPath); + } if (Is64BitProcess) { @@ -258,7 +254,7 @@ namespace SixLabors.ImageSharp.Tests private static string GetNetCoreVersion() { Assembly assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly; - string[] assemblyPath = assembly.CodeBase.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries); + string[] assemblyPath = assembly.Location.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries); int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App"); if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2) { diff --git a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs index 39ebf7f159..5f41021a06 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestUtils.cs @@ -240,7 +240,7 @@ namespace SixLabors.ImageSharp.Tests using (Image image = provider.GetImage()) { FormattableString testOutputDetails = $""; - image.Mutate(ctx => { testOutputDetails = processAndGetTestOutputDetails(ctx); }); + image.Mutate(ctx => testOutputDetails = processAndGetTestOutputDetails(ctx)); image.DebugSave( provider, diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs new file mode 100644 index 0000000000..a2f36c85a8 --- /dev/null +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/FeatureTestRunnerTests.cs @@ -0,0 +1,296 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +#if SUPPORTS_RUNTIME_INTRINSICS +using System.Runtime.Intrinsics.X86; +#endif +using Xunit; +using Xunit.Abstractions; + +namespace SixLabors.ImageSharp.Tests.TestUtilities.Tests +{ + public class FeatureTestRunnerTests + { + public static TheoryData Intrinsics => + new TheoryData + { + { HwIntrinsics.DisableAES | HwIntrinsics.AllowAll, new string[] { "EnableAES", "AllowAll" } }, + { HwIntrinsics.DisableSIMD | HwIntrinsics.DisableHWIntrinsic, new string[] { "FeatureSIMD", "EnableHWIntrinsic" } }, + { HwIntrinsics.DisableSSE42 | HwIntrinsics.DisableAVX, new string[] { "EnableSSE42", "EnableAVX" } } + }; + + [Theory] + [MemberData(nameof(Intrinsics))] + public void ToFeatureCollectionReturnsExpectedResult(HwIntrinsics expectedIntrinsics, string[] expectedValues) + { + Dictionary features = expectedIntrinsics.ToFeatureKeyValueCollection(); + HwIntrinsics[] keys = features.Keys.ToArray(); + + HwIntrinsics actualIntrinsics = keys[0]; + for (int i = 1; i < keys.Length; i++) + { + actualIntrinsics |= keys[i]; + } + + Assert.Equal(expectedIntrinsics, actualIntrinsics); + + IEnumerable actualValues = features.Select(x => x.Value); + Assert.Equal(expectedValues, actualValues); + } + + [Fact] + public void AllowsAllHwIntrinsicFeatures() + { + if (!Vector.IsHardwareAccelerated) + { + return; + } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + () => Assert.True(Vector.IsHardwareAccelerated), + HwIntrinsics.AllowAll); + } + + [Fact] + public void CanLimitHwIntrinsicSIMDFeatures() + { + FeatureTestRunner.RunWithHwIntrinsicsFeature( + () => Assert.False(Vector.IsHardwareAccelerated), + HwIntrinsics.DisableSIMD); + } + +#if SUPPORTS_RUNTIME_INTRINSICS + [Fact] + public void CanLimitHwIntrinsicBaseFeatures() + { + static void AssertDisabled() + { + Assert.False(Sse.IsSupported); + Assert.False(Sse2.IsSupported); + Assert.False(Aes.IsSupported); + Assert.False(Pclmulqdq.IsSupported); + Assert.False(Sse3.IsSupported); + Assert.False(Ssse3.IsSupported); + Assert.False(Sse41.IsSupported); + Assert.False(Sse42.IsSupported); + Assert.False(Popcnt.IsSupported); + Assert.False(Avx.IsSupported); + Assert.False(Fma.IsSupported); + Assert.False(Avx2.IsSupported); + Assert.False(Bmi1.IsSupported); + Assert.False(Bmi2.IsSupported); + Assert.False(Lzcnt.IsSupported); + } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + AssertDisabled, + HwIntrinsics.DisableHWIntrinsic); + } +#endif + + [Fact] + public void CanLimitHwIntrinsicFeaturesWithIntrinsicsParam() + { + static void AssertHwIntrinsicsFeatureDisabled(string intrinsic) + { + Assert.NotNull(intrinsic); + + switch ((HwIntrinsics)Enum.Parse(typeof(HwIntrinsics), intrinsic)) + { + case HwIntrinsics.DisableSIMD: + Assert.False(Vector.IsHardwareAccelerated); + break; +#if SUPPORTS_RUNTIME_INTRINSICS + case HwIntrinsics.DisableHWIntrinsic: + Assert.False(Sse.IsSupported); + Assert.False(Sse2.IsSupported); + Assert.False(Aes.IsSupported); + Assert.False(Pclmulqdq.IsSupported); + Assert.False(Sse3.IsSupported); + Assert.False(Ssse3.IsSupported); + Assert.False(Sse41.IsSupported); + Assert.False(Sse42.IsSupported); + Assert.False(Popcnt.IsSupported); + Assert.False(Avx.IsSupported); + Assert.False(Fma.IsSupported); + Assert.False(Avx2.IsSupported); + Assert.False(Bmi1.IsSupported); + Assert.False(Bmi2.IsSupported); + Assert.False(Lzcnt.IsSupported); + break; + case HwIntrinsics.DisableSSE: + Assert.False(Sse.IsSupported); + break; + case HwIntrinsics.DisableSSE2: + Assert.False(Sse2.IsSupported); + break; + case HwIntrinsics.DisableAES: + Assert.False(Aes.IsSupported); + break; + case HwIntrinsics.DisablePCLMULQDQ: + Assert.False(Pclmulqdq.IsSupported); + break; + case HwIntrinsics.DisableSSE3: + Assert.False(Sse3.IsSupported); + break; + case HwIntrinsics.DisableSSSE3: + Assert.False(Ssse3.IsSupported); + break; + case HwIntrinsics.DisableSSE41: + Assert.False(Sse41.IsSupported); + break; + case HwIntrinsics.DisableSSE42: + Assert.False(Sse42.IsSupported); + break; + case HwIntrinsics.DisablePOPCNT: + Assert.False(Popcnt.IsSupported); + break; + case HwIntrinsics.DisableAVX: + Assert.False(Avx.IsSupported); + break; + case HwIntrinsics.DisableFMA: + Assert.False(Fma.IsSupported); + break; + case HwIntrinsics.DisableAVX2: + Assert.False(Avx2.IsSupported); + break; + case HwIntrinsics.DisableBMI1: + Assert.False(Bmi1.IsSupported); + break; + case HwIntrinsics.DisableBMI2: + Assert.False(Bmi2.IsSupported); + break; + case HwIntrinsics.DisableLZCNT: + Assert.False(Lzcnt.IsSupported); + break; +#endif + } + } + + foreach (HwIntrinsics intrinsic in (HwIntrinsics[])Enum.GetValues(typeof(HwIntrinsics))) + { + FeatureTestRunner.RunWithHwIntrinsicsFeature(AssertHwIntrinsicsFeatureDisabled, intrinsic); + } + } + + [Fact] + public void CanLimitHwIntrinsicFeaturesWithSerializableParam() + { + static void AssertHwIntrinsicsFeatureDisabled(string serializable) + { + Assert.NotNull(serializable); + Assert.NotNull(FeatureTestRunner.DeserializeForXunit(serializable)); + +#if SUPPORTS_RUNTIME_INTRINSICS + Assert.False(Sse.IsSupported); +#endif + } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + AssertHwIntrinsicsFeatureDisabled, + HwIntrinsics.DisableSSE, + new FakeSerializable()); + } + + [Fact] + public void CanLimitHwIntrinsicFeaturesWithSerializableAndIntrinsicsParams() + { + static void AssertHwIntrinsicsFeatureDisabled(string serializable, string intrinsic) + { + Assert.NotNull(serializable); + Assert.NotNull(FeatureTestRunner.DeserializeForXunit(serializable)); + + switch ((HwIntrinsics)Enum.Parse(typeof(HwIntrinsics), intrinsic)) + { + case HwIntrinsics.DisableSIMD: + Assert.False(Vector.IsHardwareAccelerated, nameof(Vector.IsHardwareAccelerated)); + break; +#if SUPPORTS_RUNTIME_INTRINSICS + case HwIntrinsics.DisableHWIntrinsic: + Assert.False(Sse.IsSupported); + Assert.False(Sse2.IsSupported); + Assert.False(Aes.IsSupported); + Assert.False(Pclmulqdq.IsSupported); + Assert.False(Sse3.IsSupported); + Assert.False(Ssse3.IsSupported); + Assert.False(Sse41.IsSupported); + Assert.False(Sse42.IsSupported); + Assert.False(Popcnt.IsSupported); + Assert.False(Avx.IsSupported); + Assert.False(Fma.IsSupported); + Assert.False(Avx2.IsSupported); + Assert.False(Bmi1.IsSupported); + Assert.False(Bmi2.IsSupported); + Assert.False(Lzcnt.IsSupported); + break; + case HwIntrinsics.DisableSSE: + Assert.False(Sse.IsSupported); + break; + case HwIntrinsics.DisableSSE2: + Assert.False(Sse2.IsSupported); + break; + case HwIntrinsics.DisableAES: + Assert.False(Aes.IsSupported); + break; + case HwIntrinsics.DisablePCLMULQDQ: + Assert.False(Pclmulqdq.IsSupported); + break; + case HwIntrinsics.DisableSSE3: + Assert.False(Sse3.IsSupported); + break; + case HwIntrinsics.DisableSSSE3: + Assert.False(Ssse3.IsSupported); + break; + case HwIntrinsics.DisableSSE41: + Assert.False(Sse41.IsSupported); + break; + case HwIntrinsics.DisableSSE42: + Assert.False(Sse42.IsSupported); + break; + case HwIntrinsics.DisablePOPCNT: + Assert.False(Popcnt.IsSupported); + break; + case HwIntrinsics.DisableAVX: + Assert.False(Avx.IsSupported); + break; + case HwIntrinsics.DisableFMA: + Assert.False(Fma.IsSupported); + break; + case HwIntrinsics.DisableAVX2: + Assert.False(Avx2.IsSupported); + break; + case HwIntrinsics.DisableBMI1: + Assert.False(Bmi1.IsSupported); + break; + case HwIntrinsics.DisableBMI2: + Assert.False(Bmi2.IsSupported); + break; + case HwIntrinsics.DisableLZCNT: + Assert.False(Lzcnt.IsSupported); + break; +#endif + } + } + + foreach (HwIntrinsics intrinsic in (HwIntrinsics[])Enum.GetValues(typeof(HwIntrinsics))) + { + FeatureTestRunner.RunWithHwIntrinsicsFeature(AssertHwIntrinsicsFeatureDisabled, intrinsic, new FakeSerializable()); + } + } + + public class FakeSerializable : IXunitSerializable + { + public void Deserialize(IXunitSerializationInfo info) + { + } + + public void Serialize(IXunitSerializationInfo info) + { + } + } + } +} diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs index e72d953ac1..67f11e8978 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs @@ -20,9 +20,7 @@ namespace SixLabors.ImageSharp.Tests public class TestEnvironmentTests { public TestEnvironmentTests(ITestOutputHelper output) - { - this.Output = output; - } + => this.Output = output; private ITestOutputHelper Output { get; } @@ -34,21 +32,15 @@ namespace SixLabors.ImageSharp.Tests [Fact] public void SolutionDirectoryFullPath() - { - this.CheckPath(TestEnvironment.SolutionDirectoryFullPath); - } + => this.CheckPath(TestEnvironment.SolutionDirectoryFullPath); [Fact] public void InputImagesDirectoryFullPath() - { - this.CheckPath(TestEnvironment.InputImagesDirectoryFullPath); - } + => this.CheckPath(TestEnvironment.InputImagesDirectoryFullPath); [Fact] public void ExpectedOutputDirectoryFullPath() - { - this.CheckPath(TestEnvironment.ReferenceOutputDirectoryFullPath); - } + => this.CheckPath(TestEnvironment.ReferenceOutputDirectoryFullPath); [Fact] public void GetReferenceOutputFileName() @@ -67,7 +59,7 @@ namespace SixLabors.ImageSharp.Tests [InlineData("lol/Baz.gif", typeof(GifEncoder))] public void GetReferenceEncoder_ReturnsCorrectEncoders_Windows(string fileName, Type expectedEncoderType) { - if (TestEnvironment.IsLinux) + if (!TestEnvironment.IsWindows) { return; } @@ -83,7 +75,7 @@ namespace SixLabors.ImageSharp.Tests [InlineData("lol/Baz.gif", typeof(GifDecoder))] public void GetReferenceDecoder_ReturnsCorrectDecoders_Windows(string fileName, Type expectedDecoderType) { - if (TestEnvironment.IsLinux) + if (!TestEnvironment.IsWindows) { return; } diff --git a/tests/Images/External b/tests/Images/External deleted file mode 160000 index 6a00308067..0000000000 --- a/tests/Images/External +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6a003080674d1fedc66292c13ce5a357b2a33083 diff --git a/tests/Images/External/LoadTestInput/Calliphora.jpg b/tests/Images/External/LoadTestInput/Calliphora.jpg new file mode 100644 index 0000000000..aa3fdef017 --- /dev/null +++ b/tests/Images/External/LoadTestInput/Calliphora.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67172fcab405f914587b88cd1106328e6b24ab59d622ba509dcc99509951ff5c +size 254766 diff --git a/tests/Images/External/LoadTestInput/Earth.jpg b/tests/Images/External/LoadTestInput/Earth.jpg new file mode 100644 index 0000000000..43cdf12adf --- /dev/null +++ b/tests/Images/External/LoadTestInput/Earth.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2cdfeb0f3829f2179c3e00beed9863ebddd0814043a542b5b9f726616a8a0d7d +size 4088390 diff --git a/tests/Images/External/LoadTestInput/Lake.jpg b/tests/Images/External/LoadTestInput/Lake.jpg new file mode 100644 index 0000000000..d77c175f8e --- /dev/null +++ b/tests/Images/External/LoadTestInput/Lake.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b7332d4e0b1d31367e04458d7cb33fd83eac31a8299d59efacd200350ec032d6 +size 206342 diff --git a/tests/Images/External/LoadTestInput/LargeTree.jpg b/tests/Images/External/LoadTestInput/LargeTree.jpg new file mode 100644 index 0000000000..86958402b1 --- /dev/null +++ b/tests/Images/External/LoadTestInput/LargeTree.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60af9c0ea0d24a9b1bf7058a79c3f43ccc3929547a9f0c4677005a11cd3cb468 +size 3129522 diff --git a/tests/Images/External/LoadTestInput/Saturn.jpg b/tests/Images/External/LoadTestInput/Saturn.jpg new file mode 100644 index 0000000000..e69298e95b --- /dev/null +++ b/tests/Images/External/LoadTestInput/Saturn.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f96c3c18c13cc376e0c3b2eb1767487a36777aeaa2518f4f2aa8b69a26d49fd7 +size 197951 diff --git a/tests/Images/External/LoadTestInput/Snake.jpg b/tests/Images/External/LoadTestInput/Snake.jpg new file mode 100644 index 0000000000..8ec1b3b833 --- /dev/null +++ b/tests/Images/External/LoadTestInput/Snake.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f3d1b46db3b5974820fd2737db3f025d21b09c75aff73fd40ba6535dddf2ad70 +size 165200 diff --git a/tests/Images/External/LoadTestInput/caspian.jpg b/tests/Images/External/LoadTestInput/caspian.jpg new file mode 100644 index 0000000000..c39f8ae570 --- /dev/null +++ b/tests/Images/External/LoadTestInput/caspian.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a32e799ca8dc2d5f7acb14aafd8b9a604012240e651a0107eb77a26cf0fc89b6 +size 6911104 diff --git a/tests/Images/External/LoadTestInput/jpeg420exif.jpg b/tests/Images/External/LoadTestInput/jpeg420exif.jpg new file mode 100644 index 0000000000..522a4c2fe6 --- /dev/null +++ b/tests/Images/External/LoadTestInput/jpeg420exif.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:223f9ca11722e7eccae9eadb158fa2c7bf806ed0aa6ee4390a96df7770035ba4 +size 768608 diff --git a/tests/Images/External/README.md b/tests/Images/External/README.md new file mode 100644 index 0000000000..936b15e6a8 --- /dev/null +++ b/tests/Images/External/README.md @@ -0,0 +1,8 @@ +### ReferenceOutput +Contains images to validate against in ImageSharp tests. In most cases the file hierarchy follows the hierarchy of `ActualOutput` + +### tools +Various utilities to help dealing with images. +- `optipng.exe`: [lossless PNG compressor](http://optipng.sourceforge.net/), to keep the `ReferenceImages` folder as small as possible +- `optimize-all.cmd`: Runs lossless optimizer for reference PNG-s. Currently it has to be manually edited to add new test class directories. +- [`dump-jpeg-coeffs.exe`](https://github.com/SixLabors/Imagesharp/blob/master/tests/Images/External/tools/jpeg/README.md) diff --git a/tests/Images/External/ReferenceOutput/AdaptiveThresholdTests/AdaptiveThreshold_WithRectangle_Works_Rgba32_Bradley02.png b/tests/Images/External/ReferenceOutput/AdaptiveThresholdTests/AdaptiveThreshold_WithRectangle_Works_Rgba32_Bradley02.png new file mode 100644 index 0000000000..ea5a333e82 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AdaptiveThresholdTests/AdaptiveThreshold_WithRectangle_Works_Rgba32_Bradley02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:36f60abb0ade0320779e242716c61b6dbabc8243a125f0a3145be35e233e117c +size 24542 diff --git a/tests/Images/External/ReferenceOutput/AdaptiveThresholdTests/AdaptiveThreshold_Works_Rgba32_Bradley01.png b/tests/Images/External/ReferenceOutput/AdaptiveThresholdTests/AdaptiveThreshold_Works_Rgba32_Bradley01.png new file mode 100644 index 0000000000..62660ef4b6 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AdaptiveThresholdTests/AdaptiveThreshold_Works_Rgba32_Bradley01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c4a92f0ecd0f2ec06b12091b14f2d421605ef178092bf4f7f7cb4e661270945 +size 52876 diff --git a/tests/Images/External/ReferenceOutput/AdaptiveThresholdTests/AdaptiveThreshold_Works_Rgba32_Bradley02.png b/tests/Images/External/ReferenceOutput/AdaptiveThresholdTests/AdaptiveThreshold_Works_Rgba32_Bradley02.png new file mode 100644 index 0000000000..7c40f64c0b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AdaptiveThresholdTests/AdaptiveThreshold_Works_Rgba32_Bradley02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c6d99bcaefa9e344e602465d08714f628b165e7783f73ddb3316e31c3f679825 +size 5760 diff --git a/tests/Images/External/ReferenceOutput/AdaptiveThresholdTests/AdaptiveThreshold_Works_Rgba32_ducky.png b/tests/Images/External/ReferenceOutput/AdaptiveThresholdTests/AdaptiveThreshold_Works_Rgba32_ducky.png new file mode 100644 index 0000000000..467206ea69 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AdaptiveThresholdTests/AdaptiveThreshold_Works_Rgba32_ducky.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6826d39280ffd36f075e52cd055975748fedec25a4b58c148b623a6dc6a517f4 +size 2040 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle1_Rgba32_TestPattern96x48.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle1_Rgba32_TestPattern96x48.png new file mode 100644 index 0000000000..f5af011026 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle1_Rgba32_TestPattern96x48.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b01d54838d678b61c3b7a1c7e76ff9a60b3f5f4faef5af848231177eac956eb1 +size 1262 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle2_Rgba32_TestPattern96x48.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle2_Rgba32_TestPattern96x48.png new file mode 100644 index 0000000000..e5005ac5d4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_FromSourceRectangle2_Rgba32_TestPattern96x48.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d34394771605c2a70cc23f3841592c20d22a68aaabf2ad6e8aba7348a181afb3 +size 531 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(1,1)_T(-20,-10).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(1,1)_T(-20,-10).png new file mode 100644 index 0000000000..d2ee69ce84 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(1,1)_T(-20,-10).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b6b13fd15f767271628930510b9a00cc71c8dbe37158cdee7459e8184b2c254b +size 689 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(1,1)_T(0,0).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(1,1)_T(0,0).png new file mode 100644 index 0000000000..b3dc8be7f7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(1,1)_T(0,0).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5c186653c2431d706175ac59b06637852942d18a9177b21772d3ab511c563202 +size 723 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(1,1)_T(20,10).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(1,1)_T(20,10).png new file mode 100644 index 0000000000..f00a63f90d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(1,1)_T(20,10).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:291e1044a062943cc91840cd252e7cc4722d8f5bc59386597c6c2aac5565b5f4 +size 757 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(1,2)_T(0,0).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(1,2)_T(0,0).png new file mode 100644 index 0000000000..1b361c4674 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(1,2)_T(0,0).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8f2167445c7ca069b0f33b56f4e758e9929ff5753d076c987cf53c5d7cc3bc2 +size 3318 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(2,1)_T(0,0).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(2,1)_T(0,0).png new file mode 100644 index 0000000000..7a8fe20870 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(0)_S(2,1)_T(0,0).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:462eaba7681f5a43f3012f8b6445180173b398c932a3cd8ec2e15cb1df9d9c4e +size 4327 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(-20,-10).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(-20,-10).png new file mode 100644 index 0000000000..ec3bfb5d11 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(-20,-10).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:57376aa4446fc2d034d2a0cb627163ac416d1b6768b063b2c11ccf8517443bda +size 10135 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(0,0).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(0,0).png new file mode 100644 index 0000000000..ad39ebb12c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(0,0).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d1fb97a28b5f754150343a3dc3c6974ac9abbb1577a44d88db61f0169983db0 +size 11083 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(20,10).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(20,10).png new file mode 100644 index 0000000000..20d15c665d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(20,10).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c78c6310b6b716e9fdb1605b5b356fa7e1b0fbed9f6e6ff0d705d5152ce52665 +size 11148 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1.1,1.3)_T(30,-20).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1.1,1.3)_T(30,-20).png new file mode 100644 index 0000000000..713ce31038 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1.1,1.3)_T(30,-20).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4b00b7801fd844035d9235f3d1163587e9847001b918b2d971ea7e917485371 +size 13683 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1.5,1.5)_T(0,0).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1.5,1.5)_T(0,0).png new file mode 100644 index 0000000000..df59e96932 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1.5,1.5)_T(0,0).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0b6f27c2361cc100b6928195522e0c8e76ee3ceeda814bd036d0636957024c9f +size 22761 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50__original.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50__original.png new file mode 100644 index 0000000000..bdad18d1dc --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50__original.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c83b59471a50df9e1d7b8f0e35c50aa417cd3be1730d6369f47f5cc99b87cef +size 6405 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScale_ManuallyCentered_Rgba32_TestPattern96x96_R(50)_S(0.8).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScale_ManuallyCentered_Rgba32_TestPattern96x96_R(50)_S(0.8).png new file mode 100644 index 0000000000..27a25224d3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScale_ManuallyCentered_Rgba32_TestPattern96x96_R(50)_S(0.8).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad5beec2c4a09ef8c4718bb39bda5b2d0bfcccfa4634b7458ac748d2fda498fe +size 11738 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png new file mode 100644 index 0000000000..526096e7c0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f9f149093c5d9d487f3e16cb59e6807ea6ce581b5c307e57aeb4edaf921de9ca +size 15138 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Box.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Box.png new file mode 100644 index 0000000000..5a8c0f2faa --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Box.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21f13832d15b9491e8b73711b3081fa56c08ca69bd9b165c323dec0ba4e6f99f +size 11358 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png new file mode 100644 index 0000000000..526096e7c0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f9f149093c5d9d487f3e16cb59e6807ea6ce581b5c307e57aeb4edaf921de9ca +size 15138 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Hermite.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Hermite.png new file mode 100644 index 0000000000..7bfe765533 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Hermite.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:829f7e7315a5a0cc3e88115529305ddb0c53a104863a8a66f6ad1f2efc440109 +size 12231 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png new file mode 100644 index 0000000000..b3439a5c88 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0c7467702a784807a3a5813a75d5f643655ed5ad427e978d6ee079da67b05961 +size 15363 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png new file mode 100644 index 0000000000..4622adab47 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a836c63c0912f69683bc9c8f59687b11e6b84f257816a01ff979ad0b6f4ab656 +size 19059 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png new file mode 100644 index 0000000000..753764631b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05de30dc282a0b8a096a476f689a1d2b6bb298098692a2f665c59c3d14902aa6 +size 20426 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png new file mode 100644 index 0000000000..c0840e5f76 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8892179d8edf96583900048bdd895eff24e57be0105e91efafe1de971414db0e +size 22457 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png new file mode 100644 index 0000000000..094777eec3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f351ec6ae6df56537e383494984c2fbcf35a66c44a6ce53d6fd8d6d74a330f3 +size 15342 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_NearestNeighbor.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_NearestNeighbor.png new file mode 100644 index 0000000000..06c6bfa22e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_NearestNeighbor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37332e56f71506663b00deacc52adaa7574167565e395217b493d235965b29b9 +size 11563 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png new file mode 100644 index 0000000000..c580f0cffd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b0fb38dbdded32a1518d62ac79f4aa88133aaddad947f23c1066dc33d6938e0b +size 15372 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png new file mode 100644 index 0000000000..4c0bb37bc3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0be42a5fd4ff10680af74a99ed1e0561ae38181f4efe4641bd63891222dcdf3c +size 15283 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png new file mode 100644 index 0000000000..7527157d50 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1eabaf35e0dda3eccd5e8866ddd65e0c45557c8d5cc29423a99e2f377ee1bfa9 +size 16271 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png new file mode 100644 index 0000000000..1ee2a15ff6 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5ab9bea8f45e7d29d7a8c5e3d0182c0f3f3aa7014aa358883dee53db6dfeb3f7 +size 14076 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png new file mode 100644 index 0000000000..d3b8938091 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea452bc46c508f6990870a34d908224a58aa350c4ccebabd4fa6ba138e8034a0 +size 18383 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdFilter_Rgba32_colors-saturation-lightness_0.25.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdFilter_Rgba32_colors-saturation-lightness_0.25.png new file mode 100644 index 0000000000..2493321a4c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdFilter_Rgba32_colors-saturation-lightness_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:51cb254212641ec3d81a7d412cc31c2e0e6b006581796d7507af15127e1d08a9 +size 7913 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdFilter_Rgba32_colors-saturation-lightness_0.75.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdFilter_Rgba32_colors-saturation-lightness_0.75.png new file mode 100644 index 0000000000..5d8e11424e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdFilter_Rgba32_colors-saturation-lightness_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc004ff9b47bcd9300b7dfbd14f2351f17ed4bff205f90845aac823713531dfc +size 4388 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdFilter_Rgba32_rgb-48bpp_0.25.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdFilter_Rgba32_rgb-48bpp_0.25.png new file mode 100644 index 0000000000..58f41d1a6e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdFilter_Rgba32_rgb-48bpp_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0110c27732a1986430589bd9caf849f92525b5dae7be820879883cec7dbd14f +size 10367 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdFilter_Rgba32_rgb-48bpp_0.75.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdFilter_Rgba32_rgb-48bpp_0.75.png new file mode 100644 index 0000000000..47e82d92e1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdFilter_Rgba32_rgb-48bpp_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:428c04136ce785178f498d2496d395fd173c35593a290da3224ac798041bf7da +size 9843 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdInBox_Rgba32_colors-saturation-lightness_0.25.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdInBox_Rgba32_colors-saturation-lightness_0.25.png new file mode 100644 index 0000000000..be28e7de22 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdInBox_Rgba32_colors-saturation-lightness_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11d9396bf4d48bd2dccdc2e4d9d0fe3bd2d1b1b774453151e520db7fb1c0bfac +size 325147 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdInBox_Rgba32_colors-saturation-lightness_0.75.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdInBox_Rgba32_colors-saturation-lightness_0.75.png new file mode 100644 index 0000000000..c24432571b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdInBox_Rgba32_colors-saturation-lightness_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6c350a217923d4812599bf7d53d0dc1d69384bf44ce08b348c5c0d7d41cf63c2 +size 324065 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdInBox_Rgba32_rgb-48bpp_0.25.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdInBox_Rgba32_rgb-48bpp_0.25.png new file mode 100644 index 0000000000..2f8536385b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdInBox_Rgba32_rgb-48bpp_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e936af882acaa38d82aef579b976c3d6183482e7b9611a0dd9868056f0190647 +size 316095 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdInBox_Rgba32_rgb-48bpp_0.75.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdInBox_Rgba32_rgb-48bpp_0.75.png new file mode 100644 index 0000000000..4d82cc2d97 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryMaxChromaThresholdInBox_Rgba32_rgb-48bpp_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b43edc1dea9209588dd81fc21cec9ae9dd067e74df7c6d157519371e21c54292 +size 316286 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdFilter_Rgba32_colors-saturation-lightness_0.25.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdFilter_Rgba32_colors-saturation-lightness_0.25.png new file mode 100644 index 0000000000..96658289aa --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdFilter_Rgba32_colors-saturation-lightness_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0565725dc6b81dab6e4553b5d1956f7fdce5d442c99af9d3bd4eca5faafb2a4c +size 9120 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdFilter_Rgba32_colors-saturation-lightness_0.75.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdFilter_Rgba32_colors-saturation-lightness_0.75.png new file mode 100644 index 0000000000..e437183049 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdFilter_Rgba32_colors-saturation-lightness_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e2fac1d23e6638ff2479ea6010a1466651b6a9b2e4e8ab1c5309361682377175 +size 8501 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdFilter_Rgba32_rgb-48bpp_0.25.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdFilter_Rgba32_rgb-48bpp_0.25.png new file mode 100644 index 0000000000..3b7ba96029 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdFilter_Rgba32_rgb-48bpp_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ade68e760e7aa28499ba7fa9324027b66d377438565901b4bf3db40ebb95c3f +size 9795 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdFilter_Rgba32_rgb-48bpp_0.75.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdFilter_Rgba32_rgb-48bpp_0.75.png new file mode 100644 index 0000000000..64d4620f88 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdFilter_Rgba32_rgb-48bpp_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:351b945c4f1ae794d166a141d745c509003147e54fc735c3a97987b7912bf1f0 +size 10813 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdInBox_Rgba32_colors-saturation-lightness_0.25.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdInBox_Rgba32_colors-saturation-lightness_0.25.png new file mode 100644 index 0000000000..11fedec168 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdInBox_Rgba32_colors-saturation-lightness_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7cb7b90177c8f136accea0e5649fcf91c5467cac8310c39818001bd67ade1931 +size 325514 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdInBox_Rgba32_colors-saturation-lightness_0.75.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdInBox_Rgba32_colors-saturation-lightness_0.75.png new file mode 100644 index 0000000000..4c1009b8fd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdInBox_Rgba32_colors-saturation-lightness_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8058aba0e2f553d9badd6bc12b152465fd8bd3dfb0933d303a565c3472b8cf91 +size 325033 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdInBox_Rgba32_rgb-48bpp_0.25.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdInBox_Rgba32_rgb-48bpp_0.25.png new file mode 100644 index 0000000000..2ccba1fdaf --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdInBox_Rgba32_rgb-48bpp_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:260a432d56e9972a4b0617c47c81090dd768363eac3cae27c91a4176eac30fde +size 315799 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdInBox_Rgba32_rgb-48bpp_0.75.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdInBox_Rgba32_rgb-48bpp_0.75.png new file mode 100644 index 0000000000..4d42e08c3c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinarySaturationThresholdInBox_Rgba32_rgb-48bpp_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a0abfdf31816948bb3ea72b2d4b1ea0d6e648c87e8f2283e38cf133505f1d39c +size 316284 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdFilter_Rgba32_colors-saturation-lightness_0.25.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdFilter_Rgba32_colors-saturation-lightness_0.25.png new file mode 100644 index 0000000000..5cd2ac4066 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdFilter_Rgba32_colors-saturation-lightness_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ffe0d135aa932ec246edca7124a550121acd090d7d56c8cb3f1d80cd6139831f +size 6906 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdFilter_Rgba32_colors-saturation-lightness_0.75.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdFilter_Rgba32_colors-saturation-lightness_0.75.png new file mode 100644 index 0000000000..bd7ad3e9a2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdFilter_Rgba32_colors-saturation-lightness_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b76320eec406b546e6d9e7c00f01faf4528d1e5573b52665df4664392b406c6a +size 6708 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdFilter_Rgba32_rgb-48bpp_0.25.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdFilter_Rgba32_rgb-48bpp_0.25.png new file mode 100644 index 0000000000..a94e4a7559 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdFilter_Rgba32_rgb-48bpp_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ade047ec10bfd20a7ac0205c9aff3bda33607883291d4fe23704ac8864ac239 +size 8066 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdFilter_Rgba32_rgb-48bpp_0.75.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdFilter_Rgba32_rgb-48bpp_0.75.png new file mode 100644 index 0000000000..15a94b2bee --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdFilter_Rgba32_rgb-48bpp_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bbe9c25d68423cba508713f85c4753c302dbf95afec45a0ed5bc21299438e222 +size 6817 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdInBox_Rgba32_colors-saturation-lightness_0.25.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdInBox_Rgba32_colors-saturation-lightness_0.25.png new file mode 100644 index 0000000000..6969b25924 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdInBox_Rgba32_colors-saturation-lightness_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7427a84c0ea1cb41543604eeb8aba6bfad15799c9814e7a9e8346bea2c01a354 +size 324724 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdInBox_Rgba32_colors-saturation-lightness_0.75.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdInBox_Rgba32_colors-saturation-lightness_0.75.png new file mode 100644 index 0000000000..84895fa885 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdInBox_Rgba32_colors-saturation-lightness_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c7408fa9679d211fc161b89850e6e68cb90719ddc4d1d7ff4d029debbac24e32 +size 325185 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdInBox_Rgba32_rgb-48bpp_0.25.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdInBox_Rgba32_rgb-48bpp_0.25.png new file mode 100644 index 0000000000..bc9ca43a47 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdInBox_Rgba32_rgb-48bpp_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e0f34b0685e327e986186775288fb034d9154073c2986c714eb59eae7f4112bf +size 315109 diff --git a/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdInBox_Rgba32_rgb-48bpp_0.75.png b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdInBox_Rgba32_rgb-48bpp_0.75.png new file mode 100644 index 0000000000..fe1af1539b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BinaryThresholdTest/ImageShouldApplyBinaryThresholdInBox_Rgba32_rgb-48bpp_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:51a988d37b88327b244b7ca991c225550b5e5ba1e5322c0756a8108e7cf6cb98 +size 314609 diff --git a/tests/Images/External/ReferenceOutput/BmpEncoderTests/Encode_8BitColor_WithOctreeQuantizer_rgb32.bmp b/tests/Images/External/ReferenceOutput/BmpEncoderTests/Encode_8BitColor_WithOctreeQuantizer_rgb32.bmp new file mode 100644 index 0000000000..b4d4754885 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BmpEncoderTests/Encode_8BitColor_WithOctreeQuantizer_rgb32.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6dba331639d724f198d7d11af971156d34076b57bba0f2d0d45e699104a3a674 +size 9270 diff --git a/tests/Images/External/ReferenceOutput/BmpEncoderTests/Encode_8BitColor_WithWuQuantizer_rgb32.bmp b/tests/Images/External/ReferenceOutput/BmpEncoderTests/Encode_8BitColor_WithWuQuantizer_rgb32.bmp new file mode 100644 index 0000000000..01c9196964 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BmpEncoderTests/Encode_8BitColor_WithWuQuantizer_rgb32.bmp @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9213e188b3a2f715ae21a5ab2fb2acedc23397207820c0999b06fa60e7052b85 +size 9270 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_BikeGrayscale_R16_C1_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_BikeGrayscale_R16_C1_G3.png new file mode 100644 index 0000000000..564a76f90c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_BikeGrayscale_R16_C1_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3a6e47d880b7276702e6bf4b1ba1b4781abfa2cd99ee9321a56169440fc318c +size 49844 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_BikeGrayscale_R16_C2_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_BikeGrayscale_R16_C2_G3.png new file mode 100644 index 0000000000..4f2dc77b06 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_BikeGrayscale_R16_C2_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18b4837dceb9a065c5b27133b67ef257a0f050fa1342d02a7e06d3501e068f47 +size 44966 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_BikeGrayscale_R8_C1_G1.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_BikeGrayscale_R8_C1_G1.png new file mode 100644 index 0000000000..57ce8295ee --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_BikeGrayscale_R8_C1_G1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e652706e1aec475c8eec08392d65be1bd888cc79eccc4019eb3826db71c6dac0 +size 54744 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bike_R16_C1_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bike_R16_C1_G3.png new file mode 100644 index 0000000000..a0e9c1b248 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bike_R16_C1_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ffc82427285a2bfeb3226e3e87ac316e41a2a8f853bb406b88ba2ae7bfae099d +size 164923 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bike_R16_C2_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bike_R16_C2_G3.png new file mode 100644 index 0000000000..caf152f9b9 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bike_R16_C2_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ea08065be7271e7ff75ed49e63544701bc14a03bd44d754fb056370559dd105 +size 149483 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bike_R8_C1_G1.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bike_R8_C1_G1.png new file mode 100644 index 0000000000..5ad60a4bf9 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bike_R8_C1_G1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7a61bca9de7e0b6bf6f88c4d01b9e3f1611f6866db10e4a1168550ab84804f42 +size 178531 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_BikeGrayscale_R16_C1_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_BikeGrayscale_R16_C1_G3.png new file mode 100644 index 0000000000..4e3d437e03 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_BikeGrayscale_R16_C1_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3260ab8cc85b9fd64720376cb7c2fee026af7f30aba0a273d961a44635ed2e87 +size 79287 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_BikeGrayscale_R16_C2_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_BikeGrayscale_R16_C2_G3.png new file mode 100644 index 0000000000..4053a152de --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_BikeGrayscale_R16_C2_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b59f781529494c62951cddbcd99ef29a334e39ff04f27391526e24aa5cb46450 +size 77995 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_BikeGrayscale_R8_C1_G1.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_BikeGrayscale_R8_C1_G1.png new file mode 100644 index 0000000000..bd7c886b95 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_BikeGrayscale_R8_C1_G1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae5c8924f261044fbf6ea4257c05a05c5715fa64fd5b04f93f9a0c591619a3d9 +size 83978 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_Bike_R16_C1_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_Bike_R16_C1_G3.png new file mode 100644 index 0000000000..7a45ae8f14 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_Bike_R16_C1_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5587863a814ad37010464313d1351399617e3f2d94e363dd3196e82f7bc3ee9d +size 247417 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_Bike_R16_C2_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_Bike_R16_C2_G3.png new file mode 100644 index 0000000000..8dd39701d6 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_Bike_R16_C2_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4eaf2e9d13e73f9b7744cba89c2d0c268e3ab5718b3df7ccb01f4521ca4af002 +size 243906 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_Bike_R8_C1_G1.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_Bike_R8_C1_G1.png new file mode 100644 index 0000000000..3fbac62f90 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_Bike_R8_C1_G1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8d80a75091d547cb0d30ac61eba714d5a6562265a2c36f79c227ad060a1eeb4a +size 256901 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_CalliphoraPartial_R16_C1_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_CalliphoraPartial_R16_C1_G3.png new file mode 100644 index 0000000000..a6d274bfd3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_CalliphoraPartial_R16_C1_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6019cc0bc65d0f1e9bdb03e3954b04d220414a0a4cf345c95764e893e1b7cddf +size 257288 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_CalliphoraPartial_R16_C2_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_CalliphoraPartial_R16_C2_G3.png new file mode 100644 index 0000000000..0ea7d75512 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_CalliphoraPartial_R16_C2_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b1251c453bede61ec3bc09c1ce070f4be89b5dfac9913e4a2ed8a3d9b1ef362 +size 255308 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_CalliphoraPartial_R8_C1_G1.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_CalliphoraPartial_R8_C1_G1.png new file mode 100644 index 0000000000..c0bd195839 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_CalliphoraPartial_R8_C1_G1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:040e5aa93a5d57d0cc3312a20401a5535bc7f03c7f9612c885e1b5fd1e6e892f +size 269037 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_cross_R16_C1_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_cross_R16_C1_G3.png new file mode 100644 index 0000000000..a377eb690f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_cross_R16_C1_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dfdc65d04ea7e1e05ee952e6a1a3fb87ecabd9a280624cf9745ec11d9c2efd60 +size 5818 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_cross_R16_C2_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_cross_R16_C2_G3.png new file mode 100644 index 0000000000..b947522a52 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_cross_R16_C2_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:71c8bd171de42cd17dbfea8a7012ab76526dcf166948f72aa6ed42e52c4d6437 +size 5723 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_cross_R8_C1_G1.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_cross_R8_C1_G1.png new file mode 100644 index 0000000000..ada75d578e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Bounded_cross_R8_C1_G1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d13652480cc8a57bcc2c9c07b882f92ad7f089dc96e2ad2578a01841962e578d +size 5874 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_CalliphoraPartial_R16_C1_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_CalliphoraPartial_R16_C1_G3.png new file mode 100644 index 0000000000..d1b15eb8e3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_CalliphoraPartial_R16_C1_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4e2f6c6c42ddd15c0730edcd402bf8fd05a1116cb72495e3156a545988ff0230 +size 85901 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_CalliphoraPartial_R16_C2_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_CalliphoraPartial_R16_C2_G3.png new file mode 100644 index 0000000000..3acb240b32 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_CalliphoraPartial_R16_C2_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8193ce8690dbb99517cd56e5a866268c0a5c971c992058afb818393658781b91 +size 77762 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_CalliphoraPartial_R8_C1_G1.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_CalliphoraPartial_R8_C1_G1.png new file mode 100644 index 0000000000..335375205e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_CalliphoraPartial_R8_C1_G1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:412c302f92500d855658d466aa1a686386ed998f6a3d5fe7326cd148a6f829ae +size 116229 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Solid50x50_(255,0,0,255)_R16_C1_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Solid50x50_(255,0,0,255)_R16_C1_G3.png new file mode 100644 index 0000000000..ffa9624d04 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Solid50x50_(255,0,0,255)_R16_C1_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d753a7dc732d6f01f7bce8c6de50d70158639aa5e0eb18d168e417fe36492731 +size 135 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Solid50x50_(255,0,0,255)_R16_C2_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Solid50x50_(255,0,0,255)_R16_C2_G3.png new file mode 100644 index 0000000000..ffa9624d04 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Solid50x50_(255,0,0,255)_R16_C2_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d753a7dc732d6f01f7bce8c6de50d70158639aa5e0eb18d168e417fe36492731 +size 135 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Solid50x50_(255,0,0,255)_R8_C1_G1.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Solid50x50_(255,0,0,255)_R8_C1_G1.png new file mode 100644 index 0000000000..ffa9624d04 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_Solid50x50_(255,0,0,255)_R8_C1_G1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d753a7dc732d6f01f7bce8c6de50d70158639aa5e0eb18d168e417fe36492731 +size 135 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern200x100_R16_C1_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern200x100_R16_C1_G3.png new file mode 100644 index 0000000000..e155d618df --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern200x100_R16_C1_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:570cb16b4026d38cbf586592c34d0fe303f2c1d99baeb531670c4ba25956f9c3 +size 15489 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern200x100_R16_C2_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern200x100_R16_C2_G3.png new file mode 100644 index 0000000000..3f93014b6d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern200x100_R16_C2_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27813f975640c7ac15e78af910efc796ada950cd7efcd9a4fe045d531de24ec8 +size 15197 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern200x100_R8_C1_G1.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern200x100_R8_C1_G1.png new file mode 100644 index 0000000000..198baadf7d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern200x100_R8_C1_G1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e10a91175585b3843b25b710dc45f734ba706b60fc56a21748da355f27b8dcf5 +size 12776 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern23x31_R16_C1_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern23x31_R16_C1_G3.png new file mode 100644 index 0000000000..9140cdb0b4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern23x31_R16_C1_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6c0aca87ea94ec94c4d9e458dd33d366e0166533ee3e3c39066ee9d8be63a74e +size 1393 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern23x31_R16_C2_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern23x31_R16_C2_G3.png new file mode 100644 index 0000000000..32778c0a7f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern23x31_R16_C2_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d486512f51a57c90de6c3126791fbd3b7e7dd756932b5bd716660ee9b72f010 +size 1168 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern23x31_R8_C1_G1.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern23x31_R8_C1_G1.png new file mode 100644 index 0000000000..a60c7f0cbf --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern23x31_R8_C1_G1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79f344abd9f1cfe6e8c2f0be52fd9498ee3ee6370cea94244d90fdaba7fa5e71 +size 1488 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern30x20_R16_C1_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern30x20_R16_C1_G3.png new file mode 100644 index 0000000000..ae9b64afad --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern30x20_R16_C1_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:90a45e7212ce97754be0e1432fffdc62ef5d2bdc30fdff0477a1951754cc0929 +size 1113 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern30x20_R16_C2_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern30x20_R16_C2_G3.png new file mode 100644 index 0000000000..1e9dc61e6e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern30x20_R16_C2_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7c61766f05dc48413c21baea8af1994895aa354732109fd5701a42f746f1f412 +size 1005 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern30x20_R8_C1_G1.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern30x20_R8_C1_G1.png new file mode 100644 index 0000000000..99a249b1df --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_TestPattern30x20_R8_C1_G1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be002593c2874eab803d0dc9b5646fb51b94ea92e17158797609219f46c2f723 +size 1518 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_WorksWithAllPixelTypes_Bgr24.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_WorksWithAllPixelTypes_Bgr24.png new file mode 100644 index 0000000000..8f8267160a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_WorksWithAllPixelTypes_Bgr24.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:42c62ed7ff832efa4a5f7c25db0fa76eaadd4c702c3c6b3afff7c115d3748f63 +size 15109 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_WorksWithAllPixelTypes_Bgra32.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_WorksWithAllPixelTypes_Bgra32.png new file mode 100644 index 0000000000..3924423e26 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_WorksWithAllPixelTypes_Bgra32.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ad02d12edd4706280de4c6133c6c173fb8ede339e91d26fe013d78f53b0609c +size 20502 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_WorksWithAllPixelTypes_Gray8.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_WorksWithAllPixelTypes_Gray8.png new file mode 100644 index 0000000000..aa0af1f556 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_WorksWithAllPixelTypes_Gray8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bc13a3bedc8ac11627c770134d422662f3d6ec2158a4167ad026d59ec6fc196d +size 5006 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_cross_R16_C1_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_cross_R16_C1_G3.png new file mode 100644 index 0000000000..d4ff4e16bc --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_cross_R16_C1_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11edba36c7f73271d9575b16cc7663a1e75c3b34560df51b7430cfde3ce1ea08 +size 6576 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_cross_R16_C2_G3.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_cross_R16_C2_G3.png new file mode 100644 index 0000000000..a02c2d6702 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_cross_R16_C2_G3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75320c25e8977e5d56ff32f054e15773bd797e4ba745cd7bf3a2fd4c7000e3df +size 6400 diff --git a/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_cross_R8_C1_G1.png b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_cross_R8_C1_G1.png new file mode 100644 index 0000000000..5fbabed0ac --- /dev/null +++ b/tests/Images/External/ReferenceOutput/BokehBlurTest/BokehBlurFilterProcessor_cross_R8_C1_G1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8bb334d24245359fda8b64a74cbd30267cbdd1238e0aeae674b57be5371cd7db +size 6266 diff --git a/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/InBox_Rgba32_CalliphoraPartial_3.png b/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/InBox_Rgba32_CalliphoraPartial_3.png new file mode 100644 index 0000000000..66df78ea2f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/InBox_Rgba32_CalliphoraPartial_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e4f4145fd269e8b2bb911becc72cda2a0bfca96d797de9ebf030b8ddaf874d8 +size 276572 diff --git a/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/InBox_Rgba32_CalliphoraPartial_5.png b/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/InBox_Rgba32_CalliphoraPartial_5.png new file mode 100644 index 0000000000..347a4648e7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/InBox_Rgba32_CalliphoraPartial_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:045bff9c9d46545a61b9cf38d49b7ee631e36861eb814e94ce387a891c73ed7a +size 267458 diff --git a/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/InBox_Rgba32_Car_3.png b/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/InBox_Rgba32_Car_3.png new file mode 100644 index 0000000000..e8baa7ed83 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/InBox_Rgba32_Car_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:76b1f4181eede513d21633af1c33e7ba484545f41c775a8cb50aca50fb882c5c +size 192721 diff --git a/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/InBox_Rgba32_Car_5.png b/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/InBox_Rgba32_Car_5.png new file mode 100644 index 0000000000..81e9695073 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/InBox_Rgba32_Car_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0abf372faf736c53d427c303d12c400bcdb226640a12b3117f87e1ca3a25435b +size 184541 diff --git a/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/OnFullImage_Rgba32_CalliphoraPartial_3.png b/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/OnFullImage_Rgba32_CalliphoraPartial_3.png new file mode 100644 index 0000000000..b98943653d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/OnFullImage_Rgba32_CalliphoraPartial_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d4962891ff596cc2d1e43721786e7cede417175d7f8773abd092e5949c968d2d +size 156753 diff --git a/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/OnFullImage_Rgba32_CalliphoraPartial_5.png b/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/OnFullImage_Rgba32_CalliphoraPartial_5.png new file mode 100644 index 0000000000..4ae85071b5 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/OnFullImage_Rgba32_CalliphoraPartial_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb0a3b2ec77cdbcddd522e0567b8223658fbbf145bc49306b67b839f0c0fa7d7 +size 117061 diff --git a/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/OnFullImage_Rgba32_Car_3.png b/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/OnFullImage_Rgba32_Car_3.png new file mode 100644 index 0000000000..d69f06f6c7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/OnFullImage_Rgba32_Car_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1d0df644e610026de22d8867345bcfd7d0ba08e8653a833b666141b79954ea3c +size 141890 diff --git a/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/OnFullImage_Rgba32_Car_5.png b/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/OnFullImage_Rgba32_Car_5.png new file mode 100644 index 0000000000..e5d8265d9c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/BoxBlurTest/OnFullImage_Rgba32_Car_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6967b83a2494f4fdef672a748a1855bcd418e9fd1fc3a416472a70a39980856d +size 121606 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_Bike_Kayyali.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_Bike_Kayyali.png new file mode 100644 index 0000000000..73c2ec1593 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_Bike_Kayyali.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:66169470cf7b29ded78cfd3abc221e5374e4ee70b704ce0f8d4aa082b6a54fc9 +size 81056 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_Bike_Prewitt.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_Bike_Prewitt.png new file mode 100644 index 0000000000..1e789d3ee1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_Bike_Prewitt.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f12129c2de0e085a40dcaac2de40700f8f961ef2a64cd930f23df3d81935a9bc +size 129869 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_Bike_RobertsCross.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_Bike_RobertsCross.png new file mode 100644 index 0000000000..f8527f2fd3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_Bike_RobertsCross.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:efe7f70d49a3822c759bf9a0a4245abf387620f5e840de6fdb9f6131d4e99259 +size 106478 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_Bike_Scharr.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_Bike_Scharr.png new file mode 100644 index 0000000000..b394720efe --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_Bike_Scharr.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:81e0e6a8c512967d48bfc61065f9d4a9eaca78f8ddf54cd0138cbdb00b6e0f0f +size 114230 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_Bike_Sobel.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_Bike_Sobel.png new file mode 100644 index 0000000000..6634c39017 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_Bike_Sobel.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c403541d7e0cc0d8913cc652077d937b3d12ab0978dacfb102ab324efe88b632 +size 130771 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_TestPattern100x100_Kayyali.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_TestPattern100x100_Kayyali.png new file mode 100644 index 0000000000..4a85a4e1bd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_TestPattern100x100_Kayyali.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5ea6a5da616e343ba1d5518e847fe0fea97dfa046e2a18f45efba10457f1fd74 +size 1394 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_TestPattern100x100_Prewitt.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_TestPattern100x100_Prewitt.png new file mode 100644 index 0000000000..3c8ab0c327 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_TestPattern100x100_Prewitt.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c5ec7f464eb63163cc70f4c64ac5df3e719972dd2e674a21546a57caed8e87ac +size 5349 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_TestPattern100x100_RobertsCross.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_TestPattern100x100_RobertsCross.png new file mode 100644 index 0000000000..0324e0b1cc --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_TestPattern100x100_RobertsCross.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5d4adff74b72f273e3022f07ffaecbc79126cd176ebcfa33a2b99400853d4cd4 +size 3463 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_TestPattern100x100_Scharr.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_TestPattern100x100_Scharr.png new file mode 100644 index 0000000000..d7c28104f4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_TestPattern100x100_Scharr.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60a4a4876939f689be731e62e557b3680bae7ab2c795eae9047e939681f03cce +size 1656 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_TestPattern100x100_Sobel.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_TestPattern100x100_Sobel.png new file mode 100644 index 0000000000..c336649767 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges2D_WorksWithAllFilters_Rgba32_TestPattern100x100_Sobel.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:49fc488684c58b7d91dc25003997111b36c37fbd45d4513168dd3a4682fdbb4a +size 4235 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdgesCompass_WorksWithAllFilters_Rgba32_Bike_Kirsch.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdgesCompass_WorksWithAllFilters_Rgba32_Bike_Kirsch.png new file mode 100644 index 0000000000..ef571da585 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdgesCompass_WorksWithAllFilters_Rgba32_Bike_Kirsch.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4d99cc705a6c7bc9bbce009eae3637472efde5ff5f832826eba6d74fa386c348 +size 119073 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdgesCompass_WorksWithAllFilters_Rgba32_Bike_Robinson.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdgesCompass_WorksWithAllFilters_Rgba32_Bike_Robinson.png new file mode 100644 index 0000000000..2c3cea6c61 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdgesCompass_WorksWithAllFilters_Rgba32_Bike_Robinson.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:113af6d7e451fabcf94090de69ad9c711394e8473c7c627de3baa67f88bb42cd +size 130874 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdgesCompass_WorksWithAllFilters_Rgba32_TestPattern100x100_Kirsch.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdgesCompass_WorksWithAllFilters_Rgba32_TestPattern100x100_Kirsch.png new file mode 100644 index 0000000000..8dec16bfcd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdgesCompass_WorksWithAllFilters_Rgba32_TestPattern100x100_Kirsch.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:186937ce04f61b42a3ecae29f0b0aa50614532933f05565ed44b1ebc60acfc9f +size 4323 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdgesCompass_WorksWithAllFilters_Rgba32_TestPattern100x100_Robinson.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdgesCompass_WorksWithAllFilters_Rgba32_TestPattern100x100_Robinson.png new file mode 100644 index 0000000000..039841268c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdgesCompass_WorksWithAllFilters_Rgba32_TestPattern100x100_Robinson.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:326c5a44caf11818852cc4174c8bf8db7171bd64c219ce1c0fa86771f1eff8cd +size 4550 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_InBox_Rgba32_Bike.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_InBox_Rgba32_Bike.png new file mode 100644 index 0000000000..89d9898a79 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_InBox_Rgba32_Bike.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea9814d2724d4180e6628f9fc7f3041ca3a8c0518164b4941e97aee7c2876273 +size 258518 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_IsNotBoundToSinglePixelType_Bgra32_Bike.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_IsNotBoundToSinglePixelType_Bgra32_Bike.png new file mode 100644 index 0000000000..6634c39017 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_IsNotBoundToSinglePixelType_Bgra32_Bike.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c403541d7e0cc0d8913cc652077d937b3d12ab0978dacfb102ab324efe88b632 +size 130771 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_IsNotBoundToSinglePixelType_Rgba32_Bike.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_IsNotBoundToSinglePixelType_Rgba32_Bike.png new file mode 100644 index 0000000000..6634c39017 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_IsNotBoundToSinglePixelType_Rgba32_Bike.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c403541d7e0cc0d8913cc652077d937b3d12ab0978dacfb102ab324efe88b632 +size 130771 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_IsNotBoundToSinglePixelType_RgbaVector_Bike.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_IsNotBoundToSinglePixelType_RgbaVector_Bike.png new file mode 100644 index 0000000000..68aeb832c7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_IsNotBoundToSinglePixelType_RgbaVector_Bike.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:addcd6b062106fbad8d89cf551df9c932b53e7eda9ca37ec1f0c47ab1b177cd5 +size 134460 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_Bike_Laplacian3x3.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_Bike_Laplacian3x3.png new file mode 100644 index 0000000000..3187748f9a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_Bike_Laplacian3x3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aeaa731c83d735037950755cf66b4bee374cdf52a602ce0e456c35efe0be73b2 +size 85549 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_Bike_Laplacian5x5.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_Bike_Laplacian5x5.png new file mode 100644 index 0000000000..de1442a56d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_Bike_Laplacian5x5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc1dcf10f0bc03d0ef89acd6ff6c3278f2284269ae9936ebcbb412c2144320f5 +size 82666 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_Bike_LaplacianOfGaussian.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_Bike_LaplacianOfGaussian.png new file mode 100644 index 0000000000..ee061ae873 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_Bike_LaplacianOfGaussian.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cd18b8c62e4e7acece0a134252492d8451501e042628834946e4c7f3788c78db +size 88291 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_TestPattern100x100_Laplacian3x3.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_TestPattern100x100_Laplacian3x3.png new file mode 100644 index 0000000000..6a2ded3cc2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_TestPattern100x100_Laplacian3x3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a2ddaa3c4b7286f256f50bdad575612dee641046b950e4cf806bbfc2de4e9bf1 +size 4323 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_TestPattern100x100_Laplacian5x5.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_TestPattern100x100_Laplacian5x5.png new file mode 100644 index 0000000000..8731d51b84 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_TestPattern100x100_Laplacian5x5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d2d1960d83de64b2bd48f4eec5db4ca34d5f5d99c069ccad06d9889025650af1 +size 4323 diff --git a/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_TestPattern100x100_LaplacianOfGaussian.png b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_TestPattern100x100_LaplacianOfGaussian.png new file mode 100644 index 0000000000..794aa9423b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/DetectEdgesTest/DetectEdges_WorksWithAllFilters_Rgba32_TestPattern100x100_LaplacianOfGaussian.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c2942d8809e5fde2b1890ec6db7aa64617787933a0990ec0a52185b0cd4edbfd +size 4323 diff --git a/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/InBox_Rgba32_CalliphoraPartial_3.png b/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/InBox_Rgba32_CalliphoraPartial_3.png new file mode 100644 index 0000000000..24939678e8 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/InBox_Rgba32_CalliphoraPartial_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e2e7a74fe02c795d77c2221482a96bfd17cc0b91882cb49d94b978a4eb553813 +size 262921 diff --git a/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/InBox_Rgba32_CalliphoraPartial_5.png b/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/InBox_Rgba32_CalliphoraPartial_5.png new file mode 100644 index 0000000000..3127167a66 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/InBox_Rgba32_CalliphoraPartial_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:35dcaf3afea6c68196d3b684f675410dc2c61cdb6d77fb7c772981d0aade51fd +size 258423 diff --git a/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/InBox_Rgba32_Car_3.png b/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/InBox_Rgba32_Car_3.png new file mode 100644 index 0000000000..5a0a55a327 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/InBox_Rgba32_Car_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd006c7ed0bccc968720b752584419c7983481c146a88c0b7e003c7759e4a89e +size 183106 diff --git a/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/InBox_Rgba32_Car_5.png b/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/InBox_Rgba32_Car_5.png new file mode 100644 index 0000000000..a8aeba3760 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/InBox_Rgba32_Car_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b65b30789c22f0357ee35fed9fe046c255c6aa0835faa1ede269084d02857f73 +size 173555 diff --git a/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/OnFullImage_Rgba32_CalliphoraPartial_3.png b/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/OnFullImage_Rgba32_CalliphoraPartial_3.png new file mode 100644 index 0000000000..645597e25a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/OnFullImage_Rgba32_CalliphoraPartial_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca66b363d2566ae50f8e2fabb5811e83f8a797aac8850148b4f4d1689d9472ef +size 103659 diff --git a/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/OnFullImage_Rgba32_CalliphoraPartial_5.png b/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/OnFullImage_Rgba32_CalliphoraPartial_5.png new file mode 100644 index 0000000000..7ea9a66552 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/OnFullImage_Rgba32_CalliphoraPartial_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e37e52779e9c74d6543fd49bbd5644ae9b773ee40cb413fd06af3a4a8c54370 +size 80731 diff --git a/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/OnFullImage_Rgba32_Car_3.png b/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/OnFullImage_Rgba32_Car_3.png new file mode 100644 index 0000000000..16efbe2d0f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/OnFullImage_Rgba32_Car_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd774c1ebd288a48a686a55e9f750cf275bb63cc692185b29e275b18e64a298c +size 116146 diff --git a/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/OnFullImage_Rgba32_Car_5.png b/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/OnFullImage_Rgba32_Car_5.png new file mode 100644 index 0000000000..b7c81ed63e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/GaussianBlurTest/OnFullImage_Rgba32_Car_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b722332185401bdd4e4bb6fe3f56369d5f59a752acfec11805def4de7cb949b9 +size 98421 diff --git a/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/InBox_Rgba32_CalliphoraPartial_3.png b/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/InBox_Rgba32_CalliphoraPartial_3.png new file mode 100644 index 0000000000..432027deb0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/InBox_Rgba32_CalliphoraPartial_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5ea444d62b7476712274f427d42b69b83e421c9a6f05553076fa71af9ed7aeb5 +size 324209 diff --git a/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/InBox_Rgba32_CalliphoraPartial_5.png b/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/InBox_Rgba32_CalliphoraPartial_5.png new file mode 100644 index 0000000000..9bc336e3b5 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/InBox_Rgba32_CalliphoraPartial_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4844920e31f0f57fccabacd3866a8afe0ebc03f5f0592f9f13e9e42e02e35850 +size 323024 diff --git a/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/InBox_Rgba32_Car_3.png b/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/InBox_Rgba32_Car_3.png new file mode 100644 index 0000000000..70e3a67b49 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/InBox_Rgba32_Car_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62fc4aa5af3e2edf8ce40f970f29656188d415c0abeb975dc3a19946505faa7e +size 255668 diff --git a/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/InBox_Rgba32_Car_5.png b/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/InBox_Rgba32_Car_5.png new file mode 100644 index 0000000000..4bbf154949 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/InBox_Rgba32_Car_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:08b53445a3c4634ff3f2cde3bc4081527d69b6f4e392ca52b18bef1e7530c179 +size 249687 diff --git a/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/OnFullImage_Rgba32_CalliphoraPartial_3.png b/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/OnFullImage_Rgba32_CalliphoraPartial_3.png new file mode 100644 index 0000000000..f4c5eff4d3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/OnFullImage_Rgba32_CalliphoraPartial_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:733be45cd59fa377369fbd6f625f19f04814423744bbf412c5d2dcba8223f9dc +size 303740 diff --git a/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/OnFullImage_Rgba32_CalliphoraPartial_5.png b/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/OnFullImage_Rgba32_CalliphoraPartial_5.png new file mode 100644 index 0000000000..531ca6e08f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/OnFullImage_Rgba32_CalliphoraPartial_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1c592d0e9fc06eff1c9826cf8d670357b5cd4338bc98de8f7810f41cf2751f0b +size 293410 diff --git a/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/OnFullImage_Rgba32_Car_3.png b/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/OnFullImage_Rgba32_Car_3.png new file mode 100644 index 0000000000..b90b67656d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/OnFullImage_Rgba32_Car_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:23fd386d1a9e021ec2e65ed8bf72903769a65a61649a40297c3a96d8318f2e92 +size 307951 diff --git a/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/OnFullImage_Rgba32_Car_5.png b/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/OnFullImage_Rgba32_Car_5.png new file mode 100644 index 0000000000..f23fe7116e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Convolution/GaussianSharpenTest/OnFullImage_Rgba32_Car_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9217f4041b8fa51879961cca45f112d15a43ea2cfa994b6db41edece2f014e25 +size 298201 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/ApplyDiffusionFilterInBox_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/DitherTests/ApplyDiffusionFilterInBox_Rgba32_CalliphoraPartial.png new file mode 100644 index 0000000000..80149fa376 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/ApplyDiffusionFilterInBox_Rgba32_CalliphoraPartial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1aa62e798c085eb7b0e8e5ce5e4cb2cccfe925dd8ac3e29659f9afd53fca977c +size 329912 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/ApplyDitherFilterInBox_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/DitherTests/ApplyDitherFilterInBox_Rgba32_CalliphoraPartial.png new file mode 100644 index 0000000000..5059748d2b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/ApplyDitherFilterInBox_Rgba32_CalliphoraPartial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d0c8ccdfbf6b1c961f6531ae61207a7f89507f469c875677f1755ea3d6c8d900 +size 326504 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_ShouldNotDependOnSinglePixelType_Bgra32_filter0.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_ShouldNotDependOnSinglePixelType_Bgra32_filter0.png new file mode 100644 index 0000000000..8f0ad4f184 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_ShouldNotDependOnSinglePixelType_Bgra32_filter0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0216f1684430087035b387ab02d33b043c526bd8c7d78343c31e1bc410581bfb +size 727 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_ShouldNotDependOnSinglePixelType_Rgb24_filter0.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_ShouldNotDependOnSinglePixelType_Rgb24_filter0.png new file mode 100644 index 0000000000..8f0ad4f184 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_ShouldNotDependOnSinglePixelType_Rgb24_filter0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0216f1684430087035b387ab02d33b043c526bd8c7d78343c31e1bc410581bfb +size 727 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_ShouldNotDependOnSinglePixelType_Rgba32_filter0.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_ShouldNotDependOnSinglePixelType_Rgba32_filter0.png new file mode 100644 index 0000000000..8f0ad4f184 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_ShouldNotDependOnSinglePixelType_Rgba32_filter0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0216f1684430087035b387ab02d33b043c526bd8c7d78343c31e1bc410581bfb +size 727 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_ShouldNotDependOnSinglePixelType_RgbaVector_filter0.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_ShouldNotDependOnSinglePixelType_RgbaVector_filter0.png new file mode 100644 index 0000000000..ca40d71efa --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_ShouldNotDependOnSinglePixelType_RgbaVector_filter0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24191da3ce18438edefa7a189d9beadaa3057b5e4d4c550254e3a81ed159c0f8 +size 723 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_Atkinson.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_Atkinson.png new file mode 100644 index 0000000000..b03fe7b9fb --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_Atkinson.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:087148425a048f33c6ae063064cfe374f7fb88f075d767e62c73675ec52a3e0a +size 100066 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_Burks.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_Burks.png new file mode 100644 index 0000000000..33cd02bda3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_Burks.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b2a90c8463632606b40461ad91d80d44826f7b468ba5f1a905acfc85ad0344c9 +size 114413 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_FloydSteinberg.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_FloydSteinberg.png new file mode 100644 index 0000000000..e0d901ea77 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_FloydSteinberg.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:192c742bfd53f3a74d96c79e92443a922ac60c354b73d7abf292f30d10131307 +size 114842 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_JarvisJudiceNinke.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_JarvisJudiceNinke.png new file mode 100644 index 0000000000..aa0446d48d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_JarvisJudiceNinke.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:50c12659dc05b3ce8a6692cdbc72971bbc691cc7fd26c34df65b4bd71d190e5b +size 108799 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_Sierra2.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_Sierra2.png new file mode 100644 index 0000000000..ef0afb9bd7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_Sierra2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a1c408687899b57b96e9f01ea889bc6f16d9a479386346c6bd9babc45ef99d0 +size 109095 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_Sierra3.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_Sierra3.png new file mode 100644 index 0000000000..8ecbc15453 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_Sierra3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d3d8aead7f9f69dac7eec1b2d8e2200331bf28218c98b7fa3435c9610ff88264 +size 110221 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_SierraLite.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_SierraLite.png new file mode 100644 index 0000000000..417ee7b49e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_SierraLite.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f1fed9d8f58e38cfa938d7735cbdfcbac0aa02f58eda0dddfe29a5ebed0e74eb +size 117802 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_StevensonArce.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_StevensonArce.png new file mode 100644 index 0000000000..b668b84cb9 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_StevensonArce.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dbeeda3f4e505c46e1ec218001f0f1aade4eb64c3932e2c374a74c4b0702d7a8 +size 103735 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_Stucki.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_Stucki.png new file mode 100644 index 0000000000..ea7a103ba5 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_Bike_Stucki.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8003014c90f6c3a722c75e9cafb397d1be3818bb84c3484e28ee79ae273d7d0b +size 109707 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_Atkinson.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_Atkinson.png new file mode 100644 index 0000000000..a519e10948 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_Atkinson.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f02a9465aaaa62b6fc0e9e0578362ccf65ce57bf7a8e1e2899f254863e72807f +size 100060 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_Burks.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_Burks.png new file mode 100644 index 0000000000..5fa4e46134 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_Burks.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f50c240c062cb66e820e8f632107e63bc0de85013143a81975e56f0b72499d8f +size 102871 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_FloydSteinberg.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_FloydSteinberg.png new file mode 100644 index 0000000000..d87f3fd5a2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_FloydSteinberg.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa6c2bb78faaf689cf979dd87b3a24b6405720755ce16c028cafab690ac7b318 +size 104334 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_JarvisJudiceNinke.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_JarvisJudiceNinke.png new file mode 100644 index 0000000000..3a8de62bef --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_JarvisJudiceNinke.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5bddfb2d8b8aa83fd532b3157fe78e75199d591d415524f04f688baafd1744a8 +size 101155 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_Sierra2.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_Sierra2.png new file mode 100644 index 0000000000..184c917957 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_Sierra2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ce16c4b23075e784927143d4077063be3b42bd8a88ca1358082c00974c40150 +size 102434 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_Sierra3.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_Sierra3.png new file mode 100644 index 0000000000..79ec8e0702 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_Sierra3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ddbd3cc8250205b38fbedef85c938920608826d5a39e5e9ecfc835b6b2583453 +size 101438 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_SierraLite.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_SierraLite.png new file mode 100644 index 0000000000..5848f60bf2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_SierraLite.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a880481e38ca282f29a8d00fb041de67c5231304ecdc8cef9167efb58dd482ff +size 105295 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_StevensonArce.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_StevensonArce.png new file mode 100644 index 0000000000..300d827952 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_StevensonArce.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df9945efaa843da6b95c883f109075f116009bec688191d7dae5429a7fa157fc +size 100713 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_Stucki.png b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_Stucki.png new file mode 100644 index 0000000000..a0a7af21ba --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DiffusionFilter_WorksWithAllErrorDiffusers_CalliphoraPartial_Stucki.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c58aeb0e9bcc20b405b5700ec1ac12c7759e77e16da7887186b8d61903e9d906 +size 101013 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Bgra32_filter0.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Bgra32_filter0.png new file mode 100644 index 0000000000..0082bae441 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Bgra32_filter0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14231fa7c5c98504277b6452901679027661c5e272106bdcfc516dd519a5ff6c +size 1049 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Rgb24_filter0.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Rgb24_filter0.png new file mode 100644 index 0000000000..0082bae441 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Rgb24_filter0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14231fa7c5c98504277b6452901679027661c5e272106bdcfc516dd519a5ff6c +size 1049 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Rgba32_filter0.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Rgba32_filter0.png new file mode 100644 index 0000000000..208e4fe0ef --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_Rgba32_filter0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d55bf31ae306fcf91993b488444e83ad0f684f4a2642879e38e27e7b9fb1fa56 +size 1051 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_RgbaVector_filter0.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_RgbaVector_filter0.png new file mode 100644 index 0000000000..0082bae441 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_ShouldNotDependOnSinglePixelType_RgbaVector_filter0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14231fa7c5c98504277b6452901679027661c5e272106bdcfc516dd519a5ff6c +size 1049 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer16x16.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer16x16.png new file mode 100644 index 0000000000..6b7ee76a90 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer16x16.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:208a0b9a189c8801e97495a93302814679441bbbe1769810eb37bcb52a78518f +size 83344 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer2x2.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer2x2.png new file mode 100644 index 0000000000..e91a9551f1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer2x2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c95ae441b8b090a0c838db5ed3e9b3ae1040225420e79b76c806f88b96716b8f +size 80344 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer4x4.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer4x4.png new file mode 100644 index 0000000000..ffd30f62ce --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer4x4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e5ab9eb0b80de50f117446c46025918893c431c228e212bef9371f4f788cee14 +size 82652 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer8x8.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer8x8.png new file mode 100644 index 0000000000..e24920a4d5 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Bayer8x8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f76c909b7e804c8dd80b07fd5346d2036d2fded2bf9a855bd20f7da154a111f3 +size 83554 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Ordered3x3.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Ordered3x3.png new file mode 100644 index 0000000000..d70774d3a7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_Bike_Ordered3x3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:656dfb6c9a53830d915a8c8810d09872333a9230073e25b4f0668269afb15e00 +size 83188 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer16x16.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer16x16.png new file mode 100644 index 0000000000..c3eda832a4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer16x16.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b56aa9a03e7f6733fac6b6ceddba50e85727201c4f79aea64540cc79f7fd942e +size 88333 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer2x2.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer2x2.png new file mode 100644 index 0000000000..56660f434b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer2x2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:863debcf1bc4a4e3fb0e3c29b8b3f8b98bb7ac47901e89a90a57a2dde5d81f53 +size 90431 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer4x4.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer4x4.png new file mode 100644 index 0000000000..c434e317af --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer4x4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a92785de634c09d73dc91d1a33e52dedd7d5dea79d269753d959f2a1f81afb2b +size 89207 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer8x8.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer8x8.png new file mode 100644 index 0000000000..4b04715b9a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Bayer8x8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e0aeb15a04553142cade051d523bbc18b2e63997efa0b0c5f5b8bab8662074f7 +size 88550 diff --git a/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Ordered3x3.png b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Ordered3x3.png new file mode 100644 index 0000000000..fc1e540cc0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/DitherTests/DitherFilter_WorksWithAllDitherers_CalliphoraPartial_Ordered3x3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4801d48fc6691bc2fd555a4bed8a7abdde7edac3dc13b33da580688d11bc4eb4 +size 89543 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/DrawImageOfDifferentPixelType_Bgra32.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/DrawImageOfDifferentPixelType_Bgra32.png new file mode 100644 index 0000000000..2c7f156630 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/DrawImageOfDifferentPixelType_Bgra32.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ffaff9fb6fa2295c00fe5024b7661499a61cc34c78c8b479aecc0509b57bc476 +size 33852 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/DrawImageOfDifferentPixelType_Rgba32.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/DrawImageOfDifferentPixelType_Rgba32.png new file mode 100644 index 0000000000..2c7f156630 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/DrawImageOfDifferentPixelType_Rgba32.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ffaff9fb6fa2295c00fe5024b7661499a61cc34c78c8b479aecc0509b57bc476 +size 33852 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/DrawTransformed.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/DrawTransformed.png new file mode 100644 index 0000000000..bfb9ab5edf --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/DrawTransformed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c83df7a2f70aec8f150799055ce42db09568b47b95216c91a79233ce69381d5 +size 191563 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Add.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Add.png new file mode 100644 index 0000000000..eeea5c3507 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Add.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4756b6b82d15345b151942960c1abae9c697ec8d7ec128b4f3bd796e88779427 +size 15684 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Darken.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Darken.png new file mode 100644 index 0000000000..5438131cdf --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Darken.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:860e2966148cb2c29a690c9998f359f22cb1113c7fec2cf307df17bf7a7cf229 +size 10177 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-HardLight.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-HardLight.png new file mode 100644 index 0000000000..26bc317f90 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-HardLight.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:defb24dde47675ee3e7647a8055f0d437fb3c79856ca41326fd1edf39ee46535 +size 22338 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Lighten.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Lighten.png new file mode 100644 index 0000000000..e8f65763b3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Lighten.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a16c7ed0cd8213b478f1a754c9684aeddd218275d6637585f7ced7d925492db0 +size 18362 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Multiply.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Multiply.png new file mode 100644 index 0000000000..872b0a0c63 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Multiply.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe691de9af39c939d740a1ea900b1378d42b025d3ba14a57e0cf999c8139215b +size 17149 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Normal.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Normal.png new file mode 100644 index 0000000000..c6dcf4ef05 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Normal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e19e8b5beb10a266939414d01c3e3319ac11513f821514669a7abd300be6ea8 +size 23869 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Overlay.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Overlay.png new file mode 100644 index 0000000000..03ac3f0715 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Overlay.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3995b89d929437611d1c2a544c06cdcd1fb147685ff33970744513ace04fb5d6 +size 16637 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Screen.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Screen.png new file mode 100644 index 0000000000..21ef3eadaf --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Screen.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8267f374c311d751ca82696ea75591941e2f252e09db44403caa07ccc85ecb9 +size 18775 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Subtract.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Subtract.png new file mode 100644 index 0000000000..70f5ad14b1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/ImageBlendingMatchesSvgSpecExamples_mode-Subtract.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c99be5e8c4f1d81377f3cf133cf3dfc36253ba01dac4a8a94b371e5eef5a6d88 +size 12231 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Bgr24_CalliphoraPartial_Bike-Normal-1.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Bgr24_CalliphoraPartial_Bike-Normal-1.png new file mode 100644 index 0000000000..87b5c9afbf --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Bgr24_CalliphoraPartial_Bike-Normal-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:72f7b3d4fd46d23d773ee0287896650330b39d50740b3b5d3eec318d832eaa63 +size 234903 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_CalliphoraPartial_splash-Normal-0.25.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_CalliphoraPartial_splash-Normal-0.25.png new file mode 100644 index 0000000000..5fa25265e3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_CalliphoraPartial_splash-Normal-0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:50c734b7de7f85c0866a98a7eccb17fe00c4cff0b4830bc6a31d9850b8bedd07 +size 315291 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_CalliphoraPartial_splash-Normal-0.75.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_CalliphoraPartial_splash-Normal-0.75.png new file mode 100644 index 0000000000..39c8ef938f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_CalliphoraPartial_splash-Normal-0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7903fd89a872a2f2c9a72a5382051bd4b420df7e6252867caa6caff46cdef83e +size 310382 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_CalliphoraPartial_splash-Normal-1.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_CalliphoraPartial_splash-Normal-1.png new file mode 100644 index 0000000000..0333685d62 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_CalliphoraPartial_splash-Normal-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c5ed6c781e52f7a94868a01749ba116a6720dc6099f7f02913412869adf77ea +size 299040 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_TestPattern400x400_splash-Add-0.5.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_TestPattern400x400_splash-Add-0.5.png new file mode 100644 index 0000000000..883c5c0566 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_TestPattern400x400_splash-Add-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8500e834f7244df4b8ec31492e66f7139406e673b9784a10ecf784149995b303 +size 73186 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_TestPattern400x400_splash-Multiply-0.5.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_TestPattern400x400_splash-Multiply-0.5.png new file mode 100644 index 0000000000..4c67726558 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_TestPattern400x400_splash-Multiply-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4caf90bc51068ff44e77e12098bf41a83a99ddd36a95848e0dfcd3a79a1d4126 +size 68999 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_TestPattern400x400_splash-Subtract-0.5.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_TestPattern400x400_splash-Subtract-0.5.png new file mode 100644 index 0000000000..8f80c6b397 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba32_TestPattern400x400_splash-Subtract-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f62d2811997ca73c4b3d6448de225b1f4799e8562a8b638e5369fd9f79d3bfd8 +size 67224 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba64_rgb-48bpp_splash-Normal-0.25.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba64_rgb-48bpp_splash-Normal-0.25.png new file mode 100644 index 0000000000..0eed0d3ad2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba64_rgb-48bpp_splash-Normal-0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e71d1de16ac7fe77c20a68e47a01d8cc1e4b0a1241526e203e0c638aff4286aa +size 1278034 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba64_rgb-48bpp_splash-Normal-1.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba64_rgb-48bpp_splash-Normal-1.png new file mode 100644 index 0000000000..5323084253 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentConfigurations_Rgba64_rgb-48bpp_splash-Normal-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be647ef8a62c383f20887eca63cbee452bbb708219de20e351dff5a4c5bb981c +size 1327872 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentLocations_-25_-30.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentLocations_-25_-30.png new file mode 100644 index 0000000000..9ba0cded73 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentLocations_-25_-30.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fafc33a1eb3e8600f11b6199da605b5a1ae63b72704a49328f9f473d933c3416 +size 158 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentLocations_0_0.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentLocations_0_0.png new file mode 100644 index 0000000000..e1b23865fd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentLocations_0_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe7d4706ea0b98f902cd40de5d6f06a1be964166f5f1e4fe3f4b18c738df123c +size 157 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentLocations_25_25.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentLocations_25_25.png new file mode 100644 index 0000000000..9adde49d31 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentLocations_25_25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6f8687a87b1a795be966912781cacced6682efb6a3ce2063b0ed8ad603e43444 +size 429 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentLocations_75_50.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentLocations_75_50.png new file mode 100644 index 0000000000..de65215fa7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/WorksWithDifferentLocations_75_50.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b9164f54bb563f72029b7b7884918e50004222fed56fe00287260871dcff5e54 +size 155 diff --git a/tests/Images/External/ReferenceOutput/Effects/BackgroundColorTest/FullImage_Rgba32_ducky.png b/tests/Images/External/ReferenceOutput/Effects/BackgroundColorTest/FullImage_Rgba32_ducky.png new file mode 100644 index 0000000000..779d37f356 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/BackgroundColorTest/FullImage_Rgba32_ducky.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d6b98e16e2e7d9ef9da9fa2c6414ca9f92184c129120458cbcfbc82b0340da87 +size 24481 diff --git a/tests/Images/External/ReferenceOutput/Effects/BackgroundColorTest/FullImage_Rgba32_splash.png b/tests/Images/External/ReferenceOutput/Effects/BackgroundColorTest/FullImage_Rgba32_splash.png new file mode 100644 index 0000000000..c8a7d677b0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/BackgroundColorTest/FullImage_Rgba32_splash.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b43d6bc258e310bb26b25dc2504a1ce1d0e5ac97bfecf1f98f429e0d4f6302ae +size 156564 diff --git a/tests/Images/External/ReferenceOutput/Effects/BackgroundColorTest/InBox_Rgba32_ducky.png b/tests/Images/External/ReferenceOutput/Effects/BackgroundColorTest/InBox_Rgba32_ducky.png new file mode 100644 index 0000000000..f19d92a5dc --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/BackgroundColorTest/InBox_Rgba32_ducky.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00b563114b3d4bbb3126570b7b4365ec25705483f60059937eb1eb32bbf8fdfb +size 27751 diff --git a/tests/Images/External/ReferenceOutput/Effects/BackgroundColorTest/InBox_Rgba32_splash.png b/tests/Images/External/ReferenceOutput/Effects/BackgroundColorTest/InBox_Rgba32_splash.png new file mode 100644 index 0000000000..bcc3848396 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/BackgroundColorTest/InBox_Rgba32_splash.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:649b9cf315c04b682f1bbcf273247207aa49be718a6106113d04ed5f8f61757d +size 185665 diff --git a/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/FullImage_CalliphoraPartial_15-10.png b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/FullImage_CalliphoraPartial_15-10.png new file mode 100644 index 0000000000..7e287a8d3e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/FullImage_CalliphoraPartial_15-10.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df3385c0c2db5109881a8f5023f40f3a4f6164a13c81a113e23b3f150442ac05 +size 174615 diff --git a/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/FullImage_CalliphoraPartial_6-5.png b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/FullImage_CalliphoraPartial_6-5.png new file mode 100644 index 0000000000..a1bfd21286 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/FullImage_CalliphoraPartial_6-5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:767f4139969e3db85a5e8e9fea9b288db40e2441617415e6f29a41175771e072 +size 249718 diff --git a/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/FullImage_Car_15-10.png b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/FullImage_Car_15-10.png new file mode 100644 index 0000000000..cf55511946 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/FullImage_Car_15-10.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:134b2e0d4ae9cf3d69b4cbd327d487b506d182e58c9c385264b8159f5be107c2 +size 147594 diff --git a/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/FullImage_Car_6-5.png b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/FullImage_Car_6-5.png new file mode 100644 index 0000000000..9084997571 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/FullImage_Car_6-5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:607db63b25c8c6d761d8febd4ff0e3fdc7a7e650153d8a94a60f0194d6eb1287 +size 203322 diff --git a/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_CalliphoraPartial_15-10.png b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_CalliphoraPartial_15-10.png new file mode 100644 index 0000000000..9a9cfb7302 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_CalliphoraPartial_15-10.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2734d3fc16ffb492e9b972c23897cf6c55c2950cf666dc22857e2ac104d59dee +size 280896 diff --git a/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_CalliphoraPartial_6-5.png b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_CalliphoraPartial_6-5.png new file mode 100644 index 0000000000..1ba6688f86 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_CalliphoraPartial_6-5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:36c2a36e8b684298cc621ca05b934e4d897e265084988cc211ec9ef1967beae9 +size 300401 diff --git a/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_Car_15-10.png b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_Car_15-10.png new file mode 100644 index 0000000000..d95a2890e7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_Car_15-10.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f2728ee47feae4206b4383f04588cdb1ac54d4c6c39878c3998ebc28db3b8d97 +size 191705 diff --git a/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_Car_6-5.png b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_Car_6-5.png new file mode 100644 index 0000000000..a9b4571cda --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_Car_6-5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7458b084fbb22231a87f0e81bf6d8daa6ff83567eba23f0544e8f879916c04c1 +size 217144 diff --git a/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_TestPattern100x100_15-10.png b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_TestPattern100x100_15-10.png new file mode 100644 index 0000000000..422634be4a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_TestPattern100x100_15-10.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:374aef670a6ec6709d4dc7c530bb0d6673c3116c6a4d7bc9deb8c0d340243476 +size 3006 diff --git a/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_TestPattern100x100_6-5.png b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_TestPattern100x100_6-5.png new file mode 100644 index 0000000000..9a276cb383 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/OilPaintTest/InBox_Rgba32_TestPattern100x100_6-5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c548f53eada78896332eff3b4338262c32a6e690fde60f06ef09805ede036fb +size 2815 diff --git a/tests/Images/External/ReferenceOutput/Effects/PixelShaderTest/FullImage_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/Effects/PixelShaderTest/FullImage_CalliphoraPartial.png new file mode 100644 index 0000000000..df100d838c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/PixelShaderTest/FullImage_CalliphoraPartial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6d63631501771368531c38c045ac6b1496dc3236809468e91412cbf356376265 +size 113408 diff --git a/tests/Images/External/ReferenceOutput/Effects/PixelShaderTest/InBox_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/Effects/PixelShaderTest/InBox_Rgba32_CalliphoraPartial.png new file mode 100644 index 0000000000..13aead41cc --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/PixelShaderTest/InBox_Rgba32_CalliphoraPartial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad798a33ac81a0e4750084c2710b3e49508c04bffaf7708aac3d099a6f9fecea +size 309998 diff --git a/tests/Images/External/ReferenceOutput/Effects/PixelShaderTest/PositionAwareFullImage_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/Effects/PixelShaderTest/PositionAwareFullImage_CalliphoraPartial.png new file mode 100644 index 0000000000..7947e74708 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/PixelShaderTest/PositionAwareFullImage_CalliphoraPartial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca94e553d47dfad79df1b9d26b0322d94a075f8c19666b69f3d27c163442c8dd +size 236159 diff --git a/tests/Images/External/ReferenceOutput/Effects/PixelShaderTest/PositionAwareInBox_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/Effects/PixelShaderTest/PositionAwareInBox_Rgba32_CalliphoraPartial.png new file mode 100644 index 0000000000..98dd1e43f6 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/PixelShaderTest/PositionAwareInBox_Rgba32_CalliphoraPartial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f6ffac4a9d911c47b0e8bcaa8493f266e7e5bfa8c223261d21f804d6d67f00c1 +size 344529 diff --git a/tests/Images/External/ReferenceOutput/Effects/PixelateTest/FullImage_ducky_4.png b/tests/Images/External/ReferenceOutput/Effects/PixelateTest/FullImage_ducky_4.png new file mode 100644 index 0000000000..5348388b53 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/PixelateTest/FullImage_ducky_4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:76d73db6c4739325675e38cec68dfc98d735b0198bafad1b4d37738f93e42d81 +size 4241 diff --git a/tests/Images/External/ReferenceOutput/Effects/PixelateTest/FullImage_ducky_8.png b/tests/Images/External/ReferenceOutput/Effects/PixelateTest/FullImage_ducky_8.png new file mode 100644 index 0000000000..8768ecba90 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/PixelateTest/FullImage_ducky_8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:43d3b1627ec9fed6a35296dc4fb7c933b75e27fefe2029cec45926895a8b167f +size 1610 diff --git a/tests/Images/External/ReferenceOutput/Effects/PixelateTest/InBox_Rgba32_CalliphoraPartial_4.png b/tests/Images/External/ReferenceOutput/Effects/PixelateTest/InBox_Rgba32_CalliphoraPartial_4.png new file mode 100644 index 0000000000..fbcea4a901 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/PixelateTest/InBox_Rgba32_CalliphoraPartial_4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8b1d0565f2d015751e798c0cf016ec1aa1041cdfb2e4e5c4ac306a266e192f8 +size 245285 diff --git a/tests/Images/External/ReferenceOutput/Effects/PixelateTest/InBox_Rgba32_CalliphoraPartial_8.png b/tests/Images/External/ReferenceOutput/Effects/PixelateTest/InBox_Rgba32_CalliphoraPartial_8.png new file mode 100644 index 0000000000..ce5f59cd63 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/PixelateTest/InBox_Rgba32_CalliphoraPartial_8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c1d1f66eeb8edb379004f4a4a789d8cf74400fbfac696b6b3c2231a293a1cb26 +size 239213 diff --git a/tests/Images/External/ReferenceOutput/Effects/PixelateTest/InBox_Rgba32_TestPattern320x240_4.png b/tests/Images/External/ReferenceOutput/Effects/PixelateTest/InBox_Rgba32_TestPattern320x240_4.png new file mode 100644 index 0000000000..555e9fb76f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/PixelateTest/InBox_Rgba32_TestPattern320x240_4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:09764588a7cd1cdd850a3e662db4a8fbc2520a1769203d730b965b794a044f45 +size 2232 diff --git a/tests/Images/External/ReferenceOutput/Effects/PixelateTest/InBox_Rgba32_TestPattern320x240_8.png b/tests/Images/External/ReferenceOutput/Effects/PixelateTest/InBox_Rgba32_TestPattern320x240_8.png new file mode 100644 index 0000000000..6758394ed5 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Effects/PixelateTest/InBox_Rgba32_TestPattern320x240_8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8c8012c9ab85780e5eadf78fb43ed9d417ce95928ce595bfbd8cb2ec496987d7 +size 2210 diff --git a/tests/Images/External/ReferenceOutput/Filters/BlackWhiteTest/ApplyBlackWhiteFilter_Rgba32_TestPattern48x48.png b/tests/Images/External/ReferenceOutput/Filters/BlackWhiteTest/ApplyBlackWhiteFilter_Rgba32_TestPattern48x48.png new file mode 100644 index 0000000000..4f57775dc0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/BlackWhiteTest/ApplyBlackWhiteFilter_Rgba32_TestPattern48x48.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:65d3a099dd24fcee2fc86c63b8664ebd81d7b3c530168da5f4e50ee0ca925496 +size 759 diff --git a/tests/Images/External/ReferenceOutput/Filters/BrightnessTest/ApplyBrightnessFilter_Rgba32_TestPattern48x48_0.5.png b/tests/Images/External/ReferenceOutput/Filters/BrightnessTest/ApplyBrightnessFilter_Rgba32_TestPattern48x48_0.5.png new file mode 100644 index 0000000000..1bc68f24e7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/BrightnessTest/ApplyBrightnessFilter_Rgba32_TestPattern48x48_0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:15d054beec497b09b4090be71032a3a47ce12a0074b0801bb940b19702334a2f +size 393 diff --git a/tests/Images/External/ReferenceOutput/Filters/BrightnessTest/ApplyBrightnessFilter_Rgba32_TestPattern48x48_1.5.png b/tests/Images/External/ReferenceOutput/Filters/BrightnessTest/ApplyBrightnessFilter_Rgba32_TestPattern48x48_1.5.png new file mode 100644 index 0000000000..f57571c5b8 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/BrightnessTest/ApplyBrightnessFilter_Rgba32_TestPattern48x48_1.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0f59a36a3bfec064e7cf48bf3775a8e52414bce470b44b6f05f313a3ac3a3260 +size 751 diff --git a/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Achromatomaly.png b/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Achromatomaly.png new file mode 100644 index 0000000000..0fa82a3ac6 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Achromatomaly.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:34bcad1e22ffd0d73086208dfb75d12001089bfc707dee2c9260acc000f9eda7 +size 924 diff --git a/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Achromatopsia.png b/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Achromatopsia.png new file mode 100644 index 0000000000..8f076e38e9 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Achromatopsia.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c3ee638487a8d2a75c683aff7ad04a58a27895195a9c3eed108f62a285955dbd +size 496 diff --git a/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Deuteranomaly.png b/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Deuteranomaly.png new file mode 100644 index 0000000000..80cecfb257 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Deuteranomaly.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf4f0090e3c7119b2eac65c0c47bcba6d76df1cbf778ab8d80225337707a68cb +size 648 diff --git a/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Deuteranopia.png b/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Deuteranopia.png new file mode 100644 index 0000000000..aa8b2e3210 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Deuteranopia.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:347051d8de005cc1ad92eeef40c065d02c0031f1891143c133b2fe6406a2b8b4 +size 847 diff --git a/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Protanomaly.png b/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Protanomaly.png new file mode 100644 index 0000000000..3d115d1ceb --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Protanomaly.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ccbb048d622665022847c127e8c18b125e27b046a1aeca3e9f9728b0d5554e8 +size 757 diff --git a/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Protanopia.png b/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Protanopia.png new file mode 100644 index 0000000000..c866e1c1b3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Protanopia.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0965ea8ebe5679bcaa7e00ac5c73a382722e81a8568f5be7951573c255d5990c +size 827 diff --git a/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Tritanomaly.png b/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Tritanomaly.png new file mode 100644 index 0000000000..31ae6e2b12 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Tritanomaly.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d89234ba5185decbe3e0d21475657a19b9db349c45d239ec017b34f54ebe8ef +size 860 diff --git a/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Tritanopia.png b/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Tritanopia.png new file mode 100644 index 0000000000..fb2dccfb40 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/ColorBlindnessTest/ApplyColorBlindnessFilter_Rgba32_TestPattern48x48_Tritanopia.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:80fdf463be6fd54b0ce8977b7b6e564503052f26062de48a1c8ad51232b26f59 +size 683 diff --git a/tests/Images/External/ReferenceOutput/Filters/ContrastTest/ApplyContrastFilter_Rgba32_TestPattern48x48_0.5.png b/tests/Images/External/ReferenceOutput/Filters/ContrastTest/ApplyContrastFilter_Rgba32_TestPattern48x48_0.5.png new file mode 100644 index 0000000000..5e6834dcac --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/ContrastTest/ApplyContrastFilter_Rgba32_TestPattern48x48_0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94fd1158d54d50563ec5658b3f278dc51a99f808740e022a4ead7dd69a91b879 +size 2923 diff --git a/tests/Images/External/ReferenceOutput/Filters/ContrastTest/ApplyContrastFilter_Rgba32_TestPattern48x48_1.5.png b/tests/Images/External/ReferenceOutput/Filters/ContrastTest/ApplyContrastFilter_Rgba32_TestPattern48x48_1.5.png new file mode 100644 index 0000000000..3ad2338c8a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/ContrastTest/ApplyContrastFilter_Rgba32_TestPattern48x48_1.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a96097f3248bb50244f3aa07753b077066576e0ecb2f96010607a7ebf0bd8af8 +size 2807 diff --git a/tests/Images/External/ReferenceOutput/Filters/FilterTest/ApplyFilterInBox_Rgba32_TestPattern48x48.png b/tests/Images/External/ReferenceOutput/Filters/FilterTest/ApplyFilterInBox_Rgba32_TestPattern48x48.png new file mode 100644 index 0000000000..0c2096dccd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/FilterTest/ApplyFilterInBox_Rgba32_TestPattern48x48.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d7987df208917e972307c5924164466d62a18ff3b47e6425d2bf6db3fe8deb4 +size 2744 diff --git a/tests/Images/External/ReferenceOutput/Filters/FilterTest/ApplyFilter_Bgra32_TestPattern48x48.png b/tests/Images/External/ReferenceOutput/Filters/FilterTest/ApplyFilter_Bgra32_TestPattern48x48.png new file mode 100644 index 0000000000..9f95c88792 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/FilterTest/ApplyFilter_Bgra32_TestPattern48x48.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf644d60432e4ac0980faaae82ded41706c6fbe25ad2db94e0ca8316a169bfd7 +size 2807 diff --git a/tests/Images/External/ReferenceOutput/Filters/FilterTest/ApplyFilter_Rgba32_TestPattern48x48.png b/tests/Images/External/ReferenceOutput/Filters/FilterTest/ApplyFilter_Rgba32_TestPattern48x48.png new file mode 100644 index 0000000000..9f95c88792 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/FilterTest/ApplyFilter_Rgba32_TestPattern48x48.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf644d60432e4ac0980faaae82ded41706c6fbe25ad2db94e0ca8316a169bfd7 +size 2807 diff --git a/tests/Images/External/ReferenceOutput/Filters/GrayscaleTest/ApplyGrayscaleFilter_Rgba32_TestPattern48x48_Bt601.png b/tests/Images/External/ReferenceOutput/Filters/GrayscaleTest/ApplyGrayscaleFilter_Rgba32_TestPattern48x48_Bt601.png new file mode 100644 index 0000000000..9010cad7ec --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/GrayscaleTest/ApplyGrayscaleFilter_Rgba32_TestPattern48x48_Bt601.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ddd12a6a0ba522c738ebd08ce8bbe4a0c4bb41cdf01e55ea08ca8ced509cb4ba +size 2689 diff --git a/tests/Images/External/ReferenceOutput/Filters/GrayscaleTest/ApplyGrayscaleFilter_Rgba32_TestPattern48x48_Bt709.png b/tests/Images/External/ReferenceOutput/Filters/GrayscaleTest/ApplyGrayscaleFilter_Rgba32_TestPattern48x48_Bt709.png new file mode 100644 index 0000000000..a88d1613b7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/GrayscaleTest/ApplyGrayscaleFilter_Rgba32_TestPattern48x48_Bt709.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:df275704a518359615540bf355464655196ecbb2ea66c69c77feec8e47249068 +size 2658 diff --git a/tests/Images/External/ReferenceOutput/Filters/HueTest/ApplyHueFilter_Rgba32_TestPattern48x48_-180.png b/tests/Images/External/ReferenceOutput/Filters/HueTest/ApplyHueFilter_Rgba32_TestPattern48x48_-180.png new file mode 100644 index 0000000000..ee959e9118 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/HueTest/ApplyHueFilter_Rgba32_TestPattern48x48_-180.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:297694e34588a4d2bdeb4856ca0665f92b8133d53e362d18a853c73e8416c608 +size 2833 diff --git a/tests/Images/External/ReferenceOutput/Filters/HueTest/ApplyHueFilter_Rgba32_TestPattern48x48_180.png b/tests/Images/External/ReferenceOutput/Filters/HueTest/ApplyHueFilter_Rgba32_TestPattern48x48_180.png new file mode 100644 index 0000000000..ee959e9118 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/HueTest/ApplyHueFilter_Rgba32_TestPattern48x48_180.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:297694e34588a4d2bdeb4856ca0665f92b8133d53e362d18a853c73e8416c608 +size 2833 diff --git a/tests/Images/External/ReferenceOutput/Filters/InvertTest/ApplyInvertFilter_Rgba32_TestPattern48x48.png b/tests/Images/External/ReferenceOutput/Filters/InvertTest/ApplyInvertFilter_Rgba32_TestPattern48x48.png new file mode 100644 index 0000000000..a0cb6ba41b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/InvertTest/ApplyInvertFilter_Rgba32_TestPattern48x48.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:19b4539af71059a004bcbfaffb81da342e05b65723b7c528556e3516cae36b41 +size 2633 diff --git a/tests/Images/External/ReferenceOutput/Filters/KodachromeTest/ApplyKodachromeFilter_Rgba32_TestPattern48x48.png b/tests/Images/External/ReferenceOutput/Filters/KodachromeTest/ApplyKodachromeFilter_Rgba32_TestPattern48x48.png new file mode 100644 index 0000000000..02d8deb119 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/KodachromeTest/ApplyKodachromeFilter_Rgba32_TestPattern48x48.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:789ff8ee73b3e18c8d96b662002aeab476270c495447961055a60d8b83c5a94e +size 3038 diff --git a/tests/Images/External/ReferenceOutput/Filters/LightnessTest/ApplyLightnessFilter_Rgba32_TestPattern48x48_0.5.png b/tests/Images/External/ReferenceOutput/Filters/LightnessTest/ApplyLightnessFilter_Rgba32_TestPattern48x48_0.5.png new file mode 100644 index 0000000000..cdb03b4c7c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/LightnessTest/ApplyLightnessFilter_Rgba32_TestPattern48x48_0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0a295d26c02b8ed04d19cc9621f60df8ccca097b2ee98200309beb0444c64125 +size 821 diff --git a/tests/Images/External/ReferenceOutput/Filters/LightnessTest/ApplyLightnessFilter_Rgba32_TestPattern48x48_1.5.png b/tests/Images/External/ReferenceOutput/Filters/LightnessTest/ApplyLightnessFilter_Rgba32_TestPattern48x48_1.5.png new file mode 100644 index 0000000000..477542f39d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/LightnessTest/ApplyLightnessFilter_Rgba32_TestPattern48x48_1.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1cce46b79ca3fd6c23267c54801bf7934d6fd69964338fc25dcb6e63adf3a02b +size 799 diff --git a/tests/Images/External/ReferenceOutput/Filters/LomographTest/ApplyLomographFilter_Rgba32_TestPattern48x48.png b/tests/Images/External/ReferenceOutput/Filters/LomographTest/ApplyLomographFilter_Rgba32_TestPattern48x48.png new file mode 100644 index 0000000000..f4d9b4538b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/LomographTest/ApplyLomographFilter_Rgba32_TestPattern48x48.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1c11bb97fe2e2d6f8bf4c8a21c9a58702e1cff6bb02bb52412a8f54d4e1d3bbb +size 6428 diff --git a/tests/Images/External/ReferenceOutput/Filters/OpacityTest/ApplyAlphaFilter_Rgba32_TestPattern48x48_0.2.png b/tests/Images/External/ReferenceOutput/Filters/OpacityTest/ApplyAlphaFilter_Rgba32_TestPattern48x48_0.2.png new file mode 100644 index 0000000000..4e1731515a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/OpacityTest/ApplyAlphaFilter_Rgba32_TestPattern48x48_0.2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7089899b93d357320558f3e75fa5c609d18d89eb9965cfcf8bf20e6f6c21b9f0 +size 2528 diff --git a/tests/Images/External/ReferenceOutput/Filters/OpacityTest/ApplyAlphaFilter_Rgba32_TestPattern48x48_0.8.png b/tests/Images/External/ReferenceOutput/Filters/OpacityTest/ApplyAlphaFilter_Rgba32_TestPattern48x48_0.8.png new file mode 100644 index 0000000000..4a65a65d90 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/OpacityTest/ApplyAlphaFilter_Rgba32_TestPattern48x48_0.8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4425b5412647a5978bc687707635552b812a5c821d7399d491c4407ae204c6df +size 2656 diff --git a/tests/Images/External/ReferenceOutput/Filters/PolaroidTest/ApplyPolaroidFilter_Rgba32_TestPattern48x48.png b/tests/Images/External/ReferenceOutput/Filters/PolaroidTest/ApplyPolaroidFilter_Rgba32_TestPattern48x48.png new file mode 100644 index 0000000000..db3cde6bb6 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/PolaroidTest/ApplyPolaroidFilter_Rgba32_TestPattern48x48.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c91c5113e9dd6ee5b95d32b3181d3d777b6e1dbb64339630cc9817e91208f338 +size 7210 diff --git a/tests/Images/External/ReferenceOutput/Filters/SaturateTest/ApplySaturationFilter_Rgba32_TestPattern48x48_0.5.png b/tests/Images/External/ReferenceOutput/Filters/SaturateTest/ApplySaturationFilter_Rgba32_TestPattern48x48_0.5.png new file mode 100644 index 0000000000..5fef5f9f6e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/SaturateTest/ApplySaturationFilter_Rgba32_TestPattern48x48_0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d4e17b9f746d2e6b7032d41df00d6f3fbda3b1b03eedb33d81e060d8d4dabef5 +size 2955 diff --git a/tests/Images/External/ReferenceOutput/Filters/SaturateTest/ApplySaturationFilter_Rgba32_TestPattern48x48_1.5.png b/tests/Images/External/ReferenceOutput/Filters/SaturateTest/ApplySaturationFilter_Rgba32_TestPattern48x48_1.5.png new file mode 100644 index 0000000000..84eac27006 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/SaturateTest/ApplySaturationFilter_Rgba32_TestPattern48x48_1.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ca8d88eac7513d3418e6d66fb576d598940e860eb600345310228547542862f +size 2806 diff --git a/tests/Images/External/ReferenceOutput/Filters/SepiaTest/ApplySepiaFilter_Rgba32_TestPattern48x48.png b/tests/Images/External/ReferenceOutput/Filters/SepiaTest/ApplySepiaFilter_Rgba32_TestPattern48x48.png new file mode 100644 index 0000000000..8ed26346e0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Filters/SepiaTest/ApplySepiaFilter_Rgba32_TestPattern48x48.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:998821190abd23ac3c54d70866bc8e056995ac2570b78353c78fbb27626bdb56 +size 2788 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_giphy.gif/00.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_giphy.gif/00.png new file mode 100644 index 0000000000..c8b4db92cb --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_giphy.gif/00.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f2cc0d653e6f3e06b1d8828ff5794fd5f81526a9e411137a2d1a78f9d8894100 +size 7168 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_giphy.gif/01.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_giphy.gif/01.png new file mode 100644 index 0000000000..afeab25c31 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_giphy.gif/01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a7f721df04021f246e9df9f6b91c3654e8b40ded575473c05d646f7bc632b958 +size 7558 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_giphy.gif/02.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_giphy.gif/02.png new file mode 100644 index 0000000000..a03761d56c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_giphy.gif/02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a40b7f8d2779e6fdf26e2720fdf24f8da03e9ef9d8b1ff68e9bb68f001814b79 +size 6956 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_giphy.gif/03.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_giphy.gif/03.png new file mode 100644 index 0000000000..848c6be819 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_giphy.gif/03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4fc7fdca7cfec1ae6d119dbccdc7ea78c19584076a197c54e494645b2c84e45e +size 7131 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_giphy.gif/04.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_giphy.gif/04.png new file mode 100644 index 0000000000..11b93c1aa3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_giphy.gif/04.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d4b59fa394cc6205e00440428e9a141a627b88b5e2562ec6b1dd0d48651da77f +size 7104 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/00.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/00.png new file mode 100644 index 0000000000..9236bef85a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/00.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ac324bd9199113897bd986cffe8e7f3770fb2e68e6792d631071ff1db40075f +size 29351 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/01.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/01.png new file mode 100644 index 0000000000..91b3c95dcf --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f9ec5a3228c71b54a2bccd8aaf929e11436d45cb56f43cd507cfd4e7bb288fb7 +size 30538 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/02.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/02.png new file mode 100644 index 0000000000..d9c98dace4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa0c9f304a6afc62aba3b6567905160f7728f43e3b5ba3dc79bf743c9a5f49ab +size 30754 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/03.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/03.png new file mode 100644 index 0000000000..5573c15191 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e61d8611c06c4f82c0000ebac4a1b3a53d1342e23f9efb10406ae06a510580c +size 31260 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/04.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/04.png new file mode 100644 index 0000000000..a595bb707d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/04.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:168bcccba4dffeaec2f2e3978405f802451089790b6377d8c653cfaed7bae833 +size 31741 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/05.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/05.png new file mode 100644 index 0000000000..29537a2f55 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/05.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1c6675dcca4418fdc529e4de1bc0014a2463d6c6b197dd701b84044a00b31016 +size 30061 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/06.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/06.png new file mode 100644 index 0000000000..380b5aad3b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/06.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d01cfb14c66662f8972f48d62a7cbb70c2ffa174d74a5533be61a2565d923a0 +size 31139 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/07.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/07.png new file mode 100644 index 0000000000..9c815c41b3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/07.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6918449a54dea19a15f3f4ef9f5d0e890f7dc97e651d4c77bd60dfaa4f49d646 +size 31304 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/08.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/08.png new file mode 100644 index 0000000000..09521859c7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/08.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c8927c2e34c9ab90c1fbc3d4f8be289f4a47fee5cfe9c4d72bc39eb78c94a3bf +size 32500 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/09.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/09.png new file mode 100644 index 0000000000..e38de41abe --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/09.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a2ffb21368cf6c3e4d567ca19cc40187bee254ea6ebea83c6d6f9c2df02b56eb +size 32374 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/10.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/10.png new file mode 100644 index 0000000000..4d104e2738 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/10.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b903f04b431ed0d9474ef89cb48d2b7b7fa8c124b5fb1f2562d826eaa2cd3ba +size 32692 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/11.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/11.png new file mode 100644 index 0000000000..141d2df423 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/11.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:898566396d44cb9c495ed6c40c56928fe642434ed4888331bb92b17fb0cd4847 +size 33243 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/12.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/12.png new file mode 100644 index 0000000000..590132fcaa --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/12.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18a1888eb6d79f857f8336e76e50b5402127036418183e03869e58021b8f9c47 +size 32797 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/13.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/13.png new file mode 100644 index 0000000000..9ab3afd9ed --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/13.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8384afabdc9133435c61c0cec97fe599719f7cc601fc1444b1b182383dfcbd40 +size 31306 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/14.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/14.png new file mode 100644 index 0000000000..33bdd55d4c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/14.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ea0c2d692d1a5b645af16726b54cc54a0d0166292cc3b3619a96f062996f13f +size 30782 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/15.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/15.png new file mode 100644 index 0000000000..1ca1ab28ee --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/15.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e4bb35f4484cb66bf63d46f4311617dc7e675ead33b8f978f564045491eea5bc +size 31875 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/16.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/16.png new file mode 100644 index 0000000000..9dced1b137 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/16.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21aa4d98c2870022104e44de7c63e16d4a8f7ae139c7a996c862b1cbd55bc3d7 +size 32317 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/17.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/17.png new file mode 100644 index 0000000000..110ce09672 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/17.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f7550515971c3af24efb51b4a81c21e3e3a642c53b654512bc6c6ad67d049748 +size 33265 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/18.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/18.png new file mode 100644 index 0000000000..68406f480b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/18.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:161d80a458dc2418eea4ab8caa851c0632eadd64538843a2c2a5cdd0a54ff66b +size 32545 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/19.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/19.png new file mode 100644 index 0000000000..b0c387fb85 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/19.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8342d403ab99e900932b52b55f6c6583aac0567c4215c4e187eccf264f4e2c2c +size 32210 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/20.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/20.png new file mode 100644 index 0000000000..7178b780d4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/20.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a29b4ca76d42a067b3e4f27521e5a0b05c85668002e92a30d12f1a3784062ec +size 31574 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/21.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/21.png new file mode 100644 index 0000000000..ffb8ced6e5 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/21.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be2601503fadee016c5f88b137091b50c6a7451e577f253f166b212ee937b35a +size 31384 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/22.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/22.png new file mode 100644 index 0000000000..1b0034ab58 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/22.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2800403642452bff9858db473777b93030dde29c04b0280665a36aa9b57fcb18 +size 31855 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/23.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/23.png new file mode 100644 index 0000000000..ddf9fbf7a2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/23.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0225e8395085728e2988ec148e33dc9df009746d5fe0860b12539776337372a +size 32035 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/24.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/24.png new file mode 100644 index 0000000000..302c97696c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/24.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f348830b798dff6f62a5c279105181efb4e692fe83f3e42cd3cae9b5ca0af7ce +size 32097 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/25.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/25.png new file mode 100644 index 0000000000..3c3e74adb9 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd5fb5b83f44bbbc1b32690f54f995eb1709937de780ca35e31598c399c7d8ef +size 31750 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/26.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/26.png new file mode 100644 index 0000000000..1b77c89bcf --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyAllFrames_Rgba32_kumin.gif/26.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2a02cb3c82c90b05381126ff3f696e562200442aca34ba54830878701c51d932 +size 31647 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyRootFrameAndFrameCount_Rgba32_cheers.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyRootFrameAndFrameCount_Rgba32_cheers.png new file mode 100644 index 0000000000..d5be7b0b25 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyRootFrameAndFrameCount_Rgba32_cheers.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b199a36f9e682a54c5d7c67f3403bba174b37e1a7a8412481f66c6d5eb0349e9 +size 27679 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyRootFrameAndFrameCount_Rgba32_issue403_baddescriptorwidth.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyRootFrameAndFrameCount_Rgba32_issue403_baddescriptorwidth.png new file mode 100644 index 0000000000..5bd551cb16 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyRootFrameAndFrameCount_Rgba32_issue403_baddescriptorwidth.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4bedcf1a0ca0281dd5531d96c74e19c5d5fd379d6e2acb899077299917215705 +size 1013 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyRootFrameAndFrameCount_Rgba32_rings.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyRootFrameAndFrameCount_Rgba32_rings.png new file mode 100644 index 0000000000..66b3a43359 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Decode_VerifyRootFrameAndFrameCount_Rgba32_rings.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:29a3593267e0e5812180c177f52ee7daeecc3f65b0f1511e887819d446155495 +size 22840 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/GifDecoder_IsNotBoundToSinglePixelType_Argb32_trans.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/GifDecoder_IsNotBoundToSinglePixelType_Argb32_trans.png new file mode 100644 index 0000000000..1cfc3adb88 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/GifDecoder_IsNotBoundToSinglePixelType_Argb32_trans.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa4c441acc8fe614c9b375e8e609e735e1c767918ecc1f8f2f028665fdcfcf34 +size 12441 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/GifDecoder_IsNotBoundToSinglePixelType_Rgba32_trans.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/GifDecoder_IsNotBoundToSinglePixelType_Rgba32_trans.png new file mode 100644 index 0000000000..1cfc3adb88 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/GifDecoder_IsNotBoundToSinglePixelType_Rgba32_trans.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa4c441acc8fe614c9b375e8e609e735e1c767918ecc1f8f2f028665fdcfcf34 +size 12441 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/GifDecoder_IsNotBoundToSinglePixelType_RgbaVector_trans.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/GifDecoder_IsNotBoundToSinglePixelType_RgbaVector_trans.png new file mode 100644 index 0000000000..1cfc3adb88 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/GifDecoder_IsNotBoundToSinglePixelType_RgbaVector_trans.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa4c441acc8fe614c9b375e8e609e735e1c767918ecc1f8f2f028665fdcfcf34 +size 12441 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/00.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/00.png new file mode 100644 index 0000000000..4bd1d004ba --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/00.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:38df828a5ab6e64c1e79966bf956f6f103501777e386ddd181d41889ec8ea953 +size 84562 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/01.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/01.png new file mode 100644 index 0000000000..fc0edc512e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:52b3ce4d07be0d34bf48c4a33ecd0edc0c0fc902f72eeae060a09e737e6e15ab +size 99275 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/02.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/02.png new file mode 100644 index 0000000000..4966a0d6f9 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1bf8f2fb237726ba0bcea83f95520e0bcc98d2a22a9586757e1eb9d3bb1f3002 +size 126960 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/03.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/03.png new file mode 100644 index 0000000000..e272c737bb --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bb0aa4a7a1bc275e651ca1f0e5f3cdbce6e4c36e1d788e2c68e9e5712bb90357 +size 147957 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/04.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/04.png new file mode 100644 index 0000000000..17e71b51d4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/04.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2feebd1770257640e9e15f4ab7fa13d6e5d3e98132de90dade4060c5fa47c023 +size 106486 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/05.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/05.png new file mode 100644 index 0000000000..a0812eb6ba --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/05.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ffec2754a35a8fd818c90a2c40c36f9960ad57ef70b179e70424cbe0c8293eb +size 106151 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/06.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/06.png new file mode 100644 index 0000000000..ec90b1f236 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/06.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:80480b5bbef516b8827adcadcb285aaf8880dfc9f852b79da8d16f019b489078 +size 82907 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/07.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/07.png new file mode 100644 index 0000000000..b3c9b0d86a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/07.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce6601f18dca6270293085736912c45e7686c64461b4838ee1769bc8da96f484 +size 96002 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/08.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/08.png new file mode 100644 index 0000000000..9231fc42fc --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue1530_BadDescriptorDimensions_Rgba32_issue1530.gif/08.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ade295a2ab40d2e6d41ff2cce9ced919a5b1dfcfc966b3e8c10cbcf256618ea8 +size 79170 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue405_BadApplicationExtensionBlockLength_Rgba32_issue405_badappextlength252-2.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue405_BadApplicationExtensionBlockLength_Rgba32_issue405_badappextlength252-2.png new file mode 100644 index 0000000000..7a3a9e97e8 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue405_BadApplicationExtensionBlockLength_Rgba32_issue405_badappextlength252-2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:84ef6779f440fbea83fc7c967a9478d5146bd8655831cb07c196f8c12e0b13fc +size 19029 diff --git a/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue405_BadApplicationExtensionBlockLength_Rgba32_issue405_badappextlength252.png b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue405_BadApplicationExtensionBlockLength_Rgba32_issue405_badappextlength252.png new file mode 100644 index 0000000000..8a98c17ad6 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifDecoderTests/Issue405_BadApplicationExtensionBlockLength_Rgba32_issue405_badappextlength252.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b770547a1720854670a9ec3d2265328a8346e4c05de49e47255fac363f78c966 +size 35528 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/EncodeGeneratedPatterns_Argb32_TestPattern100x100.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/EncodeGeneratedPatterns_Argb32_TestPattern100x100.gif new file mode 100644 index 0000000000..91bee0ade1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/EncodeGeneratedPatterns_Argb32_TestPattern100x100.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:548cc02ad75f76ccad5d5597d4558fe9acf2993ee04190acd363e613123cbdbb +size 3321 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/EncodeGeneratedPatterns_Rgba32_TestPattern100x100.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/EncodeGeneratedPatterns_Rgba32_TestPattern100x100.gif new file mode 100644 index 0000000000..91bee0ade1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/EncodeGeneratedPatterns_Rgba32_TestPattern100x100.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:548cc02ad75f76ccad5d5597d4558fe9acf2993ee04190acd363e613123cbdbb +size 3321 diff --git a/tests/Images/External/ReferenceOutput/GifEncoderTests/EncodeGeneratedPatterns_RgbaVector_TestPattern100x100.gif b/tests/Images/External/ReferenceOutput/GifEncoderTests/EncodeGeneratedPatterns_RgbaVector_TestPattern100x100.gif new file mode 100644 index 0000000000..91bee0ade1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/GifEncoderTests/EncodeGeneratedPatterns_RgbaVector_TestPattern100x100.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:548cc02ad75f76ccad5d5597d4558fe9acf2993ee04190acd363e613123cbdbb +size 3321 diff --git a/tests/Images/External/ReferenceOutput/HistogramEqualizationTests/Adaptive_SlidingWindow_15Tiles_WithClipping_Rgba32_AsianCarvingLowContrast.png b/tests/Images/External/ReferenceOutput/HistogramEqualizationTests/Adaptive_SlidingWindow_15Tiles_WithClipping_Rgba32_AsianCarvingLowContrast.png new file mode 100644 index 0000000000..d3856b03da --- /dev/null +++ b/tests/Images/External/ReferenceOutput/HistogramEqualizationTests/Adaptive_SlidingWindow_15Tiles_WithClipping_Rgba32_AsianCarvingLowContrast.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b58d63df4bc2912d8bfa352df9ef7fcd47d62cc01f5d9133480b0d99b9483fe +size 532096 diff --git a/tests/Images/External/ReferenceOutput/HistogramEqualizationTests/Adaptive_TileInterpolation_10Tiles_WithClipping_Rgba32_AsianCarvingLowContrast.png b/tests/Images/External/ReferenceOutput/HistogramEqualizationTests/Adaptive_TileInterpolation_10Tiles_WithClipping_Rgba32_AsianCarvingLowContrast.png new file mode 100644 index 0000000000..539c35a37e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/HistogramEqualizationTests/Adaptive_TileInterpolation_10Tiles_WithClipping_Rgba32_AsianCarvingLowContrast.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ccf3e04cc755ce7414a03eda4d298952a81b48871585d00672d62353fe3a433 +size 516071 diff --git a/tests/Images/External/ReferenceOutput/HistogramEqualizationTests/GlobalHistogramEqualization_CompareToReferenceOutput_Rgba32_640px-Unequalized_Hawkes_Bay_NZ.png b/tests/Images/External/ReferenceOutput/HistogramEqualizationTests/GlobalHistogramEqualization_CompareToReferenceOutput_Rgba32_640px-Unequalized_Hawkes_Bay_NZ.png new file mode 100644 index 0000000000..0824baff28 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/HistogramEqualizationTests/GlobalHistogramEqualization_CompareToReferenceOutput_Rgba32_640px-Unequalized_Hawkes_Bay_NZ.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0d6705ee5e9c596b093817777a6679bc243c84a1bf1a72fff7618d7695a9b7d0 +size 275596 diff --git a/tests/Images/External/ReferenceOutput/HistogramEqualizationTests/Issue984_Rgb24_TestPattern110x110.png b/tests/Images/External/ReferenceOutput/HistogramEqualizationTests/Issue984_Rgb24_TestPattern110x110.png new file mode 100644 index 0000000000..dbc67c93a9 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/HistogramEqualizationTests/Issue984_Rgb24_TestPattern110x110.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f950a1a637d215517201b160ad789824c97b898ac9743274746b338160b8e0fc +size 6720 diff --git a/tests/Images/External/ReferenceOutput/HistogramEqualizationTests/Issue984_Rgb24_TestPattern170x170.png b/tests/Images/External/ReferenceOutput/HistogramEqualizationTests/Issue984_Rgb24_TestPattern170x170.png new file mode 100644 index 0000000000..cfeb34ffae --- /dev/null +++ b/tests/Images/External/ReferenceOutput/HistogramEqualizationTests/Issue984_Rgb24_TestPattern170x170.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:74a86d0ed3dc5a92dc5bfd469ec94450bc035b993dbf05f3d96f25fdb6a8b86c +size 11288 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Calliphora.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Calliphora.png new file mode 100644 index 0000000000..07c29c0976 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Calliphora.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:362eddc5e06d672b4654bfe7a1ded995934a1c59719a3f909773b2e61931ffac +size 1332495 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue373-safari-canvas.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue373-safari-canvas.png new file mode 100644 index 0000000000..e06128be01 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue373-safari-canvas.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2de8725dca8c77f45f93c8c012cbda4c3565160e13d4f77fcc1979bd69c10390 +size 76659 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue394-MultiHuffmanBaseline-Speakers.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue394-MultiHuffmanBaseline-Speakers.png new file mode 100644 index 0000000000..1f38ec542f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue394-MultiHuffmanBaseline-Speakers.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b7a1e89adcd70f792d678786a177bac927a15d6065001cd76aab0bf3cc1b7b4c +size 1034853 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue694-Decode-Exif-OutOfRange.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue694-Decode-Exif-OutOfRange.png new file mode 100644 index 0000000000..3d5ac22d2e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue694-Decode-Exif-OutOfRange.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dfa9faa5717b28d933f74477f6c053cf1afd00ce7f4869b9ae567d706e67b9bb +size 244817 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue695-Invalid-EOI.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue695-Invalid-EOI.png new file mode 100644 index 0000000000..802fb841e2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue695-Invalid-EOI.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d6f13dba90f4d9aedf8539b4a48fadeb9cbf9372d54452c7c9e47eab4637676 +size 6375901 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue696-Resize-Exif-OutOfRange.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue696-Resize-Exif-OutOfRange.png new file mode 100644 index 0000000000..128f1f4b3d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue696-Resize-Exif-OutOfRange.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b648d5ed3514e9de994a79b97d888c1711b6d1051b348cf6ccaf22a52b624cc2 +size 5673967 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue721-InvalidAPP0.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue721-InvalidAPP0.png new file mode 100644 index 0000000000..0cda806d08 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue721-InvalidAPP0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e917465b52d246fd3023fed044b17492f50072e96ea938f992d887e3c941c030 +size 6036838 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue824-IndexOutOfRangeException-C.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue824-IndexOutOfRangeException-C.png new file mode 100644 index 0000000000..aa141e7889 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue824-IndexOutOfRangeException-C.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:297b875f926adc2aac6a0b182b4453b32414d1ea53b55336b459697b28fc5276 +size 788 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue825-ArgumentOutOfRangeException-B.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue825-ArgumentOutOfRangeException-B.png new file mode 100644 index 0000000000..bfdab76c0b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue825-ArgumentOutOfRangeException-B.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b9d86b65deadcfd8dd3c222f72b5c531e0856da6d109b4788f31b3d4964555af +size 1455 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue922-AccessViolationException.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue922-AccessViolationException.png new file mode 100644 index 0000000000..9951e66cbe --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_Issue922-AccessViolationException.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:64e363f3f18260376fd7da2f7bf74b9300b8c375b68fd8825081d87b934a2857 +size 3441980 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_MultiScanBaselineCMYK.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_MultiScanBaselineCMYK.png new file mode 100644 index 0000000000..349ff64858 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_MultiScanBaselineCMYK.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d9dbb00a4be909d4b7fd605f83f786ff85545da54272a256c100afd80d687e8f +size 93253 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_badeof.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_badeof.png new file mode 100644 index 0000000000..830a95bd74 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_badeof.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24f637742951c438da5acbae6a93545830ea4d0065031572a3bdd1c96be15cce +size 48990 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_badrst.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_badrst.png new file mode 100644 index 0000000000..0512251ab4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_badrst.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0501e53f97ddb4252e15073dc75f4129428befe5594a07297c21ae9f89f075b2 +size 316278 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_cmyk.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_cmyk.png new file mode 100644 index 0000000000..27c22ecc6d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_cmyk.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d2253c83151238056caef2f3bca8800108a84360b2ff21979e4ff37fdddd2232 +size 419852 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_issue-1076-invalid-subsampling.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_issue-1076-invalid-subsampling.png new file mode 100644 index 0000000000..0879d5b953 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_issue-1076-invalid-subsampling.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e251c0be31c3ea2b7f900c8476eddbd81503139d0d6c06c7d4366c5bf172ffeb +size 258065 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_issue750-exif-load.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_issue750-exif-load.png new file mode 100644 index 0000000000..15b869f3bf --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_issue750-exif-load.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67273b46424bd21197e69e8a73e17ffb8dd671e174834c42cf1432b806f14130 +size 66636 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_issue750-exif-tranform.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_issue750-exif-tranform.png new file mode 100644 index 0000000000..3ea627e53d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_issue750-exif-tranform.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e52a0b68d0284a652bd4aac9a6e1e0f4cae4f76aac2180e35a673451155f5847 +size 13344917 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_issue855-incorrect-colorspace.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_issue855-incorrect-colorspace.png new file mode 100644 index 0000000000..f1a05089a8 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_issue855-incorrect-colorspace.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e690980f6638edcadb159cfe70402b38214ed1376b6ee4219fc365c65c45b37 +size 527390 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_jpeg400jfif.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_jpeg400jfif.png new file mode 100644 index 0000000000..b2c3effdda --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_jpeg400jfif.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad22f28d20ea0ceda983a138b3bf9503ed836d779ed75a313f668329c910665e +size 168405 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_jpeg420small.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_jpeg420small.png new file mode 100644 index 0000000000..c57b00d0e3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_jpeg420small.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a76832570111a868ea6cb6e8287aae1976c575c94c63880c74346a4b5db5d305 +size 27007 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_jpeg444.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_jpeg444.png new file mode 100644 index 0000000000..e5ce7eb3d3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_jpeg444.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6543f546fac9d05ebdac7a534b0cc422f31bfd81067212a19cb3a52ad24560a8 +size 3978 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_testorig.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_testorig.png new file mode 100644 index 0000000000..830a95bd74 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_testorig.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24f637742951c438da5acbae6a93545830ea4d0065031572a3bdd1c96be15cce +size 48990 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_testorig12.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_testorig12.png new file mode 100644 index 0000000000..23f1941dcc --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_testorig12.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad57cf87eade9ee6663f575b358eafaa869a16b3b02d0fb00ca8c683422b85a0 +size 47601 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_turtle.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_turtle.png new file mode 100644 index 0000000000..e9c683acc6 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_turtle.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:046fe6eae57fb46183752b51301adff256054d2a760214dad3fb9f9151e2bcb8 +size 205475 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_ycck-subsample-1222.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_ycck-subsample-1222.png new file mode 100644 index 0000000000..f35c40ed89 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_ycck-subsample-1222.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a17478333c6ef0943aeb96faba1c0ea560995d0612564fe033b72b2949f4869f +size 66748 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_ycck.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_ycck.png new file mode 100644 index 0000000000..5f41fb5239 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeBaselineJpeg_ycck.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63f7105e9e2d0794b3f7225af2187a5717c12b806b68b33b98e08e0a0b1ffa79 +size 71051 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_BadEofProgressive.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_BadEofProgressive.png new file mode 100644 index 0000000000..2386ae49a2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_BadEofProgressive.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6e5d84fa88ac8b552c21c042f155801924240d764da365440d28eb8133950925 +size 568177 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_ExifUndefType.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_ExifUndefType.png new file mode 100644 index 0000000000..3de8b15578 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_ExifUndefType.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb636a9f304cdef713b823adc7424108b4d44fada294c48a366278c9b9e7b4b5 +size 20163 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Festzug.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Festzug.png new file mode 100644 index 0000000000..594751f848 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Festzug.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6784f3cb639e85faee358355863a225a21a852dc5b70f8dc864241308f326d36 +size 594836 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue159-MissingFF00-Progressive-Bedroom.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue159-MissingFF00-Progressive-Bedroom.png new file mode 100644 index 0000000000..c9fa410b35 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue159-MissingFF00-Progressive-Bedroom.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d0cdf9392235cd259939f27cf798b2686841763a546fb8d8e6d711903593cdc0 +size 2824881 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue159-MissingFF00-Progressive-Girl.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue159-MissingFF00-Progressive-Girl.png new file mode 100644 index 0000000000..62c7a365f9 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue159-MissingFF00-Progressive-Girl.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26946518298219a1849c427aceceac9a7044481c8f6779159c4a330f6d405383 +size 527325 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue178-BadCoeffsProgressive-Lemon.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue178-BadCoeffsProgressive-Lemon.png new file mode 100644 index 0000000000..004a8c8d27 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue178-BadCoeffsProgressive-Lemon.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b0bf7820856841bc4de54fb9c28cdea73f0144f22c5b60c176a0d280f7a69087 +size 685062 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue385-BadZigZag-Progressive.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue385-BadZigZag-Progressive.png new file mode 100644 index 0000000000..695c405a1b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue385-BadZigZag-Progressive.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3b9f196e2068b19eee76795c2fa63b8693877e1a0c4393079553659dd03b3f8f +size 2985759 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue517-No-EOI-Progressive.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue517-No-EOI-Progressive.png new file mode 100644 index 0000000000..6def638319 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue517-No-EOI-Progressive.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9837490352431cd0d9cecd592af896f1c77015c06d78d3ec24ba8f288d686dcb +size 5101873 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue518-Bad-RST-Progressive.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue518-Bad-RST-Progressive.png new file mode 100644 index 0000000000..36e5f079a0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue518-Bad-RST-Progressive.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27aa686906175da3c2c757435c75687ddb1f07a4eb461a924e386cc967976611 +size 17003842 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue624-DhtHasWrongLength-Progressive-N.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue624-DhtHasWrongLength-Progressive-N.png new file mode 100644 index 0000000000..fd7319dc3d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue624-DhtHasWrongLength-Progressive-N.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d6590f717fa3838ef199ae462b36b1c98e7077211a3cb3be9b1c298a9bf99972 +size 118171 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue723-Ordered-Interleaved-Progressive-A.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue723-Ordered-Interleaved-Progressive-A.png new file mode 100644 index 0000000000..2b7975ea61 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue723-Ordered-Interleaved-Progressive-A.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f5bd28773fc18b0d01b2216284a613438d668d583e7b8c60da3d8ac24b4b465 +size 141528 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue723-Ordered-Interleaved-Progressive-B.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue723-Ordered-Interleaved-Progressive-B.png new file mode 100644 index 0000000000..4ed2771fd8 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue723-Ordered-Interleaved-Progressive-B.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b430c535d98abd54fd9efc03808efc9efed40b8a39ef1d09928835cbf8c2c315 +size 166935 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue723-Ordered-Interleaved-Progressive-C.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue723-Ordered-Interleaved-Progressive-C.png new file mode 100644 index 0000000000..a790a57730 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_Issue723-Ordered-Interleaved-Progressive-C.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:848e193354962b70cb6b1f330d56a509f6edc9a4ac20f2b6e1462fde7e995e3d +size 112013 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_fb.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_fb.png new file mode 100644 index 0000000000..07a7c3573e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_fb.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2935d3dc66eec334eec65c1ed9fbb04046404a9c28bed413ac635878e63ea6cf +size 114688 diff --git a/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_progress.png b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_progress.png new file mode 100644 index 0000000000..8241c36ac3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/JpegDecoderTests/DecodeProgressiveJpeg_progress.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b48730a7a149e13dd87a24e62c0704895b08a5ed1f8ea48a6a6a7248450750d +size 301416 diff --git a/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyColor_ducky_Blue.png b/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyColor_ducky_Blue.png new file mode 100644 index 0000000000..f02846c752 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyColor_ducky_Blue.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5914ffa2b1d53ceb89c41f367636948240820d4eaebc390709f327da58ab826b +size 31035 diff --git a/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyColor_ducky_White.png b/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyColor_ducky_White.png new file mode 100644 index 0000000000..f618871b8a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyColor_ducky_White.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a69316f411f7e0b93685a1be5edbf7d7a958897bcb4cd489a2e78bbb70df31e0 +size 29572 diff --git a/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyColor_splash_Blue.png b/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyColor_splash_Blue.png new file mode 100644 index 0000000000..1d98663573 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyColor_splash_Blue.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:96e8fb3433f941d09b943907f28a4f7c5dbc19adec4cfb2574d19b2df6a973f3 +size 177065 diff --git a/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyColor_splash_White.png b/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyColor_splash_White.png new file mode 100644 index 0000000000..5842d77301 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyColor_splash_White.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c074d00bd13915db29be2cc661d55abd98c778e5dad4db75a3a0795684b26d4c +size 173089 diff --git a/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyRadius_ducky.png b/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyRadius_ducky.png new file mode 100644 index 0000000000..46775b04d3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyRadius_ducky.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3ab23f50a7388dd037cff407d75a058b1ec5e1871dba9adf3223985272e8baa +size 28251 diff --git a/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyRadius_splash.png b/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyRadius_splash.png new file mode 100644 index 0000000000..2fb42d1b27 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Overlays/GlowTest/FullImage_ApplyRadius_splash.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00107744d9d89c7f54c7b7c08263870a37e96ecea64d675db4bd40758cffa35b +size 185085 diff --git a/tests/Images/External/ReferenceOutput/Overlays/GlowTest/InBox_Rgba32_ducky.png b/tests/Images/External/ReferenceOutput/Overlays/GlowTest/InBox_Rgba32_ducky.png new file mode 100644 index 0000000000..75d006aa55 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Overlays/GlowTest/InBox_Rgba32_ducky.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:84fb55bd8a5f2e9ac5c9ba4d4ed91ed956e294f7d995e2e151d6e1bb775e18ea +size 28196 diff --git a/tests/Images/External/ReferenceOutput/Overlays/GlowTest/InBox_Rgba32_splash.png b/tests/Images/External/ReferenceOutput/Overlays/GlowTest/InBox_Rgba32_splash.png new file mode 100644 index 0000000000..f109dbbddf --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Overlays/GlowTest/InBox_Rgba32_splash.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eeb82d5bd94efec03cb8abd526fdd342be28a128cf27c871b9b2c0de5499db38 +size 184811 diff --git a/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyColor_ducky_Blue.png b/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyColor_ducky_Blue.png new file mode 100644 index 0000000000..b86fcccead --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyColor_ducky_Blue.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:858101dc090f13e4505ae122264796c8f7f25c78af10f2e75597b69bd66dc601 +size 32548 diff --git a/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyColor_ducky_White.png b/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyColor_ducky_White.png new file mode 100644 index 0000000000..f6bd71fd19 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyColor_ducky_White.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2d937c56e560417375497a9cad9c975c6f26aac6288b660df0f289c527eba5f7 +size 31077 diff --git a/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyColor_splash_Blue.png b/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyColor_splash_Blue.png new file mode 100644 index 0000000000..ebf50e3737 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyColor_splash_Blue.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e30e720280d640107ccb16774b9474ea3e1bb51075168a4909695fbc551b4e48 +size 185595 diff --git a/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyColor_splash_White.png b/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyColor_splash_White.png new file mode 100644 index 0000000000..3c6eb7486c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyColor_splash_White.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28300b5e383a76529008c347c25c76342a0ef44920a7c5b609c228f44293d6a8 +size 179871 diff --git a/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyRadius_ducky.png b/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyRadius_ducky.png new file mode 100644 index 0000000000..bc47cb5dee --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyRadius_ducky.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2954849386fc73a3033b363e078a0bcc5e19578858e3842000a47586d771b89c +size 17164 diff --git a/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyRadius_splash.png b/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyRadius_splash.png new file mode 100644 index 0000000000..72a012bac3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/FullImage_ApplyRadius_splash.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a4b23691b30785517aa151c8932d95e3b9876744a611c14cfac31131809a6894 +size 98590 diff --git a/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/InBox_Rgba32_ducky.png b/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/InBox_Rgba32_ducky.png new file mode 100644 index 0000000000..7e56e614f6 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/InBox_Rgba32_ducky.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7eef77407d0d941c2cafe5de0e3dccdf1a25c9e0d2533a30cb9e36a365a5bff2 +size 27057 diff --git a/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/InBox_Rgba32_splash.png b/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/InBox_Rgba32_splash.png new file mode 100644 index 0000000000..37f431c5e6 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Overlays/VignetteTest/InBox_Rgba32_splash.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:570cdf156974aa10f8b7148cfc8bb0a180afff6388f372a5b6817f8ec1e41be1 +size 180694 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Bgra32_TestPattern24x24_Grayscale.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Bgra32_TestPattern24x24_Grayscale.png new file mode 100644 index 0000000000..33493c48e7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Bgra32_TestPattern24x24_Grayscale.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff65220be22a707edb8c0a5ad8b9fda3ed33759602854000d31d324504e6ca47 +size 205 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Bgra32_TestPattern24x24_GrayscaleWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Bgra32_TestPattern24x24_GrayscaleWithAlpha.png new file mode 100644 index 0000000000..e100807c74 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Bgra32_TestPattern24x24_GrayscaleWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8eeec299c4781b373d6d30ca542ee6bdf53a6188e3b32c2f19ab007fab2de050 +size 258 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Bgra32_TestPattern24x24_Rgb.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Bgra32_TestPattern24x24_Rgb.png new file mode 100644 index 0000000000..fbef0353ed --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Bgra32_TestPattern24x24_Rgb.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7013153c9b6f6b75d5272b24da147ac20b1a8c47b32d7e33447c370cc9d573f8 +size 320 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Bgra32_TestPattern24x24_RgbWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Bgra32_TestPattern24x24_RgbWithAlpha.png new file mode 100644 index 0000000000..5610623bb1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Bgra32_TestPattern24x24_RgbWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f97fcfd003c28ad8347541a5660b6f4cef63735473f167bda72a3f1e89fb51e +size 346 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgb24_TestPattern24x24_Grayscale.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgb24_TestPattern24x24_Grayscale.png new file mode 100644 index 0000000000..33493c48e7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgb24_TestPattern24x24_Grayscale.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff65220be22a707edb8c0a5ad8b9fda3ed33759602854000d31d324504e6ca47 +size 205 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgb24_TestPattern24x24_GrayscaleWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgb24_TestPattern24x24_GrayscaleWithAlpha.png new file mode 100644 index 0000000000..33493c48e7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgb24_TestPattern24x24_GrayscaleWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff65220be22a707edb8c0a5ad8b9fda3ed33759602854000d31d324504e6ca47 +size 205 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgb24_TestPattern24x24_Rgb.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgb24_TestPattern24x24_Rgb.png new file mode 100644 index 0000000000..fbef0353ed --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgb24_TestPattern24x24_Rgb.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7013153c9b6f6b75d5272b24da147ac20b1a8c47b32d7e33447c370cc9d573f8 +size 320 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgb24_TestPattern24x24_RgbWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgb24_TestPattern24x24_RgbWithAlpha.png new file mode 100644 index 0000000000..9b9d13f595 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgb24_TestPattern24x24_RgbWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:44347ef52a157829f9f3ae12847102d9114529f62820d24a5fcf503aaeb40f9e +size 347 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgba32_TestPattern24x24_Grayscale.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgba32_TestPattern24x24_Grayscale.png new file mode 100644 index 0000000000..33493c48e7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgba32_TestPattern24x24_Grayscale.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff65220be22a707edb8c0a5ad8b9fda3ed33759602854000d31d324504e6ca47 +size 205 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgba32_TestPattern24x24_GrayscaleWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgba32_TestPattern24x24_GrayscaleWithAlpha.png new file mode 100644 index 0000000000..e100807c74 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgba32_TestPattern24x24_GrayscaleWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8eeec299c4781b373d6d30ca542ee6bdf53a6188e3b32c2f19ab007fab2de050 +size 258 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgba32_TestPattern24x24_Rgb.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgba32_TestPattern24x24_Rgb.png new file mode 100644 index 0000000000..fbef0353ed --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgba32_TestPattern24x24_Rgb.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7013153c9b6f6b75d5272b24da147ac20b1a8c47b32d7e33447c370cc9d573f8 +size 320 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgba32_TestPattern24x24_RgbWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgba32_TestPattern24x24_RgbWithAlpha.png new file mode 100644 index 0000000000..5610623bb1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/IsNotBoundToSinglePixelType_Rgba32_TestPattern24x24_RgbWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f97fcfd003c28ad8347541a5660b6f4cef63735473f167bda72a3f1e89fb51e +size 346 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/PaletteColorType_WuQuantizer_palette-8bpp__PaletteSize-100.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/PaletteColorType_WuQuantizer_palette-8bpp__PaletteSize-100.png new file mode 100644 index 0000000000..e7fe7aafc6 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/PaletteColorType_WuQuantizer_palette-8bpp__PaletteSize-100.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5dc9b81363a92aed7d9cd9764e025a139eb050aef95bfd65c6c5f3ad21d77319 +size 18703 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/PaletteColorType_WuQuantizer_palette-8bpp__PaletteSize-120.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/PaletteColorType_WuQuantizer_palette-8bpp__PaletteSize-120.png new file mode 100644 index 0000000000..76a9fb4ac4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/PaletteColorType_WuQuantizer_palette-8bpp__PaletteSize-120.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:81d4c0d7ef41bf871a9af3c9822bab24abc93635e8a3a7690ec382e4d03557e6 +size 13802 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/PaletteColorType_WuQuantizer_palette-8bpp__PaletteSize-230.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/PaletteColorType_WuQuantizer_palette-8bpp__PaletteSize-230.png new file mode 100644 index 0000000000..7e4c3fd5b9 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/PaletteColorType_WuQuantizer_palette-8bpp__PaletteSize-230.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f4537406e7548f68291add108fb6d5eda8b673c1e0b66000e02a1a341cb293e5 +size 8970 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/PaletteColorType_WuQuantizer_palette-8bpp__PaletteSize-80.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/PaletteColorType_WuQuantizer_palette-8bpp__PaletteSize-80.png new file mode 100644 index 0000000000..e7965815be --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/PaletteColorType_WuQuantizer_palette-8bpp__PaletteSize-80.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da02e2b7e90609fec94ea37266c1d8f997bb6c09e7f7b5e1b16cab82f76616c9 +size 26729 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C1.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C1.png new file mode 100644 index 0000000000..91319bea65 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:951670a3539073b7ebf9266e520b0de9fec52e7624e744e15bef6a363b2fae00 +size 381 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C2.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C2.png new file mode 100644 index 0000000000..91319bea65 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:951670a3539073b7ebf9266e520b0de9fec52e7624e744e15bef6a363b2fae00 +size 381 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C3.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C3.png new file mode 100644 index 0000000000..20c3fc5860 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:605bbced9701ebd478d4a3652e202b9aea994dac8c73bba01c37ed9303d44bda +size 381 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C4.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C4.png new file mode 100644 index 0000000000..20c3fc5860 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:605bbced9701ebd478d4a3652e202b9aea994dac8c73bba01c37ed9303d44bda +size 381 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C5.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C5.png new file mode 100644 index 0000000000..f44da65721 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:55eaa24ca3071c1d8fa3386fe89b7f3312b83aa9e162c7bafbd775c41a9d367c +size 381 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C6.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C6.png new file mode 100644 index 0000000000..5610623bb1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C6.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f97fcfd003c28ad8347541a5660b6f4cef63735473f167bda72a3f1e89fb51e +size 346 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C7.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C7.png new file mode 100644 index 0000000000..68fe313757 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C7.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:482f180ba69acf181ee426fbc0772c150f5789c22ca5436a668427c5397818ba +size 346 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C8.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C8.png new file mode 100644 index 0000000000..68fe313757 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:482f180ba69acf181ee426fbc0772c150f5789c22ca5436a668427c5397818ba +size 346 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C9.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C9.png new file mode 100644 index 0000000000..68fe313757 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllCompressionLevels_TestPattern24x24__C9.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:482f180ba69acf181ee426fbc0772c150f5789c22ca5436a668427c5397818ba +size 346 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_Adaptive.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_Adaptive.png new file mode 100644 index 0000000000..71569be348 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_Adaptive.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2bc648e6b717cbf9e0d6d59508ce40d10545e024e1822c15e71363b687a17774 +size 318 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_Average.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_Average.png new file mode 100644 index 0000000000..f487d4f9b3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_Average.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b5e1803065a679cfd06da7360dcc3c5593ae9a299bc348dad5c6fbe2eeb128e4 +size 453 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_None.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_None.png new file mode 100644 index 0000000000..bbdaae2002 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_None.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e096b4d0909f7945b9a1cb9469487a0878232ae181df465f4e08bf27194ec7d4 +size 738 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_Paeth.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_Paeth.png new file mode 100644 index 0000000000..71569be348 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_Paeth.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2bc648e6b717cbf9e0d6d59508ce40d10545e024e1822c15e71363b687a17774 +size 318 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_Sub.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_Sub.png new file mode 100644 index 0000000000..ae93d84ec7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_Sub.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f8db52999e860c92622d87bccded2be2270f27f57e66e8c184c655445aa319df +size 293 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_Up.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_Up.png new file mode 100644 index 0000000000..8bb95c5fc1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithAllFilterMethods_TestPattern24x24_Up.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:afc1a1a3835b46b3814b664edf65a3b8d9b32706d58d418a7cadf3e125fa1d87 +size 311 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_Solid1x1_(255,100,50,255)_Grayscale.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_Solid1x1_(255,100,50,255)_Grayscale.png new file mode 100644 index 0000000000..143a38082b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_Solid1x1_(255,100,50,255)_Grayscale.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea65e8b135b4720fbc68c6a8402909b97b65c948cc911a4ad7c6581483fd4be6 +size 67 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_Solid1x1_(255,100,50,255)_GrayscaleWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_Solid1x1_(255,100,50,255)_GrayscaleWithAlpha.png new file mode 100644 index 0000000000..143a38082b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_Solid1x1_(255,100,50,255)_GrayscaleWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea65e8b135b4720fbc68c6a8402909b97b65c948cc911a4ad7c6581483fd4be6 +size 67 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_Solid1x1_(255,100,50,255)_Rgb.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_Solid1x1_(255,100,50,255)_Rgb.png new file mode 100644 index 0000000000..08b85c0d52 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_Solid1x1_(255,100,50,255)_Rgb.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:db7d8576f90d9da55c4fdcd119e5533c6e1bb3aef27135d9bcadbf28458fdd71 +size 90 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_Solid1x1_(255,100,50,255)_RgbWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_Solid1x1_(255,100,50,255)_RgbWithAlpha.png new file mode 100644 index 0000000000..378305b9c8 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_Solid1x1_(255,100,50,255)_RgbWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e1f6c6a4cd27e3c462d60450c929fdcb93bb2f56a419aa7e1c79662e834b8dc +size 90 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern47x8_Grayscale.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern47x8_Grayscale.png new file mode 100644 index 0000000000..2d1bb19416 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern47x8_Grayscale.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89e0c828c17a222455f5e8921576dd5d957ed5fc1a77f225b214abec30f1a727 +size 166 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern47x8_GrayscaleWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern47x8_GrayscaleWithAlpha.png new file mode 100644 index 0000000000..6433e6325d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern47x8_GrayscaleWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:29bb576d3b8576b4dbaa51f27e0d42487e4337830768b150c87bf3511656af12 +size 204 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern47x8_Rgb.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern47x8_Rgb.png new file mode 100644 index 0000000000..db5b99f134 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern47x8_Rgb.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c66cad0e2a813f622e5cf466eb379e9e916fb412b38bb0cfb8d53a1520ce6f23 +size 218 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern47x8_RgbWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern47x8_RgbWithAlpha.png new file mode 100644 index 0000000000..a1a2fddc91 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern47x8_RgbWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b9a33310796ab7419e3e6a6a7db16c529263df8c9e36ade0a799faa0889351d5 +size 256 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern48x24_Grayscale.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern48x24_Grayscale.png new file mode 100644 index 0000000000..7d3d314c38 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern48x24_Grayscale.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a04779aebceb5ba41f0819f02c9b687a0242b3298f669cfa386c41ff8dcda6a +size 286 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern48x24_GrayscaleWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern48x24_GrayscaleWithAlpha.png new file mode 100644 index 0000000000..3ddf98642f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern48x24_GrayscaleWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:829f520aa0eb26b1332337e7a75999533682732f272a9e59fb0b02f35cb87065 +size 354 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern48x24_Rgb.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern48x24_Rgb.png new file mode 100644 index 0000000000..9af4cb10c5 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern48x24_Rgb.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8d3e9cabfdfee0f7c630542a7459b26ca5f156dceefd8614e2f58ef1ed46465d +size 277 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern48x24_RgbWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern48x24_RgbWithAlpha.png new file mode 100644 index 0000000000..fcc46af00b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern48x24_RgbWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8e6cd212359a6c5e8c14b8e9e9b928be3c58c8ddd725d649818d8eecf2c5f8c1 +size 343 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern49x7_Grayscale.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern49x7_Grayscale.png new file mode 100644 index 0000000000..e3fe422dc8 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern49x7_Grayscale.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6255fe1f072b6678ad0d84ce96484511e909ad46e5322a32df50d88085792a63 +size 148 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern49x7_GrayscaleWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern49x7_GrayscaleWithAlpha.png new file mode 100644 index 0000000000..8b1bbf2f21 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern49x7_GrayscaleWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26b4688239ef7074e342b1c4272fe8375cf86851a43f25256db7fb555e8cea42 +size 178 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern49x7_Rgb.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern49x7_Rgb.png new file mode 100644 index 0000000000..9fef14be81 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern49x7_Rgb.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6f8a1ebadedeea9fbbfca336e74b94c20146c153e4a19dd40aaa8fc86ecfbb5c +size 272 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern49x7_RgbWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern49x7_RgbWithAlpha.png new file mode 100644 index 0000000000..1003bc2dd7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern49x7_RgbWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa1811959cf030f31f1312b9f4d4ed0d2484c966127dab49f5fcc6f640fa6b87 +size 276 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern7x5_Grayscale.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern7x5_Grayscale.png new file mode 100644 index 0000000000..ecfd8cc93b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern7x5_Grayscale.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:57ec7e645f7b84b2d80c417261c5989b8ede091b546bf971ca9c44abb8c00f83 +size 99 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern7x5_GrayscaleWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern7x5_GrayscaleWithAlpha.png new file mode 100644 index 0000000000..3607474329 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern7x5_GrayscaleWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c388b21ae6dd5d75c13ce032694356dc025f0081081585babef87e72f228f591 +size 114 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern7x5_Rgb.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern7x5_Rgb.png new file mode 100644 index 0000000000..293cd71ce3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern7x5_Rgb.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b375a3912dac12f68f85cf1b560def2cc5c4ef6b829709a17bdfb2e635b13c87 +size 139 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern7x5_RgbWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern7x5_RgbWithAlpha.png new file mode 100644 index 0000000000..1668deea69 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_TestPattern7x5_RgbWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:45ebbfc1451a278ae552ba976bdecf3d3171531926006c4a8aa2a33bebf027f9 +size 150 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_palette-8bpp_Grayscale.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_palette-8bpp_Grayscale.png new file mode 100644 index 0000000000..93a7c53fbd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_palette-8bpp_Grayscale.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3908f71273e4b7d1b9a44c0842f6cb24cbe6300a52d0adba3f10a78d2ebdcda2 +size 8371 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_palette-8bpp_GrayscaleWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_palette-8bpp_GrayscaleWithAlpha.png new file mode 100644 index 0000000000..93a7c53fbd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_palette-8bpp_GrayscaleWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3908f71273e4b7d1b9a44c0842f6cb24cbe6300a52d0adba3f10a78d2ebdcda2 +size 8371 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_palette-8bpp_Rgb.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_palette-8bpp_Rgb.png new file mode 100644 index 0000000000..4a1873e798 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_palette-8bpp_Rgb.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9277365e29296f63aeab22ada1de9a13a88111b65319ea7976dee39ba5d4e995 +size 8971 diff --git a/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_palette-8bpp_RgbWithAlpha.png b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_palette-8bpp_RgbWithAlpha.png new file mode 100644 index 0000000000..4a1873e798 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PngEncoderTests/WorksWithDifferentSizes_palette-8bpp_RgbWithAlpha.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9277365e29296f63aeab22ada1de9a13a88111b65319ea7976dee39ba5d4e995 +size 8971 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Atop.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Atop.png new file mode 100644 index 0000000000..5a4f8d34a6 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Atop.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f12f5c8259e679d9f4acf5c11232f9292f6f40543e2371aecd8fb43ec071fb58 +size 2434 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Clear.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Clear.png new file mode 100644 index 0000000000..082c6e00a0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Clear.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c65cffc9f97689cf51756007ac1e17e6efe2ca25dbd0e0e753a9ad481c56cd17 +size 154 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Dest.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Dest.png new file mode 100644 index 0000000000..8dff6ab28c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Dest.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3cb54316e7a74eef0f7bf22bd1e9ced22c7760cf2f61519f221597a37f212031 +size 1777 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_DestAtop.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_DestAtop.png new file mode 100644 index 0000000000..30b9671f06 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_DestAtop.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88f6568316c223e209c5270625621917f856fdbae0975569bc02c722434002d9 +size 2812 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_DestIn.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_DestIn.png new file mode 100644 index 0000000000..5a55e65a84 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_DestIn.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dcbb9056a5c0c9accf074076b17ea92b842d897fdfec7220fa198656efdd6f36 +size 1745 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_DestOut.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_DestOut.png new file mode 100644 index 0000000000..bd50175d7c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_DestOut.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2952981bde801d566e5b7503722907b2f4318b71c327276735e929d9f598ffc0 +size 1707 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_DestOver.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_DestOver.png new file mode 100644 index 0000000000..64e4ec606c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_DestOver.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd75a792f7e72f4831a97297452eef3567fded1d319ddbe10bd69653f8b42329 +size 3079 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_In.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_In.png new file mode 100644 index 0000000000..265985c3f2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_In.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:de9b2fbf7dce7980ade102386aa070c48a31ee32807a13a28b4e172c0fc26a16 +size 1561 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Out.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Out.png new file mode 100644 index 0000000000..8cdaf949d2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Out.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3effcb28b17363a5ee26d38d55f7354e1e9499824863cb389a1b002c18ad3644 +size 2099 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Over.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Over.png new file mode 100644 index 0000000000..a309b2424c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Over.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f4522f90e489c166a929f224fbad1dfdd57031221c83a57ef4c8779c69ed086e +size 3136 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Src.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Src.png new file mode 100644 index 0000000000..1a2dbba274 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Src.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e85a216b2d522d959042dd46a9ff4185868771f6666ff75a06db4dd3aa86c3ae +size 2238 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Xor.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Xor.png new file mode 100644 index 0000000000..9c0854dfd7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/PorterDuffOutputIsCorrect_Rgba32_pd-dest_Xor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5d6a1569a5c14a4513c5a5c4fe60bfe26daede6575575cdfdb236e8d56786e7c +size 3347 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-Clear.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-Clear.png new file mode 100644 index 0000000000..23be844ee9 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-Clear.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1cb3f8b6ed1e17ecc1d21d0714aaedd3a012288357ca356b023222eb37d09be6 +size 456 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-Dest.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-Dest.png new file mode 100644 index 0000000000..7f498531dd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-Dest.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ffd19acb8847faa6ca622e91b1826e5097d3f9dc4c3ad1593a4399decbb5b274 +size 1740 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-DestAtop.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-DestAtop.png new file mode 100644 index 0000000000..2746c97b1e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-DestAtop.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fc703ef5018d6863161ef2f54e146f4890fccefc98c46e3fa18300074250427a +size 2009 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-DestIn.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-DestIn.png new file mode 100644 index 0000000000..cf15ddf862 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-DestIn.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a0e1dd82691de4bd1af5943301b3755108bca807ccf0ca4c8489036b30a00260 +size 1307 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-DestOut.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-DestOut.png new file mode 100644 index 0000000000..9271b52147 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-DestOut.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f6ed02bad85f4778abc4547f65562a206067d1c09d61fc37c951e0ce59a1d63e +size 1693 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-DestOver.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-DestOver.png new file mode 100644 index 0000000000..b780257900 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-DestOver.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:78a821911725368ca95d050ed3c8e2045f0adff6222cd737f70e071f3166c3b7 +size 2417 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-Src.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-Src.png new file mode 100644 index 0000000000..14c2f7cedd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-Src.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:376b1545be400ae42208747f703fd6ef5bd9e89e602d349da4951d4c64ca40af +size 1471 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-SrcAtop.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-SrcAtop.png new file mode 100644 index 0000000000..1bc9ef0cf7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-SrcAtop.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed89722596249864322f0da8e2361f40c2775a430231398d115c379cadb5de99 +size 2181 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-SrcIn.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-SrcIn.png new file mode 100644 index 0000000000..1a7e8f52dd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-SrcIn.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2bccd7d93e0ae0d7ca8e1b1347a6972e25064dc38386d6238d259daa77387095 +size 1300 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-SrcOut.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-SrcOut.png new file mode 100644 index 0000000000..b4bcbee87b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-SrcOut.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:843ed090a0afb6b862482ed8594474ab5f2e13a33958eade4e7fa6e8870d8fad +size 1499 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-SrcOver.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-SrcOver.png new file mode 100644 index 0000000000..8a3d8659b1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-SrcOver.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:251ca7123e4fdd709b10c8aa4422ddba7875d5b15a0eb4d66781e3a1a0861f2b +size 2332 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-Xor.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-Xor.png new file mode 100644 index 0000000000..9b9cf2342f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_100_100-Xor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:db29f362784772d0402b945bdfad332add380aa882c00a7535527322ebc18761 +size 2530 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-Clear.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-Clear.png new file mode 100644 index 0000000000..23be844ee9 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-Clear.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1cb3f8b6ed1e17ecc1d21d0714aaedd3a012288357ca356b023222eb37d09be6 +size 456 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-Dest.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-Dest.png new file mode 100644 index 0000000000..ae617e5da9 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-Dest.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94fed8daf3953f72d536dddec211b1157d8cd12df212841076456ea31f06027d +size 1447 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-DestAtop.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-DestAtop.png new file mode 100644 index 0000000000..f8e1c2bc65 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-DestAtop.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89e01c6d30a98a40db4200369d514dc0065df0ab742ff824125418c0dc7c665e +size 1806 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-DestIn.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-DestIn.png new file mode 100644 index 0000000000..ac1deb760c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-DestIn.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:61f4222b4fc162283b5098f3e649368054bacc26121592192b051d76704e8aac +size 1066 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-DestOut.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-DestOut.png new file mode 100644 index 0000000000..7bc47ea8db --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-DestOut.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2fa6f68dc494a820c375096a011b78415bea150f2e0f3eae3fd3b086a1268b2d +size 1583 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-DestOver.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-DestOver.png new file mode 100644 index 0000000000..2bebae164f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-DestOver.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2a8701b685dc00f3cb08c50f4e935e391aa9eb8738acf88c45a6ebf08fd5b20f +size 2619 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-Src.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-Src.png new file mode 100644 index 0000000000..8a000e3574 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-Src.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c23b99156cd398d59102abcf62b401b82b64ab5536ff704437f89ab9eb976989 +size 1333 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-SrcAtop.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-SrcAtop.png new file mode 100644 index 0000000000..7139eb4430 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-SrcAtop.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:48d766dd70abd95ec060db03ccd8fab6b5337ad19ad1031ca39064b345538ded +size 1871 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-SrcIn.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-SrcIn.png new file mode 100644 index 0000000000..681a51a9c9 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-SrcIn.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:093e8b875a8a45335f85eea52574cf6c135e8f20359eff5d1abaa86f110ae827 +size 1053 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-SrcOut.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-SrcOut.png new file mode 100644 index 0000000000..8aaf38b1c4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-SrcOut.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ebacf629fed0f3f5ea3b1dd8a10d3db0ddf7dd27dca13f9d55a9620b3eb16dc4 +size 1543 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-SrcOver.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-SrcOver.png new file mode 100644 index 0000000000..df0f6e2ba8 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-SrcOver.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ab36f490f9fc1c75521f87fadcc3ede9a8983ce9ca01405ac59175e29cd0fbaa +size 2565 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-Xor.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-Xor.png new file mode 100644 index 0000000000..1a76e2ac45 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/AlphaComposition_50_50-Xor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:595af24828244ee03b365ad137fb77f57f7f40c45c509dd684c0f9d58cec8b30 +size 2482 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Add.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Add.png new file mode 100644 index 0000000000..9e20d1cc41 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Add.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3b1646fff1b16380ec87af89c7f1f5ec0245a420af3a1cdfac026eb0ee7ccb0 +size 2486 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Darken.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Darken.png new file mode 100644 index 0000000000..2dbaec1794 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Darken.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75d09a597c04076496f76035337cb6f0701df985e5879cb781abffa66ae7697c +size 2484 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-HardLight.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-HardLight.png new file mode 100644 index 0000000000..8a3d8659b1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-HardLight.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:251ca7123e4fdd709b10c8aa4422ddba7875d5b15a0eb4d66781e3a1a0861f2b +size 2332 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Lighten.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Lighten.png new file mode 100644 index 0000000000..9e20d1cc41 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Lighten.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3b1646fff1b16380ec87af89c7f1f5ec0245a420af3a1cdfac026eb0ee7ccb0 +size 2486 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Multiply.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Multiply.png new file mode 100644 index 0000000000..2dbaec1794 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Multiply.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75d09a597c04076496f76035337cb6f0701df985e5879cb781abffa66ae7697c +size 2484 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Normal.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Normal.png new file mode 100644 index 0000000000..8a3d8659b1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Normal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:251ca7123e4fdd709b10c8aa4422ddba7875d5b15a0eb4d66781e3a1a0861f2b +size 2332 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Overlay.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Overlay.png new file mode 100644 index 0000000000..b780257900 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Overlay.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:78a821911725368ca95d050ed3c8e2045f0adff6222cd737f70e071f3166c3b7 +size 2417 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Screen.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Screen.png new file mode 100644 index 0000000000..9e20d1cc41 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Screen.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b3b1646fff1b16380ec87af89c7f1f5ec0245a420af3a1cdfac026eb0ee7ccb0 +size 2486 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Subtract.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Subtract.png new file mode 100644 index 0000000000..b780257900 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_100_100-Subtract.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:78a821911725368ca95d050ed3c8e2045f0adff6222cd737f70e071f3166c3b7 +size 2417 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Add.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Add.png new file mode 100644 index 0000000000..d19be3dc2b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Add.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1280694140e81583767dbaad4117a9166bc1dd3601be12556aa0e8fd86f357ca +size 2647 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Darken.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Darken.png new file mode 100644 index 0000000000..15ef323525 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Darken.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75d7e9cfc9979dfdd59f77a9ad91b9469baa13a003de53ae6ff09637b8e2a0ba +size 2639 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-HardLight.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-HardLight.png new file mode 100644 index 0000000000..df0f6e2ba8 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-HardLight.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ab36f490f9fc1c75521f87fadcc3ede9a8983ce9ca01405ac59175e29cd0fbaa +size 2565 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Lighten.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Lighten.png new file mode 100644 index 0000000000..d19be3dc2b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Lighten.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1280694140e81583767dbaad4117a9166bc1dd3601be12556aa0e8fd86f357ca +size 2647 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Multiply.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Multiply.png new file mode 100644 index 0000000000..15ef323525 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Multiply.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75d7e9cfc9979dfdd59f77a9ad91b9469baa13a003de53ae6ff09637b8e2a0ba +size 2639 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Normal.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Normal.png new file mode 100644 index 0000000000..df0f6e2ba8 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Normal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ab36f490f9fc1c75521f87fadcc3ede9a8983ce9ca01405ac59175e29cd0fbaa +size 2565 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Overlay.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Overlay.png new file mode 100644 index 0000000000..2bebae164f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Overlay.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2a8701b685dc00f3cb08c50f4e935e391aa9eb8738acf88c45a6ebf08fd5b20f +size 2619 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Screen.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Screen.png new file mode 100644 index 0000000000..d19be3dc2b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Screen.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1280694140e81583767dbaad4117a9166bc1dd3601be12556aa0e8fd86f357ca +size 2647 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Subtract.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Subtract.png new file mode 100644 index 0000000000..2bebae164f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/ColorBlending_50_50-Subtract.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2a8701b685dc00f3cb08c50f4e935e391aa9eb8738acf88c45a6ebf08fd5b20f +size 2619 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/DEST.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/DEST.png new file mode 100644 index 0000000000..780852adec --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/DEST.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b8c04ef21e91dfa1f6d771a47e62a2e73a996bcfb2c9b1994bbda7e76f2c137 +size 1327 diff --git a/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/SRC.png b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/SRC.png new file mode 100644 index 0000000000..6436ac8153 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/PorterDuffCompositorTests/Set1/SRC.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:49e31bff806fcc4beca659a388f76faeac82ab6e52c43153c3de05c9553571d2 +size 1290 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/PerspectiveTransformMatchesCSS_Rgba32_Solid290x154_(0,0,255,255).png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/PerspectiveTransformMatchesCSS_Rgba32_Solid290x154_(0,0,255,255).png new file mode 100644 index 0000000000..e7ed4a95f5 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/PerspectiveTransformMatchesCSS_Rgba32_Solid290x154_(0,0,255,255).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d40d0715f695dc55dc2e435cab2c999b657b59ead2e0cc8a95edf7cea7782750 +size 6842 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/RawTransformMatchesDocumentedExample_Rgba32_Solid100x100_(0,0,255,255).png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/RawTransformMatchesDocumentedExample_Rgba32_Solid100x100_(0,0,255,255).png new file mode 100644 index 0000000000..9ce69219d8 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/RawTransformMatchesDocumentedExample_Rgba32_Solid100x100_(0,0,255,255).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75b1b9df1e5364a75ecda822a4bf811584d75244ffc1d3b608bc0ce6b9ff19da +size 192 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png new file mode 100644 index 0000000000..a83ec12e3e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac88c089bb5106d9dc9ed8e764f6495b74e1cd98d1df61319934ed78a7578866 +size 13233 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Box.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Box.png new file mode 100644 index 0000000000..5518047e4d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Box.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:23d502e2d6b0eb5f12ed3262eb4654927cc937574ae1de61a1d89f6672592017 +size 11828 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png new file mode 100644 index 0000000000..a83ec12e3e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac88c089bb5106d9dc9ed8e764f6495b74e1cd98d1df61319934ed78a7578866 +size 13233 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Hermite.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Hermite.png new file mode 100644 index 0000000000..29014117e3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Hermite.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f1e69bfd1f4e9479839d4bddfb2ecc68ff8cda9b15055427406691df94a16db +size 9583 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png new file mode 100644 index 0000000000..d417cad9c1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cd1d0350ca49ff1726c2a20769693698168497944413c653da6edcb6bc9a39e5 +size 17344 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png new file mode 100644 index 0000000000..cfd3cd48ef --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2dc8ed5f721d2d8ae81f1b70308511737b0e649a6b05a011342efce29fa5b1cb +size 23022 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png new file mode 100644 index 0000000000..2578c537e8 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a9514b25bbc875eb00b5c0dc4241f973d466075914a9ec4c4b64ba251323eb5a +size 22321 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png new file mode 100644 index 0000000000..1f6609c6f0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:09138a5ec45480a72370eba3015e7dee33360712745cb2f00e36a5994c1e48a7 +size 24090 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png new file mode 100644 index 0000000000..7e4f16695a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed80155afab90710ebab4babbbb787402ceac4f9dee1ff270361e5e8e495c73a +size 13867 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_NearestNeighbor.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_NearestNeighbor.png new file mode 100644 index 0000000000..3297f99e21 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_NearestNeighbor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:96fa0ebee48290be808d5c7dec561bbcab49e5222667e175ffff01b3a175c586 +size 2308 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png new file mode 100644 index 0000000000..48c51e7c3c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:19c3ce34e6bbd8e35ec979acc28510342dadf0bae3d91a9e1b8291cdff638465 +size 13873 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png new file mode 100644 index 0000000000..379b25ca0e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:87676e4bf55e71815acc46bdeb3384d659fe6cb3ecc7b730fd9ecc8be00d181f +size 13847 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png new file mode 100644 index 0000000000..4bcd2dc604 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:34a62df6b4e9756a7dfef965b669b522e2338b0c2e267d35e4a37fcd9d8a55c3 +size 14818 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png new file mode 100644 index 0000000000..009fc4fa60 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60cf2a3fae30bee16131092590e2a8fe139070b6cf98c3b98698e34ededb711f +size 11996 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png new file mode 100644 index 0000000000..568625cd6c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c2140365f533762cfc4411105be04a13f7d85739d955152c3e1951c2c69c7d67 +size 19934 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-Both.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-Both.png new file mode 100644 index 0000000000..92a99f0360 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-Both.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b57bd912acfd243882163775196e0b02c7d0374e81319cb29902cd560b5c6053 +size 394 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-LeftOrTop.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-LeftOrTop.png new file mode 100644 index 0000000000..cc89f5114b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-LeftOrTop.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8827b81929abd9000fcfd3ce747b82fec4c778bcd29bb12abaaed5f8b0dfc945 +size 228 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-RightOrBottom.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-RightOrBottom.png new file mode 100644 index 0000000000..61128d7b83 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Bottom-RightOrBottom.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5819f0deb160a7c7bf090919a010a2f8a3c074b3b718f56fe56f1f6eae1fcdcd +size 227 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-Both.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-Both.png new file mode 100644 index 0000000000..846fe440ef --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-Both.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1381429147add3a9d3342bb2d618a47a1a5db997a384582a288705f68f5f937a +size 343 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-LeftOrTop.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-LeftOrTop.png new file mode 100644 index 0000000000..7b0692ffe2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-LeftOrTop.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e59892f86d307e28457ebd621fec84b8ab839cdc11afe38e978420c4173058e4 +size 236 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-RightOrBottom.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-RightOrBottom.png new file mode 100644 index 0000000000..4c0d43feaf --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Left-RightOrBottom.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6d25a9407bb5a3c8ba7126c9082dfbc5f29c5b52fc46e1a21e1c8968ac9f1c11 +size 230 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-Both.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-Both.png new file mode 100644 index 0000000000..a832badcb0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-Both.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:398d1ca71075c541fdb88eb63f5889edea2259fdd0df643bed77e64baa246ceb +size 317 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-LeftOrTop.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-LeftOrTop.png new file mode 100644 index 0000000000..bdef30001b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-LeftOrTop.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:62546cd019fa11a43d254936c12b5adcbe8eebe6ae012bc1024949df6b28303f +size 220 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-RightOrBottom.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-RightOrBottom.png new file mode 100644 index 0000000000..3012731317 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Right-RightOrBottom.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27e444aff3db9c5a1149de73f3b0ed18e48c8dc372be13c3555dcda0ec4ad893 +size 221 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-Both.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-Both.png new file mode 100644 index 0000000000..dd6b926db4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-Both.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6bdfa8eb65b5e54b9ccffb11acb2a3b7a5a434f1f22a2cdf792d892fd411f711 +size 399 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-LeftOrTop.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-LeftOrTop.png new file mode 100644 index 0000000000..fb98036ec4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-LeftOrTop.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e11a1af248350450454ba1cb415357e58f905de402a921b213a305990e8f57c3 +size 245 diff --git a/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-RightOrBottom.png b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-RightOrBottom.png new file mode 100644 index 0000000000..0e4ef4c427 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ProjectiveTransformTests/Transform_WithTaperMatrix_Rgba32_Solid30x30_(255,0,0,255)_Top-RightOrBottom.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e9cffb16fbff28901a3daf391469d32bf36f3c293aa870d169967f17611dea92 +size 241 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_OctreeQuantizer_ErrorDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_OctreeQuantizer_ErrorDither.png new file mode 100644 index 0000000000..7fd7ab9e3e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_OctreeQuantizer_ErrorDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24acf8421048a6b1a95c8fd31e8b03c1a0b0f3b2ff155c0b9747fabb44060c25 +size 319596 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_OctreeQuantizer_NoDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_OctreeQuantizer_NoDither.png new file mode 100644 index 0000000000..5fbc15f70b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_OctreeQuantizer_NoDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:26204cd4a30538a667b17e68319747ec0a9726f6955d154c3f9f8fcd73774bd3 +size 304297 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_OctreeQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_OctreeQuantizer_OrderedDither.png new file mode 100644 index 0000000000..5d8e6b4565 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_OctreeQuantizer_OrderedDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:adc156f6010679f2ff076405557d0a34cd50464240bbafafbf44edf37b5a1186 +size 321968 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WebSafePaletteQuantizer_ErrorDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WebSafePaletteQuantizer_ErrorDither.png new file mode 100644 index 0000000000..a569c4efdd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WebSafePaletteQuantizer_ErrorDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:07986a3bde930100c20a93e8fa8b03f0f9c822853ddc07d71ebf2be5a36c4620 +size 308767 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WebSafePaletteQuantizer_NoDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WebSafePaletteQuantizer_NoDither.png new file mode 100644 index 0000000000..97b3521131 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WebSafePaletteQuantizer_NoDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3774888a23cd3be4d0d3edad8ddfeab86fd52e5605803eacbb50d3eac2f9caaa +size 291234 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WebSafePaletteQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WebSafePaletteQuantizer_OrderedDither.png new file mode 100644 index 0000000000..97613bcaa3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WebSafePaletteQuantizer_OrderedDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ec93dd8fc45e9eb3b1ad13bd89dfc487f5d6eccd2ad8fa1fede67fa7819a263a +size 299393 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WernerPaletteQuantizer_ErrorDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WernerPaletteQuantizer_ErrorDither.png new file mode 100644 index 0000000000..45e966e85c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WernerPaletteQuantizer_ErrorDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1de5e7da6659b9d235b0c9b0d55bdd71a3608d72e7a38259b34936a166c11d77 +size 292205 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WernerPaletteQuantizer_NoDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WernerPaletteQuantizer_NoDither.png new file mode 100644 index 0000000000..d3e0a03e72 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WernerPaletteQuantizer_NoDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a6e11c3e422be8aae08f3d741ec4b45ce79af3603518784d22ff646cbd00c312 +size 291259 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WernerPaletteQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WernerPaletteQuantizer_OrderedDither.png new file mode 100644 index 0000000000..2ea043d6fe --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WernerPaletteQuantizer_OrderedDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8f3ef9dab0169bd262408a30ce2a1d20da5acb331fd56ce66de2f7efe4555a9a +size 299734 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WuQuantizer_ErrorDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WuQuantizer_ErrorDither.png new file mode 100644 index 0000000000..01fa37df53 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WuQuantizer_ErrorDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd9d03b02c51eadc9b27f165771c1407391bc1d29c2b10a4175324ab29152cbb +size 329877 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WuQuantizer_NoDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WuQuantizer_NoDither.png new file mode 100644 index 0000000000..3e06cf66fb --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WuQuantizer_NoDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2eba143227c5fe09d407e9ece1be5480fc55edab5f8464393d13c642b01791f3 +size 321299 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WuQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WuQuantizer_OrderedDither.png new file mode 100644 index 0000000000..e04186940b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_Bike_WuQuantizer_OrderedDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f3d8d9e978668ae8f76004dc2a8440ffe2f55875ee92046ca2be02f426def1a6 +size 333260 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_OctreeQuantizer_ErrorDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_OctreeQuantizer_ErrorDither.png new file mode 100644 index 0000000000..fe32f95439 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_OctreeQuantizer_ErrorDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37a2c548b78e117848d294ab55c6b8f4cf85ad2c6bdf84f9eec8f6eefc07b0fe +size 349177 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_OctreeQuantizer_NoDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_OctreeQuantizer_NoDither.png new file mode 100644 index 0000000000..211a6c6a66 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_OctreeQuantizer_NoDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bfdf8fa9d082c88dd902d927a525698e9752a3738771ba2a0b6ff67568b2f116 +size 344607 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_OctreeQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_OctreeQuantizer_OrderedDither.png new file mode 100644 index 0000000000..b912690dee --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_OctreeQuantizer_OrderedDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bdb6866053be7dbe1e56e6972b50bc030d30a050f73a4429993e3c639e06d345 +size 349125 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WebSafePaletteQuantizer_ErrorDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WebSafePaletteQuantizer_ErrorDither.png new file mode 100644 index 0000000000..e8d6878862 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WebSafePaletteQuantizer_ErrorDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:23be2cf98ea2cd0e5b00fc1b771ea7ba490a3ac9e1de40540fd0d20a61af820c +size 330677 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WebSafePaletteQuantizer_NoDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WebSafePaletteQuantizer_NoDither.png new file mode 100644 index 0000000000..58e77a377e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WebSafePaletteQuantizer_NoDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f032414fd20b82c0bdbaaa3e905c296961f9cdd605408f59cba7de657d8421b0 +size 324042 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png new file mode 100644 index 0000000000..f1b04e74c6 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0adaaae399376c94af866adfcb2c5777c0dd91d2d4424f24490909e68d2483c9 +size 326321 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WernerPaletteQuantizer_ErrorDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WernerPaletteQuantizer_ErrorDither.png new file mode 100644 index 0000000000..b0f969da90 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WernerPaletteQuantizer_ErrorDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c06a456d0c38121051d91d2cbfa4fcdcf8df4bc6ece89a0bda4b0f7e2a06b6f4 +size 333368 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WernerPaletteQuantizer_NoDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WernerPaletteQuantizer_NoDither.png new file mode 100644 index 0000000000..ea1442b28a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WernerPaletteQuantizer_NoDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e0e2edc030a20998d3a14bb6715417bb6b561599601710497372ed90b27a5493 +size 332861 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png new file mode 100644 index 0000000000..f54900a2f1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0571bde66f19b41cf1ba6f3b63f3d380a1025ae2f92dda8b9c494f8869c325e4 +size 334758 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WuQuantizer_ErrorDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WuQuantizer_ErrorDither.png new file mode 100644 index 0000000000..c2ec04c4be --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WuQuantizer_ErrorDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f8a04e02cdac3b2ce2db20c5108636d40ce13e8d165c4b859cc4794f89cf7f4a +size 352342 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WuQuantizer_NoDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WuQuantizer_NoDither.png new file mode 100644 index 0000000000..bb6c8c58b7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WuQuantizer_NoDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e03a52138efa504252053f39f36dbfbe6a477a9ffdd0f8bba633ab74d0088ed +size 351591 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WuQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WuQuantizer_OrderedDither.png new file mode 100644 index 0000000000..8165d47763 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationInBox_CalliphoraPartial_WuQuantizer_OrderedDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8cc6c263430489a8866fab47c26f399a034b0dd583d27b12edc68244919321d0 +size 353592 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.25.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.25.png new file mode 100644 index 0000000000..1783d1b8af --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bcf5300ab994c466cde0568afbad510f076a1d5aa16e78249645c202a7b285f4 +size 32583 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.5.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.5.png new file mode 100644 index 0000000000..1783d1b8af --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bcf5300ab994c466cde0568afbad510f076a1d5aa16e78249645c202a7b285f4 +size 32583 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.75.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.75.png new file mode 100644 index 0000000000..1783d1b8af --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bcf5300ab994c466cde0568afbad510f076a1d5aa16e78249645c202a7b285f4 +size 32583 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.png new file mode 100644 index 0000000000..1783d1b8af --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bcf5300ab994c466cde0568afbad510f076a1d5aa16e78249645c202a7b285f4 +size 32583 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_1.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_1.png new file mode 100644 index 0000000000..1783d1b8af --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_ErrorDither_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bcf5300ab994c466cde0568afbad510f076a1d5aa16e78249645c202a7b285f4 +size 32583 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.25.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.25.png new file mode 100644 index 0000000000..47552e4571 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ec01d4ee9173d01f92b5643782f4b6c7e0b4342b530acf6062f5f17c6d7b1e9a +size 36290 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.5.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.5.png new file mode 100644 index 0000000000..36e1349ede --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ed04ff17bc4d7c57a9594bb4872f430cc3df4d92c7199d5c5db2420ecc20a95 +size 38303 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.75.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.75.png new file mode 100644 index 0000000000..760d17d5aa --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f8e53d995f27780851c044d552473ee52ec9dcc2e0dfa9a806c9f8d2fd62692 +size 39251 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.png new file mode 100644 index 0000000000..1783d1b8af --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bcf5300ab994c466cde0568afbad510f076a1d5aa16e78249645c202a7b285f4 +size 32583 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_1.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_1.png new file mode 100644 index 0000000000..efaa7bb44b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_OctreeQuantizer_OrderedDither_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a7a1cefa7e70387ccb9e90c5633725ce936635da39c131a59cec7089392c358 +size 39744 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.25.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.25.png new file mode 100644 index 0000000000..a6d0c833f9 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:733b748c42d4bc7103e8edf264fad4af268f2ee7ad7bab84f4ade6e8d91227e9 +size 17206 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.5.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.5.png new file mode 100644 index 0000000000..182a2cb770 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1b44413544d4286aff611c94bb026562b0b0913db6d804ec7c9c82a595d2cd00 +size 18474 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.75.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.75.png new file mode 100644 index 0000000000..08f457ca0c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8f597c6b7abc7cd729c034d8e34a0aeef19666f8accf997767f0d963e3818ec +size 20022 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.png new file mode 100644 index 0000000000..6c3b1345a4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e970fa92294f6eb9e20f9d780f046a85f0e569660b4500ad4c8fca284b4fa27d +size 15992 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_1.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_1.png new file mode 100644 index 0000000000..2fa10ee19f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_ErrorDither_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b0586ae018f98d26298d3dc4af329eeca044c1cdc5ed5a71ff22e1b9ca46c122 +size 22701 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.25.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.25.png new file mode 100644 index 0000000000..94175f4895 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a3b56c451b5e7461782dec2f5dccab18e7ad33efe3d9f1906421c32c75923648 +size 17790 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.5.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.5.png new file mode 100644 index 0000000000..c227f65870 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c4d81ab162bd065f438504ea2a44be93cefd7f1b31d7d983e23108e8e19b86fa +size 18390 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.75.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.75.png new file mode 100644 index 0000000000..35e12cf859 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1d2cb1111d2a3915072ca53404215052bbff42ff9639e8e3c2b4f6a70591fd0e +size 19145 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.png new file mode 100644 index 0000000000..6c3b1345a4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e970fa92294f6eb9e20f9d780f046a85f0e569660b4500ad4c8fca284b4fa27d +size 15992 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_1.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_1.png new file mode 100644 index 0000000000..6ff5504ab7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WebSafePaletteQuantizer_OrderedDither_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1133884d19f663d3c643ebe11bdeac65e2ab3d533be43a40b61b3292ea59cd3b +size 19680 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.25.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.25.png new file mode 100644 index 0000000000..4d2011af41 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:770fa2009e0c6adf462db16e70ca3a2d3a97722604a28fba6c0154e660387524 +size 20899 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.5.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.5.png new file mode 100644 index 0000000000..738a0e6371 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f2a4128cb456fe55a7ef188592050270e4cc241542e59978a11222def40564a +size 21413 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.75.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.75.png new file mode 100644 index 0000000000..00f6e44fff --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eeb8c94db2e35c42f0d7b59102d35f6b00f6067870c5068e5e925e53d6e64ffd +size 22312 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.png new file mode 100644 index 0000000000..8cea7036fb --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f00ea6a1901987c517a5490e7965bc9408c88ff292b2c4c069b87d5d899c638 +size 19458 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_1.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_1.png new file mode 100644 index 0000000000..92a4779e3e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_ErrorDither_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:505bef8573a04cc809edbc671cb9d26bde49708521de1286406c3164cb9d8988 +size 24011 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.25.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.25.png new file mode 100644 index 0000000000..3b9f8866b4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:64b29bbd6edca8e444822a97ce9bc674db175c299cbec1cbe596552419f49be7 +size 22239 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.5.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.5.png new file mode 100644 index 0000000000..1efaf38b6c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae09ad6a81dbfc56c60b7e47720338b3ba3b8aa29982016c36a39baa33f75054 +size 23353 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.75.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.75.png new file mode 100644 index 0000000000..ed9531e7bb --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e9e9094177282dd635a02b97855299e9275af364fd66812dd72b3ef2545b5660 +size 24487 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.png new file mode 100644 index 0000000000..8cea7036fb --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f00ea6a1901987c517a5490e7965bc9408c88ff292b2c4c069b87d5d899c638 +size 19458 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_1.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_1.png new file mode 100644 index 0000000000..22b642dffa --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WernerPaletteQuantizer_OrderedDither_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:874ffc514300dd727c6c46943fc9f8955013c1d355fc1bd60848660ed9b4f6b2 +size 25182 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.25.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.25.png new file mode 100644 index 0000000000..f0b5f034c2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef65b07e0d25a3ce83eae05f62d938220226cdfccc641a3b51e7a03283f61e1e +size 25430 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.5.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.5.png new file mode 100644 index 0000000000..72486e2621 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:51740a55ef58532b2e753e6e26f2b4ae622db59b6a3df08aad58701ac058975f +size 25518 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.75.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.75.png new file mode 100644 index 0000000000..36a2e98af4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7d276ba0d498bac579b3944644542b41e0e8d5a50c420e75d455ce51a49393f +size 25893 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.png new file mode 100644 index 0000000000..f0b5f034c2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef65b07e0d25a3ce83eae05f62d938220226cdfccc641a3b51e7a03283f61e1e +size 25430 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_1.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_1.png new file mode 100644 index 0000000000..c4dacb6ad0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_ErrorDither_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7f1e1e92f72b2fcbc0f0659e7ef5c7c5eabea7968ec7975925480f11e639c0a0 +size 26509 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.25.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.25.png new file mode 100644 index 0000000000..39820f08c6 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:46989a5fd14a9555eee28081ad78c34e26f5c38e6d7360cb36de8a87d2916685 +size 29187 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.5.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.5.png new file mode 100644 index 0000000000..e152e9c48e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c73448e92f13c979c3a0c4f16532a6f47a14e6e1974d686674862070787b6489 +size 31145 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.75.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.75.png new file mode 100644 index 0000000000..f37e332f37 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:afc516374154a209a07f069eb7832808eefc0db4f2a3fbfa765848ca0d7acedf +size 31974 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.png new file mode 100644 index 0000000000..f0b5f034c2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef65b07e0d25a3ce83eae05f62d938220226cdfccc641a3b51e7a03283f61e1e +size 25430 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_1.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_1.png new file mode 100644 index 0000000000..e4b8623075 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantizationWithDitheringScale_david_WuQuantizer_OrderedDither_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:be814de172c0b290e4af81ea175e14643e9dc34ce3400ae1f3b64228e29bf49d +size 32237 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_ErrorDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_ErrorDither.png new file mode 100644 index 0000000000..66bc734bb5 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_ErrorDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:44dfa754a90a27a343ceba8bb68c42b255331fdbe2f1d1c5b1f64d47a6db0e89 +size 136581 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_NoDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_NoDither.png new file mode 100644 index 0000000000..d78df0b1f8 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_NoDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b12689f5116ac8077e1fec5c556b0276e2d53241bbbf0d4be078186c9280d7e8 +size 95223 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_OrderedDither.png new file mode 100644 index 0000000000..302188cf58 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_OctreeQuantizer_OrderedDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3528fe676ae29534d80edcd08ca5874bcaaae6c1133332070dcd008df2c50da7 +size 138694 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_ErrorDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_ErrorDither.png new file mode 100644 index 0000000000..e0d901ea77 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_ErrorDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:192c742bfd53f3a74d96c79e92443a922ac60c354b73d7abf292f30d10131307 +size 114842 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_NoDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_NoDither.png new file mode 100644 index 0000000000..a9e9a643a0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_NoDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9cae72debcf389db95fd4dc5053a6b1d2ea133cd56b6f268b929c68b6bf0e2e0 +size 64044 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_OrderedDither.png new file mode 100644 index 0000000000..e24920a4d5 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WebSafePaletteQuantizer_OrderedDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f76c909b7e804c8dd80b07fd5346d2036d2fded2bf9a855bd20f7da154a111f3 +size 83554 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_ErrorDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_ErrorDither.png new file mode 100644 index 0000000000..1550ce0e66 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_ErrorDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:566cf4c7ef7f08597c7381b67fd14489f7445dd216f12059a4888bd948e9e5d3 +size 62638 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_NoDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_NoDither.png new file mode 100644 index 0000000000..26a1479858 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_NoDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:22b86134c61484e0189f2b73417d36321d930474026421ba80a9ebc33a23b878 +size 61324 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_OrderedDither.png new file mode 100644 index 0000000000..32475f3874 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WernerPaletteQuantizer_OrderedDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:22cebdb64f32d4818a35c07a4a2f5c2b1bae1fd465944d553b37a211f3e78ff8 +size 79480 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_ErrorDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_ErrorDither.png new file mode 100644 index 0000000000..5ca3acc8fd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_ErrorDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:204fe52c4d99b661b2429c4659cde8fb04366c038ac7be0aa507cfba7c5aecfb +size 173275 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_NoDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_NoDither.png new file mode 100644 index 0000000000..387e79ad34 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_NoDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:af5be90cac48d0c86c6115b0fc6ceff3fdf934cecf5b332f2942f680a0636f08 +size 140801 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_OrderedDither.png new file mode 100644 index 0000000000..74c5cb62da --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_Bike_WuQuantizer_OrderedDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:385063f3976342ea525487e53801df14e644eb0a56898b1e81e0667323ff3f1a +size 172869 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_ErrorDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_ErrorDither.png new file mode 100644 index 0000000000..9d73e42801 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_ErrorDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5d9ecfd740c88faf8f159da4d704ec160fd17a4de63a870c4590cd16475248dc +size 146902 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_NoDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_NoDither.png new file mode 100644 index 0000000000..be9e2718dd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_NoDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7a247d55c2ee6b39707d929da18fa4242343c7819cd76a973397754a4dfb197f +size 123976 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_OrderedDither.png new file mode 100644 index 0000000000..2d16e4af11 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_OctreeQuantizer_OrderedDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27e0be11cb36a419a590de19cce432f5b78d9a3c86d024ca43b5904e758c569d +size 144104 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_ErrorDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_ErrorDither.png new file mode 100644 index 0000000000..d87f3fd5a2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_ErrorDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aa6c2bb78faaf689cf979dd87b3a24b6405720755ce16c028cafab690ac7b318 +size 104334 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_NoDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_NoDither.png new file mode 100644 index 0000000000..c7e9e58f93 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_NoDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3e236adf08358a44452d4a215f6267a5596ce7e824bf9818d1e6180366833b1f +size 82182 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png new file mode 100644 index 0000000000..4b04715b9a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WebSafePaletteQuantizer_OrderedDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e0aeb15a04553142cade051d523bbc18b2e63997efa0b0c5f5b8bab8662074f7 +size 88550 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_ErrorDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_ErrorDither.png new file mode 100644 index 0000000000..2a0072cc67 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_ErrorDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cf1d0ab1bead910fa3d0f0b3a6ed5bb9f26a470adc6019e1542b279b81d8d81a +size 109775 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_NoDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_NoDither.png new file mode 100644 index 0000000000..b7b3619539 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_NoDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:171a705658d932b14073ef2affbf68829b4c0a4cfdecaa6672bf8ca63c03e4ff +size 103581 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png new file mode 100644 index 0000000000..07003dfa4e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WernerPaletteQuantizer_OrderedDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e720cb4ab955614764cc0c10f08146a50e08d4c5712a02b581ae25a4e4935c3a +size 113199 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WuQuantizer_ErrorDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WuQuantizer_ErrorDither.png new file mode 100644 index 0000000000..f62dcb0bf1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WuQuantizer_ErrorDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed70179c085142e5629075084348fe3b78fb027039b73c570510f22489dfb2dd +size 170507 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WuQuantizer_NoDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WuQuantizer_NoDither.png new file mode 100644 index 0000000000..3e0a6ea3a4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WuQuantizer_NoDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b0ab1a9d1ac3ad5d9065cb7b436d1fa12eefcd467bb78defcf930e25df33a773 +size 165594 diff --git a/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WuQuantizer_OrderedDither.png b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WuQuantizer_OrderedDither.png new file mode 100644 index 0000000000..9f04685444 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/QuantizerTests/ApplyQuantization_CalliphoraPartial_WuQuantizer_OrderedDither.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:462a0d7d7d8056042e49dff3a896114d7db09b9e40e72e6b87f711caf6c1a993 +size 175519 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/CanResizeLargeImageWithCropMode_Rgba32_issue1006-incorrect-resize.png b/tests/Images/External/ReferenceOutput/ResizeTests/CanResizeLargeImageWithCropMode_Rgba32_issue1006-incorrect-resize.png new file mode 100644 index 0000000000..209ceed059 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/CanResizeLargeImageWithCropMode_Rgba32_issue1006-incorrect-resize.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:473805d7a372281d24f53c43780cbf54c75850d59b4d13dc210cbafefe5e2d44 +size 172367 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/LargeImage_TestPattern4000x4000.png b/tests/Images/External/ReferenceOutput/ResizeTests/LargeImage_TestPattern4000x4000.png new file mode 100644 index 0000000000..63f62ee861 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/LargeImage_TestPattern4000x4000.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b284baaa311a18733077be29c29a840819f0dad22e1a593642908895f7826a8c +size 23484 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeFromSourceRectangle_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeFromSourceRectangle_Rgba32_CalliphoraPartial.png new file mode 100644 index 0000000000..621057dd2a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeFromSourceRectangle_Rgba32_CalliphoraPartial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a2474d0a97e367730b71f95f87cffcda37d8edd20a67eba02231cfeaa668f2bf +size 77710 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeHeightAndKeepAspect_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeHeightAndKeepAspect_Rgba32_CalliphoraPartial.png new file mode 100644 index 0000000000..38b83af02e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeHeightAndKeepAspect_Rgba32_CalliphoraPartial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:019f29b73ab5b6c4dfd94613ed0d0e484abcf580e6cf46a9e35ffccdfb60f64d +size 34199 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWidthAndKeepAspect_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWidthAndKeepAspect_Rgba32_CalliphoraPartial.png new file mode 100644 index 0000000000..38b83af02e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWidthAndKeepAspect_Rgba32_CalliphoraPartial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:019f29b73ab5b6c4dfd94613ed0d0e484abcf580e6cf46a9e35ffccdfb60f64d +size 34199 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithBoxPadMode_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithBoxPadMode_Rgba32_CalliphoraPartial.png new file mode 100644 index 0000000000..35d633c86f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithBoxPadMode_Rgba32_CalliphoraPartial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1642520a9d4491f55af5a83280423929529e3d528637538d148b9dc2ecdd6d2d +size 365839 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithCropHeightMode_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithCropHeightMode_Rgba32_CalliphoraPartial.png new file mode 100644 index 0000000000..16d33b009e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithCropHeightMode_Rgba32_CalliphoraPartial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca81c5ff92e41df0e8fc4807982fdf650d3bbff4027735ed30fc2d17e14b77ce +size 155071 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithCropWidthMode_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithCropWidthMode_Rgba32_CalliphoraPartial.png new file mode 100644 index 0000000000..5e3d35cda0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithCropWidthMode_Rgba32_CalliphoraPartial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:33213eabb71a67a5bc7e3cdfcf764328b2fee63b613e0648f62910935114eec0 +size 165724 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithMaxMode_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithMaxMode_Rgba32_CalliphoraPartial.png new file mode 100644 index 0000000000..decfb38364 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithMaxMode_Rgba32_CalliphoraPartial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:09c8343e6acd1bd294040edfeb443604b7f0a5d903319ca759beb91d3557381a +size 197994 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithMinMode_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithMinMode_Rgba32_CalliphoraPartial.png new file mode 100644 index 0000000000..e1239549bb --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithMinMode_Rgba32_CalliphoraPartial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae2c985405fbb856dbef0637048acc7f4d6a05df3def3307730e96a9de1a1ef4 +size 281262 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithPadMode_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithPadMode_Rgba32_CalliphoraPartial.png new file mode 100644 index 0000000000..690c2ad46c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithPadMode_Rgba32_CalliphoraPartial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:060826324dcd4baa1df1b075707a9bd9527cf87c1d156e3beb3d8abb499bdcd5 +size 361829 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithStretchMode_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithStretchMode_Rgba32_CalliphoraPartial.png new file mode 100644 index 0000000000..a32878f49c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithStretchMode_Rgba32_CalliphoraPartial.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:79ae82683d812ba7180cc8ca50d3fab7808b4867f738bceaf41298a6e6b71a31 +size 156509 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_BasicSmall_BasicTestPattern15x12_(2÷3,1÷2).png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_BasicSmall_BasicTestPattern15x12_(2÷3,1÷2).png new file mode 100644 index 0000000000..4317b59b39 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_BasicSmall_BasicTestPattern15x12_(2÷3,1÷2).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a7ed51059397a81f468de76863db22d802a1a298c0a63802a2a7dfb5043015d +size 215 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_BasicSmall_BasicTestPattern2x256_(1÷1,1÷8).png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_BasicSmall_BasicTestPattern2x256_(1÷1,1÷8).png new file mode 100644 index 0000000000..c95bb11825 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_BasicSmall_BasicTestPattern2x256_(1÷1,1÷8).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9baf700cca84e05da2df13435efd7b09ef403c786a731877b9de0bae79896b1e +size 159 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_BasicSmall_BasicTestPattern2x32_(1÷1,1÷2).png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_BasicSmall_BasicTestPattern2x32_(1÷1,1÷2).png new file mode 100644 index 0000000000..a4f40eb9ba --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_BasicSmall_BasicTestPattern2x32_(1÷1,1÷2).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa7ed21b50aab289d81157a00d9cc9e41d2fe5ddca1140a9092b0932d8d8bb07 +size 158 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_Compand_Rgba32_TestPattern100x100.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_Compand_Rgba32_TestPattern100x100.png new file mode 100644 index 0000000000..9afe64b398 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_Compand_Rgba32_TestPattern100x100.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:143c528d178f31ed11c45ae60778266b22768ea2ca7cc3dbd274463d56d1a243 +size 4227 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_DoesNotBleedAlphaPixels.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_DoesNotBleedAlphaPixels.png new file mode 100644 index 0000000000..ef88f0d7cd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_DoesNotBleedAlphaPixels.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c9e66228746bb298c7b3c2088457adb3aa83dcd01934c7ff51fe64368c66cdd +size 88510 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_DoesNotBleedAlphaPixels_Compand.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_DoesNotBleedAlphaPixels_Compand.png new file mode 100644 index 0000000000..7933759169 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_DoesNotBleedAlphaPixels_Compand.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:96efbf6a0861dc899f1dae9995aaf68cff27083f192ef988233e8125afb23af3 +size 88432 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_IsAppliedToAllFrames_Rgba32_giphy.gif b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_IsAppliedToAllFrames_Rgba32_giphy.gif new file mode 100644 index 0000000000..10fabee6d2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_IsAppliedToAllFrames_Rgba32_giphy.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a77b7fa90ae9f92c5d31a0de7abfd3ec7e15c9465d1c7f78454adac6c6c283e3 +size 23765 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_IsNotBoundToSinglePixelType_Bgra32_TestPattern50x50.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_IsNotBoundToSinglePixelType_Bgra32_TestPattern50x50.png new file mode 100644 index 0000000000..331d87e1fd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_IsNotBoundToSinglePixelType_Bgra32_TestPattern50x50.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:953fc2e66b8666c62773a0224f6bbe7ff5eee8da68182c3d714a1bc6012ab692 +size 1532 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_IsNotBoundToSinglePixelType_Rgba32_TestPattern50x50.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_IsNotBoundToSinglePixelType_Rgba32_TestPattern50x50.png new file mode 100644 index 0000000000..331d87e1fd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_IsNotBoundToSinglePixelType_Rgba32_TestPattern50x50.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:953fc2e66b8666c62773a0224f6bbe7ff5eee8da68182c3d714a1bc6012ab692 +size 1532 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_IsNotBoundToSinglePixelType_RgbaVector_TestPattern50x50.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_IsNotBoundToSinglePixelType_RgbaVector_TestPattern50x50.png new file mode 100644 index 0000000000..5b72a7fcf1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_IsNotBoundToSinglePixelType_RgbaVector_TestPattern50x50.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bbc66de56ab05c3d98139ea4e8b2cd7f534852710f0620da2e8b7b9c25ca82b1 +size 1533 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_PremultiplyAlpha_Off.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_PremultiplyAlpha_Off.png new file mode 100644 index 0000000000..e38f57c18f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_PremultiplyAlpha_Off.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:72400ad12a726c71127fb53de713e0cbfbb0a74171667c67c89201383ae0da75 +size 83140 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_PremultiplyAlpha_On.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_PremultiplyAlpha_On.png new file mode 100644 index 0000000000..a3b6144165 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_PremultiplyAlpha_On.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2a568089d1163c02e2435335f41a85565f0e6f1212c4753fe19a27e724fc7387 +size 88512 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllParallelismLevels_MDP-1.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllParallelismLevels_MDP-1.png new file mode 100644 index 0000000000..dca6b95614 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllParallelismLevels_MDP-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:147370fecca5ef6e90653c4ee4ee94f3a535a1a0c9c79fbf9948e9cb19c3341f +size 78863 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllParallelismLevels_MDP1.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllParallelismLevels_MDP1.png new file mode 100644 index 0000000000..dca6b95614 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllParallelismLevels_MDP1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:147370fecca5ef6e90653c4ee4ee94f3a535a1a0c9c79fbf9948e9cb19c3341f +size 78863 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllParallelismLevels_MDP4.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllParallelismLevels_MDP4.png new file mode 100644 index 0000000000..dca6b95614 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllParallelismLevels_MDP4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:147370fecca5ef6e90653c4ee4ee94f3a535a1a0c9c79fbf9948e9cb19c3341f +size 78863 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllParallelismLevels_MDP8.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllParallelismLevels_MDP8.png new file mode 100644 index 0000000000..dca6b95614 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllParallelismLevels_MDP8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:147370fecca5ef6e90653c4ee4ee94f3a535a1a0c9c79fbf9948e9cb19c3341f +size 78863 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Bicubic-0.3.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Bicubic-0.3.png new file mode 100644 index 0000000000..42c273ea22 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Bicubic-0.3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b35b3ac63840d16137b91407968fe16ef09ebf7253cf5f050ea6e1ce3ac598fb +size 27117 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Bicubic-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Bicubic-0.5.png new file mode 100644 index 0000000000..b0ca7a6b76 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Bicubic-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:58b08a7fbd708eed222d6941608d5d9f4a4438cc76d6c84119dd6eaa1eef2995 +size 78863 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Bicubic-1.8.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Bicubic-1.8.png new file mode 100644 index 0000000000..c6fbd65213 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Bicubic-1.8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd216f1fdcec4bd1d02ffcddd07d01638f27528bb430289a4dcc8f27defb9819 +size 844830 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Box-0.3.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Box-0.3.png new file mode 100644 index 0000000000..2361cff885 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Box-0.3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:faac9be73e472d45138258cd3624c10e0e75cc45a7e7c5c7ab05af2d2b816ba1 +size 28619 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Box-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Box-0.5.png new file mode 100644 index 0000000000..413cab719e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Box-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:307cee04c98332cd4783caec027e841c4130382996a0fd3d5e50e5cf278c2b30 +size 81225 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Box-1.8.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Box-1.8.png new file mode 100644 index 0000000000..c4e02c3fbd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Box-1.8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d73445fe4a8e521c67b7ffaab348b352b40295e0b30c598e3e5d5b6476316000 +size 390833 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_CatmullRom-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_CatmullRom-0.5.png new file mode 100644 index 0000000000..3296eab8cf --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_CatmullRom-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c08c396c20539fb1dcdf99bf307744fec33531a218a39e3e447d62d1ba479c73 +size 78864 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Hermite-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Hermite-0.5.png new file mode 100644 index 0000000000..7c47282c28 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Hermite-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0bdd04a25e4985b696358221afb5c02e37b19b44bdc2f8eda3034068da3ff9a7 +size 76480 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos2-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos2-0.5.png new file mode 100644 index 0000000000..2518833fd0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos2-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6fd77a694e5788c615bb4d1b5b5824c90e28700dd1ae766ab26e8125d2700a28 +size 78983 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos3-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos3-0.5.png new file mode 100644 index 0000000000..c43946108c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos3-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6725244be68f7205a5bfedf7f729fd0f78f3210df67c047b02565336c4baf43f +size 81025 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos5-0.3.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos5-0.3.png new file mode 100644 index 0000000000..aa4ca82860 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos5-0.3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63f5148bc4be1bd1747f87dcbe562f4496228fe62ac60a561b48e7068e9a95fa +size 27791 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos5-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos5-0.5.png new file mode 100644 index 0000000000..eb5f662f80 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos5-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ccf90bfe570cffd4f4043ce62a172b5a184676469d4e91e1f345f5a923b8c8b2 +size 82136 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos5-1.8.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos5-1.8.png new file mode 100644 index 0000000000..56afdc531e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos5-1.8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60adf1e3ace2e95d6dd405156e97f60fb62b3578e66d5c6dc2d4d0258c665741 +size 883267 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos8-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos8-0.5.png new file mode 100644 index 0000000000..21a6be7a2a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Lanczos8-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dbc43b51b761b73531dadefa9e2faa44d6fd9f0c03d104a62e06a4ced39e3103 +size 82703 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_MitchellNetravali-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_MitchellNetravali-0.5.png new file mode 100644 index 0000000000..3fad53ea5f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_MitchellNetravali-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:06d66b1587b4404e14cc43914fc97e6073304bb69fd74887f80dacb778c3d3cf +size 75157 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_NearestNeighbor-0.3.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_NearestNeighbor-0.3.png new file mode 100644 index 0000000000..fa4a1729f8 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_NearestNeighbor-0.3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5696b258fcfaf4b36ba6f32c9a74b01096133099cd3d4ab60b1d4d2fa7a3d98a +size 32354 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_NearestNeighbor-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_NearestNeighbor-0.5.png new file mode 100644 index 0000000000..4f06608648 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_NearestNeighbor-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:82266a7ee38196d335b7da383cace05aed360fb21d6b6aae4215fe8b7c4b4a0b +size 87247 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_NearestNeighbor-1.8.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_NearestNeighbor-1.8.png new file mode 100644 index 0000000000..ba733699be --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_NearestNeighbor-1.8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bffe3d287d4ef65428a97d71e1f678777b91b4a68e0cb1f58d7b8e39c0c567b4 +size 390582 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Robidoux-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Robidoux-0.5.png new file mode 100644 index 0000000000..41ba0710b0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Robidoux-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f46c3bc410c94bc060914df04c6673053c1803c079026c6cdae62a93a1583b7 +size 74598 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_RobidouxSharp-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_RobidouxSharp-0.5.png new file mode 100644 index 0000000000..5621ee0bd2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_RobidouxSharp-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0643e188266539b688085ff3f0e324755e8c733244cdb386dfde719a82e26efd +size 75976 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Spline-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Spline-0.5.png new file mode 100644 index 0000000000..dced05ba34 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Spline-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c9757a5cf94dccd2361d65ed7f7f460bffb2c02ef59bec0251030bfb61adc78b +size 67019 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Triangle-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Triangle-0.5.png new file mode 100644 index 0000000000..9ad5f298f3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Triangle-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:77e0e2701d666ef0751b52bb5bf2a6b113d0e35cf8b79e00806701fa6fb636cb +size 73993 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Welch-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Welch-0.5.png new file mode 100644 index 0000000000..0f1a377141 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_CalliphoraPartial_Welch-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d03837d2fd33f63581fd87c4bfae8daf7f1ede861de4ef66ddb1a446e8362c1 +size 81566 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Bicubic-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Bicubic-0.5.png new file mode 100644 index 0000000000..dfe4800885 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Bicubic-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94528052f7dd14b7062751c033470d5ee3482800341445306ed00394b29f626a +size 3174 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Bicubic-1.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Bicubic-1.png new file mode 100644 index 0000000000..e414d7211a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Bicubic-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8ccad53509a924097e2f1e2c8536e13298b06d091b5298acba5e11b87561a78 +size 1238 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Box-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Box-0.5.png new file mode 100644 index 0000000000..28f8299975 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Box-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:39c15e43385da0fe1f03b81e5280eee5f30f245693176c718b3bde12b31f8fb0 +size 1825 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Box-1.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Box-1.png new file mode 100644 index 0000000000..e414d7211a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Box-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8ccad53509a924097e2f1e2c8536e13298b06d091b5298acba5e11b87561a78 +size 1238 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Lanczos5-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Lanczos5-0.5.png new file mode 100644 index 0000000000..ca9f6d37c2 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Lanczos5-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8635fcb4faf3ca47a258b4165c42b1485be03bd63db1be0a878194de7af59118 +size 3818 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Lanczos5-1.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Lanczos5-1.png new file mode 100644 index 0000000000..e414d7211a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_Lanczos5-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8ccad53509a924097e2f1e2c8536e13298b06d091b5298acba5e11b87561a78 +size 1238 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_NearestNeighbor-0.5.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_NearestNeighbor-0.5.png new file mode 100644 index 0000000000..14ec6b713d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_NearestNeighbor-0.5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:858c74f4eb5b69b546294371f826a197037deb70a8eb9960f9192e94d76c4ec7 +size 664 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_NearestNeighbor-1.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_NearestNeighbor-1.png new file mode 100644 index 0000000000..e414d7211a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern100x100_NearestNeighbor-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8ccad53509a924097e2f1e2c8536e13298b06d091b5298acba5e11b87561a78 +size 1238 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern201x199_Bicubic-100x99.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern201x199_Bicubic-100x99.png new file mode 100644 index 0000000000..3f0e525faf --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern201x199_Bicubic-100x99.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e58033a90199093e078591422a1e9ef3f07de6cbe5ae524a4b1b2ffcd3de1fea +size 8183 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern201x199_Box-100x99.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern201x199_Box-100x99.png new file mode 100644 index 0000000000..e0f65f2d59 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern201x199_Box-100x99.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7e628738e9c3ba2b43720a58e2467588b184787a543c319e9a4f41e7ae6b48b +size 4122 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern201x199_Lanczos5-100x99.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern201x199_Lanczos5-100x99.png new file mode 100644 index 0000000000..00d290a436 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern201x199_Lanczos5-100x99.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0102922c84028e63e6dfedd302e44384a5d8acc891beb78b5ce89f857851af98 +size 9485 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern201x199_NearestNeighbor-100x99.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern201x199_NearestNeighbor-100x99.png new file mode 100644 index 0000000000..f396a1e0aa --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern201x199_NearestNeighbor-100x99.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:706d34e65803ee40b5ffc3c1a941d8a59e5dc0bf257db220a794f2bd38c5866e +size 1219 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern301x1180_Bicubic-300x480.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern301x1180_Bicubic-300x480.png new file mode 100644 index 0000000000..d4d87ec1d1 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern301x1180_Bicubic-300x480.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:458d1c64ffd2bb62bf63babbde30fa167eba650fc81a8a953fc8dc64eef8c885 +size 95713 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern301x1180_Box-300x480.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern301x1180_Box-300x480.png new file mode 100644 index 0000000000..36ed664a78 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern301x1180_Box-300x480.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cfaf090ed7b756f52ae32cfe02f48e25e2295c899d71434c199391ef61e2da6a +size 16558 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern301x1180_Lanczos5-300x480.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern301x1180_Lanczos5-300x480.png new file mode 100644 index 0000000000..c2df28f310 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern301x1180_Lanczos5-300x480.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:97244f62df0c7ee3c9205c49707995e0d3490fae02b49360e5dd4be49521f066 +size 106447 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern301x1180_NearestNeighbor-300x480.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern301x1180_NearestNeighbor-300x480.png new file mode 100644 index 0000000000..71c71b4ea3 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern301x1180_NearestNeighbor-300x480.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f03343e91a938995a11beab3ef4c82a96131d567245ac31137411ad986f33da +size 6949 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern49x80_Bicubic-301x100.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern49x80_Bicubic-301x100.png new file mode 100644 index 0000000000..27394b1209 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern49x80_Bicubic-301x100.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f52cbbcd835b447ebfd55919b612db436fc0ab9fc583c501683f6ee88460b80 +size 22229 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern49x80_Box-301x100.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern49x80_Box-301x100.png new file mode 100644 index 0000000000..ce8b287b10 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern49x80_Box-301x100.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:89b6ebdd44855bfead0341a1607f62be9a42f96a17f92c2c035ce74a3a8e1752 +size 1142 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern49x80_Lanczos5-301x100.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern49x80_Lanczos5-301x100.png new file mode 100644 index 0000000000..ed961b6985 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern49x80_Lanczos5-301x100.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a0e8a9eab1a24fda93f6ad0c4444bf32e235a72ff13fdf8560636dfb1d95c18b +size 29708 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern49x80_NearestNeighbor-301x100.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern49x80_NearestNeighbor-301x100.png new file mode 100644 index 0000000000..22602391aa --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern49x80_NearestNeighbor-301x100.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fdc2c1ec00b11f695cbbbe53dffcb9ff98ce8bb53ff0b61b3ba8d354010e02d7 +size 1119 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern50x50_Bicubic-8.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern50x50_Bicubic-8.png new file mode 100644 index 0000000000..9f27ea0b88 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern50x50_Bicubic-8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d52b0d837d609d59f8ef559e5397d0e010f19e931cf3abf12f68bba0d03ba5f8 +size 98716 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern50x50_Box-8.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern50x50_Box-8.png new file mode 100644 index 0000000000..24a93f2941 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern50x50_Box-8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f1cec814cb9c1d1adf9971d3bedeef2daa30d114b32803a2a2b5366414bf2d9 +size 2362 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern50x50_Lanczos5-8.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern50x50_Lanczos5-8.png new file mode 100644 index 0000000000..1b3e3e7dde --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern50x50_Lanczos5-8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7c2bf273a77204766b656fe3a526c4717d3e86340a425ead52f7252d144a0157 +size 132328 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern50x50_NearestNeighbor-8.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern50x50_NearestNeighbor-8.png new file mode 100644 index 0000000000..ea67bc272c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_WorksWithAllResamplers_TestPattern50x50_NearestNeighbor-8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2214531deeecfd3db97eb9bbd9b2daa3bd02e0ec1317961a808fdc18e4415a1b +size 2361 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern100x100_50.png b/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern100x100_50.png new file mode 100644 index 0000000000..e362fdb1ae --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern100x100_50.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24dd9cbedd34091fb1a812c349925fa2c4ca0ffeaf6191693dd049d773fc5d97 +size 1141 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern100x100_60.png b/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern100x100_60.png new file mode 100644 index 0000000000..e362fdb1ae --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern100x100_60.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24dd9cbedd34091fb1a812c349925fa2c4ca0ffeaf6191693dd049d773fc5d97 +size 1141 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern100x400_110.png b/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern100x400_110.png new file mode 100644 index 0000000000..ad88805d3e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern100x400_110.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da4bde43ef0945720c64af88642765d9809c3fafc3f74ea766cc73b92c65c5f6 +size 2284 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern23x211_31.png b/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern23x211_31.png new file mode 100644 index 0000000000..b84c82066b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern23x211_31.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1483d2c06b845864390ac179b68d391c6adcb415c15759a5d5fd140afb0b155b +size 737 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern47x193_73.png b/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern47x193_73.png new file mode 100644 index 0000000000..a545a9a641 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern47x193_73.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e67978dfc069dd8d056c7a85aa68fc47ce222ecb4e586ea683c62bad556620d5 +size 1331 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern79x97_5.png b/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern79x97_5.png new file mode 100644 index 0000000000..db742c4565 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern79x97_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b774c66aa2655ae5c9d5b4bc61f8002466878ffd1ae403fe27cc276bb7c70730 +size 1010 diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern79x97_73.png b/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern79x97_73.png new file mode 100644 index 0000000000..db742c4565 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/WorkingBufferSizeHintInBytes_IsAppliedCorrectly_TestPattern79x97_73.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b774c66aa2655ae5c9d5b4bc61f8002466878ffd1ae403fe27cc276bb7c70730 +size 1010 diff --git a/tests/Images/External/ReferenceOutput/TestImageExtensionsTests/CompareToReferenceOutput_DoNotAppendPixelType_Solid10x10_(0,0,255,255).png b/tests/Images/External/ReferenceOutput/TestImageExtensionsTests/CompareToReferenceOutput_DoNotAppendPixelType_Solid10x10_(0,0,255,255).png new file mode 100644 index 0000000000..860b309a14 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/TestImageExtensionsTests/CompareToReferenceOutput_DoNotAppendPixelType_Solid10x10_(0,0,255,255).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00cc79110b20d81196a1b7fd780c8f2f7eaf52daaebf3c34e2381b464d60374f +size 103 diff --git a/tests/Images/External/ReferenceOutput/TestImageExtensionsTests/CompareToReferenceOutput_WhenReferenceOutputDoesNotMatch_Throws_Rgba32_Solid10x10_(0,0,255,255).png b/tests/Images/External/ReferenceOutput/TestImageExtensionsTests/CompareToReferenceOutput_WhenReferenceOutputDoesNotMatch_Throws_Rgba32_Solid10x10_(0,0,255,255).png new file mode 100644 index 0000000000..7858065c1f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/TestImageExtensionsTests/CompareToReferenceOutput_WhenReferenceOutputDoesNotMatch_Throws_Rgba32_Solid10x10_(0,0,255,255).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ca7319480ee1c25db571436f92034fba6a9683eae30ba9d75772be9a7f65ad2b +size 189 diff --git a/tests/Images/External/ReferenceOutput/TestImageExtensionsTests/CompareToReferenceOutput_WhenReferenceOutputMatches_ShouldNotThrow_Rgba32_Solid10x10_(0,0,255,255).png b/tests/Images/External/ReferenceOutput/TestImageExtensionsTests/CompareToReferenceOutput_WhenReferenceOutputMatches_ShouldNotThrow_Rgba32_Solid10x10_(0,0,255,255).png new file mode 100644 index 0000000000..860b309a14 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/TestImageExtensionsTests/CompareToReferenceOutput_WhenReferenceOutputMatches_ShouldNotThrow_Rgba32_Solid10x10_(0,0,255,255).png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00cc79110b20d81196a1b7fd780c8f2f7eaf52daaebf3c34e2381b464d60374f +size 103 diff --git a/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_Gray_16Bit_Rgba32_grayscale_a_UL.png b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_Gray_16Bit_Rgba32_grayscale_a_UL.png new file mode 100644 index 0000000000..cdbcd212df --- /dev/null +++ b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_Gray_16Bit_Rgba32_grayscale_a_UL.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e49f62fb9696ebe7eb2c398b39f70d9ec3b49f8698e1e3006796af10f432f902 +size 53867 diff --git a/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_Gray_WithBottomLeftOrigin_16Bit_Rgba32_grayscale_a_LL.png b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_Gray_WithBottomLeftOrigin_16Bit_Rgba32_grayscale_a_LL.png new file mode 100644 index 0000000000..6af495960a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_Gray_WithBottomLeftOrigin_16Bit_Rgba32_grayscale_a_LL.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:886afbd1a07fe62599c22e565e16779e3b08a33c0c1a7dcb872a5de9c07f006a +size 53670 diff --git a/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_Gray_WithBottomRightOrigin_16Bit_Rgba32_grayscale_a_LR.png b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_Gray_WithBottomRightOrigin_16Bit_Rgba32_grayscale_a_LR.png new file mode 100644 index 0000000000..2569802a5e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_Gray_WithBottomRightOrigin_16Bit_Rgba32_grayscale_a_LR.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1e9a76387d395379713a4cff6be5679494394c627ca6048fdd6354739589dfc4 +size 53811 diff --git a/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_Gray_WithTopRightOrigin_16Bit_Rgba32_grayscale_a_UR.png b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_Gray_WithTopRightOrigin_16Bit_Rgba32_grayscale_a_UR.png new file mode 100644 index 0000000000..bfa50606ba --- /dev/null +++ b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_Gray_WithTopRightOrigin_16Bit_Rgba32_grayscale_a_UR.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cc0bbdb2c3deeda73fff95934437d661b949a5009e743710d002332f636f3cda +size 53684 diff --git a/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_RunLengthEncoded_Gray_16Bit_Rgba32_grayscale_a_rle_UL.png b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_RunLengthEncoded_Gray_16Bit_Rgba32_grayscale_a_rle_UL.png new file mode 100644 index 0000000000..47cacdbb59 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_RunLengthEncoded_Gray_16Bit_Rgba32_grayscale_a_rle_UL.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7d63ff3a14370883e36c77ebe3ea090b8ecbcab7bc3a4b6f308a4b0516c11c8b +size 54249 diff --git a/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithBottomLeftOrigin_16Bit_Rgba32_grayscale_a_rle_LL.png b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithBottomLeftOrigin_16Bit_Rgba32_grayscale_a_rle_LL.png new file mode 100644 index 0000000000..f35b495c71 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithBottomLeftOrigin_16Bit_Rgba32_grayscale_a_rle_LL.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7eaadc4c41d33c66198624e3fef8f465a3b7abfe2597ad15b7bdfb15175a6f6d +size 54044 diff --git a/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithBottomRightOrigin_16Bit_Rgba32_grayscale_a_rle_LR.png b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithBottomRightOrigin_16Bit_Rgba32_grayscale_a_rle_LR.png new file mode 100644 index 0000000000..947ea79326 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithBottomRightOrigin_16Bit_Rgba32_grayscale_a_rle_LR.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e6979613d4c419757b8455612a29a69c12c072b86e2e502e63a1614cfd4ba0f1 +size 54192 diff --git a/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithTopRightOrigin_16Bit_Rgba32_grayscale_a_rle_UR.png b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithTopRightOrigin_16Bit_Rgba32_grayscale_a_rle_UR.png new file mode 100644 index 0000000000..4b73c56d66 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_RunLengthEncoded_Gray_WithTopRightOrigin_16Bit_Rgba32_grayscale_a_rle_UR.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:24bb93cf8157d155ae7245ee9a8c0d8851876a77e8230387a7b0ebc8cb7dae9f +size 54062 diff --git a/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_WhenAlphaBitsNotSet_Rgba32_32bit_no_alphabits.png b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_WhenAlphaBitsNotSet_Rgba32_32bit_no_alphabits.png new file mode 100644 index 0000000000..e12985f7ae --- /dev/null +++ b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_WhenAlphaBitsNotSet_Rgba32_32bit_no_alphabits.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d3dc0516f656c14b5ffcc40f88d3912f2a8fb310dfbda5836e15847e205919b5 +size 1012 diff --git a/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_WhenAlphaBitsNotSet_Rgba32_32bit_rle_no_alphabits.png b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_WhenAlphaBitsNotSet_Rgba32_32bit_rle_no_alphabits.png new file mode 100644 index 0000000000..726721824e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/TgaDecoderTests/TgaDecoder_CanDecode_WhenAlphaBitsNotSet_Rgba32_32bit_rle_no_alphabits.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cad24c7e4657f2bc8d8a60ea76397eac0adf8dee5fc81f60bc5bc02dd7eeed8f +size 90589 diff --git a/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_0.png b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_0.png new file mode 100644 index 0000000000..ee3c958a03 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_0.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:57102166a1b0457232a294625f1caef8ed9066dd7fdbedc125030499bda26240 +size 243 diff --git a/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_1.png b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_1.png new file mode 100644 index 0000000000..ee3c958a03 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:57102166a1b0457232a294625f1caef8ed9066dd7fdbedc125030499bda26240 +size 243 diff --git a/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_2.png b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_2.png new file mode 100644 index 0000000000..d2fd37326b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c0736b8603de9f1d44b43a96b4daf3338cbaa569a9e344798d3d2ff9e071b3f6 +size 246 diff --git a/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_3.png b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_3.png new file mode 100644 index 0000000000..ae0a01d0f4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:34ae9c4ce6d8b9d2a0440022593d065eac52f177a5b990746f71be454baeec29 +size 250 diff --git a/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_4.png b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_4.png new file mode 100644 index 0000000000..b489475527 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6d0f8f7fe6c51cfc6dce4e08b2a2311655c98b6786ce582a7e6d2e4386740843 +size 244 diff --git a/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_5.png b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_5.png new file mode 100644 index 0000000000..a0f530963b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bfbade89fb32597754e9ce741a1ce074a59a9d644e883eb13013255eb4557030 +size 281 diff --git a/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_6.png b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_6.png new file mode 100644 index 0000000000..3dafbb09a4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_6.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ff8172dedafe18c943de5c9969bb1630757644f34a839118b3b06e637a027fc +size 275 diff --git a/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_7.png b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_7.png new file mode 100644 index 0000000000..81c9742d81 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_7.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a329f10a752098a977758249c4944c0e4939000bbb1bc59ea204978b2baf9b08 +size 268 diff --git a/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_8.png b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_8.png new file mode 100644 index 0000000000..ba28819b08 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/AutoOrientTests/AutoOrient_WorksForAllExifOrientations_F_8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:408228d069af84eff0f5be013bfe8a1ffe8a00027472050b8e14a90f21d4a891 +size 274 diff --git a/tests/Images/External/ReferenceOutput/Transforms/CropTest/Crop_TestPattern30x70_X7Y13.W20H50.png b/tests/Images/External/ReferenceOutput/Transforms/CropTest/Crop_TestPattern30x70_X7Y13.W20H50.png new file mode 100644 index 0000000000..512aaf0dce --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/CropTest/Crop_TestPattern30x70_X7Y13.W20H50.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21e0b9998b48e865da0bbc3a272ed7a2853d8403a0e3a06dac550f41d9a736d8 +size 496 diff --git a/tests/Images/External/ReferenceOutput/Transforms/CropTest/Crop_TestPattern50x50_X-1Y-1.W100H200.png b/tests/Images/External/ReferenceOutput/Transforms/CropTest/Crop_TestPattern50x50_X-1Y-1.W100H200.png new file mode 100644 index 0000000000..72541cdab4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/CropTest/Crop_TestPattern50x50_X-1Y-1.W100H200.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:813b76f8504e846df55c441d94df98910061f085ae577a9cbb9cbd1f4945b2d2 +size 1008 diff --git a/tests/Images/External/ReferenceOutput/Transforms/CropTest/Crop_TestPattern70x30_X0Y0.W70H30.png b/tests/Images/External/ReferenceOutput/Transforms/CropTest/Crop_TestPattern70x30_X0Y0.W70H30.png new file mode 100644 index 0000000000..8ca6b04737 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/CropTest/Crop_TestPattern70x30_X0Y0.W70H30.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c9c2ffd517a52c9e6c60033893bfa13646c8617f2bc9e52e4337291aeb24acab +size 500 diff --git a/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_MultiScanBaselineCMYK_0.25.png b/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_MultiScanBaselineCMYK_0.25.png new file mode 100644 index 0000000000..331b8b30a6 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_MultiScanBaselineCMYK_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a68aa183691be3240e881057cb2f5785e50228c9c5dd98163ba766b5cafa8b55 +size 88601 diff --git a/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_MultiScanBaselineCMYK_0.75.png b/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_MultiScanBaselineCMYK_0.75.png new file mode 100644 index 0000000000..c375fff78b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_MultiScanBaselineCMYK_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:53a7bc1aa7279cce0b73568b6ed9b141377f7654b73dcf926c43c22dd908039a +size 88502 diff --git a/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_ducky_0.25.png b/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_ducky_0.25.png new file mode 100644 index 0000000000..ed48fb094e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_ducky_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7a7a525320284ad8424614e2c18cb686ff9f4d8317c6fd6f5a395ad4ff62ec25 +size 27445 diff --git a/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_ducky_0.75.png b/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_ducky_0.75.png new file mode 100644 index 0000000000..ed48fb094e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_ducky_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7a7a525320284ad8424614e2c18cb686ff9f4d8317c6fd6f5a395ad4ff62ec25 +size 27445 diff --git a/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_jpeg400jfif_0.25.png b/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_jpeg400jfif_0.25.png new file mode 100644 index 0000000000..b60b44a22f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_jpeg400jfif_0.25.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:589289a67e29883cbe17459fc1e6d44f1deab85bcea70c87bb07ebcf4a626e23 +size 167355 diff --git a/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_jpeg400jfif_0.75.png b/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_jpeg400jfif_0.75.png new file mode 100644 index 0000000000..7df378d14a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/EntropyCropTest/EntropyCrop_jpeg400jfif_0.75.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9628c9674323db2983a14e7edb63663400dda2a1c86d01997620c9509b42d349 +size 108104 diff --git a/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern17x32_Horizontal.png b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern17x32_Horizontal.png new file mode 100644 index 0000000000..593c3e06b0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern17x32_Horizontal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3efdbd62d9923dcbe19b67a6af8c97e74786edad5d8c046554885995f2509f80 +size 716 diff --git a/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern17x32_None.png b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern17x32_None.png new file mode 100644 index 0000000000..da4d741f69 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern17x32_None.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e8604559e2812867bb427c83f3752d23046a4275cde09eb3c72d138d499cdc5 +size 714 diff --git a/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern17x32_Vertical.png b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern17x32_Vertical.png new file mode 100644 index 0000000000..a562a226d7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern17x32_Vertical.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe80819519587472325c7534640c99917866c9316dafd0e23d648fbf754d1c7c +size 716 diff --git a/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern20x37_Horizontal.png b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern20x37_Horizontal.png new file mode 100644 index 0000000000..1a2954e4a8 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern20x37_Horizontal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:de933ecd5d553ba278d29156d08ff6405fe498a4dae92b1b24c57b65f23e831e +size 1096 diff --git a/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern20x37_None.png b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern20x37_None.png new file mode 100644 index 0000000000..52fe4d8ce4 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern20x37_None.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ea42b20f513e45a81e6979315d4a32411d78339414e4c27968c82bfd66458f7c +size 1097 diff --git a/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern20x37_Vertical.png b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern20x37_Vertical.png new file mode 100644 index 0000000000..d65f126408 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern20x37_Vertical.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a26b7e67ab4f1f8395bf814ac256c26f9d4d58253fb1de9a92174b4896d1f5cc +size 1093 diff --git a/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern53x37_Horizontal.png b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern53x37_Horizontal.png new file mode 100644 index 0000000000..d49e317963 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern53x37_Horizontal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28d7048bef027c6454899c7901121754821ef19245c1d2444827270d9188a5c0 +size 623 diff --git a/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern53x37_None.png b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern53x37_None.png new file mode 100644 index 0000000000..319d6d0034 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern53x37_None.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e8733b3a1106be440042c47b5271c74c169d8450c2fbd2fdb505efe544e8895d +size 560 diff --git a/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern53x37_Vertical.png b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern53x37_Vertical.png new file mode 100644 index 0000000000..7e57790aae --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_TestPattern53x37_Vertical.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ba67e21cd47395d09fb8c92acb76bcac14f6d482cd04ec08f1b59bfca50c3a6 +size 564 diff --git a/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern17x32_Horizontal.png b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern17x32_Horizontal.png new file mode 100644 index 0000000000..593c3e06b0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern17x32_Horizontal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3efdbd62d9923dcbe19b67a6af8c97e74786edad5d8c046554885995f2509f80 +size 716 diff --git a/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern17x32_None.png b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern17x32_None.png new file mode 100644 index 0000000000..da4d741f69 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern17x32_None.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e8604559e2812867bb427c83f3752d23046a4275cde09eb3c72d138d499cdc5 +size 714 diff --git a/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern17x32_Vertical.png b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern17x32_Vertical.png new file mode 100644 index 0000000000..a562a226d7 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern17x32_Vertical.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fe80819519587472325c7534640c99917866c9316dafd0e23d648fbf754d1c7c +size 716 diff --git a/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern53x37_Horizontal.png b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern53x37_Horizontal.png new file mode 100644 index 0000000000..d49e317963 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern53x37_Horizontal.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28d7048bef027c6454899c7901121754821ef19245c1d2444827270d9188a5c0 +size 623 diff --git a/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern53x37_None.png b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern53x37_None.png new file mode 100644 index 0000000000..319d6d0034 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern53x37_None.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e8733b3a1106be440042c47b5271c74c169d8450c2fbd2fdb505efe544e8895d +size 560 diff --git a/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern53x37_Vertical.png b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern53x37_Vertical.png new file mode 100644 index 0000000000..7e57790aae --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/FlipTests/Flip_WorksOnWrappedMemoryImage_TestPattern53x37_Vertical.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ba67e21cd47395d09fb8c92acb76bcac14f6d482cd04ec08f1b59bfca50c3a6 +size 564 diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_-170.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_-170.png new file mode 100644 index 0000000000..e5ac34ff9d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_-170.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:964e8e5c160d7cd57e3b1fc584a39c1c8c61b835ff6af8264ec0631175286fca +size 10794 diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_-50.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_-50.png new file mode 100644 index 0000000000..5b2ecebd6c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_-50.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2997d51c4ca534df2561f2c3bf1801f04631277b4259e25d9ef3fc164212f722 +size 11223 diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_170.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_170.png new file mode 100644 index 0000000000..d620913d41 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_170.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e8bd1219a9363bcc8dc088fb0a0a17c5e1914d418c89f4affc3fb9abf236f705 +size 10725 diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_50.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_50.png new file mode 100644 index 0000000000..ad39ebb12c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern100x50_50.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d1fb97a28b5f754150343a3dc3c6974ac9abbb1577a44d88db61f0169983db0 +size 11083 diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_-170.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_-170.png new file mode 100644 index 0000000000..8b15fa6c4e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_-170.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e62ccc2cca36898a01445ef03361b84ff19aa1c0498e9dcbf21703dc1c009dd +size 11278 diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_-50.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_-50.png new file mode 100644 index 0000000000..8bb5f272bc --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_-50.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f8f1f14a3c32d8d7e0406c2cf9480aa78dcef7bf223966e80f620680ef68375c +size 12064 diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_170.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_170.png new file mode 100644 index 0000000000..6245b32266 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_170.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7756d2402f4cf7d221d832d921fcff80fef6a36da5373cd9cb46b8e0f00e2fb1 +size 11273 diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_50.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_50.png new file mode 100644 index 0000000000..28435befbc --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithAngle_TestPattern50x100_50.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d49ac2a6529959eb2a5d257c804ba576f9426fafe918c7fb267fc397477666dd +size 12051 diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern100x50_None.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern100x50_None.png new file mode 100644 index 0000000000..9b3d61b932 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern100x50_None.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eb5c9a20be4ffb92095a7c52747ab4827e9148a4a2f25ecdd97b13c48ce381ea +size 882 diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern100x50_Rotate180.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern100x50_Rotate180.png new file mode 100644 index 0000000000..f8b7dd0863 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern100x50_Rotate180.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1bee59ee4be347d16c1d22a2d35ea7fef87c44ad57d0336da9e1b605cc15f707 +size 966 diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern100x50_Rotate270.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern100x50_Rotate270.png new file mode 100644 index 0000000000..86cce91278 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern100x50_Rotate270.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:77226d61a79c94af981cbad0fcf1af3643b7834f8f6b72e8d115b5e9d88afaa1 +size 1036 diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern100x50_Rotate90.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern100x50_Rotate90.png new file mode 100644 index 0000000000..cc9f147d68 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern100x50_Rotate90.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:07f064f60a532aa7ff86a99ef0894bdd1e41c2a6b4e9486c107644aeed9a55a9 +size 934 diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern50x100_None.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern50x100_None.png new file mode 100644 index 0000000000..fdebec3ba0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern50x100_None.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e081d2d3e1dd921459887a5d2715f2697d63844c55a465411f86766d8c657798 +size 1032 diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern50x100_Rotate180.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern50x100_Rotate180.png new file mode 100644 index 0000000000..1263a2374b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern50x100_Rotate180.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bb9e7281b019e2681034ee4a16b739ffe4e8de6e4ec925f7b29eaeb97b9b2216 +size 973 diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern50x100_Rotate270.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern50x100_Rotate270.png new file mode 100644 index 0000000000..43f26c1a11 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern50x100_Rotate270.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f8bd244b20e42588f1cd62c7dcc9f9ba398abd61ffb3d9f17fe41e618c4dac7f +size 908 diff --git a/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern50x100_Rotate90.png b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern50x100_Rotate90.png new file mode 100644 index 0000000000..8bab9de3af --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/RotateTests/Rotate_WithRotateTypeEnum_TestPattern50x100_Rotate90.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff7e04e8f651ef69cb5ea4d0f9d0b567450c72dbdf30efd6e9cb9c32f80546dd +size 1027 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Bgra32_TestPattern100x50_-20_-10.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Bgra32_TestPattern100x50_-20_-10.png new file mode 100644 index 0000000000..163cc401df --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Bgra32_TestPattern100x50_-20_-10.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d56651460aa5c942d800f2c92f0934f4c53b0f83e6fe8a2eb891a85bd9d93542 +size 10244 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Bgra32_TestPattern100x50_20_10.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Bgra32_TestPattern100x50_20_10.png new file mode 100644 index 0000000000..d080ba778d --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Bgra32_TestPattern100x50_20_10.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d2912a3cd8088e9ad5e4e33b7c85825aedf9f910c32abbe78f3560510024b770 +size 10141 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Rgb24_TestPattern100x50_-20_-10.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Rgb24_TestPattern100x50_-20_-10.png new file mode 100644 index 0000000000..058b229a2c --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Rgb24_TestPattern100x50_-20_-10.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:58aea9e0fb398d84dc2f27e1b06ad53d195f2dd06bb1f489c6e51fae5724867d +size 7478 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Rgb24_TestPattern100x50_20_10.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Rgb24_TestPattern100x50_20_10.png new file mode 100644 index 0000000000..899864e537 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_IsNotBoundToSinglePixelType_Rgb24_TestPattern100x50_20_10.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:49b3eaeedfdd1c90b5ec48bf07e387d6cac8062ba15826971c22868b29ecb769 +size 7462 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Bicubic.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Bicubic.png new file mode 100644 index 0000000000..0e0106041a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Bicubic.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e27f9c12e743d3bcc328dc7e5708c738c5a8ccba3ac99a465bb2fbc045afdc45 +size 28062 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Box.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Box.png new file mode 100644 index 0000000000..8f9dd4e74f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Box.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3dfbc7ca2c42fba08daff44f29fdc64f76cb5515ee8f0fd5798270ed64fdeb27 +size 26282 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_CatmullRom.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_CatmullRom.png new file mode 100644 index 0000000000..65e094dc1f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_CatmullRom.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ad0e7cf115b2057fa223c45340f67b1659be6f6acefad32e0b02ca35327ffdf8 +size 28052 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Hermite.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Hermite.png new file mode 100644 index 0000000000..6d1eb77e19 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Hermite.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ca5e0729371222626d711a3f425c602198f5b51c8629e59027e37d63fadf5fa +size 25870 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos2.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos2.png new file mode 100644 index 0000000000..9098e51bee --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf1df2d5b53bc779f01e6ad32ca502cd5fb40826cb1fbf5ddc55b769f68e0d8c +size 28060 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos3.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos3.png new file mode 100644 index 0000000000..00f4e8d925 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f21b8a574beb978befbb44e65def5a4d818fbca6be211cccc455fd819c278531 +size 34325 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos5.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos5.png new file mode 100644 index 0000000000..69afe9a6fd --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5ced1fc39a97381af2ef369b94351a96930a58052343dcaa464b12da1747906f +size 37066 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos8.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos8.png new file mode 100644 index 0000000000..53e0dfa079 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Lanczos8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b60fa32cf39ee70103d8498e5dc751fe2d5801fa30ff9f0948376fac64cb1021 +size 41427 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_MitchellNetravali.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_MitchellNetravali.png new file mode 100644 index 0000000000..9216e2f17b --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_MitchellNetravali.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ce56cc11a369838e011a796cc380f9f06ca915a845e5b6b0425cb7366f162a5c +size 27303 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_NearestNeighbor.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_NearestNeighbor.png new file mode 100644 index 0000000000..8f9dd4e74f --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_NearestNeighbor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3dfbc7ca2c42fba08daff44f29fdc64f76cb5515ee8f0fd5798270ed64fdeb27 +size 26282 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Robidoux.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Robidoux.png new file mode 100644 index 0000000000..79ef7ef283 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Robidoux.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ce82b69d9dde2621a3d54647e7a659d440e2f9b0102831773a97abca4bcfa4c +size 27248 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_RobidouxSharp.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_RobidouxSharp.png new file mode 100644 index 0000000000..823f471f2a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_RobidouxSharp.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:71d45938ec05003c5dcae0962ac6847041410123ba1dc2debbbf41e22ac2d91a +size 27519 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Spline.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Spline.png new file mode 100644 index 0000000000..23766e557a --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Spline.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75bd6138967d8795d0be7fe2e76c889718276924d702349105003c24f08957e2 +size 25559 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Triangle.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Triangle.png new file mode 100644 index 0000000000..33e7b6ef1e --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Triangle.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b280a880b864a14225fd433378dede02cfad897059939cebbe0e04659de6d5a9 +size 25382 diff --git a/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Welch.png b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Welch.png new file mode 100644 index 0000000000..a170cc2cb0 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/Transforms/SkewTests/Skew_WorksWithAllResamplers_ducky_Welch.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c94d6ae8ad8ddab17a5ad1cfc73e711912a3f13e6bd3dfe9e5f0c8ec2c004af +size 33257 diff --git a/tests/Images/External/tools/jpeg/README.md b/tests/Images/External/tools/jpeg/README.md new file mode 100644 index 0000000000..5078f7f161 --- /dev/null +++ b/tests/Images/External/tools/jpeg/README.md @@ -0,0 +1,13 @@ +### dump-jpeg-coeffs.exe +Usage: +``` +dump-jpeg-coeffs [output.dctdump] +``` + +Dumps the raw DCT blocks of the input image into a binary file. The output file follows the following liear layout: +1. The number of components as `Int16` +2. For each component: (2.1) widthInBlocks as `Int16` (2.2) heightInBlocks as `Int16` +3. The block data as a raw `Int16` dump + +The source code could be found here: +https://github.com/antonfirsov/libjpeg-turbo/blob/dump-jpeg-coeffs_/jcstest.cpp diff --git a/tests/Images/External/tools/jpeg/dump-jpeg-coeffs.exe b/tests/Images/External/tools/jpeg/dump-jpeg-coeffs.exe new file mode 100644 index 0000000000..1b490fa8a6 Binary files /dev/null and b/tests/Images/External/tools/jpeg/dump-jpeg-coeffs.exe differ diff --git a/tests/Images/External/tools/jpeg/jpeg62.dll b/tests/Images/External/tools/jpeg/jpeg62.dll new file mode 100644 index 0000000000..ebf21ab141 Binary files /dev/null and b/tests/Images/External/tools/jpeg/jpeg62.dll differ diff --git a/tests/Images/External/tools/jpeg2png-usage-example.cmd b/tests/Images/External/tools/jpeg2png-usage-example.cmd new file mode 100644 index 0000000000..3d7253a5d7 --- /dev/null +++ b/tests/Images/External/tools/jpeg2png-usage-example.cmd @@ -0,0 +1,2 @@ +rem make sure the destination directory "test" exists! +jpeg2png.cmd ..\..\Input\Jpg\baseline .\test \ No newline at end of file diff --git a/tests/Images/External/tools/jpeg2png.cmd b/tests/Images/External/tools/jpeg2png.cmd new file mode 100644 index 0000000000..60d37cfa49 --- /dev/null +++ b/tests/Images/External/tools/jpeg2png.cmd @@ -0,0 +1,9 @@ +@echo off + +set SourceDir=%1 +set DestDir=%2 + +echo Converting all jpeg-s in %InputDir% to PNG into %DestDir% + +for /r "%SourceDir%" %%f in (*.jpeg *.jpg) do magick convert %%f "%DestDir%\%%~nf.png" + diff --git a/tests/Images/External/tools/optimize-all.cmd b/tests/Images/External/tools/optimize-all.cmd new file mode 100644 index 0000000000..75b03e7d04 --- /dev/null +++ b/tests/Images/External/tools/optimize-all.cmd @@ -0,0 +1 @@ +optipng.exe -o 7 ../ReferenceOutput/**/*.png \ No newline at end of file diff --git a/tests/Images/External/tools/optipng.exe b/tests/Images/External/tools/optipng.exe new file mode 100644 index 0000000000..49f9dee097 Binary files /dev/null and b/tests/Images/External/tools/optipng.exe differ diff --git a/tests/Images/Input/Gif/issues/issue1505_argumentoutofrange.png b/tests/Images/Input/Gif/issues/issue1505_argumentoutofrange.png new file mode 100644 index 0000000000..15dfa52a82 --- /dev/null +++ b/tests/Images/Input/Gif/issues/issue1505_argumentoutofrange.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bea0faf09782d0d972e72ad94e53b8ca9c823fd3056fc6a97aba8c43105fcd66 +size 102581 diff --git a/tests/Images/Input/Gif/issues/issue1530.gif b/tests/Images/Input/Gif/issues/issue1530.gif new file mode 100644 index 0000000000..ce8bf4905e --- /dev/null +++ b/tests/Images/Input/Gif/issues/issue1530.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:08b33cab34de2622a7d22edff25fe479a5018c2e0fbc65870b2f21ea7901fc61 +size 1844876 diff --git a/tests/Images/Input/Jpg/baseline/640px-Unequalized_Hawkes_Bay_NZ.jpg b/tests/Images/Input/Jpg/baseline/640px-Unequalized_Hawkes_Bay_NZ.jpg new file mode 100644 index 0000000000..bb89de5895 --- /dev/null +++ b/tests/Images/Input/Jpg/baseline/640px-Unequalized_Hawkes_Bay_NZ.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1fafc61231325c42d94fe163486a6c5144fb6211ccdceb902d5cb4ddebda9e1 +size 32428 diff --git a/tests/Images/Input/Png/colors-saturation-lightness.png b/tests/Images/Input/Png/colors-saturation-lightness.png new file mode 100644 index 0000000000..7af32025c7 --- /dev/null +++ b/tests/Images/Input/Png/colors-saturation-lightness.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bccb0284da98a4edd0a6262ac6a608e252f88c7c63321098b24e9cc11d7a201c +size 146402 diff --git a/tests/Images/Input/Png/issues/Issue_935.png b/tests/Images/Input/Png/issues/Issue_935.png new file mode 100644 index 0000000000..9f9e84dc3c --- /dev/null +++ b/tests/Images/Input/Png/issues/Issue_935.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a9c5cdacc9bedf481c883828de5bfb7902e2bec038fff08830171cf7075e4f9 +size 870 diff --git a/tests/coverlet.runsettings b/tests/coverlet.runsettings index ee408a5f04..cffce3540b 100644 --- a/tests/coverlet.runsettings +++ b/tests/coverlet.runsettings @@ -1,5 +1,9 @@ + + + category!=failing +