mirror of
https://github.com/Cykooz/fast_image_resize.git
synced 2026-10-08 01:11:09 +00:00
Fixed resizing when the destination image has the same dimensions as the source image (#9).
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
## [Unreleased] - ReleaseDate
|
||||
|
||||
- Fixed resizing when the destination image has the same dimensions
|
||||
as the source image
|
||||
([#9](https://github.com/Cykooz/fast_image_resize/issues/9)).
|
||||
|
||||
## [0.9.6] - 2022-06-28
|
||||
|
||||
- Added support of new type of pixels `PixelType::U16x4`.
|
||||
|
||||
Generated
+62
-39
@@ -39,9 +39,9 @@ checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704"
|
||||
|
||||
[[package]]
|
||||
name = "argh"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbb41d85d92dfab96cb95ab023c265c5e4261bb956c0fb49ca06d90c570f1958"
|
||||
checksum = "a7e7e4aa7e40747e023c0761dafcb42333a9517575bbf1241747f68dd3177a62"
|
||||
dependencies = [
|
||||
"argh_derive",
|
||||
"argh_shared",
|
||||
@@ -49,9 +49,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "argh_derive"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be69f70ef5497dd6ab331a50bd95c6ac6b8f7f17a7967838332743fbd58dc3b5"
|
||||
checksum = "69f2bd7ff6ed6414f4e5521bd509bae46454bbd513801767ced3f21a751ab4bc"
|
||||
dependencies = [
|
||||
"argh_shared",
|
||||
"heck",
|
||||
@@ -62,9 +62,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "argh_shared"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6f8c380fa28aa1b36107cd97f0196474bb7241bb95a453c5c01a15ac74b2eac"
|
||||
checksum = "47253b98986dafc7a3e1cf3259194f1f47ac61abb57a57f46ec09e48d004ecda"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
@@ -110,9 +110,9 @@ checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.9.1"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc"
|
||||
checksum = "c53dfa917ec274df8ed3c572698f381a24eef2efba9492d797301b72b6db408a"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
@@ -151,12 +151,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cli-log"
|
||||
version = "0.1.0"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f47673f2992075892b3e983499410c92af91a7d7cee72cf55ec4caea278de6cf"
|
||||
checksum = "3d2ab00dc4c82ec28af25ac085aecc11ffeabf353755715a3113a7aa044ca5cc"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"file-size",
|
||||
"log",
|
||||
"proc-status",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -301,9 +303,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "csv2svg"
|
||||
version = "0.1.7"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5eede96fa4be061f1b49b92c756f8d150de9fbb5b11e09c6c2b3d670e32fd9f5"
|
||||
checksum = "22bc4e544d47a40c5d62c5583d3df357e40e0a5f5027d38ffc8d4e5c141276a6"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"argh",
|
||||
@@ -316,7 +318,7 @@ dependencies = [
|
||||
"log",
|
||||
"num-traits",
|
||||
"open",
|
||||
"svg",
|
||||
"svg 0.10.0",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
@@ -352,9 +354,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be"
|
||||
|
||||
[[package]]
|
||||
name = "exr"
|
||||
@@ -390,7 +392,7 @@ version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c195cf4b2285d3c993eb887b4dc56b0d5728bbe1d0f9a99c0ac6bec2da3e4d85"
|
||||
dependencies = [
|
||||
"hashbrown 0.12.1",
|
||||
"hashbrown 0.12.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -417,6 +419,12 @@ dependencies = [
|
||||
"instant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "file-size"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9544f10105d33957765016b8a9baea7e689bf1f0f2f32c2fa2f568770c38d2b3"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.24"
|
||||
@@ -514,7 +522,7 @@ dependencies = [
|
||||
"rusqlite",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"svg",
|
||||
"svg 0.8.2",
|
||||
"tempfile",
|
||||
"termimad",
|
||||
"thiserror",
|
||||
@@ -537,9 +545,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.1"
|
||||
version = "0.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3"
|
||||
checksum = "607c8a29735385251a339424dd462993c0fed8fa09d378f259377df08c126022"
|
||||
dependencies = [
|
||||
"ahash 0.7.6",
|
||||
]
|
||||
@@ -855,9 +863,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.12.0"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
|
||||
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
|
||||
|
||||
[[package]]
|
||||
name = "open"
|
||||
@@ -906,18 +914,18 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.0.10"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e"
|
||||
checksum = "78203e83c48cffbe01e4a2d35d566ca4de445d79a85372fc64e378bfc812a260"
|
||||
dependencies = [
|
||||
"pin-project-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-internal"
|
||||
version = "1.0.10"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb"
|
||||
checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -951,6 +959,15 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-status"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0e0c0ac915e7b76b47850ba4ffc377abde6c6ff9eeace61d0a89623db449712"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.20"
|
||||
@@ -1073,18 +1090,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.137"
|
||||
version = "1.0.139"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
|
||||
checksum = "0171ebb889e45aa68b44aee0859b3eede84c6f5f5c228e6f140c0b2a0a46cad6"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.137"
|
||||
version = "1.0.139"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
|
||||
checksum = "dc1d3230c1de7932af58ad8ffbe1d784bd55efd5a9d84ac24f69c72d83543dfb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1093,9 +1110,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.81"
|
||||
version = "1.0.82"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
|
||||
checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7"
|
||||
dependencies = [
|
||||
"itoa 1.0.2",
|
||||
"ryu",
|
||||
@@ -1134,15 +1151,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.8.1"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2"
|
||||
checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.3"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c530c2b0d0bf8b69304b39fe2001993e267461948b890cd037d8ad4293fa1a0d"
|
||||
checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
@@ -1153,6 +1170,12 @@ version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bdb25a4593d6656239319426f4025f7a658157e25e89f0e0319d7516d46042d"
|
||||
|
||||
[[package]]
|
||||
name = "svg"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e72d8b19ab05827afefcca66bf47040c1e66a0901eb814784c77d4ec118bd309"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.98"
|
||||
@@ -1280,9 +1303,9 @@ checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.20"
|
||||
version = "0.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81dee68f85cab8cf68dec42158baf3a79a1cdc065a8b103025965d6ccb7f6cbd"
|
||||
checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
@@ -1391,9 +1414,9 @@ checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be"
|
||||
|
||||
[[package]]
|
||||
name = "weezl"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c97e489d8f836838d497091de568cf16b117486d529ec5579233521065bd5e4"
|
||||
checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
|
||||
@@ -49,11 +49,11 @@ Pipeline:
|
||||
|
||||
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|
||||
|------------|:-------:|:--------:|:----------:|:--------:|
|
||||
| image | 19.24 | 82.52 | 152.17 | 207.63 |
|
||||
| resize | - | 52.19 | 103.40 | 154.15 |
|
||||
| fir rust | 0.28 | 40.88 | 69.39 | 101.53 |
|
||||
| fir sse4.1 | 0.28 | 28.21 | 43.03 | 59.46 |
|
||||
| fir avx2 | 0.28 | 7.33 | 9.47 | 13.59 |
|
||||
| image | 18.75 | 83.16 | 148.86 | 205.11 |
|
||||
| resize | - | 52.27 | 103.40 | 154.10 |
|
||||
| fir rust | 0.28 | 41.93 | 76.81 | 114.10 |
|
||||
| fir sse4.1 | 0.28 | 27.98 | 43.16 | 58.43 |
|
||||
| fir avx2 | 0.28 | 7.42 | 9.71 | 13.91 |
|
||||
|
||||
### Resize RGBA8 image (U8x4) 4928x3279 => 852x567
|
||||
|
||||
@@ -68,10 +68,10 @@ Pipeline:
|
||||
|
||||
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|
||||
|------------|:-------:|:--------:|:----------:|:--------:|
|
||||
| resize | - | 61.93 | 122.10 | 182.55 |
|
||||
| fir rust | 0.18 | 36.57 | 52.28 | 74.14 |
|
||||
| fir sse4.1 | 0.18 | 13.14 | 17.21 | 22.44 |
|
||||
| fir avx2 | 0.18 | 9.69 | 11.99 | 16.23 |
|
||||
| resize | - | 61.37 | 122.00 | 181.84 |
|
||||
| fir rust | 0.18 | 37.42 | 53.36 | 75.87 |
|
||||
| fir sse4.1 | 0.18 | 13.33 | 17.40 | 22.71 |
|
||||
| fir avx2 | 0.18 | 9.69 | 12.09 | 16.35 |
|
||||
|
||||
### Resize L8 (luma) image (U8) 4928x3279 => 852x567
|
||||
|
||||
@@ -85,11 +85,11 @@ Pipeline:
|
||||
|
||||
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|
||||
|------------|:-------:|:--------:|:----------:|:--------:|
|
||||
| image | 15.86 | 47.17 | 74.46 | 102.53 |
|
||||
| resize | - | 17.30 | 35.92 | 61.52 |
|
||||
| fir rust | 0.15 | 14.10 | 16.20 | 24.12 |
|
||||
| fir sse4.1 | 0.15 | 11.93 | 12.13 | 18.20 |
|
||||
| fir avx2 | 0.15 | 6.30 | 4.71 | 7.62 |
|
||||
| image | 15.48 | 46.20 | 73.56 | 101.74 |
|
||||
| resize | - | 17.29 | 35.60 | 61.27 |
|
||||
| fir rust | 0.16 | 13.79 | 15.31 | 22.76 |
|
||||
| fir sse4.1 | 0.16 | 12.01 | 12.12 | 18.10 |
|
||||
| fir avx2 | 0.16 | 6.29 | 4.81 | 7.71 |
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
+36
-36
@@ -5,8 +5,8 @@ Environment:
|
||||
- CPU: AMD Ryzen 9 5950X
|
||||
- RAM: DDR4 3800 MHz
|
||||
- Ubuntu 22.04 (linux 5.15.0)
|
||||
- Rust 1.61.0
|
||||
- fast_image_resize = "0.9.3"
|
||||
- Rust 1.62.0
|
||||
- fast_image_resize = "0.9.7"
|
||||
- glassbench = "0.3.3"
|
||||
|
||||
Other Rust libraries used to compare of resizing speed:
|
||||
@@ -32,11 +32,11 @@ Pipeline:
|
||||
|
||||
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|
||||
|------------|:-------:|:--------:|:----------:|:--------:|
|
||||
| image | 19.50 | 83.55 | 142.66 | 202.49 |
|
||||
| resize | - | 52.12 | 102.98 | 153.42 |
|
||||
| fir rust | 0.28 | 40.94 | 69.96 | 100.86 |
|
||||
| fir sse4.1 | 0.28 | 28.10 | 43.06 | 58.05 |
|
||||
| fir avx2 | 0.28 | 7.24 | 9.49 | 13.61 |
|
||||
| image | 18.75 | 83.16 | 148.86 | 205.11 |
|
||||
| resize | - | 52.27 | 103.40 | 154.10 |
|
||||
| fir rust | 0.28 | 41.93 | 76.81 | 114.10 |
|
||||
| fir sse4.1 | 0.28 | 27.98 | 43.16 | 58.43 |
|
||||
| fir avx2 | 0.28 | 7.42 | 9.71 | 13.91 |
|
||||
|
||||
### Resize RGBA8 image (U8x4) 4928x3279 => 852x567
|
||||
|
||||
@@ -51,10 +51,10 @@ Pipeline:
|
||||
|
||||
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|
||||
|------------|:-------:|:--------:|:----------:|:--------:|
|
||||
| resize | - | 61.96 | 122.09 | 182.24 |
|
||||
| fir rust | 0.19 | 36.38 | 52.06 | 74.03 |
|
||||
| fir sse4.1 | 0.19 | 13.37 | 17.44 | 22.63 |
|
||||
| fir avx2 | 0.19 | 9.76 | 12.18 | 16.30 |
|
||||
| resize | - | 61.37 | 122.00 | 181.84 |
|
||||
| fir rust | 0.18 | 37.42 | 53.36 | 75.87 |
|
||||
| fir sse4.1 | 0.18 | 13.33 | 17.40 | 22.71 |
|
||||
| fir avx2 | 0.18 | 9.69 | 12.09 | 16.35 |
|
||||
|
||||
### Resize L8 (luma) image (U8) 4928x3279 => 852x567
|
||||
|
||||
@@ -68,11 +68,11 @@ Pipeline:
|
||||
|
||||
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|
||||
|------------|:-------:|:--------:|:----------:|:--------:|
|
||||
| image | 15.95 | 47.09 | 74.65 | 103.92 |
|
||||
| resize | - | 17.28 | 35.54 | 61.15 |
|
||||
| fir rust | 0.16 | 14.33 | 16.25 | 24.35 |
|
||||
| fir sse4.1 | 0.16 | 12.17 | 12.18 | 18.41 |
|
||||
| fir avx2 | 0.16 | 6.31 | 4.66 | 7.97 |
|
||||
| image | 15.48 | 46.20 | 73.56 | 101.74 |
|
||||
| resize | - | 17.29 | 35.60 | 61.27 |
|
||||
| fir rust | 0.16 | 13.79 | 15.31 | 22.76 |
|
||||
| fir sse4.1 | 0.16 | 12.01 | 12.12 | 18.10 |
|
||||
| fir avx2 | 0.16 | 6.29 | 4.81 | 7.71 |
|
||||
|
||||
### Resize LA8 (luma with alpha channel) image (U8x2) 4928x3279 => 852x567
|
||||
|
||||
@@ -89,9 +89,9 @@ Pipeline:
|
||||
|
||||
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|
||||
|------------|:-------:|:--------:|:----------:|:--------:|
|
||||
| fir rust | 0.18 | 25.79 | 30.79 | 42.38 |
|
||||
| fir sse4.1 | 0.17 | 12.71 | 14.68 | 18.16 |
|
||||
| fir avx2 | 0.17 | 11.25 | 12.53 | 15.53 |
|
||||
| fir rust | 0.17 | 25.97 | 31.30 | 43.20 |
|
||||
| fir sse4.1 | 0.17 | 12.73 | 14.69 | 18.16 |
|
||||
| fir avx2 | 0.17 | 11.24 | 12.51 | 15.45 |
|
||||
|
||||
### Resize RGB16 image (U16x3) 4928x3279 => 852x567
|
||||
|
||||
@@ -105,11 +105,11 @@ Pipeline:
|
||||
|
||||
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|
||||
|------------|:-------:|:--------:|:----------:|:--------:|
|
||||
| image | 19.09 | 76.86 | 140.93 | 191.14 |
|
||||
| resize | - | 55.19 | 107.76 | 159.66 |
|
||||
| fir rust | 0.33 | 43.89 | 80.03 | 117.89 |
|
||||
| fir sse4.1 | 0.33 | 24.46 | 39.45 | 55.91 |
|
||||
| fir avx2 | 0.33 | 21.01 | 31.07 | 36.95 |
|
||||
| image | 18.34 | 75.56 | 136.94 | 186.09 |
|
||||
| resize | - | 55.09 | 107.12 | 158.71 |
|
||||
| fir rust | 0.33 | 43.65 | 79.55 | 117.51 |
|
||||
| fir sse4.1 | 0.33 | 24.39 | 39.47 | 55.81 |
|
||||
| fir avx2 | 0.33 | 20.79 | 30.79 | 36.76 |
|
||||
|
||||
### Resize RGBA16 image (U16x4) 4928x3279 => 852x567
|
||||
|
||||
@@ -124,10 +124,10 @@ Pipeline:
|
||||
|
||||
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|
||||
|------------|:-------:|:--------:|:----------:|:--------:|
|
||||
| resize | - | 62.92 | 124.11 | 185.29 |
|
||||
| fir rust | 0.38 | 84.98 | 123.53 | 163.92 |
|
||||
| fir sse4.1 | 0.38 | 42.35 | 63.57 | 85.62 |
|
||||
| fir avx2 | 0.38 | 23.60 | 34.29 | 45.60 |
|
||||
| resize | - | 63.90 | 127.59 | 191.40 |
|
||||
| fir rust | 0.37 | 87.77 | 125.78 | 165.53 |
|
||||
| fir sse4.1 | 0.37 | 42.54 | 63.71 | 85.59 |
|
||||
| fir avx2 | 0.37 | 23.43 | 34.04 | 45.37 |
|
||||
|
||||
### Resize L16 image (U16) 4928x3279 => 852x567
|
||||
|
||||
@@ -141,11 +141,11 @@ Pipeline:
|
||||
|
||||
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|
||||
|------------|:-------:|:--------:|:----------:|:--------:|
|
||||
| image | 16.43 | 48.12 | 75.85 | 104.63 |
|
||||
| resize | - | 15.48 | 32.05 | 57.16 |
|
||||
| fir rust | 0.17 | 19.31 | 26.93 | 37.76 |
|
||||
| fir sse4.1 | 0.18 | 7.87 | 13.22 | 19.26 |
|
||||
| fir avx2 | 0.18 | 7.17 | 9.62 | 14.73 |
|
||||
| image | 15.70 | 45.79 | 73.63 | 103.38 |
|
||||
| resize | - | 15.52 | 32.13 | 57.22 |
|
||||
| fir rust | 0.17 | 18.51 | 27.75 | 38.42 |
|
||||
| fir sse4.1 | 0.17 | 7.77 | 13.21 | 19.16 |
|
||||
| fir avx2 | 0.17 | 7.07 | 9.54 | 14.81 |
|
||||
|
||||
### Resize LA16 (luma with alpha channel) image (U16x2) 4928x3279 => 852x567
|
||||
|
||||
@@ -162,6 +162,6 @@ Pipeline:
|
||||
|
||||
| | Nearest | Bilinear | CatmullRom | Lanczos3 |
|
||||
|------------|:-------:|:--------:|:----------:|:--------:|
|
||||
| fir rust | 0.19 | 34.70 | 54.59 | 74.64 |
|
||||
| fir sse4.1 | 0.19 | 22.71 | 34.82 | 47.46 |
|
||||
| fir avx2 | 0.20 | 15.68 | 22.42 | 29.13 |
|
||||
| fir rust | 0.19 | 33.85 | 53.43 | 72.17 |
|
||||
| fir sse4.1 | 0.19 | 21.92 | 34.05 | 46.44 |
|
||||
| fir avx2 | 0.19 | 15.16 | 21.93 | 28.98 |
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
pub use errors::*;
|
||||
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
|
||||
mod common;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U16x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
use super::sse4;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U16x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
|
||||
use super::AlphaMulDiv;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::alpha::common::{div_and_clip16, mul_div_65535, RECIP_ALPHA16};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U16x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
pub(crate) fn multiply_alpha(
|
||||
src_image: TypedImageView<U16x2>,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U16x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
use super::native;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U16x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
use super::sse4;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U16x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
|
||||
use super::AlphaMulDiv;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::alpha::common::{div_and_clip16, mul_div_65535, RECIP_ALPHA16};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U16x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
pub(crate) fn multiply_alpha(
|
||||
src_image: TypedImageView<U16x4>,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U16x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
use super::native;
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use super::sse4;
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U8x2;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
use super::sse4;
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn multiply_alpha(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U8x2;
|
||||
use crate::CpuExtensions;
|
||||
use crate::pixels::U8x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
use super::AlphaMulDiv;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::alpha::common::{div_and_clip, mul_div_255, RECIP_ALPHA};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U8x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
pub(crate) fn multiply_alpha(
|
||||
src_image: TypedImageView<U8x2>,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U8x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
use super::native;
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use super::{native, sse4};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U8x4;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
use super::{native, sse4};
|
||||
|
||||
#[target_feature(enable = "avx2")]
|
||||
pub(crate) unsafe fn multiply_alpha(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U8x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
|
||||
use super::AlphaMulDiv;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::alpha::common::{div_and_clip, mul_div_255, RECIP_ALPHA};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U8x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
pub(crate) fn multiply_alpha(
|
||||
src_image: TypedImageView<U8x4>,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U8x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
use super::native;
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use super::{Coefficients, Convolution};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::F32;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
mod native;
|
||||
|
||||
impl Convolution for F32 {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::convolution::Coefficients;
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::F32;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<F32>,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use super::{Coefficients, Convolution};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::I32;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
mod native;
|
||||
|
||||
impl Convolution for I32 {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::convolution::Coefficients;
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::I32;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<I32>,
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::CpuExtensions;
|
||||
pub use filters::{get_filter_func, FilterType};
|
||||
|
||||
use crate::pixels::Pixel;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut, TypedImageView, TypedImageViewMut};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U16;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use super::{Coefficients, Convolution};
|
||||
use crate::convolution::vertical_u16::vert_convolution_u16;
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U16;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod avx2;
|
||||
mod native;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U16;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut, TypedImageView, TypedImageViewMut};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U16;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut, TypedImageView, TypedImageViewMut};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U16x2;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use super::{Coefficients, Convolution};
|
||||
use crate::convolution::vertical_u16::vert_convolution_u16;
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U16x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod avx2;
|
||||
mod native;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U16x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut, TypedImageView, TypedImageViewMut};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U16x2;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut, TypedImageView, TypedImageViewMut};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U16x3;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use super::{Coefficients, Convolution};
|
||||
use crate::convolution::vertical_u16::vert_convolution_u16;
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U16x3;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod avx2;
|
||||
mod native;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U16x3;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -2,9 +2,10 @@ use std::arch::x86_64::*;
|
||||
|
||||
use crate::convolution::optimisations::CoefficientsI32Chunk;
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut, TypedImageView, TypedImageViewMut};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U16x3;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut, TypedImageView, TypedImageViewMut};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U16x4;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use super::{Coefficients, Convolution};
|
||||
use crate::convolution::vertical_u16::vert_convolution_u16;
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U16x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod avx2;
|
||||
mod native;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U16x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut, TypedImageView, TypedImageViewMut};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U16x4;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut, TypedImageView, TypedImageViewMut};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U8;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use super::{Coefficients, Convolution};
|
||||
use crate::convolution::vertical_u8::vert_convolution_u8;
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U8;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod avx2;
|
||||
mod native;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U8;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut, TypedImageView, TypedImageViewMut};
|
||||
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};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::convolution::vertical_u8::vert_convolution_u8;
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U8x2;
|
||||
use crate::CpuExtensions;
|
||||
use crate::pixels::U8x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U8x2;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U8x2>,
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut, TypedImageView, TypedImageViewMut};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U8x2;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -2,9 +2,10 @@ use std::arch::x86_64::*;
|
||||
use std::intrinsics::transmute;
|
||||
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut, TypedImageView, TypedImageViewMut};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U8x3;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use super::{Coefficients, Convolution};
|
||||
use crate::convolution::vertical_u8::vert_convolution_u8;
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U8x3;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod avx2;
|
||||
mod native;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U8x3;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn horiz_convolution(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::convolution::Coefficients;
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U8x3;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
use super::native;
|
||||
|
||||
|
||||
@@ -2,9 +2,10 @@ use std::arch::x86_64::*;
|
||||
use std::intrinsics::transmute;
|
||||
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut, TypedImageView, TypedImageViewMut};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U8x4;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
// This code is based on C-implementation from Pillow-SIMD package for Python
|
||||
// https://github.com/uploadcare/pillow-simd
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use super::{Coefficients, Convolution};
|
||||
use crate::convolution::vertical_u8::vert_convolution_u8;
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U8x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
|
||||
use super::{Coefficients, Convolution};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
mod avx2;
|
||||
mod native;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::U8x4;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
pub(crate) fn horiz_convolution(
|
||||
src_image: TypedImageView<U8x4>,
|
||||
|
||||
@@ -2,9 +2,10 @@ use std::arch::x86_64::*;
|
||||
use std::intrinsics::transmute;
|
||||
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{FourRows, FourRowsMut, TypedImageView, TypedImageViewMut};
|
||||
use crate::image_view::{FourRows, FourRowsMut};
|
||||
use crate::pixels::U8x4;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
// This code is based on C-implementation from Pillow-SIMD package for Python
|
||||
// https://github.com/uploadcare/pillow-simd
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
pub(crate) fn vert_convolution<T>(
|
||||
src_image: TypedImageView<T>,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::convolution::Coefficients;
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn vert_convolution<T: Pixel<Component = u16>>(
|
||||
|
||||
@@ -3,9 +3,9 @@ use std::arch::x86_64::*;
|
||||
use crate::convolution::optimisations::CoefficientsI32Chunk;
|
||||
use crate::convolution::vertical_u16::native::convolution_by_u16;
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
pub(crate) fn vert_convolution<T: Pixel<Component = u16>>(
|
||||
src_image: TypedImageView<T>,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn vert_convolution<T>(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::convolution::Coefficients;
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::CpuExtensions;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn vert_convolution<T>(
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::convolution::{optimisations, Coefficients};
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::Pixel;
|
||||
use crate::simd_utils;
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn vert_convolution<T: Pixel<Component = u8>>(
|
||||
|
||||
+8
-2
@@ -10,7 +10,7 @@ pub enum ImageRowsError {
|
||||
|
||||
#[derive(Error, Debug, Clone, Copy, PartialEq)]
|
||||
pub enum ImageBufferError {
|
||||
#[error("Size of buffer is smaller than required.")]
|
||||
#[error("Size of buffer is smaller than required")]
|
||||
InvalidBufferSize,
|
||||
#[error("Alignment of buffer don't match to alignment of u32")]
|
||||
InvalidBufferAlignment,
|
||||
@@ -25,5 +25,11 @@ pub enum CropBoxError {
|
||||
}
|
||||
|
||||
#[derive(Error, Debug, Clone, Copy)]
|
||||
#[error("Type of pixels of the source image is not equal to pixel type of the destination image.")]
|
||||
#[error("Type of pixels of the source image is not equal to pixel type of the destination image")]
|
||||
pub struct DifferentTypesOfPixelsError;
|
||||
|
||||
#[derive(Error, Debug, Clone, Copy)]
|
||||
#[error(
|
||||
"The dimensions of the source image are not equal to the dimensions of the destination image"
|
||||
)]
|
||||
pub(crate) struct DifferentDimensionsError;
|
||||
|
||||
+2
-1
@@ -1,7 +1,8 @@
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use crate::image_view::{ImageRows, ImageRowsMut, TypedImageView, TypedImageViewMut};
|
||||
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};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
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);
|
||||
+9
-544
@@ -1,8 +1,8 @@
|
||||
use std::num::NonZeroU32;
|
||||
use std::slice;
|
||||
|
||||
use crate::errors::{CropBoxError, ImageBufferError, ImageRowsError};
|
||||
use crate::pixels::{Pixel, PixelType, U16x2, U16x3, U16x4, U8x2, U8x3, U8x4, F32, I32, U16, U8};
|
||||
use crate::image_rows::{ImageRows, ImageRowsMut};
|
||||
use crate::pixels::{Pixel, PixelType};
|
||||
|
||||
pub(crate) type RowMut<'a, 'b, T> = &'a mut &'b mut [T];
|
||||
pub(crate) type TwoRows<'a, T> = (&'a [T], &'a [T]);
|
||||
@@ -23,131 +23,6 @@ pub struct CropBox {
|
||||
pub height: NonZeroU32,
|
||||
}
|
||||
|
||||
/// 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/// A mutable rows of image.
|
||||
#[derive(Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum ImageRowsMut<'a> {
|
||||
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]>),
|
||||
U8(Vec<&'a mut [U8]>),
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An immutable view of image data used by resizer as source image.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ImageView<'a> {
|
||||
@@ -308,6 +183,11 @@ impl<'a> ImageView<'a> {
|
||||
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
|
||||
@@ -387,240 +267,6 @@ impl<'a> ImageView<'a> {
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub(crate) fn u8x2_image(&self) -> Option<TypedImageView<U8x2>> {
|
||||
if let ImageRows::U8x2(ref rows) = self.rows {
|
||||
Some(TypedImageView {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
crop_box: self.crop_box,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn u8x3_image(&self) -> Option<TypedImageView<U8x3>> {
|
||||
if let ImageRows::U8x3(ref rows) = self.rows {
|
||||
Some(TypedImageView {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
crop_box: self.crop_box,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn u8x4_image(&self) -> Option<TypedImageView<U8x4>> {
|
||||
if let ImageRows::U8x4(ref rows) = self.rows {
|
||||
Some(TypedImageView {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
crop_box: self.crop_box,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn u16_image(&self) -> Option<TypedImageView<U16>> {
|
||||
if let ImageRows::U16(ref rows) = self.rows {
|
||||
Some(TypedImageView {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
crop_box: self.crop_box,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn u16x2_image(&self) -> Option<TypedImageView<U16x2>> {
|
||||
if let ImageRows::U16x2(ref rows) = self.rows {
|
||||
Some(TypedImageView {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
crop_box: self.crop_box,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn u16x3_image(&self) -> Option<TypedImageView<U16x3>> {
|
||||
if let ImageRows::U16x3(ref rows) = self.rows {
|
||||
Some(TypedImageView {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
crop_box: self.crop_box,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn u16x4_image(&self) -> Option<TypedImageView<U16x4>> {
|
||||
if let ImageRows::U16x4(ref rows) = self.rows {
|
||||
Some(TypedImageView {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
crop_box: self.crop_box,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn i32_image(&self) -> Option<TypedImageView<I32>> {
|
||||
if let ImageRows::I32(ref rows) = self.rows {
|
||||
Some(TypedImageView {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
crop_box: self.crop_box,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn f32_image(&self) -> Option<TypedImageView<F32>> {
|
||||
if let ImageRows::F32(ref rows) = self.rows {
|
||||
Some(TypedImageView {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
crop_box: self.crop_box,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn u8_image(&self) -> Option<TypedImageView<U8>> {
|
||||
if let ImageRows::U8(ref rows) = self.rows {
|
||||
Some(TypedImageView {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
crop_box: self.crop_box,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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,
|
||||
}
|
||||
}
|
||||
|
||||
#[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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// A mutable view of image data used by resizer as destination image.
|
||||
@@ -770,191 +416,10 @@ impl<'a> ImageViewMut<'a> {
|
||||
self.height
|
||||
}
|
||||
|
||||
pub(crate) fn u8x2_image<'s>(&'s mut self) -> Option<TypedImageViewMut<'s, 'a, U8x2>> {
|
||||
if let ImageRowsMut::U8x2(rows) = &mut self.rows {
|
||||
Some(TypedImageViewMut {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn u8x3_image<'s>(&'s mut self) -> Option<TypedImageViewMut<'s, 'a, U8x3>> {
|
||||
if let ImageRowsMut::U8x3(rows) = &mut self.rows {
|
||||
Some(TypedImageViewMut {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn u8x4_image<'s>(&'s mut self) -> Option<TypedImageViewMut<'s, 'a, U8x4>> {
|
||||
if let ImageRowsMut::U8x4(rows) = &mut self.rows {
|
||||
Some(TypedImageViewMut {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn u16_image<'s>(&'s mut self) -> Option<TypedImageViewMut<'s, 'a, U16>> {
|
||||
if let ImageRowsMut::U16(rows) = &mut self.rows {
|
||||
Some(TypedImageViewMut {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn u16x2_image<'s>(&'s mut self) -> Option<TypedImageViewMut<'s, 'a, U16x2>> {
|
||||
if let ImageRowsMut::U16x2(rows) = &mut self.rows {
|
||||
Some(TypedImageViewMut {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn u16x3_image<'s>(&'s mut self) -> Option<TypedImageViewMut<'s, 'a, U16x3>> {
|
||||
if let ImageRowsMut::U16x3(rows) = &mut self.rows {
|
||||
Some(TypedImageViewMut {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn u16x4_image<'s>(&'s mut self) -> Option<TypedImageViewMut<'s, 'a, U16x4>> {
|
||||
if let ImageRowsMut::U16x4(rows) = &mut self.rows {
|
||||
Some(TypedImageViewMut {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn i32_image<'s>(&'s mut self) -> Option<TypedImageViewMut<'s, 'a, I32>> {
|
||||
if let ImageRowsMut::I32(rows) = &mut self.rows {
|
||||
Some(TypedImageViewMut {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn f32_image<'s>(&'s mut self) -> Option<TypedImageViewMut<'s, 'a, F32>> {
|
||||
if let ImageRowsMut::F32(rows) = &mut self.rows {
|
||||
Some(TypedImageViewMut {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn u8_image<'s>(&'s mut self) -> Option<TypedImageViewMut<'s, 'a, U8>> {
|
||||
if let ImageRowsMut::U8(rows) = &mut self.rows {
|
||||
Some(TypedImageViewMut {
|
||||
width: self.width,
|
||||
height: self.height,
|
||||
rows,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn width(&self) -> NonZeroU32 {
|
||||
self.width
|
||||
pub(crate) fn typed_rows<P: Pixel>(&mut self) -> Option<&mut [&'a mut [P]]> {
|
||||
self.rows.typed_rows()
|
||||
}
|
||||
|
||||
#[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)
|
||||
}
|
||||
}
|
||||
|
||||
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> {
|
||||
|
||||
+5
-1
@@ -3,7 +3,9 @@
|
||||
pub use alpha::errors::*;
|
||||
pub use convolution::FilterType;
|
||||
pub use errors::*;
|
||||
pub use image_view::{CropBox, ImageRows, ImageRowsMut, ImageView, ImageViewMut};
|
||||
pub use image_rows::ImageRows;
|
||||
pub use image_rows::ImageRowsMut;
|
||||
pub use image_view::{CropBox, ImageView, ImageViewMut};
|
||||
pub use mul_div::MulDiv;
|
||||
pub use pixels::PixelType;
|
||||
pub use resizer::{CpuExtensions, ResizeAlg, Resizer};
|
||||
@@ -14,9 +16,11 @@ mod alpha;
|
||||
mod convolution;
|
||||
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;
|
||||
|
||||
+13
-29
@@ -1,6 +1,6 @@
|
||||
use crate::alpha::AlphaMulDiv;
|
||||
use crate::image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::{U16x2, U16x4, U8x2, U8x4};
|
||||
use crate::typed_image_view::{TypedImageView, TypedImageViewMut};
|
||||
use crate::{
|
||||
CpuExtensions, ImageView, ImageViewMut, MulDivImageError, MulDivImagesError, PixelType,
|
||||
};
|
||||
@@ -175,11 +175,9 @@ fn assert_images_u8x2<'s, 'd, 'da>(
|
||||
),
|
||||
MulDivImagesError,
|
||||
> {
|
||||
let src_image_u8x2 = src_image
|
||||
.u8x2_image()
|
||||
let src_image_u8x2 = TypedImageView::from_image_view(src_image)
|
||||
.ok_or(MulDivImagesError::UnsupportedPixelType)?;
|
||||
let dst_image_u8x2 = dst_image
|
||||
.u8x2_image()
|
||||
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()
|
||||
@@ -193,9 +191,7 @@ fn assert_images_u8x2<'s, 'd, 'da>(
|
||||
fn assert_image_u8x2<'a, 'b>(
|
||||
image: &'a mut ImageViewMut<'b>,
|
||||
) -> Result<TypedImageViewMut<'a, 'b, U8x2>, MulDivImageError> {
|
||||
image
|
||||
.u8x2_image()
|
||||
.ok_or(MulDivImageError::UnsupportedPixelType)
|
||||
TypedImageViewMut::from_image_view(image).ok_or(MulDivImageError::UnsupportedPixelType)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -209,11 +205,9 @@ fn assert_images_u8x4<'s, 'd, 'da>(
|
||||
),
|
||||
MulDivImagesError,
|
||||
> {
|
||||
let src_image_u8x4 = src_image
|
||||
.u8x4_image()
|
||||
let src_image_u8x4 = TypedImageView::from_image_view(src_image)
|
||||
.ok_or(MulDivImagesError::UnsupportedPixelType)?;
|
||||
let dst_image_u8x4 = dst_image
|
||||
.u8x4_image()
|
||||
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()
|
||||
@@ -227,9 +221,7 @@ fn assert_images_u8x4<'s, 'd, 'da>(
|
||||
fn assert_image_u8x4<'a, 'b>(
|
||||
image: &'a mut ImageViewMut<'b>,
|
||||
) -> Result<TypedImageViewMut<'a, 'b, U8x4>, MulDivImageError> {
|
||||
image
|
||||
.u8x4_image()
|
||||
.ok_or(MulDivImageError::UnsupportedPixelType)
|
||||
TypedImageViewMut::from_image_view(image).ok_or(MulDivImageError::UnsupportedPixelType)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -243,11 +235,9 @@ fn assert_images_u16x2<'s, 'd, 'da>(
|
||||
),
|
||||
MulDivImagesError,
|
||||
> {
|
||||
let src_image_u16x2 = src_image
|
||||
.u16x2_image()
|
||||
let src_image_u16x2 = TypedImageView::from_image_view(src_image)
|
||||
.ok_or(MulDivImagesError::UnsupportedPixelType)?;
|
||||
let dst_image_u16x2 = dst_image
|
||||
.u16x2_image()
|
||||
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()
|
||||
@@ -261,9 +251,7 @@ fn assert_images_u16x2<'s, 'd, 'da>(
|
||||
fn assert_image_u16x2<'a, 'b>(
|
||||
image: &'a mut ImageViewMut<'b>,
|
||||
) -> Result<TypedImageViewMut<'a, 'b, U16x2>, MulDivImageError> {
|
||||
image
|
||||
.u16x2_image()
|
||||
.ok_or(MulDivImageError::UnsupportedPixelType)
|
||||
TypedImageViewMut::from_image_view(image).ok_or(MulDivImageError::UnsupportedPixelType)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -277,11 +265,9 @@ fn assert_images_u16x4<'s, 'd, 'da>(
|
||||
),
|
||||
MulDivImagesError,
|
||||
> {
|
||||
let src_image_u16x4 = src_image
|
||||
.u16x4_image()
|
||||
let src_image_u16x4 = TypedImageView::from_image_view(src_image)
|
||||
.ok_or(MulDivImagesError::UnsupportedPixelType)?;
|
||||
let dst_image_u16x4 = dst_image
|
||||
.u16x4_image()
|
||||
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()
|
||||
@@ -295,9 +281,7 @@ fn assert_images_u16x4<'s, 'd, 'da>(
|
||||
fn assert_image_u16x4<'a, 'b>(
|
||||
image: &'a mut ImageViewMut<'b>,
|
||||
) -> Result<TypedImageViewMut<'a, 'b, U16x4>, MulDivImageError> {
|
||||
image
|
||||
.u16x4_image()
|
||||
.ok_or(MulDivImageError::UnsupportedPixelType)
|
||||
TypedImageViewMut::from_image_view(image).ok_or(MulDivImageError::UnsupportedPixelType)
|
||||
}
|
||||
|
||||
fn multiply_alpha<P>(
|
||||
|
||||
+41
-37
@@ -3,8 +3,9 @@ use std::num::NonZeroU32;
|
||||
use crate::convolution::{self, Convolution, FilterType};
|
||||
use crate::errors::DifferentTypesOfPixelsError;
|
||||
use crate::image::InnerImage;
|
||||
use crate::image_view::{ImageView, ImageViewMut, TypedImageView, TypedImageViewMut};
|
||||
use crate::pixels::{Pixel, PixelType};
|
||||
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};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum CpuExtensions {
|
||||
@@ -83,73 +84,73 @@ impl Resizer {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
PixelType::U8x2 => {
|
||||
if let Some(src_rows) = src_image.u8x2_image() {
|
||||
if let Some(dst_rows) = dst_image.u8x2_image() {
|
||||
self.resize_inner(src_rows, dst_rows);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
PixelType::U8x3 => {
|
||||
if let Some(src_rows) = src_image.u8x3_image() {
|
||||
if let Some(dst_rows) = dst_image.u8x3_image() {
|
||||
self.resize_inner(src_rows, dst_rows);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
PixelType::U8x4 => {
|
||||
if let Some(src_rows) = src_image.u8x4_image() {
|
||||
if let Some(dst_rows) = dst_image.u8x4_image() {
|
||||
self.resize_inner(src_rows, dst_rows);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
PixelType::U16 => {
|
||||
if let Some(src_rows) = src_image.u16_image() {
|
||||
if let Some(dst_rows) = dst_image.u16_image() {
|
||||
self.resize_inner(src_rows, dst_rows);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
PixelType::U16x2 => {
|
||||
if let Some(src_rows) = src_image.u16x2_image() {
|
||||
if let Some(dst_rows) = dst_image.u16x2_image() {
|
||||
self.resize_inner(src_rows, dst_rows);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
PixelType::U16x3 => {
|
||||
if let Some(src_rows) = src_image.u16x3_image() {
|
||||
if let Some(dst_rows) = dst_image.u16x3_image() {
|
||||
self.resize_inner(src_rows, dst_rows);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
PixelType::U16x4 => {
|
||||
if let Some(src_rows) = src_image.u16x4_image() {
|
||||
if let Some(dst_rows) = dst_image.u16x4_image() {
|
||||
self.resize_inner(src_rows, dst_rows);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
PixelType::I32 => {
|
||||
if let Some(src_rows) = src_image.i32_image() {
|
||||
if let Some(dst_rows) = dst_image.i32_image() {
|
||||
self.resize_inner(src_rows, dst_rows);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
PixelType::F32 => {
|
||||
if let Some(src_rows) = src_image.f32_image() {
|
||||
if let Some(dst_rows) = dst_image.f32_image() {
|
||||
self.resize_inner(src_rows, dst_rows);
|
||||
}
|
||||
}
|
||||
}
|
||||
PixelType::U8 => {
|
||||
if let Some(src_rows) = src_image.u8_image() {
|
||||
if let Some(dst_rows) = dst_image.u8_image() {
|
||||
self.resize_inner(src_rows, dst_rows);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -157,10 +158,13 @@ impl Resizer {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn resize_inner<P>(&mut self, src_image: TypedImageView<P>, dst_image: TypedImageViewMut<P>)
|
||||
fn resize_inner<P>(&mut self, src_image: TypedImageView<P>, mut dst_image: TypedImageViewMut<P>)
|
||||
where
|
||||
P: Convolution,
|
||||
{
|
||||
if dst_image.copy_from_view(&src_image).is_ok() {
|
||||
return;
|
||||
}
|
||||
match self.algorithm {
|
||||
ResizeAlg::Nearest => resample_nearest(src_image, dst_image),
|
||||
ResizeAlg::Convolution(filter_type) => {
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
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(())
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use fast_image_resize::pixels::{Pixel, U16x2, U16x4, U8x2, U8x4};
|
||||
use fast_image_resize::{
|
||||
CpuExtensions, Image, ImageRows, ImageRowsMut, ImageView, ImageViewMut, MulDiv, PixelType,
|
||||
};
|
||||
use fast_image_resize::{CpuExtensions, Image, ImageView, ImageViewMut, MulDiv, PixelType};
|
||||
use fast_image_resize::{ImageRows, ImageRowsMut};
|
||||
|
||||
trait IntoImageRows
|
||||
where
|
||||
|
||||
+59
-2
@@ -1,9 +1,10 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use fast_image_resize::pixels::*;
|
||||
use fast_image_resize::{
|
||||
CpuExtensions, DifferentTypesOfPixelsError, FilterType, Image, ImageView, PixelType, ResizeAlg,
|
||||
Resizer,
|
||||
CpuExtensions, CropBox, DifferentTypesOfPixelsError, FilterType, Image, ImageView, PixelType,
|
||||
ResizeAlg, Resizer,
|
||||
};
|
||||
use testing::PixelExt;
|
||||
|
||||
@@ -30,6 +31,62 @@ 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 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);
|
||||
let mut resizer = Resizer::new(ResizeAlg::Convolution(FilterType::Lanczos3));
|
||||
resizer
|
||||
.resize(&src_image.view(), &mut dst_image.view_mut())
|
||||
.unwrap();
|
||||
assert!(matches!(
|
||||
src_image.buffer().cmp(dst_image.buffer()),
|
||||
Ordering::Equal
|
||||
));
|
||||
}
|
||||
|
||||
#[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 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();
|
||||
src_view
|
||||
.set_crop_box(CropBox {
|
||||
top: 10,
|
||||
left: 10,
|
||||
width,
|
||||
height,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let mut dst_image = Image::new(width, height, PixelType::U8);
|
||||
let mut resizer = Resizer::new(ResizeAlg::Convolution(FilterType::Lanczos3));
|
||||
resizer
|
||||
.resize(&src_view, &mut dst_image.view_mut())
|
||||
.unwrap();
|
||||
|
||||
let cropped_buffer: Vec<u8> = (0..12000u32)
|
||||
.filter_map(|v| {
|
||||
let row = v / 120;
|
||||
let col = v % 120;
|
||||
if (10..90u32).contains(&row) && (10..110u32).contains(&col) {
|
||||
Some((v & 0xff) as u8)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let dst_buffer = dst_image.into_vec();
|
||||
assert!(matches!(cropped_buffer.cmp(&dst_buffer), Ordering::Equal));
|
||||
}
|
||||
|
||||
fn downscale_test<P: PixelExt>(resize_alg: ResizeAlg, cpu_extensions: CpuExtensions) -> Vec<u8> {
|
||||
let image = P::load_big_src_image();
|
||||
assert_eq!(image.pixel_type(), P::pixel_type());
|
||||
|
||||
Reference in New Issue
Block a user