mirror of
https://github.com/Cykooz/fast_image_resize.git
synced 2026-10-08 01:11:09 +00:00
- Breaking changes:
- Struct `ImageView` replaced by enum `DynamicImageView`.
- Struct `ImageViewMut` replaced by enum `DynamicImageViewMut`.
- Trait `Pixel` changed:
- Associated type `ComponentsCount` renamed into `CountOfComponents`.
- Associated type `ComponentCountOfValues` renamed into `CountOfComponentValues`.
- Associated method `components_count` renamed into `count_of_components`.
- Associated method `component_count_of_values` renamed into `count_of_component_values`.
- Added generic structs `ImageView` and `ImageViewMut`.
- Added module `color` for working with colorspace and gamma.
- Added functions `change_type_of_pixel_components` and
`change_type_of_pixel_components_dyn` to change type of pixel's
components in whole image.
- Added generic trait `IntoPixelComponent<Out: PixelComponent>`.
### Example application
- Added option `--high_precision` to use `u16` as pixel components
for intermediate image representation.
- Added converting of source image into linear colorspace before it will be resized.
Destination image will be returned into original colorspace before it will be saved.
This commit is contained in:
@@ -1,3 +1,29 @@
|
||||
## [Unreleased] - ReleaseDate
|
||||
|
||||
### Crate
|
||||
|
||||
- Breaking changes:
|
||||
- Struct `ImageView` replaced by enum `DynamicImageView`.
|
||||
- Struct `ImageViewMut` replaced by enum `DynamicImageViewMut`.
|
||||
- Trait `Pixel` changed:
|
||||
- Associated type `ComponentsCount` renamed into `CountOfComponents`.
|
||||
- Associated type `ComponentCountOfValues` renamed into `CountOfComponentValues`.
|
||||
- Associated method `components_count` renamed into `count_of_components`.
|
||||
- Associated method `component_count_of_values` renamed into `count_of_component_values`.
|
||||
- Added generic structs `ImageView` and `ImageViewMut`.
|
||||
- Added module `color` for working with colorspace and gamma.
|
||||
- Added functions `change_type_of_pixel_components` and
|
||||
`change_type_of_pixel_components_dyn` to change type of pixel's
|
||||
components in whole image.
|
||||
- Added generic trait `IntoPixelComponent<Out: PixelComponent>`.
|
||||
|
||||
### Example application
|
||||
|
||||
- Added option `--high_precision` to use `u16` as pixel components
|
||||
for intermediate image representation.
|
||||
- Added converting of source image into linear colorspace before it will be resized.
|
||||
Destination image will be returned into original colorspace before it will be saved.
|
||||
|
||||
## [1.0.0] - 2022-07-24
|
||||
|
||||
- Added example of command line application "resizer".
|
||||
|
||||
Generated
+133
-135
@@ -8,12 +8,6 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "adler32"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.4.7"
|
||||
@@ -33,18 +27,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.18"
|
||||
version = "0.7.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
|
||||
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.58"
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.65"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602"
|
||||
|
||||
[[package]]
|
||||
name = "argh"
|
||||
@@ -124,15 +127,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.10.0"
|
||||
version = "3.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3"
|
||||
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.11.0"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5377c8865e74a160d21f29c2d40669f53286db6eab59b88540cbb12ffc8b835"
|
||||
checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
@@ -157,23 +160,25 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.19"
|
||||
version = "0.4.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
|
||||
checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"time",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.2.14"
|
||||
version = "3.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54635806b078b7925d6e36810b1755f2a4b5b4d57560432c1ecf60bcbe10602b"
|
||||
checksum = "1ed5341b2301a26ab80be5cbdced622e80ed808483c52e45e3310a877d3b37d7"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
@@ -198,9 +203,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.2.7"
|
||||
version = "3.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "759bf187376e1afa7b85b959e6a664a3e7a95203415dba952ad19139e798f902"
|
||||
checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
|
||||
dependencies = [
|
||||
"heck 0.4.0",
|
||||
"proc-macro-error",
|
||||
@@ -245,6 +250,12 @@ dependencies = [
|
||||
"crossterm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
@@ -391,15 +402,6 @@ dependencies = [
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deflate"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f"
|
||||
dependencies = [
|
||||
"adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "directories-next"
|
||||
version = "2.0.0"
|
||||
@@ -423,9 +425,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.7.0"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be"
|
||||
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
@@ -442,16 +444,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "exr"
|
||||
version = "1.4.2"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14cc0e06fb5f67e5d6beadf3a382fec9baca1aa751c6d5368fdeee7e5932c215"
|
||||
checksum = "78c26a90d9dd411a3d119d6f55752fb4c134ca243250c32fb9cab7b2561638d2"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"deflate",
|
||||
"flume",
|
||||
"half",
|
||||
"inflate",
|
||||
"lebe",
|
||||
"miniz_oxide",
|
||||
"smallvec",
|
||||
"threadpool",
|
||||
]
|
||||
@@ -533,25 +534,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.0.1"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
|
||||
checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
|
||||
dependencies = [
|
||||
"matches",
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.21"
|
||||
version = "0.3.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
|
||||
checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf"
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.21"
|
||||
version = "0.3.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
|
||||
checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
@@ -675,12 +675,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.2.3"
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
|
||||
checksum = "237a0714f28b1ee39ccec0770ccb544eb02c9ef2c82bb096230eefcffa6468b0"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"js-sys",
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
|
||||
dependencies = [
|
||||
"matches",
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
]
|
||||
@@ -714,15 +727,6 @@ dependencies = [
|
||||
"hashbrown 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inflate"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff"
|
||||
dependencies = [
|
||||
"adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
@@ -740,9 +744,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.2"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
|
||||
checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
@@ -764,9 +768,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.58"
|
||||
version = "0.3.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27"
|
||||
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
@@ -779,15 +783,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "lebe"
|
||||
version = "0.5.1"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7efd1d698db0759e6ef11a7cd44407407399a910c774dd804c64c032da7826ff"
|
||||
checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.126"
|
||||
version = "0.2.132"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||
checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
|
||||
|
||||
[[package]]
|
||||
name = "libgit2-sys"
|
||||
@@ -826,9 +830,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.7"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
|
||||
checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
@@ -843,12 +847,6 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matches"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
@@ -875,9 +873,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.5.3"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
|
||||
checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
@@ -905,10 +903,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.24.2"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc"
|
||||
checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
@@ -956,9 +955,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.13.0"
|
||||
version = "1.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
|
||||
checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
|
||||
|
||||
[[package]]
|
||||
name = "open"
|
||||
@@ -972,9 +971,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.2.0"
|
||||
version = "6.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4"
|
||||
checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
@@ -1007,24 +1006,24 @@ checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.1.0"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.0.11"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78203e83c48cffbe01e4a2d35d566ca4de445d79a85372fc64e378bfc812a260"
|
||||
checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
|
||||
dependencies = [
|
||||
"pin-project-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-internal"
|
||||
version = "1.0.11"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74"
|
||||
checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1039,13 +1038,13 @@ checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
|
||||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.17.5"
|
||||
version = "0.17.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba"
|
||||
checksum = "8f0e7f4c94ec26ff209cee506314212639d6c91b80afb82984819fafce9df01c"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crc32fast",
|
||||
"deflate",
|
||||
"flate2",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
@@ -1075,9 +1074,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.40"
|
||||
version = "1.0.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
|
||||
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -1093,9 +1092,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.20"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@@ -1126,9 +1125,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.15"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "534cfe58d6a18cc17120fbf4635d53d14691c1fe4d951064df9bd326178d7d5a"
|
||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
@@ -1178,9 +1177,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "resize"
|
||||
version = "0.7.3"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d05ed0e778666d123be79444a5ddb81506fda18ea6d7c05a8b6a701a6215d310"
|
||||
checksum = "87e7bdfff05e26408cf8f82fe896ce3d7624f0c0b06c84b2f1009c50452ead41"
|
||||
dependencies = [
|
||||
"fallible_collections",
|
||||
"rgb",
|
||||
@@ -1225,9 +1224,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.10"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
|
||||
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
|
||||
|
||||
[[package]]
|
||||
name = "scoped_threadpool"
|
||||
@@ -1243,18 +1242,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.140"
|
||||
version = "1.0.144"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03"
|
||||
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.140"
|
||||
version = "1.0.144"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f2122636b9fe3b81f1cb25099fcf2d3f542cdb1d45940d56c713158884a05da"
|
||||
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1263,11 +1262,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.82"
|
||||
version = "1.0.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7"
|
||||
checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
|
||||
dependencies = [
|
||||
"itoa 1.0.2",
|
||||
"itoa 1.0.3",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
@@ -1337,9 +1336,9 @@ checksum = "e72d8b19ab05827afefcca66bf47040c1e66a0901eb814784c77d4ec118bd309"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.98"
|
||||
version = "1.0.99"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
|
||||
checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1399,18 +1398,18 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.31"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
|
||||
checksum = "c53f98874615aea268107765aa1ed8f6116782501d18e53d08b471733bea6c85"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.31"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
|
||||
checksum = "f8b463991b4eab2d801e724172285ec4195c650e8ec79b149e6c2a8e6dd3f783"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1428,9 +1427,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tiff"
|
||||
version = "0.7.2"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cfada0986f446a770eca461e8c6566cb879682f7d687c8348aa0c857bd52286"
|
||||
checksum = "7259662e32d1e219321eb309d5f9d898b779769d81b76e762c07c8e5d38fcb65"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"jpeg-decoder",
|
||||
@@ -1471,9 +1470,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.2"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7"
|
||||
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
@@ -1486,25 +1485,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.9.0"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
|
||||
checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.9"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.2.2"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
|
||||
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
"matches",
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
@@ -1534,9 +1532,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.81"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994"
|
||||
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
@@ -1544,13 +1542,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.81"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a"
|
||||
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
@@ -1559,9 +1557,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.81"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa"
|
||||
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@@ -1569,9 +1567,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.81"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048"
|
||||
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1582,9 +1580,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.81"
|
||||
version = "0.2.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be"
|
||||
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
|
||||
|
||||
[[package]]
|
||||
name = "weezl"
|
||||
|
||||
+5
-5
@@ -21,17 +21,17 @@ exclude = ["/data"]
|
||||
|
||||
[dependencies]
|
||||
num-traits = "0.2.15"
|
||||
once_cell = "1.13.0"
|
||||
thiserror = "1.0.31"
|
||||
once_cell = "1.14.0"
|
||||
thiserror = "1.0.35"
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
glassbench = "0.3.3"
|
||||
image = "0.24.3"
|
||||
resize = "0.7.3"
|
||||
resize = "0.7.4"
|
||||
rgb = "0.8.33"
|
||||
png = "0.17.5"
|
||||
nix = { version = "0.24.1", default-features = false, features = ["sched"] }
|
||||
png = "0.17.6"
|
||||
nix = { version = "0.25.0", default-features = false, features = ["sched"] }
|
||||
testing = {path= "testing" }
|
||||
|
||||
|
||||
|
||||
@@ -118,8 +118,7 @@ fn main() {
|
||||
height,
|
||||
img.to_rgba8().into_raw(),
|
||||
fr::PixelType::U8x4,
|
||||
)
|
||||
.unwrap();
|
||||
).unwrap();
|
||||
|
||||
// Multiple RGB channels of source image by alpha channel
|
||||
// (not required for the Nearest algorithm)
|
||||
@@ -176,7 +175,7 @@ use image::{ColorType, GenericImageView};
|
||||
use fast_image_resize as fr;
|
||||
|
||||
fn resize_image_with_cropping(
|
||||
mut src_view: fr::ImageView,
|
||||
mut src_view: fr::DynamicImageView,
|
||||
dst_width: NonZeroU32,
|
||||
dst_height: NonZeroU32
|
||||
) -> fr::Image {
|
||||
|
||||
+93
-24
@@ -48,6 +48,10 @@ struct Cli {
|
||||
#[clap(short, long, value_enum, default_value_t = structs::FilterType::Lanczos3)]
|
||||
filter: structs::FilterType,
|
||||
|
||||
/// Use u16 as pixel components for intermediate image representation.
|
||||
#[clap(long, action)]
|
||||
high_precision: bool,
|
||||
|
||||
#[clap(flatten)]
|
||||
verbose: clap_verbosity_flag::Verbosity,
|
||||
}
|
||||
@@ -61,7 +65,7 @@ fn main() -> Result<()> {
|
||||
}
|
||||
|
||||
fn resize(cli: &Cli) -> Result<()> {
|
||||
let (mut src_image, color_type) = open_source_image(cli)?;
|
||||
let (mut src_image, color_type, orig_pixel_type) = open_source_image(cli)?;
|
||||
let mut dst_image = create_destination_image(cli, &src_image);
|
||||
|
||||
let mul_div = fr::MulDiv::default();
|
||||
@@ -91,10 +95,10 @@ fn resize(cli: &Cli) -> Result<()> {
|
||||
.with_context(|| "Failed to divide color channels by alpha")?;
|
||||
}
|
||||
|
||||
save_result(cli, dst_image, color_type)
|
||||
save_result(cli, dst_image, color_type, orig_pixel_type)
|
||||
}
|
||||
|
||||
fn open_source_image(cli: &Cli) -> Result<(fr::Image<'static>, ColorType)> {
|
||||
fn open_source_image(cli: &Cli) -> Result<(fr::Image<'static>, ColorType, fr::PixelType)> {
|
||||
let source_path = &cli.source_path;
|
||||
debug!("Opening the source image {:?}", source_path);
|
||||
let image = ImageReader::open(&source_path)
|
||||
@@ -108,11 +112,27 @@ fn open_source_image(cli: &Cli) -> Result<(fr::Image<'static>, ColorType)> {
|
||||
.with_context(|| "Failed to get height of the source image")?;
|
||||
|
||||
let color_type = image.color();
|
||||
let (src_buffer, pixel_type) = match color_type {
|
||||
ColorType::L8 => (image.to_luma8().into_raw(), fr::PixelType::U8),
|
||||
ColorType::La8 => (image.to_luma_alpha8().into_raw(), fr::PixelType::U8x2),
|
||||
ColorType::Rgb8 => (image.to_rgb8().into_raw(), fr::PixelType::U8x3),
|
||||
ColorType::Rgba8 => (image.to_rgba8().into_raw(), fr::PixelType::U8x4),
|
||||
let (src_buffer, pixel_type, mut internal_pixel_type) = match color_type {
|
||||
ColorType::L8 => (
|
||||
image.to_luma8().into_raw(),
|
||||
fr::PixelType::U8,
|
||||
fr::PixelType::U16,
|
||||
),
|
||||
ColorType::La8 => (
|
||||
image.to_luma_alpha8().into_raw(),
|
||||
fr::PixelType::U8x2,
|
||||
fr::PixelType::U16x2,
|
||||
),
|
||||
ColorType::Rgb8 => (
|
||||
image.to_rgb8().into_raw(),
|
||||
fr::PixelType::U8x3,
|
||||
fr::PixelType::U16x3,
|
||||
),
|
||||
ColorType::Rgba8 => (
|
||||
image.to_rgba8().into_raw(),
|
||||
fr::PixelType::U8x4,
|
||||
fr::PixelType::U16x4,
|
||||
),
|
||||
ColorType::L16 => (
|
||||
image
|
||||
.to_luma16()
|
||||
@@ -121,6 +141,7 @@ fn open_source_image(cli: &Cli) -> Result<(fr::Image<'static>, ColorType)> {
|
||||
.flat_map(|&c| c.to_le_bytes())
|
||||
.collect(),
|
||||
fr::PixelType::U16,
|
||||
fr::PixelType::U16,
|
||||
),
|
||||
ColorType::La16 => (
|
||||
image
|
||||
@@ -130,6 +151,7 @@ fn open_source_image(cli: &Cli) -> Result<(fr::Image<'static>, ColorType)> {
|
||||
.flat_map(|&c| c.to_le_bytes())
|
||||
.collect(),
|
||||
fr::PixelType::U16x2,
|
||||
fr::PixelType::U16x2,
|
||||
),
|
||||
ColorType::Rgb16 => (
|
||||
image
|
||||
@@ -139,6 +161,7 @@ fn open_source_image(cli: &Cli) -> Result<(fr::Image<'static>, ColorType)> {
|
||||
.flat_map(|&c| c.to_le_bytes())
|
||||
.collect(),
|
||||
fr::PixelType::U16x3,
|
||||
fr::PixelType::U16x3,
|
||||
),
|
||||
ColorType::Rgba16 => (
|
||||
image
|
||||
@@ -148,6 +171,7 @@ fn open_source_image(cli: &Cli) -> Result<(fr::Image<'static>, ColorType)> {
|
||||
.flat_map(|&c| c.to_le_bytes())
|
||||
.collect(),
|
||||
fr::PixelType::U16x4,
|
||||
fr::PixelType::U16x4,
|
||||
),
|
||||
_ => {
|
||||
return Err(anyhow!(
|
||||
@@ -157,11 +181,44 @@ fn open_source_image(cli: &Cli) -> Result<(fr::Image<'static>, ColorType)> {
|
||||
}
|
||||
};
|
||||
|
||||
Ok((
|
||||
fr::Image::from_vec_u8(src_width, src_height, src_buffer, pixel_type)
|
||||
.with_context(|| "Failed to create source image pixels container")?,
|
||||
color_type,
|
||||
))
|
||||
if !cli.high_precision {
|
||||
internal_pixel_type = pixel_type;
|
||||
}
|
||||
|
||||
let mut src_image = fr::Image::from_vec_u8(src_width, src_height, src_buffer, pixel_type)
|
||||
.with_context(|| "Failed to create source image pixels container")?;
|
||||
|
||||
src_image = match cli.colorspace {
|
||||
structs::ColorSpace::NonLinear => {
|
||||
debug!("Convert the source image from non-linear colorspace into linear");
|
||||
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())?;
|
||||
} else {
|
||||
fr::color::mappers::GAMMA22_TO_LINEAR
|
||||
.forward_map(&src_image.view(), &mut linear_src_image.view_mut())?;
|
||||
}
|
||||
linear_src_image
|
||||
}
|
||||
_ => {
|
||||
if internal_pixel_type != pixel_type {
|
||||
// Convert components of source image into version with high precision
|
||||
let mut hi_src_image =
|
||||
fr::Image::new(src_image.width(), src_image.height(), internal_pixel_type);
|
||||
fr::change_type_of_pixel_components_dyn(
|
||||
&src_image.view(),
|
||||
&mut hi_src_image.view_mut(),
|
||||
)?;
|
||||
hi_src_image
|
||||
} else {
|
||||
src_image
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok((src_image, color_type, pixel_type))
|
||||
}
|
||||
|
||||
fn create_destination_image(cli: &Cli, src_image: &fr::Image) -> fr::Image<'static> {
|
||||
@@ -196,7 +253,12 @@ fn get_resizing_algorithm(cli: &Cli) -> fr::ResizeAlg {
|
||||
}
|
||||
}
|
||||
|
||||
fn save_result(cli: &Cli, mut image: fr::Image, color_type: ColorType) -> Result<()> {
|
||||
fn save_result(
|
||||
cli: &Cli,
|
||||
mut image: fr::Image,
|
||||
color_type: ColorType,
|
||||
pixel_type: fr::PixelType,
|
||||
) -> Result<()> {
|
||||
let result_path = if let Some(path) = cli.destination_path.clone() {
|
||||
path
|
||||
} else {
|
||||
@@ -220,21 +282,28 @@ fn save_result(cli: &Cli, mut image: fr::Image, color_type: ColorType) -> Result
|
||||
structs::ColorSpace::NonLinear => {
|
||||
debug!("Convert the result image from linear colorspace into non-linear");
|
||||
let mut non_linear_dst_image =
|
||||
fr::Image::new(image.width(), image.height(), image.pixel_type());
|
||||
fr::Image::new(image.width(), image.height(), pixel_type);
|
||||
if color_type.has_color() {
|
||||
fr::color::srgb::rgb_into_srgb(
|
||||
&image.view(),
|
||||
&mut non_linear_dst_image.view_mut(),
|
||||
)?;
|
||||
fr::color::mappers::SRGB_TO_RGB
|
||||
.backward_map(&image.view(), &mut non_linear_dst_image.view_mut())?;
|
||||
} else {
|
||||
fr::color::gamma::linear_into_gamma22(
|
||||
&image.view(),
|
||||
&mut non_linear_dst_image.view_mut(),
|
||||
)?;
|
||||
fr::color::mappers::GAMMA22_TO_LINEAR
|
||||
.backward_map(&image.view(), &mut non_linear_dst_image.view_mut())?;
|
||||
}
|
||||
non_linear_dst_image
|
||||
}
|
||||
_ => image,
|
||||
_ => {
|
||||
if image.pixel_type() != pixel_type {
|
||||
let mut lo_src_image = fr::Image::new(image.width(), image.height(), pixel_type);
|
||||
fr::change_type_of_pixel_components_dyn(
|
||||
&image.view(),
|
||||
&mut lo_src_image.view_mut(),
|
||||
)?;
|
||||
lo_src_image
|
||||
} else {
|
||||
image
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
debug!("Save the result image into the file {:?}", result_path);
|
||||
|
||||
+7
-7
@@ -1,8 +1,8 @@
|
||||
pub use errors::*;
|
||||
|
||||
use crate::pixels::Pixel;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
mod common;
|
||||
pub(crate) mod errors;
|
||||
@@ -18,22 +18,22 @@ where
|
||||
/// Multiplies RGB-channels of source image by alpha-channel and store
|
||||
/// result into destination image.
|
||||
fn multiply_alpha(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
cpu_extensions: CpuExtensions,
|
||||
);
|
||||
|
||||
/// Multiplies RGB-channels of image by alpha-channel inplace.
|
||||
fn multiply_alpha_inplace(image: TypedImageViewMut<Self>, cpu_extensions: CpuExtensions);
|
||||
fn multiply_alpha_inplace(image: &mut ImageViewMut<Self>, cpu_extensions: CpuExtensions);
|
||||
|
||||
/// Divides RGB-channels of source image by alpha-channel and store
|
||||
/// result into destination image.
|
||||
fn divide_alpha(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
cpu_extensions: CpuExtensions,
|
||||
);
|
||||
|
||||
/// Divides RGB-channels of image by alpha-channel inplace.
|
||||
fn divide_alpha_inplace(image: TypedImageViewMut<Self>, cpu_extensions: CpuExtensions);
|
||||
fn divide_alpha_inplace(image: &mut ImageViewMut<Self>, cpu_extensions: CpuExtensions);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::pixels::U16x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::sse4;
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn multiply_alpha(
|
||||
src_image: TypedImageView<U16x2>,
|
||||
mut dst_image: TypedImageViewMut<U16x2>,
|
||||
src_image: &ImageView<U16x2>,
|
||||
dst_image: &mut ImageViewMut<U16x2>,
|
||||
) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
@@ -19,7 +19,7 @@ pub(crate) unsafe fn multiply_alpha(
|
||||
}
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn multiply_alpha_inplace(mut image: TypedImageViewMut<U16x2>) {
|
||||
pub(crate) unsafe fn multiply_alpha_inplace(image: &mut ImageViewMut<U16x2>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len());
|
||||
multiply_alpha_row(src_row, dst_row);
|
||||
@@ -81,8 +81,8 @@ pub(crate) unsafe fn multiply_alpha_row(src_row: &[U16x2], dst_row: &mut [U16x2]
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn divide_alpha(
|
||||
src_image: TypedImageView<U16x2>,
|
||||
mut dst_image: TypedImageViewMut<U16x2>,
|
||||
src_image: &ImageView<U16x2>,
|
||||
dst_image: &mut ImageViewMut<U16x2>,
|
||||
) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
@@ -93,7 +93,7 @@ pub(crate) unsafe fn divide_alpha(
|
||||
}
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn divide_alpha_inplace(mut image: TypedImageViewMut<U16x2>) {
|
||||
pub(crate) unsafe fn divide_alpha_inplace(image: &mut ImageViewMut<U16x2>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len());
|
||||
divide_alpha_row(src_row, dst_row);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::pixels::U16x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::AlphaMulDiv;
|
||||
|
||||
@@ -12,8 +12,8 @@ mod sse4;
|
||||
|
||||
impl AlphaMulDiv for U16x2 {
|
||||
fn multiply_alpha(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
match cpu_extensions {
|
||||
@@ -25,7 +25,7 @@ impl AlphaMulDiv for U16x2 {
|
||||
}
|
||||
}
|
||||
|
||||
fn multiply_alpha_inplace(image: TypedImageViewMut<Self>, cpu_extensions: CpuExtensions) {
|
||||
fn multiply_alpha_inplace(image: &mut ImageViewMut<Self>, cpu_extensions: CpuExtensions) {
|
||||
match cpu_extensions {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
CpuExtensions::Avx2 => unsafe { avx2::multiply_alpha_inplace(image) },
|
||||
@@ -36,8 +36,8 @@ impl AlphaMulDiv for U16x2 {
|
||||
}
|
||||
|
||||
fn divide_alpha(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
match cpu_extensions {
|
||||
@@ -49,7 +49,7 @@ impl AlphaMulDiv for U16x2 {
|
||||
}
|
||||
}
|
||||
|
||||
fn divide_alpha_inplace(image: TypedImageViewMut<Self>, cpu_extensions: CpuExtensions) {
|
||||
fn divide_alpha_inplace(image: &mut ImageViewMut<Self>, cpu_extensions: CpuExtensions) {
|
||||
match cpu_extensions {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
CpuExtensions::Avx2 => unsafe { avx2::divide_alpha_inplace(image) },
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
use crate::alpha::common::{div_and_clip16, mul_div_65535, RECIP_ALPHA16};
|
||||
use crate::pixels::U16x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
pub(crate) fn multiply_alpha(
|
||||
src_image: TypedImageView<U16x2>,
|
||||
mut dst_image: TypedImageViewMut<U16x2>,
|
||||
) {
|
||||
pub(crate) fn multiply_alpha(src_image: &ImageView<U16x2>, dst_image: &mut ImageViewMut<U16x2>) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
|
||||
@@ -14,7 +11,7 @@ pub(crate) fn multiply_alpha(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn multiply_alpha_inplace(mut image: TypedImageViewMut<U16x2>) {
|
||||
pub(crate) fn multiply_alpha_inplace(image: &mut ImageViewMut<U16x2>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = unsafe { std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len()) };
|
||||
multiply_alpha_row(src_row, dst_row);
|
||||
@@ -33,10 +30,7 @@ pub(crate) fn multiply_alpha_row(src_row: &[U16x2], dst_row: &mut [U16x2]) {
|
||||
// Divide
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn divide_alpha(
|
||||
src_image: TypedImageView<U16x2>,
|
||||
mut dst_image: TypedImageViewMut<U16x2>,
|
||||
) {
|
||||
pub(crate) fn divide_alpha(src_image: &ImageView<U16x2>, dst_image: &mut ImageViewMut<U16x2>) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
|
||||
@@ -46,7 +40,7 @@ pub(crate) fn divide_alpha(
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn divide_alpha_inplace(mut image: TypedImageViewMut<U16x2>) {
|
||||
pub(crate) fn divide_alpha_inplace(image: &mut ImageViewMut<U16x2>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = unsafe { std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len()) };
|
||||
divide_alpha_row(src_row, dst_row);
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::pixels::U16x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::native;
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn multiply_alpha(
|
||||
src_image: TypedImageView<U16x2>,
|
||||
mut dst_image: TypedImageViewMut<U16x2>,
|
||||
src_image: &ImageView<U16x2>,
|
||||
dst_image: &mut ImageViewMut<U16x2>,
|
||||
) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
@@ -19,7 +19,7 @@ pub(crate) unsafe fn multiply_alpha(
|
||||
}
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn multiply_alpha_inplace(mut image: TypedImageViewMut<U16x2>) {
|
||||
pub(crate) unsafe fn multiply_alpha_inplace(image: &mut ImageViewMut<U16x2>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len());
|
||||
multiply_alpha_row(src_row, dst_row);
|
||||
@@ -77,8 +77,8 @@ pub(crate) unsafe fn multiply_alpha_row(src_row: &[U16x2], dst_row: &mut [U16x2]
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn divide_alpha(
|
||||
src_image: TypedImageView<U16x2>,
|
||||
mut dst_image: TypedImageViewMut<U16x2>,
|
||||
src_image: &ImageView<U16x2>,
|
||||
dst_image: &mut ImageViewMut<U16x2>,
|
||||
) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
@@ -89,7 +89,7 @@ pub(crate) unsafe fn divide_alpha(
|
||||
}
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn divide_alpha_inplace(mut image: TypedImageViewMut<U16x2>) {
|
||||
pub(crate) unsafe fn divide_alpha_inplace(image: &mut ImageViewMut<U16x2>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len());
|
||||
divide_alpha_row(src_row, dst_row);
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::pixels::U16x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::sse4;
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn multiply_alpha(
|
||||
src_image: TypedImageView<U16x4>,
|
||||
mut dst_image: TypedImageViewMut<U16x4>,
|
||||
src_image: &ImageView<U16x4>,
|
||||
dst_image: &mut ImageViewMut<U16x4>,
|
||||
) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
@@ -19,7 +19,7 @@ pub(crate) unsafe fn multiply_alpha(
|
||||
}
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn multiply_alpha_inplace(mut image: TypedImageViewMut<U16x4>) {
|
||||
pub(crate) unsafe fn multiply_alpha_inplace(image: &mut ImageViewMut<U16x4>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len());
|
||||
multiply_alpha_row(src_row, dst_row);
|
||||
@@ -80,8 +80,8 @@ pub(crate) unsafe fn multiply_alpha_row(src_row: &[U16x4], dst_row: &mut [U16x4]
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn divide_alpha(
|
||||
src_image: TypedImageView<U16x4>,
|
||||
mut dst_image: TypedImageViewMut<U16x4>,
|
||||
src_image: &ImageView<U16x4>,
|
||||
dst_image: &mut ImageViewMut<U16x4>,
|
||||
) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
@@ -92,7 +92,7 @@ pub(crate) unsafe fn divide_alpha(
|
||||
}
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn divide_alpha_inplace(mut image: TypedImageViewMut<U16x4>) {
|
||||
pub(crate) unsafe fn divide_alpha_inplace(image: &mut ImageViewMut<U16x4>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len());
|
||||
divide_alpha_row(src_row, dst_row);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::pixels::U16x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::AlphaMulDiv;
|
||||
|
||||
@@ -12,8 +12,8 @@ mod sse4;
|
||||
|
||||
impl AlphaMulDiv for U16x4 {
|
||||
fn multiply_alpha(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
match cpu_extensions {
|
||||
@@ -25,7 +25,7 @@ impl AlphaMulDiv for U16x4 {
|
||||
}
|
||||
}
|
||||
|
||||
fn multiply_alpha_inplace(image: TypedImageViewMut<Self>, cpu_extensions: CpuExtensions) {
|
||||
fn multiply_alpha_inplace(image: &mut ImageViewMut<Self>, cpu_extensions: CpuExtensions) {
|
||||
match cpu_extensions {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
CpuExtensions::Avx2 => unsafe { avx2::multiply_alpha_inplace(image) },
|
||||
@@ -36,8 +36,8 @@ impl AlphaMulDiv for U16x4 {
|
||||
}
|
||||
|
||||
fn divide_alpha(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
match cpu_extensions {
|
||||
@@ -49,7 +49,7 @@ impl AlphaMulDiv for U16x4 {
|
||||
}
|
||||
}
|
||||
|
||||
fn divide_alpha_inplace(image: TypedImageViewMut<Self>, cpu_extensions: CpuExtensions) {
|
||||
fn divide_alpha_inplace(image: &mut ImageViewMut<Self>, cpu_extensions: CpuExtensions) {
|
||||
match cpu_extensions {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
CpuExtensions::Avx2 => unsafe { avx2::divide_alpha_inplace(image) },
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
use crate::alpha::common::{div_and_clip16, mul_div_65535, RECIP_ALPHA16};
|
||||
use crate::pixels::U16x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
pub(crate) fn multiply_alpha(
|
||||
src_image: TypedImageView<U16x4>,
|
||||
mut dst_image: TypedImageViewMut<U16x4>,
|
||||
) {
|
||||
pub(crate) fn multiply_alpha(src_image: &ImageView<U16x4>, dst_image: &mut ImageViewMut<U16x4>) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
|
||||
@@ -14,7 +11,7 @@ pub(crate) fn multiply_alpha(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn multiply_alpha_inplace(mut image: TypedImageViewMut<U16x4>) {
|
||||
pub(crate) fn multiply_alpha_inplace(image: &mut ImageViewMut<U16x4>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = unsafe { std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len()) };
|
||||
multiply_alpha_row(src_row, dst_row);
|
||||
@@ -38,10 +35,7 @@ pub(crate) fn multiply_alpha_row(src_row: &[U16x4], dst_row: &mut [U16x4]) {
|
||||
// Divide
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn divide_alpha(
|
||||
src_image: TypedImageView<U16x4>,
|
||||
mut dst_image: TypedImageViewMut<U16x4>,
|
||||
) {
|
||||
pub(crate) fn divide_alpha(src_image: &ImageView<U16x4>, dst_image: &mut ImageViewMut<U16x4>) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
|
||||
@@ -51,7 +45,7 @@ pub(crate) fn divide_alpha(
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn divide_alpha_inplace(mut image: TypedImageViewMut<U16x4>) {
|
||||
pub(crate) fn divide_alpha_inplace(image: &mut ImageViewMut<U16x4>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = unsafe { std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len()) };
|
||||
divide_alpha_row(src_row, dst_row);
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::pixels::U16x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::native;
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn multiply_alpha(
|
||||
src_image: TypedImageView<U16x4>,
|
||||
mut dst_image: TypedImageViewMut<U16x4>,
|
||||
src_image: &ImageView<U16x4>,
|
||||
dst_image: &mut ImageViewMut<U16x4>,
|
||||
) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
@@ -19,7 +19,7 @@ pub(crate) unsafe fn multiply_alpha(
|
||||
}
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn multiply_alpha_inplace(mut image: TypedImageViewMut<U16x4>) {
|
||||
pub(crate) unsafe fn multiply_alpha_inplace(image: &mut ImageViewMut<U16x4>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len());
|
||||
multiply_alpha_row(src_row, dst_row);
|
||||
@@ -77,8 +77,8 @@ pub(crate) unsafe fn multiply_alpha_row(src_row: &[U16x4], dst_row: &mut [U16x4]
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn divide_alpha(
|
||||
src_image: TypedImageView<U16x4>,
|
||||
mut dst_image: TypedImageViewMut<U16x4>,
|
||||
src_image: &ImageView<U16x4>,
|
||||
dst_image: &mut ImageViewMut<U16x4>,
|
||||
) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
@@ -89,7 +89,7 @@ pub(crate) unsafe fn divide_alpha(
|
||||
}
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn divide_alpha_inplace(mut image: TypedImageViewMut<U16x4>) {
|
||||
pub(crate) unsafe fn divide_alpha_inplace(image: &mut ImageViewMut<U16x4>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len());
|
||||
divide_alpha_row(src_row, dst_row);
|
||||
@@ -106,7 +106,7 @@ pub(crate) unsafe fn divide_alpha_row(src_row: &[U16x4], dst_row: &mut [U16x4])
|
||||
divide_alpha_two_pixels(src.as_ptr(), dst.as_mut_ptr());
|
||||
}
|
||||
|
||||
if let Some(src) = src_remainder.get(0) {
|
||||
if let Some(src) = src_remainder.first() {
|
||||
let src_pixels = [*src, U16x4([0, 0, 0, 0])];
|
||||
let mut dst_pixels = [U16x4([0, 0, 0, 0]); 2];
|
||||
divide_alpha_two_pixels(src_pixels.as_ptr(), dst_pixels.as_mut_ptr());
|
||||
|
||||
@@ -2,14 +2,14 @@ use std::arch::x86_64::*;
|
||||
|
||||
use crate::pixels::U8x2;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::sse4;
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn multiply_alpha(
|
||||
src_image: TypedImageView<U8x2>,
|
||||
mut dst_image: TypedImageViewMut<U8x2>,
|
||||
src_image: &ImageView<U8x2>,
|
||||
dst_image: &mut ImageViewMut<U8x2>,
|
||||
) {
|
||||
let width = src_image.width().get() as usize;
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
@@ -21,7 +21,7 @@ pub(crate) unsafe fn multiply_alpha(
|
||||
}
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn multiply_alpha_inplace(mut image: TypedImageViewMut<U8x2>) {
|
||||
pub(crate) unsafe fn multiply_alpha_inplace(image: &mut ImageViewMut<U8x2>) {
|
||||
let width = image.width().get() as usize;
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len());
|
||||
@@ -82,10 +82,7 @@ unsafe fn multiply_alpha_row(src_row: &[U8x2], dst_row: &mut [U8x2], width: usiz
|
||||
// Divide
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn divide_alpha(
|
||||
src_image: TypedImageView<U8x2>,
|
||||
mut dst_image: TypedImageViewMut<U8x2>,
|
||||
) {
|
||||
pub(crate) unsafe fn divide_alpha(src_image: &ImageView<U8x2>, dst_image: &mut ImageViewMut<U8x2>) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
|
||||
@@ -95,7 +92,7 @@ pub(crate) unsafe fn divide_alpha(
|
||||
}
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn divide_alpha_inplace(mut image: TypedImageViewMut<U8x2>) {
|
||||
pub(crate) unsafe fn divide_alpha_inplace(image: &mut ImageViewMut<U8x2>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len());
|
||||
divide_alpha_row(src_row, dst_row);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::CpuExtensions;
|
||||
use crate::pixels::U8x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::AlphaMulDiv;
|
||||
|
||||
@@ -12,8 +12,8 @@ mod sse4;
|
||||
|
||||
impl AlphaMulDiv for U8x2 {
|
||||
fn multiply_alpha(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
match cpu_extensions {
|
||||
@@ -25,7 +25,7 @@ impl AlphaMulDiv for U8x2 {
|
||||
}
|
||||
}
|
||||
|
||||
fn multiply_alpha_inplace(image: TypedImageViewMut<Self>, cpu_extensions: CpuExtensions) {
|
||||
fn multiply_alpha_inplace(image: &mut ImageViewMut<Self>, cpu_extensions: CpuExtensions) {
|
||||
match cpu_extensions {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
CpuExtensions::Avx2 => unsafe { avx2::multiply_alpha_inplace(image) },
|
||||
@@ -36,8 +36,8 @@ impl AlphaMulDiv for U8x2 {
|
||||
}
|
||||
|
||||
fn divide_alpha(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
match cpu_extensions {
|
||||
@@ -49,7 +49,7 @@ impl AlphaMulDiv for U8x2 {
|
||||
}
|
||||
}
|
||||
|
||||
fn divide_alpha_inplace(image: TypedImageViewMut<Self>, cpu_extensions: CpuExtensions) {
|
||||
fn divide_alpha_inplace(image: &mut ImageViewMut<Self>, cpu_extensions: CpuExtensions) {
|
||||
match cpu_extensions {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
CpuExtensions::Avx2 => unsafe { avx2::divide_alpha_inplace(image) },
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
use crate::alpha::common::{div_and_clip, mul_div_255, RECIP_ALPHA};
|
||||
use crate::pixels::U8x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
pub(crate) fn multiply_alpha(
|
||||
src_image: TypedImageView<U8x2>,
|
||||
mut dst_image: TypedImageViewMut<U8x2>,
|
||||
) {
|
||||
pub(crate) fn multiply_alpha(src_image: &ImageView<U8x2>, dst_image: &mut ImageViewMut<U8x2>) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
|
||||
@@ -14,7 +11,7 @@ pub(crate) fn multiply_alpha(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn multiply_alpha_inplace(mut image: TypedImageViewMut<U8x2>) {
|
||||
pub(crate) fn multiply_alpha_inplace(image: &mut ImageViewMut<U8x2>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = unsafe { std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len()) };
|
||||
multiply_alpha_row(src_row, dst_row);
|
||||
@@ -33,10 +30,7 @@ pub(crate) fn multiply_alpha_row(src_row: &[U8x2], dst_row: &mut [U8x2]) {
|
||||
// Divide
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn divide_alpha(
|
||||
src_image: TypedImageView<U8x2>,
|
||||
mut dst_image: TypedImageViewMut<U8x2>,
|
||||
) {
|
||||
pub(crate) fn divide_alpha(src_image: &ImageView<U8x2>, dst_image: &mut ImageViewMut<U8x2>) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
|
||||
@@ -46,7 +40,7 @@ pub(crate) fn divide_alpha(
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn divide_alpha_inplace(mut image: TypedImageViewMut<U8x2>) {
|
||||
pub(crate) fn divide_alpha_inplace(image: &mut ImageViewMut<U8x2>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = unsafe { std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len()) };
|
||||
divide_alpha_row(src_row, dst_row);
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::pixels::U8x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::native;
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn multiply_alpha(
|
||||
src_image: TypedImageView<U8x2>,
|
||||
mut dst_image: TypedImageViewMut<U8x2>,
|
||||
src_image: &ImageView<U8x2>,
|
||||
dst_image: &mut ImageViewMut<U8x2>,
|
||||
) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
@@ -19,7 +19,7 @@ pub(crate) unsafe fn multiply_alpha(
|
||||
}
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn multiply_alpha_inplace(mut image: TypedImageViewMut<U8x2>) {
|
||||
pub(crate) unsafe fn multiply_alpha_inplace(image: &mut ImageViewMut<U8x2>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len());
|
||||
multiply_alpha_row(src_row, dst_row);
|
||||
@@ -76,10 +76,7 @@ pub(crate) unsafe fn multiply_alpha_row(src_row: &[U8x2], dst_row: &mut [U8x2])
|
||||
// Divide
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn divide_alpha(
|
||||
src_image: TypedImageView<U8x2>,
|
||||
mut dst_image: TypedImageViewMut<U8x2>,
|
||||
) {
|
||||
pub(crate) unsafe fn divide_alpha(src_image: &ImageView<U8x2>, dst_image: &mut ImageViewMut<U8x2>) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
|
||||
@@ -89,7 +86,7 @@ pub(crate) unsafe fn divide_alpha(
|
||||
}
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn divide_alpha_inplace(mut image: TypedImageViewMut<U8x2>) {
|
||||
pub(crate) unsafe fn divide_alpha_inplace(image: &mut ImageViewMut<U8x2>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len());
|
||||
divide_alpha_row(src_row, dst_row);
|
||||
|
||||
@@ -2,14 +2,14 @@ use std::arch::x86_64::*;
|
||||
|
||||
use crate::pixels::U8x4;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::{native, sse4};
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn multiply_alpha(
|
||||
src_image: TypedImageView<U8x4>,
|
||||
mut dst_image: TypedImageViewMut<U8x4>,
|
||||
src_image: &ImageView<U8x4>,
|
||||
dst_image: &mut ImageViewMut<U8x4>,
|
||||
) {
|
||||
let width = src_image.width().get() as usize;
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
@@ -21,7 +21,7 @@ pub(crate) unsafe fn multiply_alpha(
|
||||
}
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn multiply_alpha_inplace(mut image: TypedImageViewMut<U8x4>) {
|
||||
pub(crate) unsafe fn multiply_alpha_inplace(image: &mut ImageViewMut<U8x4>) {
|
||||
let width = image.width().get() as usize;
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len());
|
||||
@@ -78,10 +78,7 @@ unsafe fn multiply_alpha_row(src_row: &[U8x4], dst_row: &mut [U8x4], width: usiz
|
||||
// Divide
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn divide_alpha(
|
||||
src_image: TypedImageView<U8x4>,
|
||||
mut dst_image: TypedImageViewMut<U8x4>,
|
||||
) {
|
||||
pub(crate) unsafe fn divide_alpha(src_image: &ImageView<U8x4>, dst_image: &mut ImageViewMut<U8x4>) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
|
||||
@@ -91,7 +88,7 @@ pub(crate) unsafe fn divide_alpha(
|
||||
}
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn divide_alpha_inplace(mut image: TypedImageViewMut<U8x4>) {
|
||||
pub(crate) unsafe fn divide_alpha_inplace(image: &mut ImageViewMut<U8x4>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len());
|
||||
divide_alpha_row(src_row, dst_row);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::pixels::U8x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::AlphaMulDiv;
|
||||
|
||||
@@ -12,8 +12,8 @@ mod sse4;
|
||||
|
||||
impl AlphaMulDiv for U8x4 {
|
||||
fn multiply_alpha(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
match cpu_extensions {
|
||||
@@ -25,7 +25,7 @@ impl AlphaMulDiv for U8x4 {
|
||||
}
|
||||
}
|
||||
|
||||
fn multiply_alpha_inplace(image: TypedImageViewMut<Self>, cpu_extensions: CpuExtensions) {
|
||||
fn multiply_alpha_inplace(image: &mut ImageViewMut<Self>, cpu_extensions: CpuExtensions) {
|
||||
match cpu_extensions {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
CpuExtensions::Avx2 => unsafe { avx2::multiply_alpha_inplace(image) },
|
||||
@@ -36,8 +36,8 @@ impl AlphaMulDiv for U8x4 {
|
||||
}
|
||||
|
||||
fn divide_alpha(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
match cpu_extensions {
|
||||
@@ -49,7 +49,7 @@ impl AlphaMulDiv for U8x4 {
|
||||
}
|
||||
}
|
||||
|
||||
fn divide_alpha_inplace(image: TypedImageViewMut<Self>, cpu_extensions: CpuExtensions) {
|
||||
fn divide_alpha_inplace(image: &mut ImageViewMut<Self>, cpu_extensions: CpuExtensions) {
|
||||
match cpu_extensions {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
CpuExtensions::Avx2 => unsafe { avx2::divide_alpha_inplace(image) },
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
use crate::alpha::common::{div_and_clip, mul_div_255, RECIP_ALPHA};
|
||||
use crate::pixels::U8x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
pub(crate) fn multiply_alpha(
|
||||
src_image: TypedImageView<U8x4>,
|
||||
mut dst_image: TypedImageViewMut<U8x4>,
|
||||
) {
|
||||
pub(crate) fn multiply_alpha(src_image: &ImageView<U8x4>, dst_image: &mut ImageViewMut<U8x4>) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
|
||||
@@ -14,7 +11,7 @@ pub(crate) fn multiply_alpha(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn multiply_alpha_inplace(mut image: TypedImageViewMut<U8x4>) {
|
||||
pub(crate) fn multiply_alpha_inplace(image: &mut ImageViewMut<U8x4>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = unsafe { std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len()) };
|
||||
multiply_alpha_row(src_row, dst_row);
|
||||
@@ -38,10 +35,7 @@ pub(crate) fn multiply_alpha_row(src_row: &[U8x4], dst_row: &mut [U8x4]) {
|
||||
// Divide
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn divide_alpha(
|
||||
src_image: TypedImageView<U8x4>,
|
||||
mut dst_image: TypedImageViewMut<U8x4>,
|
||||
) {
|
||||
pub(crate) fn divide_alpha(src_image: &ImageView<U8x4>, dst_image: &mut ImageViewMut<U8x4>) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
|
||||
@@ -51,7 +45,7 @@ pub(crate) fn divide_alpha(
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn divide_alpha_inplace(mut image: TypedImageViewMut<U8x4>) {
|
||||
pub(crate) fn divide_alpha_inplace(image: &mut ImageViewMut<U8x4>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = unsafe { std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len()) };
|
||||
divide_alpha_row(src_row, dst_row);
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::pixels::U8x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::native;
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn multiply_alpha(
|
||||
src_image: TypedImageView<U8x4>,
|
||||
mut dst_image: TypedImageViewMut<U8x4>,
|
||||
src_image: &ImageView<U8x4>,
|
||||
dst_image: &mut ImageViewMut<U8x4>,
|
||||
) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
@@ -19,7 +19,7 @@ pub(crate) unsafe fn multiply_alpha(
|
||||
}
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn multiply_alpha_inplace(mut image: TypedImageViewMut<U8x4>) {
|
||||
pub(crate) unsafe fn multiply_alpha_inplace(image: &mut ImageViewMut<U8x4>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len());
|
||||
multiply_alpha_row(src_row, dst_row);
|
||||
@@ -72,10 +72,7 @@ unsafe fn multiply_alpha_row(src_row: &[U8x4], dst_row: &mut [U8x4]) {
|
||||
// Divide
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn divide_alpha(
|
||||
src_image: TypedImageView<U8x4>,
|
||||
mut dst_image: TypedImageViewMut<U8x4>,
|
||||
) {
|
||||
pub(crate) unsafe fn divide_alpha(src_image: &ImageView<U8x4>, dst_image: &mut ImageViewMut<U8x4>) {
|
||||
let src_rows = src_image.iter_rows(0);
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
|
||||
@@ -85,7 +82,7 @@ pub(crate) unsafe fn divide_alpha(
|
||||
}
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn divide_alpha_inplace(mut image: TypedImageViewMut<U8x4>) {
|
||||
pub(crate) unsafe fn divide_alpha_inplace(image: &mut ImageViewMut<U8x4>) {
|
||||
for dst_row in image.iter_rows_mut() {
|
||||
let src_row = std::slice::from_raw_parts(dst_row.as_ptr(), dst_row.len());
|
||||
divide_alpha_row(src_row, dst_row);
|
||||
|
||||
@@ -1,198 +0,0 @@
|
||||
//! Functions for changing image gamma.
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use crate::pixels::{U16x2, U16x3, U16x4, U8x2, U8x3, U8x4, U16, U8};
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut, MappingError, PixelType};
|
||||
|
||||
use super::MappingTable;
|
||||
|
||||
macro_rules! gamma_table {
|
||||
($src_type:tt, $dst_type:tt, $gamma:expr) => {{
|
||||
const TABLE_SIZE: usize = $src_type::MAX as usize + 1;
|
||||
let mut table: [$dst_type; TABLE_SIZE] = [0; TABLE_SIZE];
|
||||
table.iter_mut().enumerate().for_each(|(i, v)| {
|
||||
let signal = i as f32 / $src_type::MAX as f32;
|
||||
let power = signal.powf($gamma);
|
||||
*v = ($dst_type::MAX as f32 * power).round() as $dst_type;
|
||||
});
|
||||
table
|
||||
}};
|
||||
}
|
||||
|
||||
static GAMMA22_U8_INTO_LINEAR_U8: Lazy<MappingTable<u8, 256>> =
|
||||
Lazy::new(|| MappingTable(gamma_table!(u8, u8, 2.2)));
|
||||
static LINEAR_U8_INTO_GAMMA22_U8: Lazy<MappingTable<u8, 256>> =
|
||||
Lazy::new(|| MappingTable(gamma_table!(u8, u8, 1.0 / 2.2)));
|
||||
static GAMMA22_U8_INTO_LINEAR_U16: Lazy<MappingTable<u16, 256>> =
|
||||
Lazy::new(|| MappingTable(gamma_table!(u8, u16, 2.2)));
|
||||
static LINEAR_U8_INTO_GAMMA22_U16: Lazy<MappingTable<u16, 256>> =
|
||||
Lazy::new(|| MappingTable(gamma_table!(u8, u16, 1.0 / 2.2)));
|
||||
static GAMMA22_U16_INTO_LINEAR_U8: Lazy<MappingTable<u8, 65536>> =
|
||||
Lazy::new(|| MappingTable(gamma_table!(u16, u8, 2.2)));
|
||||
static LINEAR_U16_INTO_GAMMA22_U8: Lazy<MappingTable<u8, 65536>> =
|
||||
Lazy::new(|| MappingTable(gamma_table!(u16, u8, 1.0 / 2.2)));
|
||||
static GAMMA22_U16_INTO_LINEAR_U16: Lazy<MappingTable<u16, 65536>> =
|
||||
Lazy::new(|| MappingTable(gamma_table!(u16, u16, 2.2)));
|
||||
static LINEAR_U16_INTO_GAMMA22_U16: Lazy<MappingTable<u16, 65536>> =
|
||||
Lazy::new(|| MappingTable(gamma_table!(u16, u16, 1.0 / 2.2)));
|
||||
|
||||
/// Convert image from gamma 2.2 into linear colorspace.
|
||||
pub fn gamma22_into_linear(
|
||||
src_image: &ImageView,
|
||||
dst_image: &mut ImageViewMut,
|
||||
) -> Result<(), MappingError> {
|
||||
if src_image.width() != dst_image.width() || src_image.height() != dst_image.height() {
|
||||
return Err(MappingError::DifferentDimensions);
|
||||
}
|
||||
|
||||
macro_rules! map {
|
||||
($src_pixel:ty, $dst_pixel:ty, $mapping_table:ident) => {
|
||||
if let Some(src) = TypedImageView::<$src_pixel>::from_image_view(src_image) {
|
||||
if let Some(dst) = TypedImageViewMut::<$dst_pixel>::from_image_view(dst_image) {
|
||||
$mapping_table.map_typed_image(src, dst);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let src_pixel_type = src_image.pixel_type();
|
||||
let dst_pixel_type = dst_image.pixel_type();
|
||||
match (src_pixel_type, dst_pixel_type) {
|
||||
// U8 -> U8
|
||||
(PixelType::U8, PixelType::U8) => {
|
||||
map!(U8, U8, GAMMA22_U8_INTO_LINEAR_U8);
|
||||
}
|
||||
(PixelType::U8x2, PixelType::U8x2) => {
|
||||
map!(U8x2, U8x2, GAMMA22_U8_INTO_LINEAR_U8);
|
||||
}
|
||||
(PixelType::U8x3, PixelType::U8x3) => {
|
||||
map!(U8x3, U8x3, GAMMA22_U8_INTO_LINEAR_U8);
|
||||
}
|
||||
(PixelType::U8x4, PixelType::U8x4) => {
|
||||
map!(U8x4, U8x4, GAMMA22_U8_INTO_LINEAR_U8);
|
||||
}
|
||||
// U8 -> U16
|
||||
(PixelType::U8, PixelType::U16) => {
|
||||
map!(U8, U16, GAMMA22_U8_INTO_LINEAR_U16);
|
||||
}
|
||||
(PixelType::U8x2, PixelType::U16x2) => {
|
||||
map!(U8x2, U16x2, GAMMA22_U8_INTO_LINEAR_U16);
|
||||
}
|
||||
(PixelType::U8x3, PixelType::U16x3) => {
|
||||
map!(U8x3, U16x3, GAMMA22_U8_INTO_LINEAR_U16);
|
||||
}
|
||||
(PixelType::U8x4, PixelType::U16x4) => {
|
||||
map!(U8x4, U16x4, GAMMA22_U8_INTO_LINEAR_U16);
|
||||
}
|
||||
// U16 -> U8
|
||||
(PixelType::U16, PixelType::U8) => {
|
||||
map!(U16, U8, GAMMA22_U16_INTO_LINEAR_U8);
|
||||
}
|
||||
(PixelType::U16x2, PixelType::U8x2) => {
|
||||
map!(U16x2, U8x2, GAMMA22_U16_INTO_LINEAR_U8);
|
||||
}
|
||||
(PixelType::U16x3, PixelType::U8x3) => {
|
||||
map!(U16x3, U8x3, GAMMA22_U16_INTO_LINEAR_U8);
|
||||
}
|
||||
(PixelType::U16x4, PixelType::U8x4) => {
|
||||
map!(U16x4, U8x4, GAMMA22_U16_INTO_LINEAR_U8);
|
||||
}
|
||||
// U16 -> U16
|
||||
(PixelType::U16, PixelType::U16) => {
|
||||
map!(U16, U16, GAMMA22_U16_INTO_LINEAR_U16);
|
||||
}
|
||||
(PixelType::U16x2, PixelType::U16x2) => {
|
||||
map!(U16x2, U16x2, GAMMA22_U16_INTO_LINEAR_U16);
|
||||
}
|
||||
(PixelType::U16x3, PixelType::U16x3) => {
|
||||
map!(U16x3, U16x3, GAMMA22_U16_INTO_LINEAR_U16);
|
||||
}
|
||||
(PixelType::U16x4, PixelType::U16x4) => {
|
||||
map!(U16x4, U16x4, GAMMA22_U16_INTO_LINEAR_U16);
|
||||
}
|
||||
_ => return Err(MappingError::UnsupportedCombinationOfImageTypes),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Convert image from linear colorspace into gamma 2.2.
|
||||
pub fn linear_into_gamma22(
|
||||
src_image: &ImageView,
|
||||
dst_image: &mut ImageViewMut,
|
||||
) -> Result<(), MappingError> {
|
||||
if src_image.width() != dst_image.width() || src_image.height() != dst_image.height() {
|
||||
return Err(MappingError::DifferentDimensions);
|
||||
}
|
||||
|
||||
macro_rules! map {
|
||||
($src_pixel:ty, $dst_pixel:ty, $mapping_table:ident) => {
|
||||
if let Some(src) = TypedImageView::<$src_pixel>::from_image_view(src_image) {
|
||||
if let Some(dst) = TypedImageViewMut::<$dst_pixel>::from_image_view(dst_image) {
|
||||
$mapping_table.map_typed_image(src, dst);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let src_pixel_type = src_image.pixel_type();
|
||||
let dst_pixel_type = dst_image.pixel_type();
|
||||
match (src_pixel_type, dst_pixel_type) {
|
||||
// U8 -> U8
|
||||
(PixelType::U8, PixelType::U8) => {
|
||||
map!(U8, U8, LINEAR_U8_INTO_GAMMA22_U8);
|
||||
}
|
||||
(PixelType::U8x2, PixelType::U8x2) => {
|
||||
map!(U8x2, U8x2, LINEAR_U8_INTO_GAMMA22_U8);
|
||||
}
|
||||
(PixelType::U8x3, PixelType::U8x3) => {
|
||||
map!(U8x3, U8x3, LINEAR_U8_INTO_GAMMA22_U8);
|
||||
}
|
||||
(PixelType::U8x4, PixelType::U8x4) => {
|
||||
map!(U8x4, U8x4, LINEAR_U8_INTO_GAMMA22_U8);
|
||||
}
|
||||
// U8 -> U16
|
||||
(PixelType::U8, PixelType::U16) => {
|
||||
map!(U8, U16, LINEAR_U8_INTO_GAMMA22_U16);
|
||||
}
|
||||
(PixelType::U8x2, PixelType::U16x2) => {
|
||||
map!(U8x2, U16x2, LINEAR_U8_INTO_GAMMA22_U16);
|
||||
}
|
||||
(PixelType::U8x3, PixelType::U16x3) => {
|
||||
map!(U8x3, U16x3, LINEAR_U8_INTO_GAMMA22_U16);
|
||||
}
|
||||
(PixelType::U8x4, PixelType::U16x4) => {
|
||||
map!(U8x4, U16x4, LINEAR_U8_INTO_GAMMA22_U16);
|
||||
}
|
||||
// U16 -> U8
|
||||
(PixelType::U16, PixelType::U8) => {
|
||||
map!(U16, U8, LINEAR_U16_INTO_GAMMA22_U8);
|
||||
}
|
||||
(PixelType::U16x2, PixelType::U8x2) => {
|
||||
map!(U16x2, U8x2, LINEAR_U16_INTO_GAMMA22_U8);
|
||||
}
|
||||
(PixelType::U16x3, PixelType::U8x3) => {
|
||||
map!(U16x3, U8x3, LINEAR_U16_INTO_GAMMA22_U8);
|
||||
}
|
||||
(PixelType::U16x4, PixelType::U8x4) => {
|
||||
map!(U16x4, U8x4, LINEAR_U16_INTO_GAMMA22_U8);
|
||||
}
|
||||
// U16 -> U16
|
||||
(PixelType::U16, PixelType::U16) => {
|
||||
map!(U16, U16, LINEAR_U16_INTO_GAMMA22_U16);
|
||||
}
|
||||
(PixelType::U16x2, PixelType::U16x2) => {
|
||||
map!(U16x2, U16x2, LINEAR_U16_INTO_GAMMA22_U16);
|
||||
}
|
||||
(PixelType::U16x3, PixelType::U16x3) => {
|
||||
map!(U16x3, U16x3, LINEAR_U16_INTO_GAMMA22_U16);
|
||||
}
|
||||
(PixelType::U16x4, PixelType::U16x4) => {
|
||||
map!(U16x4, U16x4, LINEAR_U16_INTO_GAMMA22_U16);
|
||||
}
|
||||
_ => return Err(MappingError::UnsupportedCombinationOfImageTypes),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use crate::color::PixelComponentMapper;
|
||||
|
||||
fn gamma_into_linear(input: f32) -> f32 {
|
||||
input.powf(2.2)
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
/// https://en.wikipedia.org/wiki/SRGB#From_sRGB_to_CIE_XYZ
|
||||
/// http://www.ericbrasseur.org/gamma.html?i=2#formulas
|
||||
fn srgb_to_linear(input: f32) -> f32 {
|
||||
if input < 0.04045 {
|
||||
input / 12.92
|
||||
} else {
|
||||
const A: f32 = 0.055;
|
||||
((input + A) / (1. + A)).powf(2.4)
|
||||
}
|
||||
}
|
||||
|
||||
/// https://en.wikipedia.org/wiki/SRGB#From_CIE_XYZ_to_sRGB
|
||||
/// http://www.ericbrasseur.org/gamma.html?i=2#formulas
|
||||
fn linear_to_srgb(input: f32) -> f32 {
|
||||
if input < 0.0031308 {
|
||||
12.92 * input
|
||||
} else {
|
||||
const A: f32 = 0.055;
|
||||
(1. + A) * input.powf(1. / 2.4) - A
|
||||
}
|
||||
}
|
||||
|
||||
/// 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));
|
||||
+169
-16
@@ -6,18 +6,49 @@
|
||||
//! But count of components must be equal.
|
||||
//! For example, you may convert `U8x3` image with sRGB colorspace into
|
||||
//! `U16x3` image with linear colorspace.
|
||||
use crate::pixels::{GetCount, Pixel, PixelComponent, PixelComponentInto, Values};
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use num_traits::bounds::UpperBounded;
|
||||
use num_traits::Zero;
|
||||
|
||||
pub mod gamma;
|
||||
pub mod srgb;
|
||||
use crate::pixels::{GetCount, IntoPixelComponent, Pixel, PixelComponent, Values};
|
||||
use crate::{DynamicImageView, DynamicImageViewMut, MappingError};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
pub mod mappers;
|
||||
|
||||
trait FromF32 {
|
||||
fn from_f32(x: f32) -> Self;
|
||||
}
|
||||
|
||||
impl FromF32 for u8 {
|
||||
fn from_f32(x: f32) -> Self {
|
||||
x as Self
|
||||
}
|
||||
}
|
||||
|
||||
impl FromF32 for u16 {
|
||||
fn from_f32(x: f32) -> Self {
|
||||
x as Self
|
||||
}
|
||||
}
|
||||
|
||||
struct MappingTable<Out: PixelComponent, const N: usize>([Out; N]);
|
||||
|
||||
impl<Out, const N: usize> MappingTable<Out, N>
|
||||
impl<Out, const SIZE: usize> MappingTable<Out, SIZE>
|
||||
where
|
||||
Out: PixelComponent,
|
||||
Out: PixelComponent + Zero + UpperBounded + FromF32 + Into<f32>,
|
||||
{
|
||||
pub fn new<F>(map_func: &F) -> MappingTable<Out, SIZE>
|
||||
where
|
||||
F: Fn(f32) -> f32,
|
||||
{
|
||||
let mut table: [Out; SIZE] = [Out::zero(); SIZE];
|
||||
table.iter_mut().enumerate().for_each(|(input, output)| {
|
||||
let input_f32 = input as f32 / (SIZE - 1) as f32;
|
||||
*output = Out::from_f32((map_func(input_f32) * Out::max_value().into()).round());
|
||||
});
|
||||
Self(table)
|
||||
}
|
||||
|
||||
fn map<In>(&self, src_buffer: &[In], dst_buffer: &mut [Out])
|
||||
where
|
||||
In: PixelComponent + Into<usize>,
|
||||
@@ -29,7 +60,7 @@ where
|
||||
|
||||
fn map_with_gaps<In>(&self, src_buffer: &[In], dst_buffer: &mut [Out], gap_step: usize)
|
||||
where
|
||||
In: PixelComponentInto<Out> + Into<usize>,
|
||||
In: IntoPixelComponent<Out> + Into<usize>,
|
||||
{
|
||||
for (i, (&src, dst)) in src_buffer.iter().zip(dst_buffer).enumerate() {
|
||||
if (i + 1) % gap_step != 0 {
|
||||
@@ -40,22 +71,19 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn map_typed_image<S, D, CC, In>(
|
||||
&self,
|
||||
src_image: TypedImageView<S>,
|
||||
mut dst_image: TypedImageViewMut<D>,
|
||||
) where
|
||||
In: PixelComponentInto<Out> + Into<usize>,
|
||||
pub fn map_image<S, D, CC, In>(&self, src_image: &ImageView<S>, dst_image: &mut ImageViewMut<D>)
|
||||
where
|
||||
In: IntoPixelComponent<Out> + Into<usize>,
|
||||
CC: GetCount,
|
||||
S: Pixel<
|
||||
Component = In,
|
||||
ComponentsCount = CC, // Count of source pixel's components
|
||||
ComponentCountOfValues = Values<N>, // Total count of values of one source pixel's component
|
||||
CountOfComponents = CC, // Count of source pixel's components
|
||||
CountOfComponentValues = Values<SIZE>, // Total count of values of one source pixel's component
|
||||
>,
|
||||
S::Component: Into<usize>,
|
||||
D: Pixel<
|
||||
Component = Out,
|
||||
ComponentsCount = CC, // Count of destination pixel's components
|
||||
CountOfComponents = CC, // Count of destination pixel's components
|
||||
>,
|
||||
{
|
||||
for (s_row, d_row) in src_image.iter_rows(0).zip(dst_image.iter_rows_mut()) {
|
||||
@@ -69,3 +97,128 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct MappingTablesGroup {
|
||||
u8_u8: MappingTable<u8, 256>,
|
||||
u8_u16: MappingTable<u16, 256>,
|
||||
u16_u8: MappingTable<u8, 65536>,
|
||||
u16_u16: MappingTable<u16, 65536>,
|
||||
}
|
||||
|
||||
/// Mapper of pixel's components.
|
||||
///
|
||||
/// This structure holds tables for mapping values of pixel's
|
||||
/// components in forward and backward directions.
|
||||
pub struct PixelComponentMapper {
|
||||
forward_mapping_tables: MappingTablesGroup,
|
||||
backward_mapping_tables: MappingTablesGroup,
|
||||
}
|
||||
|
||||
impl PixelComponentMapper {
|
||||
/// Create an instance of the structure by filling its tables with
|
||||
/// given functions.
|
||||
///
|
||||
/// Each function takes one argument with the value of the pixel component
|
||||
/// converted into `f32` in the range `[0.0, 1.0]`.
|
||||
/// The return value must also be `f32` in the range `[0.0, 1.0]`.
|
||||
///
|
||||
/// Example:
|
||||
/// ```
|
||||
/// # use fast_image_resize::color::PixelComponentMapper;
|
||||
/// #
|
||||
/// fn gamma_into_linear(input: f32) -> f32 {
|
||||
/// input.powf(2.2)
|
||||
/// }
|
||||
///
|
||||
/// fn linear_into_gamma(input: f32) -> f32 {
|
||||
/// input.powf(1.0 / 2.2)
|
||||
/// }
|
||||
///
|
||||
/// let gamma22_to_linear = PixelComponentMapper::new(
|
||||
/// &gamma_into_linear,
|
||||
/// &linear_into_gamma,
|
||||
/// );
|
||||
/// ```
|
||||
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),
|
||||
},
|
||||
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),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn map(
|
||||
tables: &MappingTablesGroup,
|
||||
src_image: &DynamicImageView,
|
||||
dst_image: &mut DynamicImageViewMut,
|
||||
) -> Result<(), MappingError> {
|
||||
if src_image.width() != dst_image.width() || src_image.height() != dst_image.height() {
|
||||
return Err(MappingError::DifferentDimensions);
|
||||
}
|
||||
|
||||
use DynamicImageView as DI;
|
||||
use DynamicImageViewMut as DIMut;
|
||||
|
||||
macro_rules! match_img {
|
||||
(
|
||||
$tables: ident, $src_image: ident, $dst_image: ident,
|
||||
$(($p8: path, $p16: path, $p8_mut: path, $p16_mut: path),)*
|
||||
) => {
|
||||
match ($src_image, $dst_image) {
|
||||
$(
|
||||
($p8(src), $p8_mut(dst)) => $tables.u8_u8.map_image(src, dst),
|
||||
($p8(src), $p16_mut(dst)) => $tables.u8_u16.map_image(src, dst),
|
||||
($p16(src), $p8_mut(dst)) => $tables.u16_u8.map_image(src, dst),
|
||||
($p16(src), $p16_mut(dst)) => $tables.u16_u16.map_image(src, dst),
|
||||
)*
|
||||
_ => return Err(MappingError::UnsupportedCombinationOfImageTypes),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
match_img!(
|
||||
tables,
|
||||
src_image,
|
||||
dst_image,
|
||||
(DI::U8, DI::U16, DIMut::U8, DIMut::U16),
|
||||
(DI::U8x2, DI::U16x2, DIMut::U8x2, DIMut::U16x2),
|
||||
(DI::U8x3, DI::U16x3, DIMut::U8x3, DIMut::U16x3),
|
||||
(DI::U8x4, DI::U16x4, DIMut::U8x4, DIMut::U16x4),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Mapping in the forward direction of pixel's components of source image
|
||||
/// into corresponding components of destination image.
|
||||
pub fn forward_map(
|
||||
&self,
|
||||
src_image: &DynamicImageView,
|
||||
dst_image: &mut DynamicImageViewMut,
|
||||
) -> Result<(), MappingError> {
|
||||
Self::map(&self.forward_mapping_tables, src_image, dst_image)
|
||||
}
|
||||
|
||||
/// Mapping in the backward direction of pixel's components of source image
|
||||
/// into corresponding components of destination image.
|
||||
pub fn backward_map(
|
||||
&self,
|
||||
src_image: &DynamicImageView,
|
||||
dst_image: &mut DynamicImageViewMut,
|
||||
) -> Result<(), MappingError> {
|
||||
Self::map(&self.backward_mapping_tables, src_image, dst_image)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
//! Functions for converting image between sRGB and linear colorspace.
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use crate::pixels::{U16x3, U16x4, U8x3, U8x4};
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut, MappingError, PixelType};
|
||||
|
||||
use super::MappingTable;
|
||||
|
||||
/// https://en.wikipedia.org/wiki/SRGB#From_sRGB_to_CIE_XYZ
|
||||
/// http://www.ericbrasseur.org/gamma.html?i=2#formulas
|
||||
macro_rules! srgb_into_rgb_table {
|
||||
($src_type:tt, $dst_type:tt) => {{
|
||||
const TABLE_SIZE: usize = $src_type::MAX as usize + 1;
|
||||
let mut table: [$dst_type; TABLE_SIZE] = [0; TABLE_SIZE];
|
||||
table.iter_mut().enumerate().for_each(|(i, v)| {
|
||||
let signal = i as f32 / $src_type::MAX as f32;
|
||||
let power = if signal < 0.04045 {
|
||||
signal / 12.92
|
||||
} else {
|
||||
const A: f32 = 0.055;
|
||||
((signal + A) / (1. + A)).powf(2.4)
|
||||
};
|
||||
*v = ($dst_type::MAX as f32 * power).round() as $dst_type;
|
||||
});
|
||||
table
|
||||
}};
|
||||
}
|
||||
|
||||
/// https://en.wikipedia.org/wiki/SRGB#From_CIE_XYZ_to_sRGB
|
||||
/// http://www.ericbrasseur.org/gamma.html?i=2#formulas
|
||||
macro_rules! rgb_into_srgb_table {
|
||||
($src_type:tt, $dst_type:tt) => {{
|
||||
const TABLE_SIZE: usize = $src_type::MAX as usize + 1;
|
||||
let mut table: [$dst_type; TABLE_SIZE] = [0; TABLE_SIZE];
|
||||
table.iter_mut().enumerate().for_each(|(i, v)| {
|
||||
let signal = i as f32 / $src_type::MAX as f32;
|
||||
let power = if signal < 0.0031308 {
|
||||
12.92 * signal
|
||||
} else {
|
||||
const A: f32 = 0.055;
|
||||
(1. + A) * signal.powf(1. / 2.4) - A
|
||||
};
|
||||
*v = ($dst_type::MAX as f32 * power).round() as $dst_type;
|
||||
});
|
||||
table
|
||||
}};
|
||||
}
|
||||
|
||||
static SRGB8_INTO_RGB8: Lazy<MappingTable<u8, 256>> =
|
||||
Lazy::new(|| MappingTable(srgb_into_rgb_table!(u8, u8)));
|
||||
static SRGB8_INTO_RGB16: Lazy<MappingTable<u16, 256>> =
|
||||
Lazy::new(|| MappingTable(srgb_into_rgb_table!(u8, u16)));
|
||||
static SRGB16_INTO_RGB8: Lazy<MappingTable<u8, 65536>> =
|
||||
Lazy::new(|| MappingTable(srgb_into_rgb_table!(u16, u8)));
|
||||
static SRGB16_INTO_RGB16: Lazy<MappingTable<u16, 65536>> =
|
||||
Lazy::new(|| MappingTable(srgb_into_rgb_table!(u16, u16)));
|
||||
static RGB8_INTO_SRGB8: Lazy<MappingTable<u8, 256>> =
|
||||
Lazy::new(|| MappingTable(rgb_into_srgb_table!(u8, u8)));
|
||||
static RGB8_INTO_SRGB16: Lazy<MappingTable<u16, 256>> =
|
||||
Lazy::new(|| MappingTable(rgb_into_srgb_table!(u8, u16)));
|
||||
static RGB16_INTO_SRGB8: Lazy<MappingTable<u8, 65536>> =
|
||||
Lazy::new(|| MappingTable(rgb_into_srgb_table!(u16, u8)));
|
||||
static RGB16_INTO_SRGB16: Lazy<MappingTable<u16, 65536>> =
|
||||
Lazy::new(|| MappingTable(rgb_into_srgb_table!(u16, u16)));
|
||||
|
||||
/// Convert image from sRGB into linear RGB colorspace.
|
||||
pub fn srgb_into_rgb(
|
||||
src_image: &ImageView,
|
||||
dst_image: &mut ImageViewMut,
|
||||
) -> Result<(), MappingError> {
|
||||
if src_image.width() != dst_image.width() || src_image.height() != dst_image.height() {
|
||||
return Err(MappingError::DifferentDimensions);
|
||||
}
|
||||
|
||||
macro_rules! map {
|
||||
($src_pixel:ty, $dst_pixel:ty, $mapping_table:ident) => {
|
||||
if let Some(src) = TypedImageView::<$src_pixel>::from_image_view(src_image) {
|
||||
if let Some(dst) = TypedImageViewMut::<$dst_pixel>::from_image_view(dst_image) {
|
||||
$mapping_table.map_typed_image(src, dst);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let src_pixel_type = src_image.pixel_type();
|
||||
let dst_pixel_type = dst_image.pixel_type();
|
||||
match (src_pixel_type, dst_pixel_type) {
|
||||
(PixelType::U8x3, PixelType::U8x3) => {
|
||||
map!(U8x3, U8x3, SRGB8_INTO_RGB8);
|
||||
}
|
||||
(PixelType::U8x3, PixelType::U16x3) => {
|
||||
map!(U8x3, U16x3, SRGB8_INTO_RGB16);
|
||||
}
|
||||
(PixelType::U16x3, PixelType::U8x3) => {
|
||||
map!(U16x3, U8x3, SRGB16_INTO_RGB8);
|
||||
}
|
||||
(PixelType::U16x3, PixelType::U16x3) => {
|
||||
map!(U16x3, U16x3, SRGB16_INTO_RGB16);
|
||||
}
|
||||
(PixelType::U8x4, PixelType::U8x4) => {
|
||||
map!(U8x4, U8x4, SRGB8_INTO_RGB8);
|
||||
}
|
||||
(PixelType::U8x4, PixelType::U16x4) => {
|
||||
map!(U8x4, U16x4, SRGB8_INTO_RGB16);
|
||||
}
|
||||
(PixelType::U16x4, PixelType::U8x4) => {
|
||||
map!(U16x4, U8x4, SRGB16_INTO_RGB8);
|
||||
}
|
||||
(PixelType::U16x4, PixelType::U16x4) => {
|
||||
map!(U16x4, U16x4, SRGB16_INTO_RGB16);
|
||||
}
|
||||
_ => return Err(MappingError::UnsupportedCombinationOfImageTypes),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Convert image from linear RGB into sRGB colorspace.
|
||||
pub fn rgb_into_srgb(
|
||||
src_image: &ImageView,
|
||||
dst_image: &mut ImageViewMut,
|
||||
) -> Result<(), MappingError> {
|
||||
if src_image.width() != dst_image.width() || src_image.height() != dst_image.height() {
|
||||
return Err(MappingError::DifferentDimensions);
|
||||
}
|
||||
|
||||
macro_rules! map {
|
||||
($src_pixel:ty, $dst_pixel:ty, $mapping_table:ident) => {
|
||||
if let Some(src) = TypedImageView::<$src_pixel>::from_image_view(src_image) {
|
||||
if let Some(dst) = TypedImageViewMut::<$dst_pixel>::from_image_view(dst_image) {
|
||||
$mapping_table.map_typed_image(src, dst);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let src_pixel_type = src_image.pixel_type();
|
||||
let dst_pixel_type = dst_image.pixel_type();
|
||||
match (src_pixel_type, dst_pixel_type) {
|
||||
(PixelType::U8x3, PixelType::U8x3) => {
|
||||
map!(U8x3, U8x3, RGB8_INTO_SRGB8);
|
||||
}
|
||||
(PixelType::U8x3, PixelType::U16x3) => {
|
||||
map!(U8x3, U16x3, RGB8_INTO_SRGB16);
|
||||
}
|
||||
(PixelType::U16x3, PixelType::U8x3) => {
|
||||
map!(U16x3, U8x3, RGB16_INTO_SRGB8);
|
||||
}
|
||||
(PixelType::U16x3, PixelType::U16x3) => {
|
||||
map!(U16x3, U16x3, RGB16_INTO_SRGB16);
|
||||
}
|
||||
(PixelType::U8x4, PixelType::U8x4) => {
|
||||
map!(U8x4, U8x4, RGB8_INTO_SRGB8);
|
||||
}
|
||||
(PixelType::U8x4, PixelType::U16x4) => {
|
||||
map!(U8x4, U16x4, RGB8_INTO_SRGB16);
|
||||
}
|
||||
(PixelType::U16x4, PixelType::U8x4) => {
|
||||
map!(U16x4, U8x4, RGB16_INTO_SRGB8);
|
||||
}
|
||||
(PixelType::U16x4, PixelType::U16x4) => {
|
||||
map!(U16x4, U16x4, RGB16_INTO_SRGB16);
|
||||
}
|
||||
_ => return Err(MappingError::UnsupportedCombinationOfImageTypes),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::pixels::F32;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
@@ -8,8 +8,8 @@ mod native;
|
||||
|
||||
impl Convolution for F32 {
|
||||
fn horiz_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
_cpu_extensions: CpuExtensions,
|
||||
@@ -18,8 +18,8 @@ impl Convolution for F32 {
|
||||
}
|
||||
|
||||
fn vert_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
coeffs: Coefficients,
|
||||
_cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use crate::convolution::Coefficients;
|
||||
use crate::pixels::F32;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<F32>,
|
||||
mut dst_image: TypedImageViewMut<F32>,
|
||||
src_image: &ImageView<F32>,
|
||||
dst_image: &mut ImageViewMut<F32>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
@@ -25,8 +25,8 @@ pub(crate) fn horiz_convolution(
|
||||
}
|
||||
|
||||
pub(crate) fn vert_convolution(
|
||||
src_image: TypedImageView<F32>,
|
||||
mut dst_image: TypedImageViewMut<F32>,
|
||||
src_image: &ImageView<F32>,
|
||||
dst_image: &mut ImageViewMut<F32>,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
let coefficients_chunks = coeffs.get_chunks();
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::f64::consts::PI;
|
||||
|
||||
pub type FilterFn<'a> = &'a dyn Fn(f64) -> f64;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub enum FilterType {
|
||||
/// Each pixel of source image contributes to one pixel of the
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::pixels::I32;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
@@ -8,8 +8,8 @@ mod native;
|
||||
|
||||
impl Convolution for I32 {
|
||||
fn horiz_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
_cpu_extensions: CpuExtensions,
|
||||
@@ -18,8 +18,8 @@ impl Convolution for I32 {
|
||||
}
|
||||
|
||||
fn vert_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
coeffs: Coefficients,
|
||||
_cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use crate::convolution::Coefficients;
|
||||
use crate::pixels::I32;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<I32>,
|
||||
mut dst_image: TypedImageViewMut<I32>,
|
||||
src_image: &ImageView<I32>,
|
||||
dst_image: &mut ImageViewMut<I32>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
@@ -25,8 +25,8 @@ pub(crate) fn horiz_convolution(
|
||||
}
|
||||
|
||||
pub(crate) fn vert_convolution(
|
||||
src_image: TypedImageView<I32>,
|
||||
mut dst_image: TypedImageViewMut<I32>,
|
||||
src_image: &ImageView<I32>,
|
||||
dst_image: &mut ImageViewMut<I32>,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
let coefficients_chunks = coeffs.get_chunks();
|
||||
|
||||
@@ -3,8 +3,8 @@ use std::num::NonZeroU32;
|
||||
pub use filters::{get_filter_func, FilterType};
|
||||
|
||||
use crate::pixels::Pixel;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
@@ -29,16 +29,16 @@ where
|
||||
Self: Pixel,
|
||||
{
|
||||
fn horiz_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
);
|
||||
|
||||
fn vert_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
);
|
||||
|
||||
@@ -4,12 +4,12 @@ use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U16;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U16>,
|
||||
mut dst_image: TypedImageViewMut<U16>,
|
||||
src_image: &ImageView<U16>,
|
||||
dst_image: &mut ImageViewMut<U16>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::convolution::vertical_u16::vert_convolution_u16;
|
||||
use crate::pixels::U16;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
@@ -13,8 +13,8 @@ mod sse4;
|
||||
|
||||
impl Convolution for U16 {
|
||||
fn horiz_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
@@ -29,8 +29,8 @@ impl Convolution for U16 {
|
||||
}
|
||||
|
||||
fn vert_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::pixels::U16;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U16>,
|
||||
mut dst_image: TypedImageViewMut<U16>,
|
||||
src_image: &ImageView<U16>,
|
||||
dst_image: &mut ImageViewMut<U16>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
|
||||
@@ -4,12 +4,12 @@ use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U16;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U16>,
|
||||
mut dst_image: TypedImageViewMut<U16>,
|
||||
src_image: &ImageView<U16>,
|
||||
dst_image: &mut ImageViewMut<U16>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
@@ -154,7 +154,7 @@ unsafe fn horiz_convolution_four_rows(
|
||||
x += 2;
|
||||
}
|
||||
|
||||
if let Some(&k) = coeffs.get(0) {
|
||||
if let Some(&k) = coeffs.first() {
|
||||
let coeff01_i64x2 = _mm_set_epi64x(0, k as i64);
|
||||
for i in 0..4 {
|
||||
let pixel = (*s_rows[i].get_unchecked(x)).0 as i64;
|
||||
@@ -272,7 +272,7 @@ unsafe fn horiz_convolution_one_row(
|
||||
x += 2;
|
||||
}
|
||||
|
||||
if let Some(&k) = coeffs.get(0) {
|
||||
if let Some(&k) = coeffs.first() {
|
||||
let coeff01_i64x2 = _mm_set_epi64x(0, k as i64);
|
||||
let pixel = (*src_row.get_unchecked(x)).0 as i64;
|
||||
let source = _mm_set_epi64x(0, pixel);
|
||||
|
||||
@@ -4,12 +4,12 @@ use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U16x2;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U16x2>,
|
||||
mut dst_image: TypedImageViewMut<U16x2>,
|
||||
src_image: &ImageView<U16x2>,
|
||||
dst_image: &mut ImageViewMut<U16x2>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
@@ -153,7 +153,7 @@ unsafe fn horiz_convolution_four_rows(
|
||||
x += 2;
|
||||
}
|
||||
|
||||
if let Some(&k) = coeffs.get(0) {
|
||||
if let Some(&k) = coeffs.first() {
|
||||
let coeff0_i64x4 = _mm256_set1_epi64x(k as i64);
|
||||
|
||||
for (i, sum) in ll_sum.iter_mut().enumerate() {
|
||||
@@ -306,7 +306,7 @@ unsafe fn horiz_convolution_one_row(
|
||||
x += 2;
|
||||
}
|
||||
|
||||
if let Some(&k) = coeffs.get(0) {
|
||||
if let Some(&k) = coeffs.first() {
|
||||
let coeff0_i64x4 = _mm256_set_epi64x(0, 0, k as i64, k as i64);
|
||||
let source = _mm256_set_m128i(_mm_setzero_si128(), simd_utils::loadl_epi32(src_row, x));
|
||||
let p_i64x4 = _mm256_shuffle_epi8(source, p0_shuffle);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::convolution::vertical_u16::vert_convolution_u16;
|
||||
use crate::pixels::U16x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
@@ -13,8 +13,8 @@ mod sse4;
|
||||
|
||||
impl Convolution for U16x2 {
|
||||
fn horiz_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
@@ -29,8 +29,8 @@ impl Convolution for U16x2 {
|
||||
}
|
||||
|
||||
fn vert_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::pixels::U16x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U16x2>,
|
||||
mut dst_image: TypedImageViewMut<U16x2>,
|
||||
src_image: &ImageView<U16x2>,
|
||||
dst_image: &mut ImageViewMut<U16x2>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
|
||||
@@ -4,12 +4,12 @@ use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U16x2;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U16x2>,
|
||||
mut dst_image: TypedImageViewMut<U16x2>,
|
||||
src_image: &ImageView<U16x2>,
|
||||
dst_image: &mut ImageViewMut<U16x2>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
@@ -142,7 +142,7 @@ unsafe fn horiz_convolution_four_rows(
|
||||
x += 2;
|
||||
}
|
||||
|
||||
if let Some(&k) = coeffs.get(0) {
|
||||
if let Some(&k) = coeffs.first() {
|
||||
let coeff0_i64x2 = _mm_set1_epi64x(k as i64);
|
||||
for i in 0..4 {
|
||||
let source = simd_utils::loadl_epi32(s_rows[i], x);
|
||||
@@ -249,7 +249,7 @@ unsafe fn horiz_convolution_one_row(
|
||||
x += 2;
|
||||
}
|
||||
|
||||
if let Some(&k) = coeffs.get(0) {
|
||||
if let Some(&k) = coeffs.first() {
|
||||
let coeff0_i64x2 = _mm_set1_epi64x(k as i64);
|
||||
let source = simd_utils::loadl_epi32(src_row, x);
|
||||
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::image_view::{FourRows, FourRowsMut, ImageView, ImageViewMut};
|
||||
use crate::pixels::U16x3;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U16x3>,
|
||||
mut dst_image: TypedImageViewMut<U16x3>,
|
||||
src_image: &ImageView<U16x3>,
|
||||
dst_image: &mut ImageViewMut<U16x3>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::convolution::vertical_u16::vert_convolution_u16;
|
||||
use crate::pixels::U16x3;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
@@ -13,8 +13,8 @@ mod sse4;
|
||||
|
||||
impl Convolution for U16x3 {
|
||||
fn horiz_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
@@ -29,8 +29,8 @@ impl Convolution for U16x3 {
|
||||
}
|
||||
|
||||
fn vert_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::pixels::U16x3;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U16x3>,
|
||||
mut dst_image: TypedImageViewMut<U16x3>,
|
||||
src_image: &ImageView<U16x3>,
|
||||
dst_image: &mut ImageViewMut<U16x3>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
|
||||
@@ -5,12 +5,12 @@ use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U16x3;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U16x3>,
|
||||
mut dst_image: TypedImageViewMut<U16x3>,
|
||||
src_image: &ImageView<U16x3>,
|
||||
dst_image: &mut ImageViewMut<U16x3>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
|
||||
@@ -4,12 +4,12 @@ use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U16x4;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U16x4>,
|
||||
mut dst_image: TypedImageViewMut<U16x4>,
|
||||
src_image: &ImageView<U16x4>,
|
||||
dst_image: &mut ImageViewMut<U16x4>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
@@ -135,7 +135,7 @@ unsafe fn horiz_convolution_four_rows(
|
||||
x += 2;
|
||||
}
|
||||
|
||||
if let Some(&k) = coeffs.get(0) {
|
||||
if let Some(&k) = coeffs.first() {
|
||||
let coeff0_i64x4 = _mm256_set1_epi64x(k as i64);
|
||||
|
||||
for i in 0..2 {
|
||||
@@ -283,7 +283,7 @@ unsafe fn horiz_convolution_one_row(
|
||||
x += 2;
|
||||
}
|
||||
|
||||
if let Some(&k) = coeffs.get(0) {
|
||||
if let Some(&k) = coeffs.first() {
|
||||
let coeff_i64x4 = _mm256_set_epi64x(0, 0, k as i64, k as i64);
|
||||
let source = _mm256_set_m128i(_mm_setzero_si128(), simd_utils::loadl_epi64(src_row, x));
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::convolution::vertical_u16::vert_convolution_u16;
|
||||
use crate::pixels::U16x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
@@ -13,8 +13,8 @@ mod sse4;
|
||||
|
||||
impl Convolution for U16x4 {
|
||||
fn horiz_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
@@ -29,8 +29,8 @@ impl Convolution for U16x4 {
|
||||
}
|
||||
|
||||
fn vert_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::pixels::U16x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U16x4>,
|
||||
mut dst_image: TypedImageViewMut<U16x4>,
|
||||
src_image: &ImageView<U16x4>,
|
||||
dst_image: &mut ImageViewMut<U16x4>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
|
||||
@@ -4,12 +4,12 @@ use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U16x4;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U16x4>,
|
||||
mut dst_image: TypedImageViewMut<U16x4>,
|
||||
src_image: &ImageView<U16x4>,
|
||||
dst_image: &mut ImageViewMut<U16x4>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
@@ -118,7 +118,7 @@ unsafe fn horiz_convolution_four_rows(
|
||||
x += 2;
|
||||
}
|
||||
|
||||
if let Some(&k) = coeffs.get(0) {
|
||||
if let Some(&k) = coeffs.first() {
|
||||
let coeff0_i64x2 = _mm_set1_epi64x(k as i64);
|
||||
for i in 0..4 {
|
||||
let source = simd_utils::loadl_epi64(s_rows[i], x);
|
||||
@@ -213,7 +213,7 @@ unsafe fn horiz_convolution_one_row(
|
||||
x += 2;
|
||||
}
|
||||
|
||||
if let Some(&k) = coeffs.get(0) {
|
||||
if let Some(&k) = coeffs.first() {
|
||||
let coeff0_i64x2 = _mm_set1_epi64x(k as i64);
|
||||
let source = simd_utils::loadl_epi64(src_row, x);
|
||||
let rg_i64x2 = _mm_shuffle_epi8(source, rg0_shuffle);
|
||||
|
||||
@@ -4,12 +4,12 @@ use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U8;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U8>,
|
||||
mut dst_image: TypedImageViewMut<U8>,
|
||||
src_image: &ImageView<U8>,
|
||||
dst_image: &mut ImageViewMut<U8>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::convolution::vertical_u8::vert_convolution_u8;
|
||||
use crate::pixels::U8;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
@@ -11,8 +11,8 @@ mod native;
|
||||
|
||||
impl Convolution for U8 {
|
||||
fn horiz_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
@@ -25,8 +25,8 @@ impl Convolution for U8 {
|
||||
}
|
||||
|
||||
fn vert_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::pixels::U8;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U8>,
|
||||
mut dst_image: TypedImageViewMut<U8>,
|
||||
src_image: &ImageView<U8>,
|
||||
dst_image: &mut ImageViewMut<U8>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
|
||||
@@ -4,12 +4,12 @@ use crate::convolution::{Coefficients, optimisations};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U8x2;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U8x2>,
|
||||
mut dst_image: TypedImageViewMut<U8x2>,
|
||||
src_image: &ImageView<U8x2>,
|
||||
dst_image: &mut ImageViewMut<U8x2>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
@@ -168,7 +168,7 @@ unsafe fn horiz_convolution_four_rows(
|
||||
x += 2;
|
||||
}
|
||||
|
||||
if let Some(&k) = reminder.get(0) {
|
||||
if let Some(&k) = reminder.first() {
|
||||
// [16] xx k0 xx k0 xx k0 xx k0 xx k0 xx k0 xx k0 xx k0
|
||||
let mmk = _mm256_set1_epi32(k as i32);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::convolution::vertical_u8::vert_convolution_u8;
|
||||
use crate::CpuExtensions;
|
||||
use crate::pixels::U8x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
@@ -13,8 +13,8 @@ mod sse4;
|
||||
|
||||
impl Convolution for U8x2 {
|
||||
fn horiz_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
@@ -29,8 +29,8 @@ impl Convolution for U8x2 {
|
||||
}
|
||||
|
||||
fn vert_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::pixels::U8x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U8x2>,
|
||||
mut dst_image: TypedImageViewMut<U8x2>,
|
||||
src_image: &ImageView<U8x2>,
|
||||
dst_image: &mut ImageViewMut<U8x2>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
|
||||
@@ -4,12 +4,12 @@ use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U8x2;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U8x2>,
|
||||
mut dst_image: TypedImageViewMut<U8x2>,
|
||||
src_image: &ImageView<U8x2>,
|
||||
dst_image: &mut ImageViewMut<U8x2>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
@@ -133,7 +133,7 @@ unsafe fn horiz_convolution_four_rows(
|
||||
x += 2;
|
||||
}
|
||||
|
||||
if let Some(&k) = reminder.get(0) {
|
||||
if let Some(&k) = reminder.first() {
|
||||
let mmk = _mm_set1_epi32(k as i32);
|
||||
|
||||
for i in 0..4 {
|
||||
|
||||
@@ -5,12 +5,12 @@ use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U8x3;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U8x3>,
|
||||
mut dst_image: TypedImageViewMut<U8x3>,
|
||||
src_image: &ImageView<U8x3>,
|
||||
dst_image: &mut ImageViewMut<U8x3>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::convolution::vertical_u8::vert_convolution_u8;
|
||||
use crate::pixels::U8x3;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
@@ -13,8 +13,8 @@ mod sse4;
|
||||
|
||||
impl Convolution for U8x3 {
|
||||
fn horiz_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
@@ -31,8 +31,8 @@ impl Convolution for U8x3 {
|
||||
}
|
||||
|
||||
fn vert_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::pixels::U8x3;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U8x3>,
|
||||
mut dst_image: TypedImageViewMut<U8x3>,
|
||||
src_image: &ImageView<U8x3>,
|
||||
dst_image: &mut ImageViewMut<U8x3>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use crate::convolution::Coefficients;
|
||||
use crate::pixels::U8x3;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::native;
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn horiz_convolution(
|
||||
src_image: TypedImageView<U8x3>,
|
||||
dst_image: TypedImageViewMut<U8x3>,
|
||||
src_image: &ImageView<U8x3>,
|
||||
dst_image: &mut ImageViewMut<U8x3>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
|
||||
@@ -5,15 +5,15 @@ use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U8x4;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
// This code is based on C-implementation from Pillow-SIMD package for Python
|
||||
// https://github.com/uploadcare/pillow-simd
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U8x4>,
|
||||
mut dst_image: TypedImageViewMut<U8x4>,
|
||||
src_image: &ImageView<U8x4>,
|
||||
dst_image: &mut ImageViewMut<U8x4>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
@@ -132,7 +132,7 @@ unsafe fn horiz_convolution_8u4x(
|
||||
x += 2;
|
||||
}
|
||||
|
||||
if let Some(&k) = reminder2.get(0) {
|
||||
if let Some(&k) = reminder2.first() {
|
||||
// [16] xx k0 xx k0 xx k0 xx k0 xx k0 xx k0 xx k0 xx k0
|
||||
let mmk = _mm256_set1_epi32(k as i32);
|
||||
|
||||
@@ -283,7 +283,7 @@ unsafe fn horiz_convolution_8u(
|
||||
x += 2
|
||||
}
|
||||
|
||||
if let Some(&k) = reminder1.get(0) {
|
||||
if let Some(&k) = reminder1.first() {
|
||||
let pix = simd_utils::mm_cvtepu8_epi32(src_row, x);
|
||||
let mmk = _mm_set1_epi32(k as i32);
|
||||
sss = _mm_add_epi32(sss, _mm_madd_epi16(pix, mmk));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::convolution::vertical_u8::vert_convolution_u8;
|
||||
use crate::pixels::U8x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
@@ -13,8 +13,8 @@ mod sse4;
|
||||
|
||||
impl Convolution for U8x4 {
|
||||
fn horiz_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
@@ -29,8 +29,8 @@ impl Convolution for U8x4 {
|
||||
}
|
||||
|
||||
fn vert_convolution(
|
||||
src_image: TypedImageView<Self>,
|
||||
dst_image: TypedImageViewMut<Self>,
|
||||
src_image: &ImageView<Self>,
|
||||
dst_image: &mut ImageViewMut<Self>,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::pixels::U8x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U8x4>,
|
||||
mut dst_image: TypedImageViewMut<U8x4>,
|
||||
src_image: &ImageView<U8x4>,
|
||||
dst_image: &mut ImageViewMut<U8x4>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
|
||||
@@ -5,15 +5,15 @@ use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U8x4;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
// This code is based on C-implementation from Pillow-SIMD package for Python
|
||||
// https://github.com/uploadcare/pillow-simd
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U8x4>,
|
||||
mut dst_image: TypedImageViewMut<U8x4>,
|
||||
src_image: &ImageView<U8x4>,
|
||||
dst_image: &mut ImageViewMut<U8x4>,
|
||||
offset: u32,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
@@ -137,7 +137,7 @@ unsafe fn horiz_convolution_8u4x(
|
||||
x += 2;
|
||||
}
|
||||
|
||||
if let Some(&k) = reminder2.get(0) {
|
||||
if let Some(&k) = reminder2.first() {
|
||||
// [16] xx k0 xx k0 xx k0 xx k0
|
||||
let mmk = _mm_set1_epi32(k as i32);
|
||||
// [16] xx a0 xx b0 xx g0 xx r0
|
||||
@@ -265,7 +265,7 @@ unsafe fn horiz_convolution_8u(
|
||||
x += 2
|
||||
}
|
||||
|
||||
if let Some(&k) = reminder2.get(0) {
|
||||
if let Some(&k) = reminder2.first() {
|
||||
let pix = simd_utils::mm_cvtepu8_epi32(src_row, x);
|
||||
let mmk = _mm_set1_epi32(k as i32);
|
||||
sss = _mm_add_epi32(sss, _mm_madd_epi16(pix, mmk));
|
||||
|
||||
@@ -3,11 +3,11 @@ use std::arch::x86_64::*;
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
pub(crate) fn vert_convolution<T>(
|
||||
src_image: TypedImageView<T>,
|
||||
mut dst_image: TypedImageViewMut<T>,
|
||||
src_image: &ImageView<T>,
|
||||
dst_image: &mut ImageViewMut<T>,
|
||||
coeffs: Coefficients,
|
||||
) where
|
||||
T: Pixel<Component = u16>,
|
||||
@@ -18,14 +18,14 @@ pub(crate) fn vert_convolution<T>(
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
for (dst_row, coeffs_chunk) in dst_rows.zip(coefficients_chunks) {
|
||||
unsafe {
|
||||
vert_convolution_into_one_row_u16(&src_image, dst_row, coeffs_chunk, &normalizer);
|
||||
vert_convolution_into_one_row_u16(src_image, dst_row, coeffs_chunk, &normalizer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn vert_convolution_into_one_row_u16<T>(
|
||||
src_img: &TypedImageView<T>,
|
||||
src_img: &ImageView<T>,
|
||||
dst_row: &mut [T],
|
||||
coeffs_chunk: optimisations::CoefficientsI32Chunk,
|
||||
normalizer: &optimisations::Normalizer32,
|
||||
@@ -33,7 +33,7 @@ pub(crate) unsafe fn vert_convolution_into_one_row_u16<T>(
|
||||
T: Pixel<Component = u16>,
|
||||
{
|
||||
let mut xx: usize = 0;
|
||||
let src_width = src_img.width().get() as usize * T::components_count();
|
||||
let src_width = src_img.width().get() as usize * T::count_of_components();
|
||||
let y_start = coeffs_chunk.start;
|
||||
let coeffs = coeffs_chunk.values;
|
||||
let dst_components = T::components_mut(dst_row);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::convolution::Coefficients;
|
||||
use crate::pixels::Pixel;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub(crate) mod avx2;
|
||||
@@ -10,8 +10,8 @@ pub(crate) mod native;
|
||||
pub(crate) mod sse4;
|
||||
|
||||
pub(crate) fn vert_convolution_u16<T: Pixel<Component = u16>>(
|
||||
src_image: TypedImageView<T>,
|
||||
dst_image: TypedImageViewMut<T>,
|
||||
src_image: &ImageView<T>,
|
||||
dst_image: &mut ImageViewMut<T>,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn vert_convolution<T: Pixel<Component = u16>>(
|
||||
src_image: TypedImageView<T>,
|
||||
mut dst_image: TypedImageViewMut<T>,
|
||||
src_image: &ImageView<T>,
|
||||
dst_image: &mut ImageViewMut<T>,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
// Check safety conditions
|
||||
@@ -25,7 +25,7 @@ pub(crate) fn vert_convolution<T: Pixel<Component = u16>>(
|
||||
let dst_components = T::components_mut(dst_row);
|
||||
|
||||
convolution_by_u16(
|
||||
&src_image,
|
||||
src_image,
|
||||
&normalizer,
|
||||
initial,
|
||||
dst_components,
|
||||
@@ -38,7 +38,7 @@ pub(crate) fn vert_convolution<T: Pixel<Component = u16>>(
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn convolution_by_u16<T: Pixel<Component = u16>>(
|
||||
src_image: &TypedImageView<T>,
|
||||
src_image: &ImageView<T>,
|
||||
normalizer: &optimisations::Normalizer32,
|
||||
initial: i64,
|
||||
dst_components: &mut [u16],
|
||||
|
||||
@@ -5,11 +5,11 @@ use crate::convolution::vertical_u16::native::convolution_by_u16;
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
pub(crate) fn vert_convolution<T: Pixel<Component = u16>>(
|
||||
src_image: TypedImageView<T>,
|
||||
mut dst_image: TypedImageViewMut<T>,
|
||||
src_image: &ImageView<T>,
|
||||
dst_image: &mut ImageViewMut<T>,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
let normalizer = optimisations::Normalizer32::new(coeffs);
|
||||
@@ -18,20 +18,20 @@ pub(crate) fn vert_convolution<T: Pixel<Component = u16>>(
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
for (dst_row, coeffs_chunk) in dst_rows.zip(coefficients_chunks) {
|
||||
unsafe {
|
||||
vert_convolution_into_one_row_u16(&src_image, dst_row, coeffs_chunk, &normalizer);
|
||||
vert_convolution_into_one_row_u16(src_image, dst_row, coeffs_chunk, &normalizer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
unsafe fn vert_convolution_into_one_row_u16<T: Pixel<Component = u16>>(
|
||||
src_img: &TypedImageView<T>,
|
||||
src_img: &ImageView<T>,
|
||||
dst_row: &mut [T],
|
||||
coeffs_chunk: CoefficientsI32Chunk,
|
||||
normalizer: &optimisations::Normalizer32,
|
||||
) {
|
||||
let mut xx: usize = 0;
|
||||
let src_width = src_img.width().get() as usize * T::components_count();
|
||||
let src_width = src_img.width().get() as usize * T::count_of_components();
|
||||
let y_start = coeffs_chunk.start;
|
||||
let coeffs = coeffs_chunk.values;
|
||||
let max_y = y_start + coeffs.len() as u32;
|
||||
@@ -93,7 +93,7 @@ unsafe fn vert_convolution_into_one_row_u16<T: Pixel<Component = u16>>(
|
||||
y += 2;
|
||||
}
|
||||
|
||||
if let Some(&k) = coeffs_reminder.get(0) {
|
||||
if let Some(&k) = coeffs_reminder.first() {
|
||||
let s_row = src_img.get_row(y_start + y).unwrap();
|
||||
let components = T::components(s_row);
|
||||
let coeff_i64x2 = _mm_set1_epi64x(k as i64);
|
||||
@@ -145,7 +145,7 @@ unsafe fn vert_convolution_into_one_row_u16<T: Pixel<Component = u16>>(
|
||||
y += 2;
|
||||
}
|
||||
|
||||
if let Some(&k) = coeffs_reminder.get(0) {
|
||||
if let Some(&k) = coeffs_reminder.first() {
|
||||
let s_row = src_img.get_row(y_start + y).unwrap();
|
||||
let components = T::components(s_row);
|
||||
let coeff_i64x2 = _mm_set1_epi64x(k as i64);
|
||||
@@ -195,7 +195,7 @@ unsafe fn vert_convolution_into_one_row_u16<T: Pixel<Component = u16>>(
|
||||
y += 2;
|
||||
}
|
||||
|
||||
if let Some(&k) = coeffs_reminder.get(0) {
|
||||
if let Some(&k) = coeffs_reminder.first() {
|
||||
let s_row = src_img.get_row(y_start + y).unwrap();
|
||||
let components = T::components(s_row);
|
||||
let coeff_i64x2 = _mm_set1_epi64x(k as i64);
|
||||
|
||||
@@ -3,12 +3,12 @@ use std::arch::x86_64::*;
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn vert_convolution<T>(
|
||||
src_image: TypedImageView<T>,
|
||||
mut dst_image: TypedImageViewMut<T>,
|
||||
src_image: &ImageView<T>,
|
||||
dst_image: &mut ImageViewMut<T>,
|
||||
coeffs: Coefficients,
|
||||
) where
|
||||
T: Pixel<Component = u8>,
|
||||
@@ -19,7 +19,7 @@ pub(crate) fn vert_convolution<T>(
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
for (dst_row, coeffs_chunk) in dst_rows.zip(coefficients_chunks) {
|
||||
unsafe {
|
||||
vert_convolution_into_one_row_u8(&src_image, dst_row, coeffs_chunk, &normalizer);
|
||||
vert_convolution_into_one_row_u8(src_image, dst_row, coeffs_chunk, &normalizer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,14 +27,14 @@ pub(crate) fn vert_convolution<T>(
|
||||
#[inline]
|
||||
#[target_feature(enable = "avx2")]
|
||||
unsafe fn vert_convolution_into_one_row_u8<T>(
|
||||
src_img: &TypedImageView<T>,
|
||||
src_img: &ImageView<T>,
|
||||
dst_row: &mut [T],
|
||||
coeffs_chunk: optimisations::CoefficientsI16Chunk,
|
||||
normalizer: &optimisations::Normalizer16,
|
||||
) where
|
||||
T: Pixel<Component = u8>,
|
||||
{
|
||||
let src_width = src_img.width().get() as usize * T::components_count();
|
||||
let src_width = src_img.width().get() as usize * T::count_of_components();
|
||||
let y_start = coeffs_chunk.start;
|
||||
let coeffs = coeffs_chunk.values;
|
||||
let max_y = y_start + coeffs.len() as u32;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::convolution::Coefficients;
|
||||
use crate::pixels::Pixel;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub(crate) mod avx2;
|
||||
@@ -10,8 +10,8 @@ pub(crate) mod native;
|
||||
pub(crate) mod sse4;
|
||||
|
||||
pub(crate) fn vert_convolution_u8<T: Pixel<Component = u8>>(
|
||||
src_image: TypedImageView<T>,
|
||||
dst_image: TypedImageViewMut<T>,
|
||||
src_image: &ImageView<T>,
|
||||
dst_image: &mut ImageViewMut<T>,
|
||||
coeffs: Coefficients,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn vert_convolution<T>(
|
||||
src_image: TypedImageView<T>,
|
||||
mut dst_image: TypedImageViewMut<T>,
|
||||
src_image: &ImageView<T>,
|
||||
dst_image: &mut ImageViewMut<T>,
|
||||
coeffs: Coefficients,
|
||||
) where
|
||||
T: Pixel<Component = u8>,
|
||||
@@ -30,7 +30,7 @@ pub(crate) fn vert_convolution<T>(
|
||||
|
||||
if !head.is_empty() {
|
||||
x_src = convolution_by_u8(
|
||||
&src_image,
|
||||
src_image,
|
||||
&normalizer,
|
||||
initial,
|
||||
head,
|
||||
@@ -62,7 +62,7 @@ pub(crate) fn vert_convolution<T>(
|
||||
|
||||
if !tail.is_empty() {
|
||||
convolution_by_u8(
|
||||
&src_image,
|
||||
src_image,
|
||||
&normalizer,
|
||||
initial,
|
||||
tail,
|
||||
@@ -76,7 +76,7 @@ pub(crate) fn vert_convolution<T>(
|
||||
|
||||
#[inline(always)]
|
||||
fn convolution_by_u8<T>(
|
||||
src_image: &TypedImageView<T>,
|
||||
src_image: &ImageView<T>,
|
||||
normalizer: &optimisations::Normalizer16,
|
||||
initial: i32,
|
||||
dst_components: &mut [u8],
|
||||
|
||||
@@ -3,12 +3,12 @@ use std::arch::x86_64::*;
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn vert_convolution<T: Pixel<Component = u8>>(
|
||||
src_image: TypedImageView<T>,
|
||||
mut dst_image: TypedImageViewMut<T>,
|
||||
src_image: &ImageView<T>,
|
||||
dst_image: &mut ImageViewMut<T>,
|
||||
coeffs: Coefficients,
|
||||
) {
|
||||
let normalizer = optimisations::Normalizer16::new(coeffs);
|
||||
@@ -17,20 +17,20 @@ pub(crate) fn vert_convolution<T: Pixel<Component = u8>>(
|
||||
let dst_rows = dst_image.iter_rows_mut();
|
||||
for (dst_row, coeffs_chunk) in dst_rows.zip(coefficients_chunks) {
|
||||
unsafe {
|
||||
vert_convolution_into_one_row_u8(&src_image, dst_row, coeffs_chunk, &normalizer);
|
||||
vert_convolution_into_one_row_u8(src_image, dst_row, coeffs_chunk, &normalizer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[target_feature(enable = "sse4.1")]
|
||||
pub(crate) unsafe fn vert_convolution_into_one_row_u8<T: Pixel<Component = u8>>(
|
||||
src_img: &TypedImageView<T>,
|
||||
src_img: &ImageView<T>,
|
||||
dst_row: &mut [T],
|
||||
coeffs_chunk: optimisations::CoefficientsI16Chunk,
|
||||
normalizer: &optimisations::Normalizer16,
|
||||
) {
|
||||
let mut xx: usize = 0;
|
||||
let src_width = src_img.width().get() as usize * T::components_count();
|
||||
let src_width = src_img.width().get() as usize * T::count_of_components();
|
||||
let y_start = coeffs_chunk.start;
|
||||
let coeffs = coeffs_chunk.values;
|
||||
let max_y = y_start + coeffs.len() as u32;
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use crate::image_view::change_type_of_pixel_components;
|
||||
use crate::pixels::{U16x2, U16x3, U16x4, U8x2, U8x3, U8x4, F32, I32, U16, U8};
|
||||
use crate::{CropBox, CropBoxError, ImageView, ImageViewMut, MappingError, PixelType};
|
||||
|
||||
/// An immutable view of image data used by resizer as source image.
|
||||
#[derive(Debug, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub enum DynamicImageView<'a> {
|
||||
U8(ImageView<'a, U8>),
|
||||
U8x2(ImageView<'a, U8x2>),
|
||||
U8x3(ImageView<'a, U8x3>),
|
||||
U8x4(ImageView<'a, U8x4>),
|
||||
U16(ImageView<'a, U16>),
|
||||
U16x2(ImageView<'a, U16x2>),
|
||||
U16x3(ImageView<'a, U16x3>),
|
||||
U16x4(ImageView<'a, U16x4>),
|
||||
I32(ImageView<'a, I32>),
|
||||
F32(ImageView<'a, F32>),
|
||||
}
|
||||
|
||||
/// A mutable view of image data used by resizer as destination image.
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum DynamicImageViewMut<'a> {
|
||||
U8(ImageViewMut<'a, U8>),
|
||||
U8x2(ImageViewMut<'a, U8x2>),
|
||||
U8x3(ImageViewMut<'a, U8x3>),
|
||||
U8x4(ImageViewMut<'a, U8x4>),
|
||||
U16(ImageViewMut<'a, U16>),
|
||||
U16x2(ImageViewMut<'a, U16x2>),
|
||||
U16x3(ImageViewMut<'a, U16x3>),
|
||||
U16x4(ImageViewMut<'a, U16x4>),
|
||||
I32(ImageViewMut<'a, I32>),
|
||||
F32(ImageViewMut<'a, F32>),
|
||||
}
|
||||
|
||||
macro_rules! dynamic_map(
|
||||
($dyn_image: expr, $image: pat => $action: expr) => ({
|
||||
use DynamicImageView::*;
|
||||
match $dyn_image {
|
||||
U8($image) => U8($action),
|
||||
U8x2($image) => U8x2($action),
|
||||
U8x3($image) => U8x3($action),
|
||||
U8x4($image) => U8x4($action),
|
||||
U16($image) => U16($action),
|
||||
U16x2($image) => U16x2($action),
|
||||
U16x3($image) => U16x3($action),
|
||||
U16x4($image) => U16x4($action),
|
||||
I32($image) => I32($action),
|
||||
F32($image) => F32($action),
|
||||
}
|
||||
});
|
||||
|
||||
($dyn_image: expr, |$image: pat_param| $action: expr) => (
|
||||
match $dyn_image {
|
||||
DynamicImageView::U8($image) => $action,
|
||||
DynamicImageView::U8x2($image) => $action,
|
||||
DynamicImageView::U8x3($image) => $action,
|
||||
DynamicImageView::U8x4($image) => $action,
|
||||
DynamicImageView::U16($image) => $action,
|
||||
DynamicImageView::U16x2($image) => $action,
|
||||
DynamicImageView::U16x3($image) => $action,
|
||||
DynamicImageView::U16x4($image) => $action,
|
||||
DynamicImageView::I32($image) => $action,
|
||||
DynamicImageView::F32($image) => $action,
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
macro_rules! dynamic_mut_map (
|
||||
($dyn_image: expr, $image: pat => $action: expr) => ({
|
||||
use DynamicImageViewMut::*;
|
||||
match $dyn_image {
|
||||
U8($image) => U8($action),
|
||||
U8x2($image) => U8x2($action),
|
||||
U8x3($image) => U8x3($action),
|
||||
U8x4($image) => U8x4($action),
|
||||
U16($image) => U16($action),
|
||||
U16x2($image) => U16x2($action),
|
||||
U16x3($image) => U16x3($action),
|
||||
U16x4($image) => U16x4($action),
|
||||
I32($image) => I32($action),
|
||||
F32($image) => F32($action),
|
||||
}
|
||||
});
|
||||
|
||||
($dyn_image: expr, |$image: pat_param| $action: expr) => (
|
||||
match $dyn_image {
|
||||
DynamicImageViewMut::U8($image) => $action,
|
||||
DynamicImageViewMut::U8x2($image) => $action,
|
||||
DynamicImageViewMut::U8x3($image) => $action,
|
||||
DynamicImageViewMut::U8x4($image) => $action,
|
||||
DynamicImageViewMut::U16($image) => $action,
|
||||
DynamicImageViewMut::U16x2($image) => $action,
|
||||
DynamicImageViewMut::U16x3($image) => $action,
|
||||
DynamicImageViewMut::U16x4($image) => $action,
|
||||
DynamicImageViewMut::I32($image) => $action,
|
||||
DynamicImageViewMut::F32($image) => $action,
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
impl<'a> DynamicImageView<'a> {
|
||||
pub fn width(&self) -> NonZeroU32 {
|
||||
dynamic_map!(self, |typed_image| typed_image.width())
|
||||
}
|
||||
|
||||
pub fn height(&self) -> NonZeroU32 {
|
||||
dynamic_map!(self, |typed_image| typed_image.height())
|
||||
}
|
||||
|
||||
pub fn pixel_type(&self) -> PixelType {
|
||||
dynamic_map!(self, |typed_image| typed_image.pixel_type())
|
||||
}
|
||||
|
||||
pub fn crop_box(&self) -> CropBox {
|
||||
dynamic_map!(self, |typed_image| typed_image.crop_box())
|
||||
}
|
||||
|
||||
pub fn set_crop_box(&mut self, crop_box: CropBox) -> Result<(), CropBoxError> {
|
||||
dynamic_map!(self, |typed_image| typed_image.set_crop_box(crop_box))
|
||||
}
|
||||
|
||||
pub fn set_crop_box_to_fit_dst_size(
|
||||
&mut self,
|
||||
dst_width: NonZeroU32,
|
||||
dst_height: NonZeroU32,
|
||||
centering: Option<(f32, f32)>,
|
||||
) {
|
||||
dynamic_map!(self, |typed_image| typed_image
|
||||
.set_crop_box_to_fit_dst_size(dst_width, dst_height, centering))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> DynamicImageViewMut<'a> {
|
||||
pub fn width(&self) -> NonZeroU32 {
|
||||
dynamic_mut_map!(self, |typed_image| typed_image.width())
|
||||
}
|
||||
|
||||
pub fn height(&self) -> NonZeroU32 {
|
||||
dynamic_mut_map!(self, |typed_image| typed_image.height())
|
||||
}
|
||||
|
||||
pub fn pixel_type(&self) -> PixelType {
|
||||
dynamic_mut_map!(self, |typed_image| typed_image.pixel_type())
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! from_typed {
|
||||
($pixel_type: ty, $enum: expr, $enum_mut: expr) => {
|
||||
impl<'a> From<ImageView<'a, $pixel_type>> for DynamicImageView<'a> {
|
||||
fn from(view: ImageView<'a, $pixel_type>) -> Self {
|
||||
$enum(view)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<ImageViewMut<'a, $pixel_type>> for DynamicImageViewMut<'a> {
|
||||
fn from(view: ImageViewMut<'a, $pixel_type>) -> Self {
|
||||
$enum_mut(view)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
from_typed!(U8, DynamicImageView::U8, DynamicImageViewMut::U8);
|
||||
from_typed!(U8x2, DynamicImageView::U8x2, DynamicImageViewMut::U8x2);
|
||||
from_typed!(U8x3, DynamicImageView::U8x3, DynamicImageViewMut::U8x3);
|
||||
from_typed!(U8x4, DynamicImageView::U8x4, DynamicImageViewMut::U8x4);
|
||||
from_typed!(U16, DynamicImageView::U16, DynamicImageViewMut::U16);
|
||||
from_typed!(U16x2, DynamicImageView::U16x2, DynamicImageViewMut::U16x2);
|
||||
from_typed!(U16x3, DynamicImageView::U16x3, DynamicImageViewMut::U16x3);
|
||||
from_typed!(U16x4, DynamicImageView::U16x4, DynamicImageViewMut::U16x4);
|
||||
from_typed!(I32, DynamicImageView::I32, DynamicImageViewMut::I32);
|
||||
from_typed!(F32, DynamicImageView::F32, DynamicImageViewMut::F32);
|
||||
|
||||
pub fn change_type_of_pixel_components_dyn(
|
||||
src_image: &DynamicImageView,
|
||||
dst_image: &mut DynamicImageViewMut,
|
||||
) -> Result<(), MappingError> {
|
||||
macro_rules! map {
|
||||
($value:expr, $(($src_first:path, $src_second:path, $dst_first:path, $dst_second:path)),*) => {
|
||||
match $value {
|
||||
$(
|
||||
($src_first(src), $dst_first(dst)) => {
|
||||
change_type_of_pixel_components(src, dst)?;
|
||||
}
|
||||
($src_first(src), $dst_second(dst)) => {
|
||||
change_type_of_pixel_components(src, dst)?;
|
||||
}
|
||||
($src_second(src), $dst_first(dst)) => {
|
||||
change_type_of_pixel_components(src, dst)?;
|
||||
}
|
||||
($src_second(src), $dst_second(dst)) => {
|
||||
change_type_of_pixel_components(src, dst)?;
|
||||
}
|
||||
)*
|
||||
_ => return Err(MappingError::UnsupportedCombinationOfImageTypes),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use DynamicImageView as IV;
|
||||
use DynamicImageViewMut as IVMut;
|
||||
|
||||
map!(
|
||||
(src_image, dst_image),
|
||||
(IV::U8, IV::U16, IVMut::U8, IVMut::U16),
|
||||
(IV::U8x2, IV::U16x2, IVMut::U8x2, IVMut::U16x2),
|
||||
(IV::U8x3, IV::U16x3, IVMut::U8x3, IVMut::U16x3),
|
||||
(IV::U8x4, IV::U16x4, IVMut::U8x4, IVMut::U16x4)
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
+11
-5
@@ -1,6 +1,6 @@
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug, Clone, Copy, PartialEq)]
|
||||
#[derive(Error, Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ImageRowsError {
|
||||
#[error("Count of rows don't match to image height")]
|
||||
InvalidRowsCount,
|
||||
@@ -8,7 +8,7 @@ pub enum ImageRowsError {
|
||||
InvalidRowSize,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug, Clone, Copy, PartialEq)]
|
||||
#[derive(Error, Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ImageBufferError {
|
||||
#[error("Size of buffer is smaller than required")]
|
||||
InvalidBufferSize,
|
||||
@@ -16,7 +16,7 @@ pub enum ImageBufferError {
|
||||
InvalidBufferAlignment,
|
||||
}
|
||||
|
||||
#[derive(Error, Debug, Clone, Copy, PartialEq)]
|
||||
#[derive(Error, Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum CropBoxError {
|
||||
#[error("Position of the crop box is out of the image boundaries")]
|
||||
PositionIsOutOfImageBoundaries,
|
||||
@@ -32,12 +32,18 @@ pub struct DifferentTypesOfPixelsError;
|
||||
#[error(
|
||||
"The dimensions of the source image are not equal to the dimensions of the destination image"
|
||||
)]
|
||||
pub(crate) struct DifferentDimensionsError;
|
||||
pub struct DifferentDimensionsError;
|
||||
|
||||
#[derive(Error, Debug, Clone, Copy)]
|
||||
#[derive(Error, Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum MappingError {
|
||||
#[error("The dimensions of the source image are not equal to the dimensions of the destination image")]
|
||||
DifferentDimensions,
|
||||
#[error("Unsupported combination of pixels of source and/or destination images")]
|
||||
UnsupportedCombinationOfImageTypes,
|
||||
}
|
||||
|
||||
impl From<DifferentDimensionsError> for MappingError {
|
||||
fn from(_: DifferentDimensionsError) -> Self {
|
||||
MappingError::DifferentDimensions
|
||||
}
|
||||
}
|
||||
|
||||
+48
-208
@@ -1,9 +1,7 @@
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use crate::image_rows::{ImageRows, ImageRowsMut};
|
||||
use crate::pixels::{Pixel, PixelType, U16x2, U16x3, U16x4, U8x2, U8x3, U8x4, F32, I32, U16, U8};
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{ImageBufferError, ImageView, ImageViewMut};
|
||||
use crate::pixels::{Pixel, PixelType};
|
||||
use crate::{DynamicImageView, DynamicImageViewMut, ImageBufferError, ImageView, ImageViewMut};
|
||||
|
||||
#[derive(Debug)]
|
||||
enum PixelsContainer<'a> {
|
||||
@@ -136,204 +134,49 @@ impl<'a> Image<'a> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn view(&self) -> ImageView {
|
||||
let buffer = self.buffer();
|
||||
let rows_count = self.height.get() as usize;
|
||||
let rows = match self.pixel_type {
|
||||
PixelType::U8x2 => {
|
||||
let pixels = unsafe { buffer.align_to::<U8x2>().1 };
|
||||
ImageRows::U8x2(
|
||||
pixels
|
||||
.chunks_exact(self.width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U8x3 => {
|
||||
let pixels = unsafe { buffer.align_to::<U8x3>().1 };
|
||||
ImageRows::U8x3(
|
||||
pixels
|
||||
.chunks_exact(self.width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U8x4 => {
|
||||
let pixels = unsafe { buffer.align_to::<U8x4>().1 };
|
||||
ImageRows::U8x4(
|
||||
pixels
|
||||
.chunks_exact(self.width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U16 => {
|
||||
let pixels = unsafe { buffer.align_to::<U16>().1 };
|
||||
ImageRows::U16(
|
||||
pixels
|
||||
.chunks_exact(self.width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U16x2 => {
|
||||
let pixels = unsafe { buffer.align_to::<U16x2>().1 };
|
||||
ImageRows::U16x2(
|
||||
pixels
|
||||
.chunks_exact(self.width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U16x3 => {
|
||||
let pixels = unsafe { buffer.align_to::<U16x3>().1 };
|
||||
ImageRows::U16x3(
|
||||
pixels
|
||||
.chunks_exact(self.width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U16x4 => {
|
||||
let pixels = unsafe { buffer.align_to::<U16x4>().1 };
|
||||
ImageRows::U16x4(
|
||||
pixels
|
||||
.chunks_exact(self.width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::I32 => {
|
||||
let pixels = unsafe { buffer.align_to::<I32>().1 };
|
||||
ImageRows::I32(
|
||||
pixels
|
||||
.chunks_exact(self.width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::F32 => {
|
||||
let pixels = unsafe { buffer.align_to::<F32>().1 };
|
||||
ImageRows::F32(
|
||||
pixels
|
||||
.chunks_exact(self.width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U8 => {
|
||||
let pixels = unsafe { buffer.align_to::<U8>().1 };
|
||||
ImageRows::U8(
|
||||
pixels
|
||||
.chunks_exact(self.width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
};
|
||||
ImageView::new(self.width, self.height, rows).unwrap()
|
||||
pub fn view(&self) -> DynamicImageView {
|
||||
macro_rules! get_dynamic_image {
|
||||
($img_type: expr) => {
|
||||
($img_type(ImageView::from_buffer(self.width, self.height, self.buffer()).unwrap()))
|
||||
};
|
||||
}
|
||||
|
||||
match self.pixel_type {
|
||||
PixelType::U8 => get_dynamic_image!(DynamicImageView::U8),
|
||||
PixelType::U8x2 => get_dynamic_image!(DynamicImageView::U8x2),
|
||||
PixelType::U8x3 => get_dynamic_image!(DynamicImageView::U8x3),
|
||||
PixelType::U8x4 => get_dynamic_image!(DynamicImageView::U8x4),
|
||||
PixelType::U16 => get_dynamic_image!(DynamicImageView::U16),
|
||||
PixelType::U16x2 => get_dynamic_image!(DynamicImageView::U16x2),
|
||||
PixelType::U16x3 => get_dynamic_image!(DynamicImageView::U16x3),
|
||||
PixelType::U16x4 => get_dynamic_image!(DynamicImageView::U16x4),
|
||||
PixelType::I32 => get_dynamic_image!(DynamicImageView::I32),
|
||||
PixelType::F32 => get_dynamic_image!(DynamicImageView::F32),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn view_mut(&mut self) -> ImageViewMut {
|
||||
let pixel_type = self.pixel_type;
|
||||
let width = self.width;
|
||||
let height = self.height;
|
||||
let buffer = self.buffer_mut();
|
||||
let rows_count = height.get() as usize;
|
||||
let rows = match pixel_type {
|
||||
PixelType::U8x2 => {
|
||||
let pixels = unsafe { buffer.align_to_mut::<U8x2>().1 };
|
||||
ImageRowsMut::U8x2(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U8x3 => {
|
||||
let pixels = unsafe { buffer.align_to_mut::<U8x3>().1 };
|
||||
ImageRowsMut::U8x3(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U8x4 => {
|
||||
let pixels = unsafe { buffer.align_to_mut::<U8x4>().1 };
|
||||
ImageRowsMut::U8x4(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U16 => {
|
||||
let pixels = unsafe { buffer.align_to_mut::<U16>().1 };
|
||||
ImageRowsMut::U16(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U16x2 => {
|
||||
let pixels = unsafe { buffer.align_to_mut::<U16x2>().1 };
|
||||
ImageRowsMut::U16x2(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U16x3 => {
|
||||
let pixels = unsafe { buffer.align_to_mut::<U16x3>().1 };
|
||||
ImageRowsMut::U16x3(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U16x4 => {
|
||||
let pixels = unsafe { buffer.align_to_mut::<U16x4>().1 };
|
||||
ImageRowsMut::U16x4(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::I32 => {
|
||||
let pixels = unsafe { buffer.align_to_mut::<I32>().1 };
|
||||
ImageRowsMut::I32(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::F32 => {
|
||||
let pixels = unsafe { buffer.align_to_mut::<F32>().1 };
|
||||
ImageRowsMut::F32(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U8 => {
|
||||
let pixels = unsafe { buffer.align_to_mut::<U8>().1 };
|
||||
ImageRowsMut::U8(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
};
|
||||
ImageViewMut::new(width, height, rows).unwrap()
|
||||
pub fn view_mut(&mut self) -> DynamicImageViewMut {
|
||||
macro_rules! get_dynamic_image {
|
||||
($img_type: expr) => {
|
||||
($img_type(
|
||||
ImageViewMut::from_buffer(self.width, self.height, self.buffer_mut()).unwrap(),
|
||||
))
|
||||
};
|
||||
}
|
||||
|
||||
match self.pixel_type {
|
||||
PixelType::U8 => get_dynamic_image!(DynamicImageViewMut::U8),
|
||||
PixelType::U8x2 => get_dynamic_image!(DynamicImageViewMut::U8x2),
|
||||
PixelType::U8x3 => get_dynamic_image!(DynamicImageViewMut::U8x3),
|
||||
PixelType::U8x4 => get_dynamic_image!(DynamicImageViewMut::U8x4),
|
||||
PixelType::U16 => get_dynamic_image!(DynamicImageViewMut::U16),
|
||||
PixelType::U16x2 => get_dynamic_image!(DynamicImageViewMut::U16x2),
|
||||
PixelType::U16x3 => get_dynamic_image!(DynamicImageViewMut::U16x3),
|
||||
PixelType::U16x4 => get_dynamic_image!(DynamicImageViewMut::U16x4),
|
||||
PixelType::I32 => get_dynamic_image!(DynamicImageViewMut::I32),
|
||||
PixelType::F32 => get_dynamic_image!(DynamicImageViewMut::F32),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,7 +187,7 @@ where
|
||||
{
|
||||
width: NonZeroU32,
|
||||
height: NonZeroU32,
|
||||
rows: Vec<&'a mut [P]>,
|
||||
pixels: &'a mut [P],
|
||||
}
|
||||
|
||||
impl<'a, P> InnerImage<'a, P>
|
||||
@@ -352,23 +195,20 @@ where
|
||||
P: Pixel,
|
||||
{
|
||||
pub fn new(width: NonZeroU32, height: NonZeroU32, pixels: &'a mut [P]) -> Self {
|
||||
let rows = pixels.chunks_mut(width.get() as usize).collect();
|
||||
Self {
|
||||
width,
|
||||
height,
|
||||
rows,
|
||||
pixels,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn src_view<'s>(&'s self) -> TypedImageView<'s, 'a, P> {
|
||||
let rows = self.rows.as_slice();
|
||||
let rows: &[&[P]] = unsafe { std::mem::transmute(rows) };
|
||||
TypedImageView::new(self.width, self.height, rows)
|
||||
pub fn src_view(&self) -> ImageView<P> {
|
||||
ImageView::from_pixels(self.width, self.height, self.pixels).unwrap()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn dst_view<'s>(&'s mut self) -> TypedImageViewMut<'s, 'a, P> {
|
||||
TypedImageViewMut::new(self.width, self.height, self.rows.as_mut_slice())
|
||||
pub fn dst_view(&mut self) -> ImageViewMut<P> {
|
||||
ImageViewMut::from_pixels(self.width, self.height, self.pixels).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
use std::mem::transmute;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use crate::pixels::{Pixel, U16x2, U16x3, U16x4, U8x2, U8x3, U8x4, F32, I32, U16, U8};
|
||||
use crate::{ImageRowsError, PixelType};
|
||||
|
||||
/// An immutable rows of image.
|
||||
#[derive(Debug, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub enum ImageRows<'a> {
|
||||
U8(Vec<&'a [U8]>),
|
||||
U8x2(Vec<&'a [U8x2]>),
|
||||
U8x3(Vec<&'a [U8x3]>),
|
||||
U8x4(Vec<&'a [U8x4]>),
|
||||
U16(Vec<&'a [U16]>),
|
||||
U16x2(Vec<&'a [U16x2]>),
|
||||
U16x3(Vec<&'a [U16x3]>),
|
||||
U16x4(Vec<&'a [U16x4]>),
|
||||
I32(Vec<&'a [I32]>),
|
||||
F32(Vec<&'a [F32]>),
|
||||
}
|
||||
|
||||
impl<'a> ImageRows<'a> {
|
||||
pub(crate) fn check_size(
|
||||
&self,
|
||||
width: NonZeroU32,
|
||||
height: NonZeroU32,
|
||||
) -> Result<(), ImageRowsError> {
|
||||
match self {
|
||||
ImageRows::U8(rows) => check_rows_count_and_size(width, height, rows),
|
||||
ImageRows::U8x2(rows) => check_rows_count_and_size(width, height, rows),
|
||||
ImageRows::U8x3(rows) => check_rows_count_and_size(width, height, rows),
|
||||
ImageRows::U8x4(rows) => check_rows_count_and_size(width, height, rows),
|
||||
ImageRows::U16(rows) => check_rows_count_and_size(width, height, rows),
|
||||
ImageRows::U16x2(rows) => check_rows_count_and_size(width, height, rows),
|
||||
ImageRows::U16x3(rows) => check_rows_count_and_size(width, height, rows),
|
||||
ImageRows::U16x4(rows) => check_rows_count_and_size(width, height, rows),
|
||||
ImageRows::I32(rows) => check_rows_count_and_size(width, height, rows),
|
||||
ImageRows::F32(rows) => check_rows_count_and_size(width, height, rows),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pixel_type(&self) -> PixelType {
|
||||
match self {
|
||||
Self::U8(_) => PixelType::U8,
|
||||
Self::U8x2(_) => PixelType::U8x2,
|
||||
Self::U8x3(_) => PixelType::U8x3,
|
||||
Self::U8x4(_) => PixelType::U8x4,
|
||||
Self::U16(_) => PixelType::U16,
|
||||
Self::U16x2(_) => PixelType::U16x2,
|
||||
Self::U16x3(_) => PixelType::U16x3,
|
||||
Self::U16x4(_) => PixelType::U16x4,
|
||||
Self::I32(_) => PixelType::I32,
|
||||
Self::F32(_) => PixelType::F32,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn typed_rows<P: Pixel>(&self) -> Option<&[&'a [P]]> {
|
||||
match (P::pixel_type(), self) {
|
||||
(PixelType::U8, Self::U8(rows)) => Some(unsafe { transmute(rows.as_slice()) }),
|
||||
(PixelType::U8x2, Self::U8x2(rows)) => Some(unsafe { transmute(rows.as_slice()) }),
|
||||
(PixelType::U8x3, Self::U8x3(rows)) => Some(unsafe { transmute(rows.as_slice()) }),
|
||||
(PixelType::U8x4, Self::U8x4(rows)) => Some(unsafe { transmute(rows.as_slice()) }),
|
||||
(PixelType::U16, Self::U16(rows)) => Some(unsafe { transmute(rows.as_slice()) }),
|
||||
(PixelType::U16x2, Self::U16x2(rows)) => Some(unsafe { transmute(rows.as_slice()) }),
|
||||
(PixelType::U16x3, Self::U16x3(rows)) => Some(unsafe { transmute(rows.as_slice()) }),
|
||||
(PixelType::U16x4, Self::U16x4(rows)) => Some(unsafe { transmute(rows.as_slice()) }),
|
||||
(PixelType::I32, Self::I32(rows)) => Some(unsafe { transmute(rows.as_slice()) }),
|
||||
(PixelType::F32, Self::F32(rows)) => Some(unsafe { transmute(rows.as_slice()) }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A mutable rows of image.
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum ImageRowsMut<'a> {
|
||||
U8(Vec<&'a mut [U8]>),
|
||||
U8x2(Vec<&'a mut [U8x2]>),
|
||||
U8x3(Vec<&'a mut [U8x3]>),
|
||||
U8x4(Vec<&'a mut [U8x4]>),
|
||||
U16(Vec<&'a mut [U16]>),
|
||||
U16x2(Vec<&'a mut [U16x2]>),
|
||||
U16x3(Vec<&'a mut [U16x3]>),
|
||||
U16x4(Vec<&'a mut [U16x4]>),
|
||||
I32(Vec<&'a mut [I32]>),
|
||||
F32(Vec<&'a mut [F32]>),
|
||||
}
|
||||
|
||||
impl<'a> ImageRowsMut<'a> {
|
||||
pub(crate) fn check_size(
|
||||
&self,
|
||||
width: NonZeroU32,
|
||||
height: NonZeroU32,
|
||||
) -> Result<(), ImageRowsError> {
|
||||
match self {
|
||||
Self::U8x2(rows) => check_rows_count_and_size(width, height, rows),
|
||||
Self::U8x3(rows) => check_rows_count_and_size(width, height, rows),
|
||||
Self::U8x4(rows) => check_rows_count_and_size(width, height, rows),
|
||||
Self::U16(rows) => check_rows_count_and_size(width, height, rows),
|
||||
Self::U16x2(rows) => check_rows_count_and_size(width, height, rows),
|
||||
Self::U16x3(rows) => check_rows_count_and_size(width, height, rows),
|
||||
Self::U16x4(rows) => check_rows_count_and_size(width, height, rows),
|
||||
Self::I32(rows) => check_rows_count_and_size(width, height, rows),
|
||||
Self::F32(rows) => check_rows_count_and_size(width, height, rows),
|
||||
Self::U8(rows) => check_rows_count_and_size(width, height, rows),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pixel_type(&self) -> PixelType {
|
||||
match self {
|
||||
Self::U8x2(_) => PixelType::U8x2,
|
||||
Self::U8x3(_) => PixelType::U8x3,
|
||||
Self::U8x4(_) => PixelType::U8x4,
|
||||
Self::U16(_) => PixelType::U16,
|
||||
Self::U16x2(_) => PixelType::U16x2,
|
||||
Self::U16x3(_) => PixelType::U16x3,
|
||||
Self::U16x4(_) => PixelType::U16x4,
|
||||
Self::I32(_) => PixelType::I32,
|
||||
Self::F32(_) => PixelType::F32,
|
||||
Self::U8(_) => PixelType::U8,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn typed_rows<P: Pixel>(&mut self) -> Option<&mut [&'a mut [P]]> {
|
||||
match (P::pixel_type(), self) {
|
||||
(PixelType::U8, Self::U8(rows)) => Some(unsafe { transmute(rows.as_mut_slice()) }),
|
||||
(PixelType::U8x2, Self::U8x2(rows)) => Some(unsafe { transmute(rows.as_mut_slice()) }),
|
||||
(PixelType::U8x3, Self::U8x3(rows)) => Some(unsafe { transmute(rows.as_mut_slice()) }),
|
||||
(PixelType::U8x4, Self::U8x4(rows)) => Some(unsafe { transmute(rows.as_mut_slice()) }),
|
||||
(PixelType::U16, Self::U16(rows)) => Some(unsafe { transmute(rows.as_mut_slice()) }),
|
||||
(PixelType::U16x2, Self::U16x2(rows)) => {
|
||||
Some(unsafe { transmute(rows.as_mut_slice()) })
|
||||
}
|
||||
(PixelType::U16x3, Self::U16x3(rows)) => {
|
||||
Some(unsafe { transmute(rows.as_mut_slice()) })
|
||||
}
|
||||
(PixelType::U16x4, Self::U16x4(rows)) => {
|
||||
Some(unsafe { transmute(rows.as_mut_slice()) })
|
||||
}
|
||||
(PixelType::I32, Self::I32(rows)) => Some(unsafe { transmute(rows.as_mut_slice()) }),
|
||||
(PixelType::F32, Self::F32(rows)) => Some(unsafe { transmute(rows.as_mut_slice()) }),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_rows_count_and_size<T>(
|
||||
width: NonZeroU32,
|
||||
height: NonZeroU32,
|
||||
rows: &[impl AsRef<[T]>],
|
||||
) -> Result<(), ImageRowsError> {
|
||||
if rows.len() != height.get() as usize {
|
||||
return Err(ImageRowsError::InvalidRowsCount);
|
||||
}
|
||||
let row_size = width.get() as usize;
|
||||
if rows.iter().any(|row| row.as_ref().len() != row_size) {
|
||||
return Err(ImageRowsError::InvalidRowSize);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
macro_rules! image_rows_from {
|
||||
($pixel_type:tt, $enum_type:expr) => {
|
||||
impl<'a> From<Vec<&'a [$pixel_type]>> for ImageRows<'a> {
|
||||
fn from(rows: Vec<&'a [$pixel_type]>) -> Self {
|
||||
$enum_type(rows)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
image_rows_from!(U8, ImageRows::U8);
|
||||
image_rows_from!(U8x2, ImageRows::U8x2);
|
||||
image_rows_from!(U8x3, ImageRows::U8x3);
|
||||
image_rows_from!(U8x4, ImageRows::U8x4);
|
||||
image_rows_from!(U16, ImageRows::U16);
|
||||
image_rows_from!(U16x2, ImageRows::U16x2);
|
||||
image_rows_from!(U16x3, ImageRows::U16x3);
|
||||
image_rows_from!(U16x4, ImageRows::U16x4);
|
||||
image_rows_from!(I32, ImageRows::I32);
|
||||
image_rows_from!(F32, ImageRows::F32);
|
||||
+238
-220
@@ -1,8 +1,8 @@
|
||||
use std::num::NonZeroU32;
|
||||
use std::slice;
|
||||
|
||||
use crate::errors::{CropBoxError, ImageBufferError, ImageRowsError};
|
||||
use crate::image_rows::{ImageRows, ImageRowsMut};
|
||||
use crate::pixels::{Pixel, PixelType};
|
||||
use crate::pixels::{GetCount, IntoPixelComponent, Pixel, PixelComponent};
|
||||
use crate::{CropBoxError, DifferentDimensionsError, ImageBufferError, ImageRowsError, PixelType};
|
||||
|
||||
pub(crate) type RowMut<'a, 'b, T> = &'a mut &'b mut [T];
|
||||
pub(crate) type TwoRows<'a, T> = (&'a [T], &'a [T]);
|
||||
@@ -14,7 +14,7 @@ pub(crate) type FourRowsMut<'a, 'b, T> = (
|
||||
&'a mut &'b mut [T],
|
||||
);
|
||||
|
||||
/// Parameters of crop box that may be used with [`ImageView`]
|
||||
/// Parameters of crop box that may be used with [`ImageView`] and [`crate::DynamicImageView`]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct CropBox {
|
||||
pub left: u32,
|
||||
@@ -23,22 +23,28 @@ pub struct CropBox {
|
||||
pub height: NonZeroU32,
|
||||
}
|
||||
|
||||
/// An immutable view of image data used by resizer as source image.
|
||||
/// Generic immutable image view.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ImageView<'a> {
|
||||
pub struct ImageView<'a, P>
|
||||
where
|
||||
P: Pixel,
|
||||
{
|
||||
width: NonZeroU32,
|
||||
height: NonZeroU32,
|
||||
crop_box: CropBox,
|
||||
rows: ImageRows<'a>,
|
||||
rows: Vec<&'a [P]>,
|
||||
}
|
||||
|
||||
impl<'a> ImageView<'a> {
|
||||
impl<'a, P> ImageView<'a, P>
|
||||
where
|
||||
P: Pixel,
|
||||
{
|
||||
pub fn new(
|
||||
width: NonZeroU32,
|
||||
height: NonZeroU32,
|
||||
rows: ImageRows<'a>,
|
||||
rows: Vec<&'a [P]>,
|
||||
) -> Result<Self, ImageRowsError> {
|
||||
rows.check_size(width, height)?;
|
||||
check_rows_count_and_size(width, height, &rows)?;
|
||||
Ok(Self {
|
||||
width,
|
||||
height,
|
||||
@@ -56,105 +62,17 @@ impl<'a> ImageView<'a> {
|
||||
width: NonZeroU32,
|
||||
height: NonZeroU32,
|
||||
buffer: &'a [u8],
|
||||
pixel_type: PixelType,
|
||||
) -> Result<Self, ImageBufferError> {
|
||||
let size = (width.get() * height.get()) as usize * pixel_type.size();
|
||||
let size = (width.get() * height.get()) as usize * P::size();
|
||||
if buffer.len() < size {
|
||||
return Err(ImageBufferError::InvalidBufferSize);
|
||||
}
|
||||
let rows_count = height.get() as usize;
|
||||
let rows = match pixel_type {
|
||||
PixelType::U8x2 => {
|
||||
let pixels = align_buffer_to(buffer)?;
|
||||
ImageRows::U8x2(
|
||||
pixels
|
||||
.chunks_exact(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U8x3 => {
|
||||
let pixels = align_buffer_to(buffer)?;
|
||||
ImageRows::U8x3(
|
||||
pixels
|
||||
.chunks_exact(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U8x4 => {
|
||||
let pixels = align_buffer_to(buffer)?;
|
||||
ImageRows::U8x4(
|
||||
pixels
|
||||
.chunks_exact(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U16 => {
|
||||
let pixels = align_buffer_to(buffer)?;
|
||||
ImageRows::U16(
|
||||
pixels
|
||||
.chunks_exact(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U16x2 => {
|
||||
let pixels = align_buffer_to(buffer)?;
|
||||
ImageRows::U16x2(
|
||||
pixels
|
||||
.chunks_exact(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U16x3 => {
|
||||
let pixels = align_buffer_to(buffer)?;
|
||||
ImageRows::U16x3(
|
||||
pixels
|
||||
.chunks_exact(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U16x4 => {
|
||||
let pixels = align_buffer_to(buffer)?;
|
||||
ImageRows::U16x4(
|
||||
pixels
|
||||
.chunks_exact(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::I32 => {
|
||||
let pixels = align_buffer_to(buffer)?;
|
||||
ImageRows::I32(
|
||||
pixels
|
||||
.chunks_exact(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::F32 => {
|
||||
let pixels = align_buffer_to(buffer)?;
|
||||
ImageRows::F32(
|
||||
pixels
|
||||
.chunks_exact(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U8 => {
|
||||
let pixels = align_buffer_to(buffer)?;
|
||||
ImageRows::U8(
|
||||
pixels
|
||||
.chunks_exact(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
};
|
||||
let pixels = align_buffer_to(buffer)?;
|
||||
let rows = pixels
|
||||
.chunks_exact(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect();
|
||||
Ok(Self {
|
||||
width,
|
||||
height,
|
||||
@@ -168,27 +86,45 @@ impl<'a> ImageView<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn from_pixels(
|
||||
width: NonZeroU32,
|
||||
height: NonZeroU32,
|
||||
pixels: &'a [P],
|
||||
) -> Result<Self, ImageBufferError> {
|
||||
let size = (width.get() * height.get()) as usize;
|
||||
if pixels.len() < size {
|
||||
return Err(ImageBufferError::InvalidBufferSize);
|
||||
}
|
||||
let rows_count = height.get() as usize;
|
||||
let rows = pixels
|
||||
.chunks_exact(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect();
|
||||
Ok(Self {
|
||||
width,
|
||||
height,
|
||||
crop_box: CropBox {
|
||||
left: 0,
|
||||
top: 0,
|
||||
width,
|
||||
height,
|
||||
},
|
||||
rows,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn pixel_type(&self) -> PixelType {
|
||||
self.rows.pixel_type()
|
||||
P::pixel_type()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn width(&self) -> NonZeroU32 {
|
||||
self.width
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn height(&self) -> NonZeroU32 {
|
||||
self.height
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn typed_rows<P: Pixel>(&self) -> Option<&[&'a [P]]> {
|
||||
self.rows.typed_rows()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn crop_box(&self) -> CropBox {
|
||||
self.crop_box
|
||||
}
|
||||
@@ -267,23 +203,98 @@ impl<'a> ImageView<'a> {
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn iter_4_rows<'s>(
|
||||
&'s self,
|
||||
start_y: u32,
|
||||
max_y: u32,
|
||||
) -> impl Iterator<Item = FourRows<'a, P>> + 's {
|
||||
let start_y = start_y as usize;
|
||||
let max_y = max_y.min(self.height.get()) as usize;
|
||||
let rows = self.rows.get(start_y..max_y).unwrap_or(&[]);
|
||||
rows.chunks_exact(4).map(|rows| match *rows {
|
||||
[r0, r1, r2, r3] => (r0, r1, r2, r3),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn iter_2_rows<'s>(
|
||||
&'s self,
|
||||
start_y: u32,
|
||||
max_y: u32,
|
||||
) -> impl Iterator<Item = TwoRows<'a, P>> + 's {
|
||||
let start_y = start_y as usize;
|
||||
let max_y = max_y.min(self.height.get()) as usize;
|
||||
let rows = self.rows.get(start_y..max_y).unwrap_or(&[]);
|
||||
rows.chunks_exact(2).map(|rows| match *rows {
|
||||
[r0, r1] => (r0, r1),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn iter_rows<'s>(&'s self, start_y: u32) -> impl Iterator<Item = &'a [P]> + 's {
|
||||
self.rows.iter().skip(start_y as usize).copied()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn get_row(&self, y: u32) -> Option<&'a [P]> {
|
||||
self.rows.get(y as usize).copied()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn iter_rows_with_step<'s>(
|
||||
&'s self,
|
||||
mut y: f64,
|
||||
step: f64,
|
||||
max_count: usize,
|
||||
) -> impl Iterator<Item = &'a [P]> + 's {
|
||||
let steps = (self.height.get() as f64 - y) / step;
|
||||
let steps = (steps.max(0.).ceil() as usize).min(max_count);
|
||||
(0..steps).map(move |_| {
|
||||
// Safety of value of y guaranteed by calculation of steps count
|
||||
let row = unsafe { *self.rows.get_unchecked(y as usize) };
|
||||
y += step;
|
||||
row
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn iter_cropped_rows<'s>(&'s self) -> impl Iterator<Item = &'a [P]> + 's {
|
||||
let first_col = self.crop_box.left as usize;
|
||||
let last_col = first_col + self.crop_box.width.get() as usize;
|
||||
self.rows
|
||||
.iter()
|
||||
.skip(self.crop_box.top as usize)
|
||||
.take(self.crop_box.height.get() as usize)
|
||||
// Safety guaranteed by method 'set_crop_box'
|
||||
.map(move |row| unsafe { row.get_unchecked(first_col..last_col) })
|
||||
}
|
||||
}
|
||||
|
||||
/// A mutable view of image data used by resizer as destination image.
|
||||
/// Generic mutable image view.
|
||||
#[derive(Debug)]
|
||||
pub struct ImageViewMut<'a> {
|
||||
pub struct ImageViewMut<'a, P>
|
||||
where
|
||||
P: Pixel,
|
||||
{
|
||||
width: NonZeroU32,
|
||||
height: NonZeroU32,
|
||||
rows: ImageRowsMut<'a>,
|
||||
rows: Vec<&'a mut [P]>,
|
||||
}
|
||||
|
||||
impl<'a> ImageViewMut<'a> {
|
||||
impl<'a, P> ImageViewMut<'a, P>
|
||||
where
|
||||
P: Pixel,
|
||||
{
|
||||
pub fn new(
|
||||
width: NonZeroU32,
|
||||
height: NonZeroU32,
|
||||
rows: ImageRowsMut<'a>,
|
||||
rows: Vec<&'a mut [P]>,
|
||||
) -> Result<Self, ImageRowsError> {
|
||||
rows.check_size(width, height)?;
|
||||
check_rows_count_and_size(width, height, &rows)?;
|
||||
Ok(Self {
|
||||
width,
|
||||
height,
|
||||
@@ -295,105 +306,17 @@ impl<'a> ImageViewMut<'a> {
|
||||
width: NonZeroU32,
|
||||
height: NonZeroU32,
|
||||
buffer: &'a mut [u8],
|
||||
pixel_type: PixelType,
|
||||
) -> Result<Self, ImageBufferError> {
|
||||
let size = (width.get() * height.get()) as usize * pixel_type.size();
|
||||
let size = (width.get() * height.get()) as usize * P::size();
|
||||
if buffer.len() < size {
|
||||
return Err(ImageBufferError::InvalidBufferSize);
|
||||
}
|
||||
let rows_count = height.get() as usize;
|
||||
let rows = match pixel_type {
|
||||
PixelType::U8x2 => {
|
||||
let pixels = align_buffer_to_mut(buffer)?;
|
||||
ImageRowsMut::U8x2(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U8x3 => {
|
||||
let pixels = align_buffer_to_mut(buffer)?;
|
||||
ImageRowsMut::U8x3(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U8x4 => {
|
||||
let pixels = align_buffer_to_mut(buffer)?;
|
||||
ImageRowsMut::U8x4(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U16 => {
|
||||
let pixels = align_buffer_to_mut(buffer)?;
|
||||
ImageRowsMut::U16(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U16x2 => {
|
||||
let pixels = align_buffer_to_mut(buffer)?;
|
||||
ImageRowsMut::U16x2(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U16x3 => {
|
||||
let pixels = align_buffer_to_mut(buffer)?;
|
||||
ImageRowsMut::U16x3(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U16x4 => {
|
||||
let pixels = align_buffer_to_mut(buffer)?;
|
||||
ImageRowsMut::U16x4(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::I32 => {
|
||||
let pixels = align_buffer_to_mut(buffer)?;
|
||||
ImageRowsMut::I32(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::F32 => {
|
||||
let pixels = align_buffer_to_mut(buffer)?;
|
||||
ImageRowsMut::F32(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
PixelType::U8 => {
|
||||
let pixels = align_buffer_to_mut(buffer)?;
|
||||
ImageRowsMut::U8(
|
||||
pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
};
|
||||
let pixels = align_buffer_to_mut(buffer)?;
|
||||
let rows = pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect();
|
||||
Ok(Self {
|
||||
width,
|
||||
height,
|
||||
@@ -401,25 +324,89 @@ impl<'a> ImageViewMut<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn from_pixels(
|
||||
width: NonZeroU32,
|
||||
height: NonZeroU32,
|
||||
pixels: &'a mut [P],
|
||||
) -> Result<Self, ImageBufferError> {
|
||||
let size = (width.get() * height.get()) as usize;
|
||||
if pixels.len() < size {
|
||||
return Err(ImageBufferError::InvalidBufferSize);
|
||||
}
|
||||
let rows_count = height.get() as usize;
|
||||
let rows = pixels
|
||||
.chunks_exact_mut(width.get() as usize)
|
||||
.take(rows_count)
|
||||
.collect();
|
||||
Ok(Self {
|
||||
width,
|
||||
height,
|
||||
rows,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn pixel_type(&self) -> PixelType {
|
||||
self.rows.pixel_type()
|
||||
P::pixel_type()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn width(&self) -> NonZeroU32 {
|
||||
self.width
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn height(&self) -> NonZeroU32 {
|
||||
self.height
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn typed_rows<P: Pixel>(&mut self) -> Option<&mut [&'a mut [P]]> {
|
||||
self.rows.typed_rows()
|
||||
pub(crate) fn iter_rows_mut(&mut self) -> slice::IterMut<&'a mut [P]> {
|
||||
self.rows.iter_mut()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn iter_4_rows_mut<'s>(
|
||||
&'s mut self,
|
||||
) -> impl Iterator<Item = FourRowsMut<'s, 'a, P>> {
|
||||
self.rows.chunks_exact_mut(4).map(|rows| match rows {
|
||||
[a, b, c, d] => (a, b, c, d),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn get_row_mut<'s>(&'s mut self, y: u32) -> Option<RowMut<'s, 'a, P>> {
|
||||
self.rows.get_mut(y as usize)
|
||||
}
|
||||
|
||||
/// Copy pixels from src_view.
|
||||
pub(crate) fn copy_from_view(
|
||||
&mut self,
|
||||
src_view: &ImageView<P>,
|
||||
) -> Result<(), DifferentDimensionsError> {
|
||||
let src_crop_box = src_view.crop_box();
|
||||
if self.width != src_crop_box.width || self.height != src_crop_box.height {
|
||||
return Err(DifferentDimensionsError);
|
||||
}
|
||||
self.rows
|
||||
.iter_mut()
|
||||
.zip(src_view.iter_cropped_rows())
|
||||
.for_each(|(d, s)| d.copy_from_slice(s));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn check_rows_count_and_size<T>(
|
||||
width: NonZeroU32,
|
||||
height: NonZeroU32,
|
||||
rows: &[impl AsRef<[T]>],
|
||||
) -> Result<(), ImageRowsError> {
|
||||
if rows.len() != height.get() as usize {
|
||||
return Err(ImageRowsError::InvalidRowsCount);
|
||||
}
|
||||
let row_size = width.get() as usize;
|
||||
if rows.iter().any(|row| row.as_ref().len() != row_size) {
|
||||
return Err(ImageRowsError::InvalidRowSize);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn align_buffer_to<T>(buffer: &[u8]) -> Result<&[T], ImageBufferError> {
|
||||
@@ -437,3 +424,34 @@ fn align_buffer_to_mut<T>(buffer: &mut [u8]) -> Result<&mut [T], ImageBufferErro
|
||||
}
|
||||
Ok(pixels)
|
||||
}
|
||||
|
||||
pub fn change_type_of_pixel_components<S, D, CC, In, Out>(
|
||||
src_image: &ImageView<S>,
|
||||
dst_image: &mut ImageViewMut<D>,
|
||||
) -> Result<(), DifferentDimensionsError>
|
||||
where
|
||||
Out: PixelComponent,
|
||||
In: IntoPixelComponent<Out>,
|
||||
CC: GetCount,
|
||||
S: Pixel<
|
||||
Component = In,
|
||||
CountOfComponents = CC, // Count of source pixel's components
|
||||
>,
|
||||
D: Pixel<
|
||||
Component = Out,
|
||||
CountOfComponents = CC, // Count of destination pixel's components
|
||||
>,
|
||||
{
|
||||
if src_image.width() != dst_image.width() || src_image.height() != dst_image.height() {
|
||||
return Err(DifferentDimensionsError);
|
||||
}
|
||||
|
||||
for (s_row, d_row) in src_image.rows.iter().zip(dst_image.rows.iter_mut()) {
|
||||
let s_components = S::components(s_row);
|
||||
let d_components = D::components_mut(d_row);
|
||||
for (&s_comp, d_comp) in s_components.iter().zip(d_components) {
|
||||
*d_comp = s_comp.into_component();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+5
-5
@@ -2,10 +2,11 @@
|
||||
|
||||
pub use alpha::errors::*;
|
||||
pub use convolution::FilterType;
|
||||
pub use dynamic_image_view::{
|
||||
change_type_of_pixel_components_dyn, DynamicImageView, DynamicImageViewMut,
|
||||
};
|
||||
pub use errors::*;
|
||||
pub use image_rows::ImageRows;
|
||||
pub use image_rows::ImageRowsMut;
|
||||
pub use image_view::{CropBox, ImageView, ImageViewMut};
|
||||
pub use image_view::{change_type_of_pixel_components, CropBox, ImageView, ImageViewMut};
|
||||
pub use mul_div::MulDiv;
|
||||
pub use pixels::PixelType;
|
||||
pub use resizer::{CpuExtensions, ResizeAlg, Resizer};
|
||||
@@ -15,13 +16,12 @@ pub use crate::image::Image;
|
||||
mod alpha;
|
||||
pub mod color;
|
||||
mod convolution;
|
||||
mod dynamic_image_view;
|
||||
mod errors;
|
||||
mod image;
|
||||
mod image_rows;
|
||||
mod image_view;
|
||||
mod mul_div;
|
||||
pub mod pixels;
|
||||
mod resizer;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod simd_utils;
|
||||
mod typed_image_view;
|
||||
|
||||
+78
-200
@@ -1,9 +1,8 @@
|
||||
use crate::alpha::AlphaMulDiv;
|
||||
use crate::pixels::{U16x2, U16x4, U8x2, U8x4};
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{
|
||||
CpuExtensions, ImageView, ImageViewMut, MulDivImageError, MulDivImagesError, PixelType,
|
||||
CpuExtensions, DynamicImageView, DynamicImageViewMut, MulDivImageError, MulDivImagesError,
|
||||
};
|
||||
use crate::{ImageView, ImageViewMut};
|
||||
|
||||
/// Methods of this structure used to multiply or divide color-channels (RGB or Luma)
|
||||
/// by alpha-channel. Supported pixel types: U8x2, U8x4, U16x2 and U16x4.
|
||||
@@ -48,55 +47,49 @@ impl MulDiv {
|
||||
/// result into destination image.
|
||||
pub fn multiply_alpha(
|
||||
&self,
|
||||
src_image: &ImageView,
|
||||
dst_image: &mut ImageViewMut,
|
||||
src_image: &DynamicImageView,
|
||||
dst_image: &mut DynamicImageViewMut,
|
||||
) -> Result<(), MulDivImagesError> {
|
||||
match src_image.pixel_type() {
|
||||
PixelType::U8x2 => {
|
||||
let (typed_src_image, typed_dst_image) = assert_images_u8x2(src_image, dst_image)?;
|
||||
multiply_alpha(typed_src_image, typed_dst_image, self.cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
PixelType::U8x4 => {
|
||||
let (typed_src_image, typed_dst_image) = assert_images_u8x4(src_image, dst_image)?;
|
||||
multiply_alpha(typed_src_image, typed_dst_image, self.cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
PixelType::U16x2 => {
|
||||
let (typed_src_image, typed_dst_image) = assert_images_u16x2(src_image, dst_image)?;
|
||||
multiply_alpha(typed_src_image, typed_dst_image, self.cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
PixelType::U16x4 => {
|
||||
let (typed_src_image, typed_dst_image) = assert_images_u16x4(src_image, dst_image)?;
|
||||
multiply_alpha(typed_src_image, typed_dst_image, self.cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
match (src_image, dst_image) {
|
||||
(
|
||||
DynamicImageView::U8x2(typed_src_image),
|
||||
DynamicImageViewMut::U8x2(typed_dst_image),
|
||||
) => multiply_alpha(typed_src_image, typed_dst_image, self.cpu_extensions),
|
||||
(
|
||||
DynamicImageView::U8x4(typed_src_image),
|
||||
DynamicImageViewMut::U8x4(typed_dst_image),
|
||||
) => multiply_alpha(typed_src_image, typed_dst_image, self.cpu_extensions),
|
||||
(
|
||||
DynamicImageView::U16x2(typed_src_image),
|
||||
DynamicImageViewMut::U16x2(typed_dst_image),
|
||||
) => multiply_alpha(typed_src_image, typed_dst_image, self.cpu_extensions),
|
||||
(
|
||||
DynamicImageView::U16x4(typed_src_image),
|
||||
DynamicImageViewMut::U16x4(typed_dst_image),
|
||||
) => multiply_alpha(typed_src_image, typed_dst_image, self.cpu_extensions),
|
||||
_ => Err(MulDivImagesError::UnsupportedPixelType),
|
||||
}
|
||||
}
|
||||
|
||||
/// Multiplies color-channels (RGB or Luma) of image by alpha-channel inplace.
|
||||
pub fn multiply_alpha_inplace(&self, image: &mut ImageViewMut) -> Result<(), MulDivImageError> {
|
||||
match image.pixel_type() {
|
||||
PixelType::U8x2 => {
|
||||
let typed_image = assert_image_u8x2(image)?;
|
||||
pub fn multiply_alpha_inplace(
|
||||
&self,
|
||||
image: &mut DynamicImageViewMut,
|
||||
) -> Result<(), MulDivImageError> {
|
||||
match image {
|
||||
DynamicImageViewMut::U8x2(typed_image) => {
|
||||
multiply_alpha_inplace(typed_image, self.cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
PixelType::U8x4 => {
|
||||
let typed_image = assert_image_u8x4(image)?;
|
||||
DynamicImageViewMut::U8x4(typed_image) => {
|
||||
multiply_alpha_inplace(typed_image, self.cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
PixelType::U16x2 => {
|
||||
let typed_image = assert_image_u16x2(image)?;
|
||||
DynamicImageViewMut::U16x2(typed_image) => {
|
||||
multiply_alpha_inplace(typed_image, self.cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
PixelType::U16x4 => {
|
||||
let typed_image = assert_image_u16x4(image)?;
|
||||
DynamicImageViewMut::U16x4(typed_image) => {
|
||||
multiply_alpha_inplace(typed_image, self.cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
@@ -108,54 +101,49 @@ impl MulDiv {
|
||||
/// result into destination image.
|
||||
pub fn divide_alpha(
|
||||
&self,
|
||||
src_image: &ImageView,
|
||||
dst_image: &mut ImageViewMut,
|
||||
src_image: &DynamicImageView,
|
||||
dst_image: &mut DynamicImageViewMut,
|
||||
) -> Result<(), MulDivImagesError> {
|
||||
match src_image.pixel_type() {
|
||||
PixelType::U8x2 => {
|
||||
let (typed_src_image, typed_dst_image) = assert_images_u8x2(src_image, dst_image)?;
|
||||
divide_alpha(typed_src_image, typed_dst_image, self.cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
PixelType::U8x4 => {
|
||||
let (typed_src_image, typed_dst_image) = assert_images_u8x4(src_image, dst_image)?;
|
||||
divide_alpha(typed_src_image, typed_dst_image, self.cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
PixelType::U16x2 => {
|
||||
let (typed_src_image, typed_dst_image) = assert_images_u16x2(src_image, dst_image)?;
|
||||
divide_alpha(typed_src_image, typed_dst_image, self.cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
PixelType::U16x4 => {
|
||||
let (typed_src_image, typed_dst_image) = assert_images_u16x4(src_image, dst_image)?;
|
||||
divide_alpha(typed_src_image, typed_dst_image, self.cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
match (src_image, dst_image) {
|
||||
(
|
||||
DynamicImageView::U8x2(typed_src_image),
|
||||
DynamicImageViewMut::U8x2(typed_dst_image),
|
||||
) => divide_alpha(typed_src_image, typed_dst_image, self.cpu_extensions),
|
||||
(
|
||||
DynamicImageView::U8x4(typed_src_image),
|
||||
DynamicImageViewMut::U8x4(typed_dst_image),
|
||||
) => divide_alpha(typed_src_image, typed_dst_image, self.cpu_extensions),
|
||||
(
|
||||
DynamicImageView::U16x2(typed_src_image),
|
||||
DynamicImageViewMut::U16x2(typed_dst_image),
|
||||
) => divide_alpha(typed_src_image, typed_dst_image, self.cpu_extensions),
|
||||
(
|
||||
DynamicImageView::U16x4(typed_src_image),
|
||||
DynamicImageViewMut::U16x4(typed_dst_image),
|
||||
) => divide_alpha(typed_src_image, typed_dst_image, self.cpu_extensions),
|
||||
_ => Err(MulDivImagesError::UnsupportedPixelType),
|
||||
}
|
||||
}
|
||||
|
||||
/// Divides color-channels (RGB or Luma) of image by alpha-channel inplace.
|
||||
pub fn divide_alpha_inplace(&self, image: &mut ImageViewMut) -> Result<(), MulDivImageError> {
|
||||
match image.pixel_type() {
|
||||
PixelType::U8x2 => {
|
||||
let typed_image = assert_image_u8x2(image)?;
|
||||
pub fn divide_alpha_inplace(
|
||||
&self,
|
||||
image: &mut DynamicImageViewMut,
|
||||
) -> Result<(), MulDivImageError> {
|
||||
match image {
|
||||
DynamicImageViewMut::U8x2(typed_image) => {
|
||||
divide_alpha_inplace(typed_image, self.cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
PixelType::U8x4 => {
|
||||
let typed_image = assert_image_u8x4(image)?;
|
||||
DynamicImageViewMut::U8x4(typed_image) => {
|
||||
divide_alpha_inplace(typed_image, self.cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
PixelType::U16x2 => {
|
||||
let typed_image = assert_image_u16x2(image)?;
|
||||
DynamicImageViewMut::U16x2(typed_image) => {
|
||||
divide_alpha_inplace(typed_image, self.cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
PixelType::U16x4 => {
|
||||
let typed_image = assert_image_u16x4(image)?;
|
||||
DynamicImageViewMut::U16x4(typed_image) => {
|
||||
divide_alpha_inplace(typed_image, self.cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
@@ -164,137 +152,22 @@ impl MulDiv {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn assert_images_u8x2<'s, 'd, 'da>(
|
||||
src_image: &'s ImageView<'s>,
|
||||
dst_image: &'d mut ImageViewMut<'da>,
|
||||
) -> Result<
|
||||
(
|
||||
TypedImageView<'s, 's, U8x2>,
|
||||
TypedImageViewMut<'d, 'da, U8x2>,
|
||||
),
|
||||
MulDivImagesError,
|
||||
> {
|
||||
let src_image_u8x2 = TypedImageView::from_image_view(src_image)
|
||||
.ok_or(MulDivImagesError::UnsupportedPixelType)?;
|
||||
let dst_image_u8x2 = TypedImageViewMut::from_image_view(dst_image)
|
||||
.ok_or(MulDivImagesError::UnsupportedPixelType)?;
|
||||
if src_image_u8x2.width() != dst_image_u8x2.width()
|
||||
|| src_image_u8x2.height() != dst_image_u8x2.height()
|
||||
{
|
||||
return Err(MulDivImagesError::SizeIsDifferent);
|
||||
}
|
||||
Ok((src_image_u8x2, dst_image_u8x2))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn assert_image_u8x2<'a, 'b>(
|
||||
image: &'a mut ImageViewMut<'b>,
|
||||
) -> Result<TypedImageViewMut<'a, 'b, U8x2>, MulDivImageError> {
|
||||
TypedImageViewMut::from_image_view(image).ok_or(MulDivImageError::UnsupportedPixelType)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn assert_images_u8x4<'s, 'd, 'da>(
|
||||
src_image: &'s ImageView<'s>,
|
||||
dst_image: &'d mut ImageViewMut<'da>,
|
||||
) -> Result<
|
||||
(
|
||||
TypedImageView<'s, 's, U8x4>,
|
||||
TypedImageViewMut<'d, 'da, U8x4>,
|
||||
),
|
||||
MulDivImagesError,
|
||||
> {
|
||||
let src_image_u8x4 = TypedImageView::from_image_view(src_image)
|
||||
.ok_or(MulDivImagesError::UnsupportedPixelType)?;
|
||||
let dst_image_u8x4 = TypedImageViewMut::from_image_view(dst_image)
|
||||
.ok_or(MulDivImagesError::UnsupportedPixelType)?;
|
||||
if src_image_u8x4.width() != dst_image_u8x4.width()
|
||||
|| src_image_u8x4.height() != dst_image_u8x4.height()
|
||||
{
|
||||
return Err(MulDivImagesError::SizeIsDifferent);
|
||||
}
|
||||
Ok((src_image_u8x4, dst_image_u8x4))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn assert_image_u8x4<'a, 'b>(
|
||||
image: &'a mut ImageViewMut<'b>,
|
||||
) -> Result<TypedImageViewMut<'a, 'b, U8x4>, MulDivImageError> {
|
||||
TypedImageViewMut::from_image_view(image).ok_or(MulDivImageError::UnsupportedPixelType)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn assert_images_u16x2<'s, 'd, 'da>(
|
||||
src_image: &'s ImageView<'s>,
|
||||
dst_image: &'d mut ImageViewMut<'da>,
|
||||
) -> Result<
|
||||
(
|
||||
TypedImageView<'s, 's, U16x2>,
|
||||
TypedImageViewMut<'d, 'da, U16x2>,
|
||||
),
|
||||
MulDivImagesError,
|
||||
> {
|
||||
let src_image_u16x2 = TypedImageView::from_image_view(src_image)
|
||||
.ok_or(MulDivImagesError::UnsupportedPixelType)?;
|
||||
let dst_image_u16x2 = TypedImageViewMut::from_image_view(dst_image)
|
||||
.ok_or(MulDivImagesError::UnsupportedPixelType)?;
|
||||
if src_image_u16x2.width() != dst_image_u16x2.width()
|
||||
|| src_image_u16x2.height() != dst_image_u16x2.height()
|
||||
{
|
||||
return Err(MulDivImagesError::SizeIsDifferent);
|
||||
}
|
||||
Ok((src_image_u16x2, dst_image_u16x2))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn assert_image_u16x2<'a, 'b>(
|
||||
image: &'a mut ImageViewMut<'b>,
|
||||
) -> Result<TypedImageViewMut<'a, 'b, U16x2>, MulDivImageError> {
|
||||
TypedImageViewMut::from_image_view(image).ok_or(MulDivImageError::UnsupportedPixelType)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn assert_images_u16x4<'s, 'd, 'da>(
|
||||
src_image: &'s ImageView<'s>,
|
||||
dst_image: &'d mut ImageViewMut<'da>,
|
||||
) -> Result<
|
||||
(
|
||||
TypedImageView<'s, 's, U16x4>,
|
||||
TypedImageViewMut<'d, 'da, U16x4>,
|
||||
),
|
||||
MulDivImagesError,
|
||||
> {
|
||||
let src_image_u16x4 = TypedImageView::from_image_view(src_image)
|
||||
.ok_or(MulDivImagesError::UnsupportedPixelType)?;
|
||||
let dst_image_u16x4 = TypedImageViewMut::from_image_view(dst_image)
|
||||
.ok_or(MulDivImagesError::UnsupportedPixelType)?;
|
||||
if src_image_u16x4.width() != dst_image_u16x4.width()
|
||||
|| src_image_u16x4.height() != dst_image_u16x4.height()
|
||||
{
|
||||
return Err(MulDivImagesError::SizeIsDifferent);
|
||||
}
|
||||
Ok((src_image_u16x4, dst_image_u16x4))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn assert_image_u16x4<'a, 'b>(
|
||||
image: &'a mut ImageViewMut<'b>,
|
||||
) -> Result<TypedImageViewMut<'a, 'b, U16x4>, MulDivImageError> {
|
||||
TypedImageViewMut::from_image_view(image).ok_or(MulDivImageError::UnsupportedPixelType)
|
||||
}
|
||||
|
||||
fn multiply_alpha<P>(
|
||||
src_image: TypedImageView<P>,
|
||||
dst_image: TypedImageViewMut<P>,
|
||||
src_image: &ImageView<P>,
|
||||
dst_image: &mut ImageViewMut<P>,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) where
|
||||
) -> Result<(), MulDivImagesError>
|
||||
where
|
||||
P: AlphaMulDiv,
|
||||
{
|
||||
P::multiply_alpha(src_image, dst_image, cpu_extensions)
|
||||
if src_image.width() != dst_image.width() || src_image.height() != dst_image.height() {
|
||||
return Err(MulDivImagesError::SizeIsDifferent);
|
||||
}
|
||||
P::multiply_alpha(src_image, dst_image, cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn multiply_alpha_inplace<P>(image: TypedImageViewMut<P>, cpu_extensions: CpuExtensions)
|
||||
fn multiply_alpha_inplace<P>(image: &mut ImageViewMut<P>, cpu_extensions: CpuExtensions)
|
||||
where
|
||||
P: AlphaMulDiv,
|
||||
{
|
||||
@@ -302,16 +175,21 @@ where
|
||||
}
|
||||
|
||||
fn divide_alpha<P>(
|
||||
src_image: TypedImageView<P>,
|
||||
dst_image: TypedImageViewMut<P>,
|
||||
src_image: &ImageView<P>,
|
||||
dst_image: &mut ImageViewMut<P>,
|
||||
cpu_extensions: CpuExtensions,
|
||||
) where
|
||||
) -> Result<(), MulDivImagesError>
|
||||
where
|
||||
P: AlphaMulDiv,
|
||||
{
|
||||
P::divide_alpha(src_image, dst_image, cpu_extensions)
|
||||
if src_image.width() != dst_image.width() || src_image.height() != dst_image.height() {
|
||||
return Err(MulDivImagesError::SizeIsDifferent);
|
||||
}
|
||||
P::divide_alpha(src_image, dst_image, cpu_extensions);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn divide_alpha_inplace<P>(image: TypedImageViewMut<P>, cpu_extensions: CpuExtensions)
|
||||
fn divide_alpha_inplace<P>(image: &mut ImageViewMut<P>, cpu_extensions: CpuExtensions)
|
||||
where
|
||||
P: AlphaMulDiv,
|
||||
{
|
||||
|
||||
+19
-19
@@ -53,7 +53,7 @@ pub trait GetCount {
|
||||
fn count() -> usize;
|
||||
}
|
||||
|
||||
/// Generic type to represent the number of component in single pixel.
|
||||
/// Generic type to represent the number of components in single pixel.
|
||||
pub struct Count<const N: usize>;
|
||||
|
||||
impl<const N: usize> GetCount for Count<N> {
|
||||
@@ -77,7 +77,7 @@ impl<const N: usize> CountOfValues for Values<N> {
|
||||
|
||||
pub trait PixelComponent
|
||||
where
|
||||
Self: Sized + Copy + 'static,
|
||||
Self: Sized + Copy + Debug + 'static,
|
||||
{
|
||||
}
|
||||
|
||||
@@ -89,26 +89,26 @@ impl PixelComponent for f32 {}
|
||||
/// Additional information about pixel type.
|
||||
pub trait Pixel
|
||||
where
|
||||
Self: Copy + Sized + Debug,
|
||||
Self: Copy + Clone + Sized + Debug,
|
||||
{
|
||||
/// Type of pixel components
|
||||
type Component: PixelComponent;
|
||||
/// Type that provides information about a count of pixel's components
|
||||
type ComponentsCount: GetCount;
|
||||
type CountOfComponents: GetCount;
|
||||
/// Type that provides information about a count of available values of one
|
||||
/// pixel's component as usize
|
||||
type ComponentCountOfValues: CountOfValues;
|
||||
/// pixel's component
|
||||
type CountOfComponentValues: CountOfValues;
|
||||
|
||||
fn pixel_type() -> PixelType;
|
||||
|
||||
/// Count of pixel's components
|
||||
fn components_count() -> usize {
|
||||
Self::ComponentsCount::count()
|
||||
fn count_of_components() -> usize {
|
||||
Self::CountOfComponents::count()
|
||||
}
|
||||
|
||||
/// Count of available values of one pixel's component as usize
|
||||
fn component_count_of_values() -> usize {
|
||||
Self::ComponentCountOfValues::count_of_values()
|
||||
/// Count of available values of one pixel's component
|
||||
fn count_of_component_values() -> usize {
|
||||
Self::CountOfComponentValues::count_of_values()
|
||||
}
|
||||
|
||||
/// Size of pixel in bytes
|
||||
@@ -126,14 +126,14 @@ where
|
||||
|
||||
/// Create slice of components of pixels from slice of pixels
|
||||
fn components(buf: &[Self]) -> &[Self::Component] {
|
||||
let size = buf.len() * Self::components_count();
|
||||
let size = buf.len() * Self::count_of_components();
|
||||
let components_ptr = buf.as_ptr() as *const Self::Component;
|
||||
unsafe { slice::from_raw_parts(components_ptr, size) }
|
||||
}
|
||||
|
||||
/// Create mutable slice of components of pixels from mutable slice of pixels
|
||||
fn components_mut(buf: &mut [Self]) -> &mut [Self::Component] {
|
||||
let size = buf.len() * Self::components_count();
|
||||
let size = buf.len() * Self::count_of_components();
|
||||
let components_ptr = buf.as_mut_ptr() as *mut Self::Component;
|
||||
unsafe { slice::from_raw_parts_mut(components_ptr, size) }
|
||||
}
|
||||
@@ -148,8 +148,8 @@ macro_rules! pixel_struct {
|
||||
|
||||
impl Pixel for $name {
|
||||
type Component = $comp_type;
|
||||
type ComponentsCount = Count<$comp_count>;
|
||||
type ComponentCountOfValues = Values<$comp_values>;
|
||||
type CountOfComponents = Count<$comp_count>;
|
||||
type CountOfComponentValues = Values<$comp_values>;
|
||||
|
||||
fn pixel_type() -> PixelType {
|
||||
$pixel_type
|
||||
@@ -249,26 +249,26 @@ pixel_struct!(
|
||||
"One `f32` component per pixel"
|
||||
);
|
||||
|
||||
pub(crate) trait PixelComponentInto<Out: PixelComponent>
|
||||
pub trait IntoPixelComponent<Out: PixelComponent>
|
||||
where
|
||||
Self: PixelComponent,
|
||||
{
|
||||
fn into_component(self) -> Out;
|
||||
}
|
||||
|
||||
impl<C: PixelComponent> PixelComponentInto<C> for C {
|
||||
impl<C: PixelComponent> IntoPixelComponent<C> for C {
|
||||
fn into_component(self) -> C {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelComponentInto<u8> for u16 {
|
||||
impl IntoPixelComponent<u8> for u16 {
|
||||
fn into_component(self) -> u8 {
|
||||
self.to_le_bytes()[1]
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelComponentInto<u16> for u8 {
|
||||
impl IntoPixelComponent<u16> for u8 {
|
||||
fn into_component(self) -> u16 {
|
||||
u16::from_le_bytes([self, self])
|
||||
}
|
||||
|
||||
+41
-81
@@ -1,11 +1,11 @@
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use crate::convolution::{self, Convolution, FilterType};
|
||||
use crate::errors::DifferentTypesOfPixelsError;
|
||||
use crate::image::InnerImage;
|
||||
use crate::image_view::{ImageView, ImageViewMut};
|
||||
use crate::pixels::{Pixel, PixelType, U16x2, U16x3, U16x4, U8x2, U8x3, U8x4, F32, I32, U16, U8};
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::{
|
||||
DifferentTypesOfPixelsError, DynamicImageView, DynamicImageViewMut, ImageView, ImageViewMut,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum CpuExtensions {
|
||||
@@ -77,92 +77,52 @@ impl Resizer {
|
||||
/// You must use [MulDiv](crate::MulDiv) for these actions.
|
||||
pub fn resize(
|
||||
&mut self,
|
||||
src_image: &ImageView,
|
||||
dst_image: &mut ImageViewMut,
|
||||
src_image: &DynamicImageView,
|
||||
dst_image: &mut DynamicImageViewMut,
|
||||
) -> Result<(), DifferentTypesOfPixelsError> {
|
||||
if src_image.pixel_type() != dst_image.pixel_type() {
|
||||
return Err(DifferentTypesOfPixelsError);
|
||||
}
|
||||
match src_image.pixel_type() {
|
||||
PixelType::U8 => {
|
||||
if let Some(src) = TypedImageView::from_image_view(src_image) {
|
||||
if let Some(dst) = TypedImageViewMut::from_image_view(dst_image) {
|
||||
self.resize_inner::<U8>(src, dst);
|
||||
}
|
||||
}
|
||||
match (src_image, dst_image) {
|
||||
(DynamicImageView::U8(src), DynamicImageViewMut::U8(dst)) => {
|
||||
self.resize_inner(src, dst);
|
||||
}
|
||||
PixelType::U8x2 => {
|
||||
if let Some(src) = TypedImageView::from_image_view(src_image) {
|
||||
if let Some(dst) = TypedImageViewMut::from_image_view(dst_image) {
|
||||
self.resize_inner::<U8x2>(src, dst);
|
||||
}
|
||||
}
|
||||
(DynamicImageView::U8x2(src), DynamicImageViewMut::U8x2(dst)) => {
|
||||
self.resize_inner(src, dst);
|
||||
}
|
||||
PixelType::U8x3 => {
|
||||
if let Some(src) = TypedImageView::from_image_view(src_image) {
|
||||
if let Some(dst) = TypedImageViewMut::from_image_view(dst_image) {
|
||||
self.resize_inner::<U8x3>(src, dst);
|
||||
}
|
||||
}
|
||||
(DynamicImageView::U8x3(src), DynamicImageViewMut::U8x3(dst)) => {
|
||||
self.resize_inner(src, dst);
|
||||
}
|
||||
PixelType::U8x4 => {
|
||||
if let Some(src) = TypedImageView::from_image_view(src_image) {
|
||||
if let Some(dst) = TypedImageViewMut::from_image_view(dst_image) {
|
||||
self.resize_inner::<U8x4>(src, dst);
|
||||
}
|
||||
}
|
||||
(DynamicImageView::U8x4(src), DynamicImageViewMut::U8x4(dst)) => {
|
||||
self.resize_inner(src, dst);
|
||||
}
|
||||
PixelType::U16 => {
|
||||
if let Some(src) = TypedImageView::from_image_view(src_image) {
|
||||
if let Some(dst) = TypedImageViewMut::from_image_view(dst_image) {
|
||||
self.resize_inner::<U16>(src, dst);
|
||||
}
|
||||
}
|
||||
(DynamicImageView::U16(src), DynamicImageViewMut::U16(dst)) => {
|
||||
self.resize_inner(src, dst);
|
||||
}
|
||||
PixelType::U16x2 => {
|
||||
if let Some(src) = TypedImageView::from_image_view(src_image) {
|
||||
if let Some(dst) = TypedImageViewMut::from_image_view(dst_image) {
|
||||
self.resize_inner::<U16x2>(src, dst);
|
||||
}
|
||||
}
|
||||
(DynamicImageView::U16x2(src), DynamicImageViewMut::U16x2(dst)) => {
|
||||
self.resize_inner(src, dst);
|
||||
}
|
||||
PixelType::U16x3 => {
|
||||
if let Some(src) = TypedImageView::from_image_view(src_image) {
|
||||
if let Some(dst) = TypedImageViewMut::from_image_view(dst_image) {
|
||||
self.resize_inner::<U16x3>(src, dst);
|
||||
}
|
||||
}
|
||||
(DynamicImageView::U16x3(src), DynamicImageViewMut::U16x3(dst)) => {
|
||||
self.resize_inner(src, dst);
|
||||
}
|
||||
PixelType::U16x4 => {
|
||||
if let Some(src) = TypedImageView::from_image_view(src_image) {
|
||||
if let Some(dst) = TypedImageViewMut::from_image_view(dst_image) {
|
||||
self.resize_inner::<U16x4>(src, dst);
|
||||
}
|
||||
}
|
||||
(DynamicImageView::U16x4(src), DynamicImageViewMut::U16x4(dst)) => {
|
||||
self.resize_inner(src, dst);
|
||||
}
|
||||
PixelType::I32 => {
|
||||
if let Some(src) = TypedImageView::from_image_view(src_image) {
|
||||
if let Some(dst) = TypedImageViewMut::from_image_view(dst_image) {
|
||||
self.resize_inner::<I32>(src, dst);
|
||||
}
|
||||
}
|
||||
(DynamicImageView::I32(src), DynamicImageViewMut::I32(dst)) => {
|
||||
self.resize_inner(src, dst);
|
||||
}
|
||||
PixelType::F32 => {
|
||||
if let Some(src) = TypedImageView::from_image_view(src_image) {
|
||||
if let Some(dst) = TypedImageViewMut::from_image_view(dst_image) {
|
||||
self.resize_inner::<F32>(src, dst);
|
||||
}
|
||||
}
|
||||
(DynamicImageView::F32(src), DynamicImageViewMut::F32(dst)) => {
|
||||
self.resize_inner(src, dst);
|
||||
}
|
||||
_ => {
|
||||
return Err(DifferentTypesOfPixelsError);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn resize_inner<P>(&mut self, src_image: TypedImageView<P>, mut dst_image: TypedImageViewMut<P>)
|
||||
fn resize_inner<P>(&mut self, src_image: &ImageView<P>, dst_image: &mut ImageViewMut<P>)
|
||||
where
|
||||
P: Convolution,
|
||||
{
|
||||
if dst_image.copy_from_view(&src_image).is_ok() {
|
||||
if dst_image.copy_from_view(src_image).is_ok() {
|
||||
return;
|
||||
}
|
||||
match self.algorithm {
|
||||
@@ -239,7 +199,7 @@ fn get_temp_image_from_buffer<P: Pixel>(
|
||||
InnerImage::new(width, height, &mut pixels[0..pixels_count])
|
||||
}
|
||||
|
||||
fn resample_nearest<P>(src_image: TypedImageView<P>, mut dst_image: TypedImageViewMut<P>)
|
||||
fn resample_nearest<P>(src_image: &ImageView<P>, dst_image: &mut ImageViewMut<P>)
|
||||
where
|
||||
P: Pixel,
|
||||
{
|
||||
@@ -269,8 +229,8 @@ where
|
||||
}
|
||||
|
||||
fn resample_convolution<P>(
|
||||
src_image: TypedImageView<P>,
|
||||
dst_image: TypedImageViewMut<P>,
|
||||
src_image: &ImageView<P>,
|
||||
dst_image: &mut ImageViewMut<P>,
|
||||
filter_type: FilterType,
|
||||
cpu_extensions: CpuExtensions,
|
||||
temp_buffer: &mut Vec<u8>,
|
||||
@@ -316,7 +276,7 @@ fn resample_convolution<P>(
|
||||
let mut temp_image = get_temp_image_from_buffer(temp_buffer, dst_width, temp_height);
|
||||
P::horiz_convolution(
|
||||
src_image,
|
||||
temp_image.dst_view(),
|
||||
&mut temp_image.dst_view(),
|
||||
y_first,
|
||||
horiz_coeffs,
|
||||
cpu_extensions,
|
||||
@@ -328,7 +288,7 @@ fn resample_convolution<P>(
|
||||
.iter_mut()
|
||||
.for_each(|b| b.start -= y_first);
|
||||
P::vert_convolution(
|
||||
temp_image.src_view(),
|
||||
&temp_image.src_view(),
|
||||
dst_image,
|
||||
vert_coeffs,
|
||||
cpu_extensions,
|
||||
@@ -342,8 +302,8 @@ fn resample_convolution<P>(
|
||||
}
|
||||
|
||||
fn resample_super_sampling<P>(
|
||||
src_image: TypedImageView<P>,
|
||||
dst_image: TypedImageViewMut<P>,
|
||||
src_image: &ImageView<P>,
|
||||
dst_image: &mut ImageViewMut<P>,
|
||||
filter_type: FilterType,
|
||||
multiplicity: u8,
|
||||
cpu_extensions: CpuExtensions,
|
||||
@@ -370,10 +330,10 @@ fn resample_super_sampling<P>(
|
||||
NonZeroU32::new((crop_box.height.get() as f32 / factor).round() as u32).unwrap();
|
||||
|
||||
let mut tmp_img = get_temp_image_from_buffer(temp_buffer, tmp_width, tmp_height);
|
||||
resample_nearest(src_image, tmp_img.dst_view());
|
||||
resample_nearest(src_image, &mut tmp_img.dst_view());
|
||||
// Second step is resizing the temporary image with a convolution.
|
||||
resample_convolution(
|
||||
tmp_img.src_view(),
|
||||
&tmp_img.src_view(),
|
||||
dst_image,
|
||||
filter_type,
|
||||
cpu_extensions,
|
||||
|
||||
@@ -1,208 +0,0 @@
|
||||
use std::num::NonZeroU32;
|
||||
use std::slice;
|
||||
|
||||
use crate::image_view::{FourRows, FourRowsMut, RowMut, TwoRows};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::{CropBox, DifferentDimensionsError, ImageView, ImageViewMut};
|
||||
|
||||
/// Generic immutable image view.
|
||||
pub(crate) struct TypedImageView<'a, 'b, P>
|
||||
where
|
||||
P: Pixel,
|
||||
{
|
||||
width: NonZeroU32,
|
||||
height: NonZeroU32,
|
||||
crop_box: CropBox,
|
||||
rows: &'a [&'b [P]],
|
||||
}
|
||||
|
||||
impl<'a, 'b, P> TypedImageView<'a, 'b, P>
|
||||
where
|
||||
P: Pixel,
|
||||
{
|
||||
pub fn new(width: NonZeroU32, height: NonZeroU32, rows: &'a [&'b [P]]) -> Self {
|
||||
Self {
|
||||
width,
|
||||
height,
|
||||
crop_box: CropBox {
|
||||
left: 0,
|
||||
top: 0,
|
||||
width,
|
||||
height,
|
||||
},
|
||||
rows,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_image_view(image_view: &'a ImageView<'b>) -> Option<Self> {
|
||||
image_view.typed_rows().map(|typed_rows| Self {
|
||||
width: image_view.width(),
|
||||
height: image_view.height(),
|
||||
crop_box: image_view.crop_box(),
|
||||
rows: typed_rows,
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn width(&self) -> NonZeroU32 {
|
||||
self.width
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn height(&self) -> NonZeroU32 {
|
||||
self.height
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn crop_box(&self) -> CropBox {
|
||||
self.crop_box
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn iter_4_rows<'s>(
|
||||
&'s self,
|
||||
start_y: u32,
|
||||
max_y: u32,
|
||||
) -> impl Iterator<Item = FourRows<'b, P>> + 's {
|
||||
let start_y = start_y as usize;
|
||||
let max_y = max_y.min(self.height.get()) as usize;
|
||||
let rows = self.rows.get(start_y..max_y).unwrap_or(&[]);
|
||||
rows.chunks_exact(4).map(|rows| match *rows {
|
||||
[r0, r1, r2, r3] => (r0, r1, r2, r3),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn iter_2_rows<'s>(
|
||||
&'s self,
|
||||
start_y: u32,
|
||||
max_y: u32,
|
||||
) -> impl Iterator<Item = TwoRows<'b, P>> + 's {
|
||||
let start_y = start_y as usize;
|
||||
let max_y = max_y.min(self.height.get()) as usize;
|
||||
let rows = self.rows.get(start_y..max_y).unwrap_or(&[]);
|
||||
rows.chunks_exact(2).map(|rows| match *rows {
|
||||
[r0, r1] => (r0, r1),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn iter_rows<'s>(&'s self, start_y: u32) -> impl Iterator<Item = &'b [P]> + 's {
|
||||
let start_y = start_y as usize;
|
||||
let rows = self.rows.get(start_y..).unwrap_or(&[]);
|
||||
rows.iter().copied()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn get_row(&self, y: u32) -> Option<&'b [P]> {
|
||||
self.rows.get(y as usize).copied()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn iter_rows_with_step<'s>(
|
||||
&'s self,
|
||||
mut y: f64,
|
||||
step: f64,
|
||||
max_count: usize,
|
||||
) -> impl Iterator<Item = &'b [P]> + 's {
|
||||
let steps = (self.height.get() as f64 - y) / step;
|
||||
let steps = (steps.max(0.).ceil() as usize).min(max_count);
|
||||
(0..steps).map(move |_| {
|
||||
// Safety of value of y guaranteed by calculation of steps count
|
||||
let row = unsafe { *self.rows.get_unchecked(y as usize) };
|
||||
y += step;
|
||||
row
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn iter_cropped_rows<'s>(&'s self) -> impl Iterator<Item = &'b [P]> + 's {
|
||||
let first_row = self.crop_box.top as usize;
|
||||
let last_row = first_row + self.crop_box.height.get() as usize;
|
||||
let rows = unsafe { self.rows.get_unchecked(first_row..last_row) };
|
||||
|
||||
let first_col = self.crop_box.left as usize;
|
||||
let last_col = first_col + self.crop_box.width.get() as usize;
|
||||
rows.iter()
|
||||
.map(move |row| unsafe { row.get_unchecked(first_col..last_col) })
|
||||
}
|
||||
}
|
||||
|
||||
/// Generic mutable image view.
|
||||
pub(crate) struct TypedImageViewMut<'a, 'b, P>
|
||||
where
|
||||
P: Pixel,
|
||||
{
|
||||
width: NonZeroU32,
|
||||
height: NonZeroU32,
|
||||
rows: &'a mut [&'b mut [P]],
|
||||
}
|
||||
|
||||
impl<'a, 'b, P> TypedImageViewMut<'a, 'b, P>
|
||||
where
|
||||
P: Pixel,
|
||||
{
|
||||
pub fn new(width: NonZeroU32, height: NonZeroU32, rows: &'a mut [&'b mut [P]]) -> Self {
|
||||
Self {
|
||||
width,
|
||||
height,
|
||||
rows,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_image_view(image_view: &'a mut ImageViewMut<'b>) -> Option<Self> {
|
||||
let width = image_view.width();
|
||||
let height = image_view.height();
|
||||
image_view.typed_rows().map(|typed_rows| Self {
|
||||
width,
|
||||
height,
|
||||
rows: typed_rows,
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn width(&self) -> NonZeroU32 {
|
||||
self.width
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn height(&self) -> NonZeroU32 {
|
||||
self.height
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn iter_rows_mut(&mut self) -> slice::IterMut<&'b mut [P]> {
|
||||
self.rows.iter_mut()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn iter_4_rows_mut<'s>(&'s mut self) -> impl Iterator<Item = FourRowsMut<'s, 'b, P>> {
|
||||
self.rows.chunks_exact_mut(4).map(|rows| match rows {
|
||||
[a, b, c, d] => (a, b, c, d),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get_row_mut<'s>(&'s mut self, y: u32) -> Option<RowMut<'s, 'b, P>> {
|
||||
self.rows.get_mut(y as usize)
|
||||
}
|
||||
|
||||
/// Copy into the view pixels from src_view.
|
||||
pub(crate) fn copy_from_view(
|
||||
&mut self,
|
||||
src_view: &TypedImageView<P>,
|
||||
) -> Result<(), DifferentDimensionsError> {
|
||||
let src_crop_box = src_view.crop_box();
|
||||
if self.width != src_crop_box.width || self.height != src_crop_box.height {
|
||||
return Err(DifferentDimensionsError);
|
||||
}
|
||||
self.rows
|
||||
.iter_mut()
|
||||
.zip(src_view.iter_cropped_rows())
|
||||
.for_each(|(d, s)| d.copy_from_slice(s));
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,10 @@ use image::{ColorType, DynamicImage};
|
||||
use fast_image_resize::pixels::*;
|
||||
use fast_image_resize::{CpuExtensions, Image, PixelType};
|
||||
|
||||
pub fn nonzero(v: u32) -> NonZeroU32 {
|
||||
NonZeroU32::new(v).unwrap()
|
||||
}
|
||||
|
||||
pub fn image_checksum<const N: usize>(buffer: &[u8]) -> [u32; N] {
|
||||
let mut res = [0u32; N];
|
||||
for pixel in buffer.chunks_exact(N) {
|
||||
|
||||
+20
-66
@@ -1,57 +1,10 @@
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use fast_image_resize::pixels::{Pixel, U16x2, U16x4, U8x2, U8x4};
|
||||
use fast_image_resize::{CpuExtensions, Image, ImageView, ImageViewMut, MulDiv, PixelType};
|
||||
use fast_image_resize::{ImageRows, ImageRowsMut};
|
||||
|
||||
trait IntoImageRows
|
||||
where
|
||||
Self: Pixel,
|
||||
{
|
||||
fn into_image_rows(rows: Vec<&[Self]>) -> ImageRows;
|
||||
|
||||
fn into_image_rows_mut(rows: Vec<&mut [Self]>) -> ImageRowsMut;
|
||||
}
|
||||
|
||||
impl IntoImageRows for U8x2 {
|
||||
fn into_image_rows(rows: Vec<&[Self]>) -> ImageRows {
|
||||
ImageRows::U8x2(rows)
|
||||
}
|
||||
|
||||
fn into_image_rows_mut(rows: Vec<&mut [Self]>) -> ImageRowsMut {
|
||||
ImageRowsMut::U8x2(rows)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoImageRows for U8x4 {
|
||||
fn into_image_rows(rows: Vec<&[Self]>) -> ImageRows {
|
||||
ImageRows::U8x4(rows)
|
||||
}
|
||||
|
||||
fn into_image_rows_mut(rows: Vec<&mut [Self]>) -> ImageRowsMut {
|
||||
ImageRowsMut::U8x4(rows)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoImageRows for U16x2 {
|
||||
fn into_image_rows(rows: Vec<&[Self]>) -> ImageRows {
|
||||
ImageRows::U16x2(rows)
|
||||
}
|
||||
|
||||
fn into_image_rows_mut(rows: Vec<&mut [Self]>) -> ImageRowsMut {
|
||||
ImageRowsMut::U16x2(rows)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoImageRows for U16x4 {
|
||||
fn into_image_rows(rows: Vec<&[Self]>) -> ImageRows {
|
||||
ImageRows::U16x4(rows)
|
||||
}
|
||||
|
||||
fn into_image_rows_mut(rows: Vec<&mut [Self]>) -> ImageRowsMut {
|
||||
ImageRowsMut::U16x4(rows)
|
||||
}
|
||||
}
|
||||
use fast_image_resize::{
|
||||
CpuExtensions, DynamicImageView, DynamicImageViewMut, Image, ImageView, ImageViewMut, MulDiv,
|
||||
PixelType,
|
||||
};
|
||||
|
||||
const fn p2(l: u8, a: u8) -> U8x2 {
|
||||
U8x2(u16::from_le_bytes([l, a]))
|
||||
@@ -70,24 +23,23 @@ enum Oper {
|
||||
|
||||
fn mul_div_alpha_test<P>(oper: Oper, src_pixel: P, result_pixel: P, cpu_extensions: CpuExtensions)
|
||||
where
|
||||
P: Pixel + IntoImageRows,
|
||||
P: Pixel + 'static,
|
||||
for<'a> ImageView<'a, P>: Into<DynamicImageView<'a>>,
|
||||
for<'a> ImageViewMut<'a, P>: Into<DynamicImageViewMut<'a>>,
|
||||
{
|
||||
let width: u32 = 8 + 8 + 7;
|
||||
let height: u32 = 3;
|
||||
|
||||
let src_size = width as usize * height as usize;
|
||||
let mut src_pixels: Vec<P> = vec![src_pixel; src_size];
|
||||
let res_pixels: Vec<P> = vec![result_pixel; src_size];
|
||||
let res_buffer = unsafe { res_pixels.align_to::<u8>().1 };
|
||||
let mut src_pixels = vec![src_pixel; src_size];
|
||||
|
||||
let rows: Vec<&[P]> = src_pixels.chunks_exact(width as usize).collect();
|
||||
|
||||
let src_image_view = ImageView::new(
|
||||
let src_dyn_image_view = ImageView::from_pixels(
|
||||
NonZeroU32::new(width).unwrap(),
|
||||
NonZeroU32::new(height).unwrap(),
|
||||
P::into_image_rows(rows),
|
||||
&src_pixels,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap()
|
||||
.into();
|
||||
|
||||
let mut dst_image = Image::new(
|
||||
NonZeroU32::new(width).unwrap(),
|
||||
@@ -103,13 +55,15 @@ where
|
||||
|
||||
match oper {
|
||||
Oper::Mul => alpha_mul_div
|
||||
.multiply_alpha(&src_image_view, &mut dst_image_view)
|
||||
.multiply_alpha(&src_dyn_image_view, &mut dst_image_view)
|
||||
.unwrap(),
|
||||
Oper::Div => alpha_mul_div
|
||||
.divide_alpha(&src_image_view, &mut dst_image_view)
|
||||
.divide_alpha(&src_dyn_image_view, &mut dst_image_view)
|
||||
.unwrap(),
|
||||
}
|
||||
|
||||
let res_pixels: Vec<P> = vec![result_pixel; src_size];
|
||||
let res_buffer = unsafe { res_pixels.align_to::<u8>().1 };
|
||||
let dst_buffer = dst_image.buffer();
|
||||
assert!(
|
||||
dst_buffer.iter().zip(res_buffer).all(|(&d, &r)| d == r),
|
||||
@@ -119,13 +73,13 @@ where
|
||||
);
|
||||
|
||||
// Inplace
|
||||
let rows: Vec<&mut [P]> = src_pixels.chunks_exact_mut(width as usize).collect();
|
||||
let mut image_view = ImageViewMut::new(
|
||||
let mut image_view = ImageViewMut::from_pixels(
|
||||
NonZeroU32::new(width).unwrap(),
|
||||
NonZeroU32::new(height).unwrap(),
|
||||
P::into_image_rows_mut(rows),
|
||||
&mut src_pixels,
|
||||
)
|
||||
.unwrap();
|
||||
.unwrap()
|
||||
.into();
|
||||
|
||||
match oper {
|
||||
Oper::Mul => alpha_mul_div
|
||||
|
||||
+32
-23
@@ -1,9 +1,5 @@
|
||||
use fast_image_resize as fr;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
fn nonzero(v: u32) -> NonZeroU32 {
|
||||
NonZeroU32::new(v).unwrap()
|
||||
}
|
||||
use testing::nonzero;
|
||||
|
||||
mod gamma_tests {
|
||||
use super::*;
|
||||
@@ -18,14 +14,16 @@ mod gamma_tests {
|
||||
|
||||
// into U8
|
||||
let mut dst_image = fr::Image::new(nonzero(16), nonzero(16), fr::PixelType::U8);
|
||||
fr::color::gamma::gamma22_into_linear(&src_image.view(), &mut dst_image.view_mut())
|
||||
fr::color::mappers::GAMMA22_TO_LINEAR
|
||||
.forward_map(&src_image.view(), &mut dst_image.view_mut())
|
||||
.unwrap();
|
||||
let dst_checksum = testing::image_checksum::<1>(dst_image.buffer());
|
||||
assert_eq!(dst_checksum, [20443]);
|
||||
|
||||
// into U16
|
||||
let mut dst_image = fr::Image::new(nonzero(16), nonzero(16), fr::PixelType::U16);
|
||||
fr::color::gamma::gamma22_into_linear(&src_image.view(), &mut dst_image.view_mut())
|
||||
fr::color::mappers::GAMMA22_TO_LINEAR
|
||||
.forward_map(&src_image.view(), &mut dst_image.view_mut())
|
||||
.unwrap();
|
||||
let dst_checksum = testing::image_u16_checksum::<1>(dst_image.buffer());
|
||||
assert_eq!(dst_checksum, [5255141]);
|
||||
@@ -38,13 +36,13 @@ mod gamma_tests {
|
||||
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::gamma::gamma22_into_linear(&src_image.view(), &mut dst_image.view_mut());
|
||||
let result = fr::color::mappers::GAMMA22_TO_LINEAR
|
||||
.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::gamma::gamma22_into_linear(&src_image.view(), &mut dst_image.view_mut());
|
||||
let result = fr::color::mappers::GAMMA22_TO_LINEAR
|
||||
.forward_map(&src_image.view(), &mut dst_image.view_mut());
|
||||
assert!(matches!(
|
||||
result,
|
||||
Err(fr::MappingError::UnsupportedCombinationOfImageTypes)
|
||||
@@ -58,7 +56,8 @@ mod gamma_tests {
|
||||
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::gamma::linear_into_gamma22(&src_image.view(), &mut dst_image.view_mut())
|
||||
fr::color::mappers::GAMMA22_TO_LINEAR
|
||||
.backward_map(&src_image.view(), &mut dst_image.view_mut())
|
||||
.unwrap();
|
||||
|
||||
let src_checksum = testing::image_checksum::<1>(src_image.buffer());
|
||||
@@ -74,13 +73,13 @@ mod gamma_tests {
|
||||
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::gamma::linear_into_gamma22(&src_image.view(), &mut dst_image.view_mut());
|
||||
let result = fr::color::mappers::GAMMA22_TO_LINEAR
|
||||
.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::gamma::linear_into_gamma22(&src_image.view(), &mut dst_image.view_mut());
|
||||
let result = fr::color::mappers::GAMMA22_TO_LINEAR
|
||||
.backward_map(&src_image.view(), &mut dst_image.view_mut());
|
||||
assert!(matches!(
|
||||
result,
|
||||
Err(fr::MappingError::UnsupportedCombinationOfImageTypes)
|
||||
@@ -100,7 +99,9 @@ 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::srgb::srgb_into_rgb(&src_image.view(), &mut dst_image.view_mut()).unwrap();
|
||||
fr::color::mappers::SRGB_TO_RGB
|
||||
.forward_map(&src_image.view(), &mut dst_image.view_mut())
|
||||
.unwrap();
|
||||
|
||||
let dst_checksum = testing::image_checksum::<3>(dst_image.buffer());
|
||||
assert_eq!(dst_checksum, [20304, 20304, 20304]);
|
||||
@@ -115,7 +116,9 @@ 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::srgb::srgb_into_rgb(&src_image.view(), &mut dst_image.view_mut()).unwrap();
|
||||
fr::color::mappers::SRGB_TO_RGB
|
||||
.forward_map(&src_image.view(), &mut dst_image.view_mut())
|
||||
.unwrap();
|
||||
|
||||
let dst_checksum = testing::image_checksum::<4>(dst_image.buffer());
|
||||
assert_eq!(dst_checksum, [20304, 20304, 20304, 65280]);
|
||||
@@ -128,11 +131,13 @@ mod srgb_tests {
|
||||
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::srgb::srgb_into_rgb(&src_image.view(), &mut dst_image.view_mut());
|
||||
let result = fr::color::mappers::SRGB_TO_RGB
|
||||
.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::srgb::srgb_into_rgb(&src_image.view(), &mut dst_image.view_mut());
|
||||
let result = fr::color::mappers::SRGB_TO_RGB
|
||||
.forward_map(&src_image.view(), &mut dst_image.view_mut());
|
||||
assert!(matches!(
|
||||
result,
|
||||
Err(fr::MappingError::UnsupportedCombinationOfImageTypes)
|
||||
@@ -148,7 +153,9 @@ 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::srgb::rgb_into_srgb(&src_image.view(), &mut dst_image.view_mut()).unwrap();
|
||||
fr::color::mappers::SRGB_TO_RGB
|
||||
.backward_map(&src_image.view(), &mut dst_image.view_mut())
|
||||
.unwrap();
|
||||
|
||||
let dst_checksum = testing::image_checksum::<3>(dst_image.buffer());
|
||||
assert_eq!(dst_checksum, [44981, 44981, 44981]);
|
||||
@@ -161,11 +168,13 @@ mod srgb_tests {
|
||||
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::srgb::rgb_into_srgb(&src_image.view(), &mut dst_image.view_mut());
|
||||
let result = fr::color::mappers::SRGB_TO_RGB
|
||||
.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::srgb::rgb_into_srgb(&src_image.view(), &mut dst_image.view_mut());
|
||||
let result = fr::color::mappers::SRGB_TO_RGB
|
||||
.backward_map(&src_image.view(), &mut dst_image.view_mut());
|
||||
assert!(matches!(
|
||||
result,
|
||||
Err(fr::MappingError::UnsupportedCombinationOfImageTypes)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use fast_image_resize as fr;
|
||||
use fast_image_resize::pixels::U8;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
#[test]
|
||||
@@ -20,10 +21,10 @@ fn create_image_view_from_small_buffer() {
|
||||
let height = NonZeroU32::new(32).unwrap();
|
||||
let mut buffer = vec![0; 64 * 30];
|
||||
|
||||
let res = fr::ImageViewMut::from_buffer(width, height, &mut buffer, fr::PixelType::U8);
|
||||
let res = fr::ImageViewMut::<U8>::from_buffer(width, height, &mut buffer);
|
||||
assert_eq!(res.unwrap_err(), fr::ImageBufferError::InvalidBufferSize);
|
||||
|
||||
let res = fr::ImageView::from_buffer(width, height, &buffer, fr::PixelType::U8);
|
||||
let res = fr::ImageView::<U8>::from_buffer(width, height, &buffer);
|
||||
assert_eq!(res.unwrap_err(), fr::ImageBufferError::InvalidBufferSize);
|
||||
}
|
||||
|
||||
@@ -46,9 +47,9 @@ fn create_image_view_from_big_buffer() {
|
||||
let height = NonZeroU32::new(32).unwrap();
|
||||
let mut buffer = vec![0; 65 * 32];
|
||||
|
||||
let res = fr::ImageViewMut::from_buffer(width, height, &mut buffer, fr::PixelType::U8);
|
||||
let res = fr::ImageViewMut::<U8>::from_buffer(width, height, &mut buffer);
|
||||
assert!(res.is_ok());
|
||||
|
||||
let res = fr::ImageView::from_buffer(width, height, &buffer, fr::PixelType::U8);
|
||||
let res = fr::ImageView::<U8>::from_buffer(width, height, &buffer);
|
||||
assert!(res.is_ok());
|
||||
}
|
||||
|
||||
+19
-29
@@ -1,14 +1,13 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use fast_image_resize::pixels::*;
|
||||
use fast_image_resize::{
|
||||
CpuExtensions, CropBox, DifferentTypesOfPixelsError, FilterType, Image, ImageView, PixelType,
|
||||
ResizeAlg, Resizer,
|
||||
CpuExtensions, CropBox, DifferentTypesOfPixelsError, DynamicImageView, FilterType, Image,
|
||||
PixelType, ResizeAlg, Resizer,
|
||||
};
|
||||
use testing::PixelExt;
|
||||
use testing::{nonzero, PixelExt};
|
||||
|
||||
fn get_new_height(src_image: &ImageView, new_width: u32) -> u32 {
|
||||
fn get_new_height(src_image: &DynamicImageView, new_width: u32) -> u32 {
|
||||
let scale = new_width as f32 / src_image.width().get() as f32;
|
||||
(src_image.height().get() as f32 * scale).round() as u32
|
||||
}
|
||||
@@ -20,11 +19,7 @@ const NEW_BIG_WIDTH: u32 = 5016;
|
||||
fn try_resize_to_other_pixel_type() {
|
||||
let src_image = U8x4::load_big_src_image();
|
||||
let mut resizer = Resizer::new(ResizeAlg::Convolution(FilterType::Lanczos3));
|
||||
let mut dst_image = Image::new(
|
||||
NonZeroU32::new(1024).unwrap(),
|
||||
NonZeroU32::new(256).unwrap(),
|
||||
PixelType::U8,
|
||||
);
|
||||
let mut dst_image = Image::new(nonzero(1024), nonzero(256), PixelType::U8);
|
||||
assert!(matches!(
|
||||
resizer.resize(&src_image.view(), &mut dst_image.view_mut()),
|
||||
Err(DifferentTypesOfPixelsError)
|
||||
@@ -33,8 +28,8 @@ fn try_resize_to_other_pixel_type() {
|
||||
|
||||
#[test]
|
||||
fn resize_to_same_size() {
|
||||
let width = NonZeroU32::new(100).unwrap();
|
||||
let height = NonZeroU32::new(80).unwrap();
|
||||
let width = nonzero(100);
|
||||
let height = nonzero(80);
|
||||
let buffer: Vec<u8> = (0..8000).map(|v| (v & 0xff) as u8).collect();
|
||||
let src_image = Image::from_vec_u8(width, height, buffer, PixelType::U8).unwrap();
|
||||
let mut dst_image = Image::new(width, height, PixelType::U8);
|
||||
@@ -50,10 +45,10 @@ fn resize_to_same_size() {
|
||||
|
||||
#[test]
|
||||
fn resize_to_same_size_after_cropping() {
|
||||
let width = NonZeroU32::new(100).unwrap();
|
||||
let height = NonZeroU32::new(80).unwrap();
|
||||
let src_width = NonZeroU32::new(120).unwrap();
|
||||
let src_height = NonZeroU32::new(100).unwrap();
|
||||
let width = nonzero(100);
|
||||
let height = nonzero(80);
|
||||
let src_width = nonzero(120);
|
||||
let src_height = nonzero(100);
|
||||
let buffer: Vec<u8> = (0..12000).map(|v| (v & 0xff) as u8).collect();
|
||||
let src_image = Image::from_vec_u8(src_width, src_height, buffer, PixelType::U8).unwrap();
|
||||
let mut src_view = src_image.view();
|
||||
@@ -95,15 +90,10 @@ fn downscale_test<P: PixelExt>(resize_alg: ResizeAlg, cpu_extensions: CpuExtensi
|
||||
unsafe {
|
||||
resizer.set_cpu_extensions(cpu_extensions);
|
||||
}
|
||||
let new_height = get_new_height(&image.view(), NEW_WIDTH);
|
||||
let mut result = Image::new(
|
||||
NonZeroU32::new(NEW_WIDTH).unwrap(),
|
||||
NonZeroU32::new(new_height).unwrap(),
|
||||
image.pixel_type(),
|
||||
);
|
||||
assert!(resizer
|
||||
.resize(&image.view(), &mut result.view_mut())
|
||||
.is_ok());
|
||||
let image_view = image.view();
|
||||
let new_height = get_new_height(&image_view, NEW_WIDTH);
|
||||
let mut result = Image::new(nonzero(NEW_WIDTH), nonzero(new_height), image.pixel_type());
|
||||
assert!(resizer.resize(&image_view, &mut result.view_mut()).is_ok());
|
||||
|
||||
let alg_name = match resize_alg {
|
||||
ResizeAlg::Nearest => "nearest",
|
||||
@@ -140,8 +130,8 @@ fn upscale_test<P: PixelExt>(resize_alg: ResizeAlg, cpu_extensions: CpuExtension
|
||||
}
|
||||
let new_height = get_new_height(&image.view(), NEW_BIG_WIDTH);
|
||||
let mut result = Image::new(
|
||||
NonZeroU32::new(NEW_BIG_WIDTH).unwrap(),
|
||||
NonZeroU32::new(new_height).unwrap(),
|
||||
nonzero(NEW_BIG_WIDTH),
|
||||
nonzero(new_height),
|
||||
image.pixel_type(),
|
||||
);
|
||||
assert!(resizer
|
||||
@@ -539,8 +529,8 @@ fn resizer_u16x4() {
|
||||
use rgb::FromSlice;
|
||||
|
||||
let src_image = U16x4::load_big_image().to_rgba16();
|
||||
let new_width = NonZeroU32::new(852).unwrap();
|
||||
let new_height = NonZeroU32::new(567).unwrap();
|
||||
let new_width = nonzero(852);
|
||||
let new_height = nonzero(567);
|
||||
|
||||
let resize_src_image = src_image.as_raw().as_rgba();
|
||||
let mut dst =
|
||||
|
||||
Reference in New Issue
Block a user