diff --git a/CHANGELOG.md b/CHANGELOG.md index 5205036..a3feb98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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`. diff --git a/Cargo.lock b/Cargo.lock index 89e2b14..3ad7fe0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/README.md b/README.md index 0e9cf36..f4cb9bd 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/benchmarks.md b/benchmarks.md index 6103ac1..6f14216 100644 --- a/benchmarks.md +++ b/benchmarks.md @@ -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 | diff --git a/src/alpha/mod.rs b/src/alpha/mod.rs index 375e1ec..6341e40 100644 --- a/src/alpha/mod.rs +++ b/src/alpha/mod.rs @@ -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; diff --git a/src/alpha/u16x2/avx2.rs b/src/alpha/u16x2/avx2.rs index ded6bc6..5d6ea01 100644 --- a/src/alpha/u16x2/avx2.rs +++ b/src/alpha/u16x2/avx2.rs @@ -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; diff --git a/src/alpha/u16x2/mod.rs b/src/alpha/u16x2/mod.rs index 32c6841..43fbb36 100644 --- a/src/alpha/u16x2/mod.rs +++ b/src/alpha/u16x2/mod.rs @@ -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; diff --git a/src/alpha/u16x2/native.rs b/src/alpha/u16x2/native.rs index 3b11632..4644949 100644 --- a/src/alpha/u16x2/native.rs +++ b/src/alpha/u16x2/native.rs @@ -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, diff --git a/src/alpha/u16x2/sse4.rs b/src/alpha/u16x2/sse4.rs index 14f0fd6..670bc9b 100644 --- a/src/alpha/u16x2/sse4.rs +++ b/src/alpha/u16x2/sse4.rs @@ -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; diff --git a/src/alpha/u16x4/avx2.rs b/src/alpha/u16x4/avx2.rs index be8e2ed..21e5ed6 100644 --- a/src/alpha/u16x4/avx2.rs +++ b/src/alpha/u16x4/avx2.rs @@ -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; diff --git a/src/alpha/u16x4/mod.rs b/src/alpha/u16x4/mod.rs index 14a1ef9..3418934 100644 --- a/src/alpha/u16x4/mod.rs +++ b/src/alpha/u16x4/mod.rs @@ -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; diff --git a/src/alpha/u16x4/native.rs b/src/alpha/u16x4/native.rs index 92d5f29..57f06e9 100644 --- a/src/alpha/u16x4/native.rs +++ b/src/alpha/u16x4/native.rs @@ -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, diff --git a/src/alpha/u16x4/sse4.rs b/src/alpha/u16x4/sse4.rs index 0cc4f8b..743fb61 100644 --- a/src/alpha/u16x4/sse4.rs +++ b/src/alpha/u16x4/sse4.rs @@ -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; diff --git a/src/alpha/u8x2/avx2.rs b/src/alpha/u8x2/avx2.rs index e1b2393..ed11b1c 100644 --- a/src/alpha/u8x2/avx2.rs +++ b/src/alpha/u8x2/avx2.rs @@ -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( diff --git a/src/alpha/u8x2/mod.rs b/src/alpha/u8x2/mod.rs index 684d9a3..5104e84 100644 --- a/src/alpha/u8x2/mod.rs +++ b/src/alpha/u8x2/mod.rs @@ -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; diff --git a/src/alpha/u8x2/native.rs b/src/alpha/u8x2/native.rs index 2931245..0302ada 100644 --- a/src/alpha/u8x2/native.rs +++ b/src/alpha/u8x2/native.rs @@ -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, diff --git a/src/alpha/u8x2/sse4.rs b/src/alpha/u8x2/sse4.rs index 4294e7a..d136d69 100644 --- a/src/alpha/u8x2/sse4.rs +++ b/src/alpha/u8x2/sse4.rs @@ -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; diff --git a/src/alpha/u8x4/avx2.rs b/src/alpha/u8x4/avx2.rs index 8d38ac0..d54f5e4 100644 --- a/src/alpha/u8x4/avx2.rs +++ b/src/alpha/u8x4/avx2.rs @@ -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( diff --git a/src/alpha/u8x4/mod.rs b/src/alpha/u8x4/mod.rs index 195ba9e..8f1ec46 100644 --- a/src/alpha/u8x4/mod.rs +++ b/src/alpha/u8x4/mod.rs @@ -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; diff --git a/src/alpha/u8x4/native.rs b/src/alpha/u8x4/native.rs index 4d52d40..4ca4290 100644 --- a/src/alpha/u8x4/native.rs +++ b/src/alpha/u8x4/native.rs @@ -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, diff --git a/src/alpha/u8x4/sse4.rs b/src/alpha/u8x4/sse4.rs index 7daf0c4..26aac50 100644 --- a/src/alpha/u8x4/sse4.rs +++ b/src/alpha/u8x4/sse4.rs @@ -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; diff --git a/src/convolution/f32x1/mod.rs b/src/convolution/f32x1/mod.rs index ccc6d00..716c94a 100644 --- a/src/convolution/f32x1/mod.rs +++ b/src/convolution/f32x1/mod.rs @@ -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 { diff --git a/src/convolution/f32x1/native.rs b/src/convolution/f32x1/native.rs index e44787d..37c0abb 100644 --- a/src/convolution/f32x1/native.rs +++ b/src/convolution/f32x1/native.rs @@ -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, diff --git a/src/convolution/i32x1/mod.rs b/src/convolution/i32x1/mod.rs index f4fbd6c..11380e6 100644 --- a/src/convolution/i32x1/mod.rs +++ b/src/convolution/i32x1/mod.rs @@ -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 { diff --git a/src/convolution/i32x1/native.rs b/src/convolution/i32x1/native.rs index a1d2286..e4dca6a 100644 --- a/src/convolution/i32x1/native.rs +++ b/src/convolution/i32x1/native.rs @@ -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, diff --git a/src/convolution/mod.rs b/src/convolution/mod.rs index b6a5486..58b2dd1 100644 --- a/src/convolution/mod.rs +++ b/src/convolution/mod.rs @@ -1,9 +1,10 @@ use std::num::NonZeroU32; -use crate::image_view::{TypedImageView, TypedImageViewMut}; +pub use filters::{get_filter_func, FilterType}; + use crate::pixels::Pixel; +use crate::typed_image_view::{TypedImageView, TypedImageViewMut}; use crate::CpuExtensions; -pub use filters::{get_filter_func, FilterType}; #[macro_use] mod macros; diff --git a/src/convolution/u16x1/avx2.rs b/src/convolution/u16x1/avx2.rs index 196f436..57eff2e 100644 --- a/src/convolution/u16x1/avx2.rs +++ b/src/convolution/u16x1/avx2.rs @@ -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( diff --git a/src/convolution/u16x1/mod.rs b/src/convolution/u16x1/mod.rs index 82f81cf..c2a8dd0 100644 --- a/src/convolution/u16x1/mod.rs +++ b/src/convolution/u16x1/mod.rs @@ -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; diff --git a/src/convolution/u16x1/native.rs b/src/convolution/u16x1/native.rs index 94c792a..a4ae4eb 100644 --- a/src/convolution/u16x1/native.rs +++ b/src/convolution/u16x1/native.rs @@ -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( diff --git a/src/convolution/u16x1/sse4.rs b/src/convolution/u16x1/sse4.rs index 50165e4..c6412c1 100644 --- a/src/convolution/u16x1/sse4.rs +++ b/src/convolution/u16x1/sse4.rs @@ -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( diff --git a/src/convolution/u16x2/avx2.rs b/src/convolution/u16x2/avx2.rs index cd7b191..78a125e 100644 --- a/src/convolution/u16x2/avx2.rs +++ b/src/convolution/u16x2/avx2.rs @@ -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( diff --git a/src/convolution/u16x2/mod.rs b/src/convolution/u16x2/mod.rs index 3212aea..05787d2 100644 --- a/src/convolution/u16x2/mod.rs +++ b/src/convolution/u16x2/mod.rs @@ -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; diff --git a/src/convolution/u16x2/native.rs b/src/convolution/u16x2/native.rs index 1ff5e39..e606cc8 100644 --- a/src/convolution/u16x2/native.rs +++ b/src/convolution/u16x2/native.rs @@ -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( diff --git a/src/convolution/u16x2/sse4.rs b/src/convolution/u16x2/sse4.rs index 8e7ab7c..fb12817 100644 --- a/src/convolution/u16x2/sse4.rs +++ b/src/convolution/u16x2/sse4.rs @@ -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( diff --git a/src/convolution/u16x3/avx2.rs b/src/convolution/u16x3/avx2.rs index 6b185c9..f97ff3c 100644 --- a/src/convolution/u16x3/avx2.rs +++ b/src/convolution/u16x3/avx2.rs @@ -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( diff --git a/src/convolution/u16x3/mod.rs b/src/convolution/u16x3/mod.rs index cad08c7..9f8e12c 100644 --- a/src/convolution/u16x3/mod.rs +++ b/src/convolution/u16x3/mod.rs @@ -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; diff --git a/src/convolution/u16x3/native.rs b/src/convolution/u16x3/native.rs index b717dc8..78323a1 100644 --- a/src/convolution/u16x3/native.rs +++ b/src/convolution/u16x3/native.rs @@ -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( diff --git a/src/convolution/u16x3/sse4.rs b/src/convolution/u16x3/sse4.rs index 220aaf8..f067d7f 100644 --- a/src/convolution/u16x3/sse4.rs +++ b/src/convolution/u16x3/sse4.rs @@ -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( diff --git a/src/convolution/u16x4/avx2.rs b/src/convolution/u16x4/avx2.rs index 3211376..dbc6c6d 100644 --- a/src/convolution/u16x4/avx2.rs +++ b/src/convolution/u16x4/avx2.rs @@ -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( diff --git a/src/convolution/u16x4/mod.rs b/src/convolution/u16x4/mod.rs index 4f4afca..79c4777 100644 --- a/src/convolution/u16x4/mod.rs +++ b/src/convolution/u16x4/mod.rs @@ -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; diff --git a/src/convolution/u16x4/native.rs b/src/convolution/u16x4/native.rs index 55cbdf3..b25f1df 100644 --- a/src/convolution/u16x4/native.rs +++ b/src/convolution/u16x4/native.rs @@ -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( diff --git a/src/convolution/u16x4/sse4.rs b/src/convolution/u16x4/sse4.rs index 487079b..0ab7865 100644 --- a/src/convolution/u16x4/sse4.rs +++ b/src/convolution/u16x4/sse4.rs @@ -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( diff --git a/src/convolution/u8x1/avx2.rs b/src/convolution/u8x1/avx2.rs index 15f05be..02c56ae 100644 --- a/src/convolution/u8x1/avx2.rs +++ b/src/convolution/u8x1/avx2.rs @@ -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( diff --git a/src/convolution/u8x1/mod.rs b/src/convolution/u8x1/mod.rs index d851225..d7cc461 100644 --- a/src/convolution/u8x1/mod.rs +++ b/src/convolution/u8x1/mod.rs @@ -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; diff --git a/src/convolution/u8x1/native.rs b/src/convolution/u8x1/native.rs index a4b0883..1755ea2 100644 --- a/src/convolution/u8x1/native.rs +++ b/src/convolution/u8x1/native.rs @@ -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( diff --git a/src/convolution/u8x2/avx2.rs b/src/convolution/u8x2/avx2.rs index 528191c..f89c53b 100644 --- a/src/convolution/u8x2/avx2.rs +++ b/src/convolution/u8x2/avx2.rs @@ -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( diff --git a/src/convolution/u8x2/mod.rs b/src/convolution/u8x2/mod.rs index 0833e84..db47a71 100644 --- a/src/convolution/u8x2/mod.rs +++ b/src/convolution/u8x2/mod.rs @@ -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}; diff --git a/src/convolution/u8x2/native.rs b/src/convolution/u8x2/native.rs index d5b986b..5cb21cd 100644 --- a/src/convolution/u8x2/native.rs +++ b/src/convolution/u8x2/native.rs @@ -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, diff --git a/src/convolution/u8x2/sse4.rs b/src/convolution/u8x2/sse4.rs index b4551aa..a71d807 100644 --- a/src/convolution/u8x2/sse4.rs +++ b/src/convolution/u8x2/sse4.rs @@ -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( diff --git a/src/convolution/u8x3/avx2.rs b/src/convolution/u8x3/avx2.rs index c82b213..0dbfdde 100644 --- a/src/convolution/u8x3/avx2.rs +++ b/src/convolution/u8x3/avx2.rs @@ -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( diff --git a/src/convolution/u8x3/mod.rs b/src/convolution/u8x3/mod.rs index 6215d27..766eb0f 100644 --- a/src/convolution/u8x3/mod.rs +++ b/src/convolution/u8x3/mod.rs @@ -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; diff --git a/src/convolution/u8x3/native.rs b/src/convolution/u8x3/native.rs index 03c76aa..630e0a5 100644 --- a/src/convolution/u8x3/native.rs +++ b/src/convolution/u8x3/native.rs @@ -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( diff --git a/src/convolution/u8x3/sse4.rs b/src/convolution/u8x3/sse4.rs index 6286829..b10bf9a 100644 --- a/src/convolution/u8x3/sse4.rs +++ b/src/convolution/u8x3/sse4.rs @@ -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; diff --git a/src/convolution/u8x4/avx2.rs b/src/convolution/u8x4/avx2.rs index 5816969..b77dcca 100644 --- a/src/convolution/u8x4/avx2.rs +++ b/src/convolution/u8x4/avx2.rs @@ -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 diff --git a/src/convolution/u8x4/mod.rs b/src/convolution/u8x4/mod.rs index c4be673..3601a4f 100644 --- a/src/convolution/u8x4/mod.rs +++ b/src/convolution/u8x4/mod.rs @@ -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; diff --git a/src/convolution/u8x4/native.rs b/src/convolution/u8x4/native.rs index 8c8e05f..fc7e581 100644 --- a/src/convolution/u8x4/native.rs +++ b/src/convolution/u8x4/native.rs @@ -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, diff --git a/src/convolution/u8x4/sse4.rs b/src/convolution/u8x4/sse4.rs index 50e5d81..a6c5d2e 100644 --- a/src/convolution/u8x4/sse4.rs +++ b/src/convolution/u8x4/sse4.rs @@ -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 diff --git a/src/convolution/vertical_u16/avx2.rs b/src/convolution/vertical_u16/avx2.rs index 2ae4ba8..ea72b26 100644 --- a/src/convolution/vertical_u16/avx2.rs +++ b/src/convolution/vertical_u16/avx2.rs @@ -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( src_image: TypedImageView, diff --git a/src/convolution/vertical_u16/mod.rs b/src/convolution/vertical_u16/mod.rs index cdd5a51..79696f9 100644 --- a/src/convolution/vertical_u16/mod.rs +++ b/src/convolution/vertical_u16/mod.rs @@ -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")] diff --git a/src/convolution/vertical_u16/native.rs b/src/convolution/vertical_u16/native.rs index 34a6117..f7d93f7 100644 --- a/src/convolution/vertical_u16/native.rs +++ b/src/convolution/vertical_u16/native.rs @@ -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>( diff --git a/src/convolution/vertical_u16/sse4.rs b/src/convolution/vertical_u16/sse4.rs index 8040736..4cfd108 100644 --- a/src/convolution/vertical_u16/sse4.rs +++ b/src/convolution/vertical_u16/sse4.rs @@ -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>( src_image: TypedImageView, diff --git a/src/convolution/vertical_u8/avx2.rs b/src/convolution/vertical_u8/avx2.rs index 53bca5b..160c511 100644 --- a/src/convolution/vertical_u8/avx2.rs +++ b/src/convolution/vertical_u8/avx2.rs @@ -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( diff --git a/src/convolution/vertical_u8/mod.rs b/src/convolution/vertical_u8/mod.rs index 6c4a6f5..4857503 100644 --- a/src/convolution/vertical_u8/mod.rs +++ b/src/convolution/vertical_u8/mod.rs @@ -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")] diff --git a/src/convolution/vertical_u8/native.rs b/src/convolution/vertical_u8/native.rs index 5ef3ee8..83307b4 100644 --- a/src/convolution/vertical_u8/native.rs +++ b/src/convolution/vertical_u8/native.rs @@ -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( diff --git a/src/convolution/vertical_u8/sse4.rs b/src/convolution/vertical_u8/sse4.rs index a3cf4f8..323a3fd 100644 --- a/src/convolution/vertical_u8/sse4.rs +++ b/src/convolution/vertical_u8/sse4.rs @@ -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>( diff --git a/src/errors.rs b/src/errors.rs index b919e33..3b6d414 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -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; diff --git a/src/image.rs b/src/image.rs index f3192ac..ed6f371 100644 --- a/src/image.rs +++ b/src/image.rs @@ -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)] diff --git a/src/image_rows.rs b/src/image_rows.rs new file mode 100644 index 0000000..b1672e7 --- /dev/null +++ b/src/image_rows.rs @@ -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(&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(&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( + 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> 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); diff --git a/src/image_view.rs b/src/image_view.rs index 0ef2d17..f87a2a0 100644 --- a/src/image_view.rs +++ b/src/image_view.rs @@ -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> 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(&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> { - 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> { - 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> { - 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> { - 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> { - 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> { - 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> { - 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> { - 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> { - 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> { - 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> + '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> + '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 + '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 + '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> { - 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> { - 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> { - 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> { - 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> { - 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> { - 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> { - 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> { - 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> { - 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> { - 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 - } - - #[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> { - 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> { - self.rows.get_mut(y as usize) - } -} - -fn check_rows_count_and_size( - 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); + pub(crate) fn typed_rows(&mut self) -> Option<&mut [&'a mut [P]]> { + self.rows.typed_rows() } - Ok(()) } fn align_buffer_to(buffer: &[u8]) -> Result<&[T], ImageBufferError> { diff --git a/src/lib.rs b/src/lib.rs index df1ebbd..b18e568 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; diff --git a/src/mul_div.rs b/src/mul_div.rs index db52121..8f68489 100644 --- a/src/mul_div.rs +++ b/src/mul_div.rs @@ -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, 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, 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, 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, MulDivImageError> { - image - .u16x4_image() - .ok_or(MulDivImageError::UnsupportedPixelType) + TypedImageViewMut::from_image_view(image).ok_or(MulDivImageError::UnsupportedPixelType) } fn multiply_alpha

( diff --git a/src/resizer.rs b/src/resizer.rs index 901d071..56e1e2b 100644 --- a/src/resizer.rs +++ b/src/resizer.rs @@ -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::(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::(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::(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::(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::(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::(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::(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::(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::(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::(src, dst); } } } @@ -157,10 +158,13 @@ impl Resizer { Ok(()) } - fn resize_inner

(&mut self, src_image: TypedImageView

, dst_image: TypedImageViewMut

) + fn resize_inner

(&mut self, src_image: TypedImageView

, mut dst_image: TypedImageViewMut

) 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) => { diff --git a/src/typed_image_view.rs b/src/typed_image_view.rs new file mode 100644 index 0000000..fd86299 --- /dev/null +++ b/src/typed_image_view.rs @@ -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 { + 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> + '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> + '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 + '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 + '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 + '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 { + 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> { + 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> { + 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

, + ) -> 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(()) + } +} diff --git a/tests/alpha_tests.rs b/tests/alpha_tests.rs index a7a6163..81301ac 100644 --- a/tests/alpha_tests.rs +++ b/tests/alpha_tests.rs @@ -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 diff --git a/tests/resize_tests.rs b/tests/resize_tests.rs index 1cd2e80..e24df94 100644 --- a/tests/resize_tests.rs +++ b/tests/resize_tests.rs @@ -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 = (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 = (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 = (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(resize_alg: ResizeAlg, cpu_extensions: CpuExtensions) -> Vec { let image = P::load_big_src_image(); assert_eq!(image.pixel_type(), P::pixel_type());