Static variables SRGB_MAPPER and GAMMA22_MAPPER replaced by functions to create these mappers.

This commit is contained in:
Kirill Kuzminykh
2022-10-28 20:59:41 +04:00
parent ff2837d704
commit 7b5a1238ca
12 changed files with 260 additions and 143 deletions
+10 -8
View File
@@ -5,7 +5,7 @@
- Breaking changes:
- Struct `ImageView` replaced by enum `DynamicImageView`.
- Struct `ImageViewMut` replaced by enum `DynamicImageViewMut`.
- Trait `Pixel` renamed into `PixelExt` and changed:
- Trait `Pixel` renamed into `PixelExt` and some its internals changed:
- associated type `ComponentsCount` renamed into `CountOfComponents`.
- associated type `ComponentCountOfValues` deleted.
- associated method `components_count` renamed into `count_of_components`.
@@ -14,18 +14,20 @@
generic structure `Pixel`. Use method `new()` to create
instance of one pixel.
- Added module `color` for working with colorspace and gamma:
- Added mapper `SRGB_TO_RGB`. It is lazy static instance of `PixelComponentMapper` to
convert images from SRGB colorspace to linear RGB and back.
- Added mapper `GAMMA22_TO_LINEAR`. It is lazy static instance of `PixelComponentMapper`
to convert images with gamma 2.2 to linear colorspace and back.
- Added structure `PixelComponentMapper` that holds tables for mapping values of pixel's
components in forward and backward directions.
- Added function `create_gamma_22_mapper()` to create instance of `PixelComponentMapper`
that converts images with gamma 2.2 to linear colorspace and back.
- Added function `create_srgb_mapper()` to create instance of `PixelComponentMapper`
that converts images from SRGB colorspace to linear RGB and back.
- Added generic structs `ImageView` and `ImageViewMut`.
- Added functions `change_type_of_pixel_components` and
`change_type_of_pixel_components_dyn` to change type of pixel's
`change_type_of_pixel_components_dyn` that change type of pixel's
components in whole image.
- Added generic trait `IntoPixelComponent<Out: PixelComponent>`.
- Added generic structure `Pixel` for create all types of pixels.
- Added full support of optimisation with help of `SSE4.1` for convolution of `U8x3` images.
- Added support of optimisation with help of `NEON SIMD` for convolution of `U8x4` images.
- Added full support of optimisation with helps of `SSE4.1` for convolution of `U8x3` images.
- Added support of optimisation with helps of `NEON SIMD` for convolution of `U8x4` images.
- Added optimisation for processing `U8x4` images by `MulDiv` with
helps of `NEON SIMD` instructions.
Generated
+176 -64
View File
@@ -45,9 +45,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.65"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602"
checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
[[package]]
name = "argh"
@@ -97,9 +97,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64"
version = "0.13.0"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "bit_field"
@@ -127,9 +127,9 @@ dependencies = [
[[package]]
name = "bumpalo"
version = "3.11.0"
version = "3.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
[[package]]
name = "bytemuck"
@@ -176,9 +176,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.0.9"
version = "4.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30607dd93c420c6f1f80b544be522a0238a7db35e6a12968d28910983fee0df0"
checksum = "335867764ed2de42325fafe6d18b8af74ba97ee0c590fa016f157535b42ab04b"
dependencies = [
"atty",
"bitflags",
@@ -201,9 +201,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.0.9"
version = "4.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a307492e1a34939f79d3b6b9650bd2b971513cd775436bf2b78defeb5af00b"
checksum = "16a1b0f6422af32d5da0c58e2703320f379216ee70198241c84173a8c5ac28f3"
dependencies = [
"heck",
"proc-macro-error",
@@ -233,6 +233,16 @@ dependencies = [
"proc-status",
]
[[package]]
name = "codespan-reporting"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
dependencies = [
"termcolor",
"unicode-width",
]
[[package]]
name = "color_quant"
version = "1.1.0"
@@ -355,6 +365,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "crunchy"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "csv"
version = "1.1.6"
@@ -398,6 +414,50 @@ dependencies = [
"tempfile",
]
[[package]]
name = "cxx"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a"
dependencies = [
"cc",
"cxxbridge-flags",
"cxxbridge-macro",
"link-cplusplus",
]
[[package]]
name = "cxx-build"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827"
dependencies = [
"cc",
"codespan-reporting",
"once_cell",
"proc-macro2",
"quote",
"scratch",
"syn",
]
[[package]]
name = "cxxbridge-flags"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a"
[[package]]
name = "cxxbridge-macro"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "directories-next"
version = "2.0.0"
@@ -440,15 +500,15 @@ dependencies = [
[[package]]
name = "exr"
version = "1.5.1"
version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9a7880199e74c6d3fe45579df2f436c5913a71405494cb89d59234d86b47dc5"
checksum = "8eb5f255b5980bb0c8cf676b675d1a99be40f316881444f44e0462eaf5df5ded"
dependencies = [
"bit_field",
"flume",
"half",
"lebe",
"miniz_oxide",
"miniz_oxide 0.6.2",
"smallvec",
"threadpool",
]
@@ -482,7 +542,6 @@ dependencies = [
"image",
"nix",
"num-traits",
"once_cell",
"png",
"resize",
"rgb",
@@ -512,7 +571,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
dependencies = [
"crc32fast",
"miniz_oxide",
"miniz_oxide 0.5.4",
]
[[package]]
@@ -539,21 +598,21 @@ dependencies = [
[[package]]
name = "futures-core"
version = "0.3.24"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf"
checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
[[package]]
name = "futures-sink"
version = "0.3.24"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56"
checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9"
[[package]]
name = "getrandom"
version = "0.2.7"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"js-sys",
@@ -609,9 +668,12 @@ dependencies = [
[[package]]
name = "half"
version = "1.8.2"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
checksum = "ad6a9459c9c30b177b925162351f97e7d967c7ea8bab3b8352805327daf45554"
dependencies = [
"crunchy",
]
[[package]]
name = "hashbrown"
@@ -663,17 +725,28 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "iana-time-zone"
version = "0.1.50"
version = "0.1.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd911b35d940d2bd0bea0f9100068e5b97b51a1cbe13d13382f132e0365257a0"
checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"winapi",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
dependencies = [
"cxx",
"cxx-build",
]
[[package]]
name = "idna"
version = "0.3.0"
@@ -720,9 +793,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "itoa"
version = "1.0.3"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
[[package]]
name = "jobserver"
@@ -765,9 +838,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
[[package]]
name = "libc"
version = "0.2.134"
version = "0.2.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb"
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
[[package]]
name = "libgit2-sys"
@@ -804,6 +877,15 @@ dependencies = [
"vcpkg",
]
[[package]]
name = "link-cplusplus"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369"
dependencies = [
"cc",
]
[[package]]
name = "lock_api"
version = "0.4.9"
@@ -857,10 +939,19 @@ dependencies = [
]
[[package]]
name = "mio"
version = "0.8.4"
name = "miniz_oxide"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [
"adler",
]
[[package]]
name = "mio"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
dependencies = [
"libc",
"log",
@@ -963,9 +1054,9 @@ dependencies = [
[[package]]
name = "parking_lot_core"
version = "0.9.3"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
dependencies = [
"cfg-if",
"libc",
@@ -1008,9 +1099,9 @@ dependencies = [
[[package]]
name = "pkg-config"
version = "0.3.25"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "png"
@@ -1021,7 +1112,7 @@ dependencies = [
"bitflags",
"crc32fast",
"flate2",
"miniz_oxide",
"miniz_oxide 0.5.4",
]
[[package]]
@@ -1050,9 +1141,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.46"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b"
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
dependencies = [
"unicode-ident",
]
@@ -1172,6 +1263,7 @@ dependencies = [
"fast_image_resize",
"image",
"log",
"once_cell",
]
[[package]]
@@ -1217,19 +1309,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
version = "1.0.145"
name = "scratch"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898"
[[package]]
name = "serde"
version = "1.0.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.145"
version = "1.0.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
dependencies = [
"proc-macro2",
"quote",
@@ -1238,11 +1336,11 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.85"
version = "1.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45"
dependencies = [
"itoa 1.0.3",
"itoa 1.0.4",
"ryu",
"serde",
]
@@ -1312,9 +1410,9 @@ checksum = "e72d8b19ab05827afefcca66bf47040c1e66a0901eb814784c77d4ec118bd309"
[[package]]
name = "syn"
version = "1.0.101"
version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2"
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
dependencies = [
"proc-macro2",
"quote",
@@ -1440,9 +1538,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
[[package]]
name = "unicode-ident"
version = "1.0.4"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
[[package]]
name = "unicode-normalization"
@@ -1587,43 +1685,57 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.36.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
name = "windows_aarch64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
-1
View File
@@ -21,7 +21,6 @@ exclude = ["/data"]
[dependencies]
num-traits = "0.2.15"
once_cell = "1.15.0"
thiserror = "1.0.37"
+6 -5
View File
@@ -25,7 +25,7 @@ Supported pixel formats and available optimisations:
## Colorspace
Resizer from this crate does not convert image into linear color space
Resizer from this crate does not convert image into linear colorspace
during resize process. If it is important for you to resize images with a
non-linear color space (e.g. sRGB) correctly, then you need to convert
it to a linear color space before resizing and convert back a color space of
@@ -33,12 +33,13 @@ result image. [Read more](https://legacy.imagemagick.org/Usage/resize/#resize_co
about resizing with respect to color space.
This crate provides the
[PixelComponentMapper](https://docs.rs/fast_image_resize/target/doc/fast_image_resize/color/struct.PixelComponentMapper.html)
structure that allows you to create color space converters for images
[PixelComponentMapper](https://docs.rs/fast_image_resize/target/doc/fast_image_resize/struct.PixelComponentMapper.html)
structure that allows you to create colorspace converters for images
whose pixels based on `u8` and `u16` components.
In addition, the crate contains lazy-static instances of the `PixelComponentMapper`
structure: `SRGB_TO_RGB` and `GAMMA22_TO_LINEAR`.
In addition, the crate contains functions `create_gamma_22_mapper()`
and `create_srgb_mapper()` to create instance of `PixelComponentMapper`
that converts images from sRGB or gamma 2.2 into linear colorspace and back.
## Some benchmarks
+2 -4
View File
@@ -1,9 +1,7 @@
use glassbench::*;
use std::ops::Deref;
use fast_image_resize::color::mappers::SRGB_TO_RGB;
use fast_image_resize::pixels::U8x3;
use fast_image_resize::Image;
use fast_image_resize::{create_srgb_mapper, Image};
use testing::PixelTestingExt;
mod utils;
@@ -17,7 +15,7 @@ pub fn bench_color_mapper(bench: &mut Bench) {
);
let src_view = src_image.view();
let mut dst_view = dst_image.view_mut();
let mapper = SRGB_TO_RGB.deref();
let mapper = create_srgb_mapper();
bench.task("SRGB U8x3 => RGB U8x3", |task| {
task.iter(|| {
mapper.forward_map(&src_view, &mut dst_view).unwrap();
+1
View File
@@ -13,3 +13,4 @@ log = "0.4.17"
env_logger = "0.9.1"
anyhow = "1.0.65"
clap-verbosity-flag = "2.0.0"
once_cell = "1.15.0"
+9 -7
View File
@@ -7,6 +7,7 @@ use clap::Parser;
use image::io::Reader as ImageReader;
use image::ColorType;
use log::debug;
use once_cell::sync::Lazy;
use fast_image_resize as fr;
@@ -36,7 +37,7 @@ struct Cli {
#[clap(short, long, action)]
overwrite: bool,
/// Colorspace of image
/// Colorspace of source image
#[clap(short, long, value_enum, default_value_t = structs::ColorSpace::NonLinear)]
colorspace: structs::ColorSpace,
@@ -56,6 +57,9 @@ struct Cli {
verbose: clap_verbosity_flag::Verbosity,
}
static SRGB_TO_RGB: Lazy<fr::PixelComponentMapper> = Lazy::new(fr::create_srgb_mapper);
static GAMMA22_TO_LINEAR: Lazy<fr::PixelComponentMapper> = Lazy::new(fr::create_gamma_22_mapper);
fn main() -> Result<()> {
let cli: Cli = Cli::parse();
env_logger::Builder::new()
@@ -194,10 +198,9 @@ fn open_source_image(cli: &Cli) -> Result<(fr::Image<'static>, ColorType, fr::Pi
let mut linear_src_image =
fr::Image::new(src_image.width(), src_image.height(), internal_pixel_type);
if color_type.has_color() {
fr::color::mappers::SRGB_TO_RGB
.forward_map(&src_image.view(), &mut linear_src_image.view_mut())?;
SRGB_TO_RGB.forward_map(&src_image.view(), &mut linear_src_image.view_mut())?;
} else {
fr::color::mappers::GAMMA22_TO_LINEAR
GAMMA22_TO_LINEAR
.forward_map(&src_image.view(), &mut linear_src_image.view_mut())?;
}
linear_src_image
@@ -293,10 +296,9 @@ fn save_result(
let mut non_linear_dst_image =
fr::Image::new(image.width(), image.height(), pixel_type);
if color_type.has_color() {
fr::color::mappers::SRGB_TO_RGB
.backward_map(&image.view(), &mut non_linear_dst_image.view_mut())?;
SRGB_TO_RGB.backward_map(&image.view(), &mut non_linear_dst_image.view_mut())?;
} else {
fr::color::mappers::GAMMA22_TO_LINEAR
GAMMA22_TO_LINEAR
.backward_map(&image.view(), &mut non_linear_dst_image.view_mut())?;
}
non_linear_dst_image
-1
View File
@@ -31,7 +31,6 @@ pub(crate) unsafe fn multiply_alpha_inplace(image: &mut ImageViewMut<U8x4>) {
#[target_feature(enable = "neon")]
unsafe fn multiply_alpha_row(src_row: &[U8x4], dst_row: &mut [U8x4]) {
let zero = vdupq_n_u8(0);
// let half = vdupq_n_u16(128);
const MAX_A: u32 = 0xff000000u32;
let max_alpha = vreinterpretq_u8_u32(vdupq_n_u32(MAX_A));
+9 -9
View File
@@ -1,6 +1,4 @@
use once_cell::sync::Lazy;
use crate::color::PixelComponentMapper;
use crate::PixelComponentMapper;
fn gamma_into_linear(input: f32) -> f32 {
input.powf(2.2)
@@ -10,9 +8,10 @@ fn linear_into_gamma(input: f32) -> f32 {
input.powf(1.0 / 2.2)
}
/// Mapper to convert an image from Gamma 2.2 to linear colorspace and back.
pub static GAMMA22_TO_LINEAR: Lazy<PixelComponentMapper> =
Lazy::new(|| PixelComponentMapper::new(&gamma_into_linear, &linear_into_gamma));
/// Create mapper to convert an image from Gamma 2.2 to linear colorspace and back.
pub fn create_gamma_22_mapper() -> PixelComponentMapper {
PixelComponentMapper::new(gamma_into_linear, linear_into_gamma)
}
/// https://en.wikipedia.org/wiki/SRGB#From_sRGB_to_CIE_XYZ
/// http://www.ericbrasseur.org/gamma.html?i=2#formulas
@@ -36,6 +35,7 @@ fn linear_to_srgb(input: f32) -> f32 {
}
}
/// Mapper to convert an image from sRGB to linear RGB colorspace and back.
pub static SRGB_TO_RGB: Lazy<PixelComponentMapper> =
Lazy::new(|| PixelComponentMapper::new(&srgb_to_linear, &linear_to_srgb));
/// Create mapper to convert an image from sRGB to linear RGB colorspace and back.
pub fn create_srgb_mapper() -> PixelComponentMapper {
PixelComponentMapper::new(srgb_to_linear, linear_to_srgb)
}
+21 -21
View File
@@ -1,11 +1,4 @@
//! Functions for working with colorspace and gamma.
//!
//! Supported all pixel types exclude `I32` and `F32`.
//!
//! Source and destination images may have different bit depth of one pixel component.
//! But count of components must be equal.
//! For example, you may convert `U8x3` image with sRGB colorspace into
//! `U16x3` image with linear colorspace.
//! Functions and structs for working with colorspace and gamma.
use num_traits::bounds::UpperBounded;
use num_traits::Zero;
@@ -13,7 +6,7 @@ use crate::pixels::{GetCount, IntoPixelComponent, PixelComponent, PixelExt, Valu
use crate::{DynamicImageView, DynamicImageViewMut, MappingError};
use crate::{ImageView, ImageViewMut};
pub mod mappers;
pub(crate) mod mappers;
trait FromF32 {
fn from_f32(x: f32) -> Self;
@@ -142,6 +135,13 @@ struct MappingTablesGroup {
/// This structure holds tables for mapping values of pixel's
/// components in forward and backward directions.
///
/// Supported all pixel types exclude `I32` and `F32`.
///
/// Source and destination images may have different bit depth of one pixel component.
/// But count of components must be equal.
/// For example, you may convert `U8x3` image with sRGB colorspace into
/// `U16x3` image with linear colorspace.
///
/// Alpha channel from such pixel types as `U8x2`, `U8x4`, `U16x2` and `U16x4`
/// not mapped with tables. This component transformed into destination
/// component type with help of [IntoPixelComponent] trait.
@@ -160,7 +160,7 @@ impl PixelComponentMapper {
///
/// Example:
/// ```
/// # use fast_image_resize::color::PixelComponentMapper;
/// # use fast_image_resize::PixelComponentMapper;
/// #
/// fn gamma_into_linear(input: f32) -> f32 {
/// input.powf(2.2)
@@ -171,27 +171,27 @@ impl PixelComponentMapper {
/// }
///
/// let gamma22_to_linear = PixelComponentMapper::new(
/// &gamma_into_linear,
/// &linear_into_gamma,
/// gamma_into_linear,
/// linear_into_gamma,
/// );
/// ```
pub fn new<FF, BF>(forward_map_func: &FF, backward_map_func: &BF) -> Self
pub fn new<FF, BF>(forward_map_func: FF, backward_map_func: BF) -> Self
where
FF: Fn(f32) -> f32,
BF: Fn(f32) -> f32,
{
Self {
forward_mapping_tables: MappingTablesGroup {
u8_u8: MappingTable::new(forward_map_func),
u8_u16: MappingTable::new(forward_map_func),
u16_u8: MappingTable::new(forward_map_func),
u16_u16: MappingTable::new(forward_map_func),
u8_u8: MappingTable::new(&forward_map_func),
u8_u16: MappingTable::new(&forward_map_func),
u16_u8: MappingTable::new(&forward_map_func),
u16_u16: MappingTable::new(&forward_map_func),
},
backward_mapping_tables: MappingTablesGroup {
u8_u8: MappingTable::new(backward_map_func),
u8_u16: MappingTable::new(backward_map_func),
u16_u8: MappingTable::new(backward_map_func),
u16_u16: MappingTable::new(backward_map_func),
u8_u8: MappingTable::new(&backward_map_func),
u8_u16: MappingTable::new(&backward_map_func),
u16_u8: MappingTable::new(&backward_map_func),
u16_u16: MappingTable::new(&backward_map_func),
},
}
}
+3 -1
View File
@@ -1,6 +1,8 @@
#![doc = include_str!("../README.md")]
pub use alpha::errors::*;
pub use color::mappers::*;
pub use color::PixelComponentMapper;
pub use convolution::FilterType;
pub use dynamic_image_view::{
change_type_of_pixel_components_dyn, DynamicImageView, DynamicImageViewMut,
@@ -14,7 +16,7 @@ pub use resizer::{CpuExtensions, ResizeAlg, Resizer};
pub use crate::image::Image;
mod alpha;
pub mod color;
mod color;
mod convolution;
mod dynamic_image_view;
mod errors;
+23 -22
View File
@@ -6,6 +6,7 @@ mod gamma_tests {
#[test]
fn gamma22_into_linear_test() {
let mapper = fr::create_gamma_22_mapper();
let buffer: Vec<u8> = (0u8..=255).collect();
let src_image =
fr::Image::from_vec_u8(nonzero(16), nonzero(16), buffer, fr::PixelType::U8).unwrap();
@@ -14,7 +15,7 @@ mod gamma_tests {
// into U8
let mut dst_image = fr::Image::new(nonzero(16), nonzero(16), fr::PixelType::U8);
fr::color::mappers::GAMMA22_TO_LINEAR
mapper
.forward_map(&src_image.view(), &mut dst_image.view_mut())
.unwrap();
let dst_checksum = testing::image_checksum::<1>(dst_image.buffer());
@@ -22,7 +23,7 @@ mod gamma_tests {
// into U16
let mut dst_image = fr::Image::new(nonzero(16), nonzero(16), fr::PixelType::U16);
fr::color::mappers::GAMMA22_TO_LINEAR
mapper
.forward_map(&src_image.view(), &mut dst_image.view_mut())
.unwrap();
let dst_checksum = testing::image_u16_checksum::<1>(dst_image.buffer());
@@ -31,18 +32,17 @@ mod gamma_tests {
#[test]
fn gamma22_into_linear_errors_test() {
let mapper = fr::create_gamma_22_mapper();
let buffer: Vec<u8> = (0u8..=255).collect();
let src_image =
fr::Image::from_vec_u8(nonzero(16), nonzero(16), buffer, fr::PixelType::U8).unwrap();
let mut dst_image = fr::Image::new(nonzero(16), nonzero(1), fr::PixelType::U8);
let result = fr::color::mappers::GAMMA22_TO_LINEAR
.forward_map(&src_image.view(), &mut dst_image.view_mut());
let result = mapper.forward_map(&src_image.view(), &mut dst_image.view_mut());
assert!(matches!(result, Err(fr::MappingError::DifferentDimensions)));
let mut dst_image = fr::Image::new(nonzero(16), nonzero(16), fr::PixelType::U8x2);
let result = fr::color::mappers::GAMMA22_TO_LINEAR
.forward_map(&src_image.view(), &mut dst_image.view_mut());
let result = mapper.forward_map(&src_image.view(), &mut dst_image.view_mut());
assert!(matches!(
result,
Err(fr::MappingError::UnsupportedCombinationOfImageTypes)
@@ -51,12 +51,13 @@ mod gamma_tests {
#[test]
fn linear_into_gamma22_test() {
let mapper = fr::create_gamma_22_mapper();
let buffer: Vec<u8> = (0u8..=255).collect();
let src_image =
fr::Image::from_vec_u8(nonzero(16), nonzero(16), buffer, fr::PixelType::U8).unwrap();
let mut dst_image = fr::Image::new(nonzero(16), nonzero(16), fr::PixelType::U8);
fr::color::mappers::GAMMA22_TO_LINEAR
mapper
.backward_map(&src_image.view(), &mut dst_image.view_mut())
.unwrap();
@@ -68,18 +69,17 @@ mod gamma_tests {
#[test]
fn linear_into_gamma22_errors_test() {
let mapper = fr::create_gamma_22_mapper();
let buffer: Vec<u8> = (0u8..=255).collect();
let src_image =
fr::Image::from_vec_u8(nonzero(16), nonzero(16), buffer, fr::PixelType::U8).unwrap();
let mut dst_image = fr::Image::new(nonzero(16), nonzero(1), fr::PixelType::U8);
let result = fr::color::mappers::GAMMA22_TO_LINEAR
.backward_map(&src_image.view(), &mut dst_image.view_mut());
let result = mapper.backward_map(&src_image.view(), &mut dst_image.view_mut());
assert!(matches!(result, Err(fr::MappingError::DifferentDimensions)));
let mut dst_image = fr::Image::new(nonzero(16), nonzero(16), fr::PixelType::U8x2);
let result = fr::color::mappers::GAMMA22_TO_LINEAR
.backward_map(&src_image.view(), &mut dst_image.view_mut());
let result = mapper.backward_map(&src_image.view(), &mut dst_image.view_mut());
assert!(matches!(
result,
Err(fr::MappingError::UnsupportedCombinationOfImageTypes)
@@ -92,6 +92,7 @@ mod srgb_tests {
#[test]
fn srgb_into_rgb_test() {
let mapper = fr::create_srgb_mapper();
let buffer: Vec<u8> = (0u8..=255).flat_map(|v| [v, v, v]).collect();
let src_image =
fr::Image::from_vec_u8(nonzero(16), nonzero(16), buffer, fr::PixelType::U8x3).unwrap();
@@ -99,7 +100,7 @@ mod srgb_tests {
assert_eq!(src_checksum, [32640, 32640, 32640]);
let mut dst_image = fr::Image::new(nonzero(16), nonzero(16), fr::PixelType::U8x3);
fr::color::mappers::SRGB_TO_RGB
mapper
.forward_map(&src_image.view(), &mut dst_image.view_mut())
.unwrap();
@@ -109,6 +110,7 @@ mod srgb_tests {
#[test]
fn srgba_into_rgba_test() {
let mapper = fr::create_srgb_mapper();
let buffer: Vec<u8> = (0u8..=255).flat_map(|v| [v, v, v, 255]).collect();
let src_image =
fr::Image::from_vec_u8(nonzero(16), nonzero(16), buffer, fr::PixelType::U8x4).unwrap();
@@ -116,7 +118,7 @@ mod srgb_tests {
assert_eq!(src_checksum, [32640, 32640, 32640, 65280]);
let mut dst_image = fr::Image::new(nonzero(16), nonzero(16), fr::PixelType::U8x4);
fr::color::mappers::SRGB_TO_RGB
mapper
.forward_map(&src_image.view(), &mut dst_image.view_mut())
.unwrap();
@@ -126,18 +128,17 @@ mod srgb_tests {
#[test]
fn srgb_into_rgb_errors_test() {
let mapper = fr::create_srgb_mapper();
let buffer: Vec<u8> = (0u8..=255).flat_map(|v| [v, v, v]).collect();
let src_image =
fr::Image::from_vec_u8(nonzero(16), nonzero(16), buffer, fr::PixelType::U8x3).unwrap();
let mut dst_image = fr::Image::new(nonzero(16), nonzero(1), fr::PixelType::U8x3);
let result = fr::color::mappers::SRGB_TO_RGB
.forward_map(&src_image.view(), &mut dst_image.view_mut());
let result = mapper.forward_map(&src_image.view(), &mut dst_image.view_mut());
assert!(matches!(result, Err(fr::MappingError::DifferentDimensions)));
let mut dst_image = fr::Image::new(nonzero(16), nonzero(16), fr::PixelType::U8x2);
let result = fr::color::mappers::SRGB_TO_RGB
.forward_map(&src_image.view(), &mut dst_image.view_mut());
let result = mapper.forward_map(&src_image.view(), &mut dst_image.view_mut());
assert!(matches!(
result,
Err(fr::MappingError::UnsupportedCombinationOfImageTypes)
@@ -146,6 +147,7 @@ mod srgb_tests {
#[test]
fn rgb_into_srgb_test() {
let mapper = fr::create_srgb_mapper();
let buffer: Vec<u8> = (0u8..=255).flat_map(|v| [v, v, v]).collect();
let src_image =
fr::Image::from_vec_u8(nonzero(16), nonzero(16), buffer, fr::PixelType::U8x3).unwrap();
@@ -153,7 +155,7 @@ mod srgb_tests {
assert_eq!(src_checksum, [32640, 32640, 32640]);
let mut dst_image = fr::Image::new(nonzero(16), nonzero(16), fr::PixelType::U8x3);
fr::color::mappers::SRGB_TO_RGB
mapper
.backward_map(&src_image.view(), &mut dst_image.view_mut())
.unwrap();
@@ -163,18 +165,17 @@ mod srgb_tests {
#[test]
fn rgb_into_srgb_errors_test() {
let mapper = fr::create_srgb_mapper();
let buffer: Vec<u8> = (0u8..=255).flat_map(|v| [v, v, v]).collect();
let src_image =
fr::Image::from_vec_u8(nonzero(16), nonzero(16), buffer, fr::PixelType::U8x3).unwrap();
let mut dst_image = fr::Image::new(nonzero(16), nonzero(1), fr::PixelType::U8x3);
let result = fr::color::mappers::SRGB_TO_RGB
.backward_map(&src_image.view(), &mut dst_image.view_mut());
let result = mapper.backward_map(&src_image.view(), &mut dst_image.view_mut());
assert!(matches!(result, Err(fr::MappingError::DifferentDimensions)));
let mut dst_image = fr::Image::new(nonzero(16), nonzero(16), fr::PixelType::U8x2);
let result = fr::color::mappers::SRGB_TO_RGB
.backward_map(&src_image.view(), &mut dst_image.view_mut());
let result = mapper.backward_map(&src_image.view(), &mut dst_image.view_mut());
assert!(matches!(
result,
Err(fr::MappingError::UnsupportedCombinationOfImageTypes)