From 9561a3c0df864693f06d69abfbcfdcdb2bf61cef Mon Sep 17 00:00:00 2001 From: Radzivon Bartoshyk Date: Wed, 6 Nov 2024 10:07:17 +0000 Subject: [PATCH] Bench --- Cargo.lock | 407 +++++++++++++++++++++++++++++++++++++--- app/Cargo.toml | 11 +- app/benches/rdp/main.rs | 330 ++++++++++++++++++++++++++++++++ app/src/main.rs | 103 +++++----- src/images.rs | 50 ++++- src/lib.rs | 3 +- src/yuv_error.rs | 47 +++++ src/yuy2_to_yuv.rs | 159 ++++++++-------- src/yuy2_to_yuv_p16.rs | 161 ++++++++-------- 9 files changed, 1018 insertions(+), 253 deletions(-) create mode 100644 app/benches/rdp/main.rs diff --git a/Cargo.lock b/Cargo.lock index 4181e4d..1d65970 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,12 +8,33 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "aligned-vec" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + [[package]] name = "anyhow" version = "1.0.86" @@ -24,6 +45,7 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" name = "app" version = "0.1.0" dependencies = [ + "criterion", "image", "yuvutils-rs", ] @@ -47,9 +69,9 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "autocfg" @@ -73,9 +95,9 @@ dependencies = [ [[package]] name = "avif-serialize" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2" +checksum = "e335041290c43101ca215eed6f43ec437eb5a42125573f600fc3fa42b9bddd62" dependencies = [ "arrayvec", ] @@ -116,18 +138,18 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78834c15cb5d5efe3452d58b1e8ba890dd62d21907f867f383358198e56ebca5" -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "byteorder-lite" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cc" version = "1.0.99" @@ -155,6 +177,58 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clap" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +dependencies = [ + "anstyle", + "clap_lex", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + [[package]] name = "color_quant" version = "1.1.0" @@ -170,6 +244,42 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "criterion" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "is-terminal", + "itertools 0.10.5", + "num-traits", + "once_cell", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools 0.10.5", +] + [[package]] name = "crossbeam-deque" version = "0.8.5" @@ -300,14 +410,20 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + [[package]] name = "image" -version = "0.25.1" +version = "0.25.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd54d660e773627692c524beaad361aca785a4f9f5730ce91f42aabe5bce3d11" +checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" dependencies = [ "bytemuck", - "byteorder", + "byteorder-lite", "color_quant", "exr", "gif", @@ -325,12 +441,12 @@ dependencies = [ [[package]] name = "image-webp" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d730b085583c4d789dfd07fdcf185be59501666a90c97c40162b37e4fdad272d" +checksum = "e031e8e3d94711a9ccb5d6ea357439ef3dcbed361798bd4071dc4d9793fbe22f" dependencies = [ "byteorder-lite", - "thiserror", + "quick-error", ] [[package]] @@ -360,6 +476,26 @@ dependencies = [ "syn", ] +[[package]] +name = "is-terminal" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.12.1" @@ -369,6 +505,12 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + [[package]] name = "jobserver" version = "0.1.31" @@ -384,6 +526,15 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lebe" version = "0.5.2" @@ -542,6 +693,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "oorandom" +version = "11.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" + [[package]] name = "paste" version = "1.0.15" @@ -554,6 +711,34 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "plotters" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] + [[package]] name = "png" version = "0.17.13" @@ -669,7 +854,7 @@ dependencies = [ "built", "cfg-if", "interpolate_name", - "itertools", + "itertools 0.12.1", "libc", "libfuzzer-sys", "log", @@ -692,9 +877,9 @@ dependencies = [ [[package]] name = "ravif" -version = "0.11.5" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc13288f5ab39e6d7c9d501759712e6969fcc9734220846fc9ed26cae2cc4234" +checksum = "2413fd96bd0ea5cdeeb37eaf446a22e6ed7b981d792828721e74ded1980a45c6" dependencies = [ "avif-serialize", "imgref", @@ -725,13 +910,54 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + [[package]] name = "rgb" -version = "0.8.37" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ - "bytemuck", + "winapi-util", ] [[package]] @@ -760,6 +986,18 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + [[package]] name = "serde_spanned" version = "0.6.6" @@ -860,6 +1098,16 @@ dependencies = [ "weezl", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "toml" version = "0.8.14" @@ -917,6 +1165,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -977,12 +1235,113 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "weezl" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "winnow" version = "0.6.13" @@ -1017,9 +1376,9 @@ dependencies = [ [[package]] name = "zune-jpeg" -version = "0.4.11" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec866b44a2a1fd6133d363f073ca1b179f438f99e7e5bfb1e33f7181facfe448" +checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768" dependencies = [ "zune-core", ] diff --git a/app/Cargo.toml b/app/Cargo.toml index 3da7f7f..b4bb173 100644 --- a/app/Cargo.toml +++ b/app/Cargo.toml @@ -4,5 +4,12 @@ version = "0.1.0" edition = "2021" [dependencies] -yuvutils-rs = { path = "..", features = ["rdp", "rayon"] } -image = "0.25.1" \ No newline at end of file +yuvutils-rs = { path = "..", features = ["rdp"] } +image = "0.25.5" + +[dev-dependencies] +criterion = "0.5.1" + +[[bench]] +name = "rdp" +harness = false diff --git a/app/benches/rdp/main.rs b/app/benches/rdp/main.rs new file mode 100644 index 0000000..40c789c --- /dev/null +++ b/app/benches/rdp/main.rs @@ -0,0 +1,330 @@ +/* + * Copyright (c) Radzivon Bartoshyk, 10/2024. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +use criterion::{criterion_group, criterion_main, Criterion}; +use image::{EncodableLayout, GenericImageView, ImageReader}; +use std::cmp::min; +use std::io::{self, Write}; +use yuvutils_rs::{rdp_rgb_to_yuv444, YuvChromaSubsample, YuvPlanarImageMut}; + +const ALPHA: u8 = 255; + +pub fn ycbcr_to_bgra(input: YCbCrBuffer<'_>, mut output: &mut [u8]) -> io::Result<()> { + for ycbcr in input { + let pixel = Rgb::from(ycbcr); + + output.write_all(&[pixel.b, pixel.g, pixel.r, ALPHA])?; + } + + Ok(()) +} + +fn iter_to_ycbcr<'a, I, C>(input: I, y: &mut [i16], cb: &mut [i16], cr: &mut [i16], conv: C) +where + I: ExactSizeIterator, + C: Fn(&[u8]) -> Rgb, +{ + for (i, pixel) in input.into_iter().enumerate() { + let pixel = YCbCr::from(conv(pixel)); + + y[i] = pixel.y; + cb[i] = pixel.cb; + cr[i] = pixel.cr; + } +} + +fn rgbx_to_rgb(pixel: &[u8]) -> Rgb { + Rgb { + r: pixel[0], + g: pixel[1], + b: pixel[2], + } +} + +const fn pixel_format_to_rgb_fn() -> fn(&[u8]) -> Rgb { + rgbx_to_rgb +} + +#[allow(clippy::too_many_arguments)] +pub fn to_ycbcr( + mut input: &[u8], + width: usize, + height: usize, + stride: usize, + mut y: &mut [i16], + mut cb: &mut [i16], + mut cr: &mut [i16], +) { + let to_rgb = pixel_format_to_rgb_fn(); + let bpp = 4; + + for _ in 0..height { + iter_to_ycbcr(input[..width * bpp].chunks_exact(bpp), y, cb, cr, to_rgb); + input = &input[stride..]; + y = &mut y[width..]; + cb = &mut cb[width..]; + cr = &mut cr[width..]; + } +} + +struct TileIterator<'a> { + slice: &'a [u8], + x: usize, + y: usize, + width: usize, + height: usize, + stride: usize, + bpp: usize, +} + +impl<'a> TileIterator<'a> { + fn new(slice: &'a [u8], width: usize, height: usize, stride: usize, bpp: usize) -> Self { + assert!(width >= 1); + assert!(height >= 1); + + Self { + slice, + x: 0, + y: 0, + width, + height, + stride, + bpp, + } + } +} + +impl<'a> Iterator for TileIterator<'a> { + type Item = &'a [u8]; + + fn next(&mut self) -> Option { + // create 64x64 tiles + if self.y >= 64 { + return None; + } + + // repeat the last column & line if necessary + let y = min(self.y, self.height - 1); + let x = min(self.x, self.width - 1); + let pos = y * self.stride + x * self.bpp; + + self.x += 1; + if self.x >= 64 { + self.x = 0; + self.y += 1; + } + + Some(&self.slice[pos..pos + self.bpp]) + } +} + +impl ExactSizeIterator for TileIterator<'_> { + fn len(&self) -> usize { + 64 * 64 + } +} + +#[allow(clippy::too_many_arguments)] +pub fn to_64x64_ycbcr_tile( + input: &[u8], + width: usize, + height: usize, + stride: usize, + y: &mut [i16], + cb: &mut [i16], + cr: &mut [i16], +) { + let bpp = 8; + + let input = TileIterator::new(input, width, height, stride, bpp); + iter_to_ycbcr(input, y, cb, cr, rgbx_to_rgb) +} + +/// Convert a 16-bit RDP color to RGB representation. Input value should be represented in +/// little-endian format. +pub fn rdp_16bit_to_rgb(color: u16) -> [u8; 3] { + let r = (((((color >> 11) & 0x1f) * 527) + 23) >> 6) as u8; + let g = (((((color >> 5) & 0x3f) * 259) + 33) >> 6) as u8; + let b = ((((color & 0x1f) * 527) + 23) >> 6) as u8; + [r, g, b] +} + +fn clip(v: i32) -> u8 { + v.clamp(0, 255) as u8 +} + +#[derive(Debug)] +pub struct YCbCrBuffer<'a> { + pub y: &'a [i16], + pub cb: &'a [i16], + pub cr: &'a [i16], +} + +impl Iterator for YCbCrBuffer<'_> { + type Item = YCbCr; + + fn next(&mut self) -> Option { + if !self.y.is_empty() && !self.cb.is_empty() && !self.cr.is_empty() { + let y = self.y[0]; + let cb = self.cb[0]; + let cr = self.cr[0]; + + self.y = &self.y[1..]; + self.cb = &self.cb[1..]; + self.cr = &self.cr[1..]; + + Some(YCbCr { y, cb, cr }) + } else { + None + } + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct YCbCr { + pub y: i16, + pub cb: i16, + pub cr: i16, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub struct Rgb { + pub r: u8, + pub g: u8, + pub b: u8, +} + +impl From for Rgb { + fn from(YCbCr { y, cb, cr }: YCbCr) -> Self { + // We scale the factors by << 16 into 32-bit integers in order to + // avoid slower floating point multiplications. Since the final + // result needs to be scaled by >> 5 we will extract only the + // upper 11 bits (>> 21) from the final sum. + // Hence we also have to scale the other terms of the sum by << 16. + const DIVISOR: f32 = (1 << 16) as f32; + + let y = i32::from(y); + let cb = i32::from(cb); + let cr = i32::from(cr); + + let yy = (y + 4096) << 16; + let cr_r = cr.overflowing_mul((1.402_525 * DIVISOR) as i32).0; + let cb_g = cb.overflowing_mul((0.343_730 * DIVISOR) as i32).0; + let cr_g = cr.overflowing_mul((0.714_401 * DIVISOR) as i32).0; + let cb_b = cb.overflowing_mul((1.769_905 * DIVISOR) as i32).0; + let cr_b = cb.overflowing_mul((0.000_013 * DIVISOR) as i32).0; + + let r = clip((yy.overflowing_add(cr_r).0) >> 21); + let g = clip((yy.overflowing_sub(cb_g).0.overflowing_sub(cr_g).0) >> 21); + let b = clip((yy.overflowing_add(cb_b).0.overflowing_add(cr_b).0) >> 21); + + Self { r, g, b } + } +} + +impl From for YCbCr { + fn from(Rgb { r, g, b }: Rgb) -> Self { + // We scale the factors by << 15 into 32-bit integers in order + // to avoid slower floating point multiplications. Since the + // terms need to be scaled by << 5 we simply scale the final + // sum by >> 10 + const DIVISOR: f32 = (1 << 15) as f32; + const Y_R: i32 = (0.299 * DIVISOR) as i32; + const Y_G: i32 = (0.587 * DIVISOR) as i32; + const Y_B: i32 = (0.114 * DIVISOR) as i32; + const CB_R: i32 = (0.168_935 * DIVISOR) as i32; + const CB_G: i32 = (0.331_665 * DIVISOR) as i32; + const CB_B: i32 = (0.500_59 * DIVISOR) as i32; + const CR_R: i32 = (0.499_813 * DIVISOR) as i32; + const CR_G: i32 = (0.418_531 * DIVISOR) as i32; + const CR_B: i32 = (0.081_282 * DIVISOR) as i32; + + let r = i32::from(r); + let g = i32::from(g); + let b = i32::from(b); + + let y_r = r.overflowing_mul(Y_R).0; + let y_g = g.overflowing_mul(Y_G).0; + let y_b = b.overflowing_mul(Y_B).0; + let y = y_r.overflowing_add(y_g).0.overflowing_add(y_b).0 >> 10; + + let cb_r = r.overflowing_mul(CB_R).0; + let cb_g = g.overflowing_mul(CB_G).0; + let cb_b = b.overflowing_mul(CB_B).0; + let cb = cb_b.overflowing_sub(cb_g).0.overflowing_sub(cb_r).0 >> 10; + + let cr_r = r.overflowing_mul(CR_R).0; + let cr_g = g.overflowing_mul(CR_G).0; + let cr_b = b.overflowing_mul(CR_B).0; + let cr = cr_r.overflowing_sub(cr_g).0.overflowing_sub(cr_b).0 >> 10; + + Self { + y: (y - 4096).clamp(-4096, 4095) as i16, + cb: cb.clamp(-4096, 4095) as i16, + cr: cr.clamp(-4096, 4095) as i16, + } + } +} + +pub fn criterion_benchmark(c: &mut Criterion) { + let img = ImageReader::open("../assets/main_test.jpg") + .unwrap() + .decode() + .unwrap(); + let dimensions = img.dimensions(); + let binding = img.to_rgba8(); + let src_bytes = binding.as_bytes(); + + c.bench_function("Rdp", |b| { + b.iter(|| { + let mut plane = + YuvPlanarImageMut::alloc(dimensions.0, dimensions.1, YuvChromaSubsample::Yuv444); + rdp_rgb_to_yuv444(&mut plane, src_bytes, dimensions.0 * 4).unwrap(); + }) + }); + + c.bench_function("IronRdp", |b| { + b.iter(|| { + let mut plane = + YuvPlanarImageMut::alloc(dimensions.0, dimensions.1, YuvChromaSubsample::Yuv444); + to_ycbcr( + src_bytes, + dimensions.0 as usize, + dimensions.1 as usize, + dimensions.0 as usize * 4, + plane.y_plane.borrow_mut(), + plane.u_plane.borrow_mut(), + plane.v_plane.borrow_mut(), + ); + }) + }); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/app/src/main.rs b/app/src/main.rs index cf546bf..12bf4a5 100644 --- a/app/src/main.rs +++ b/app/src/main.rs @@ -34,15 +34,8 @@ use std::io::Read; use std::ops::Sub; use std::time::Instant; use yuvutils_rs::{ - gbr_to_rgb, rdp_rgb_to_yuv444, rdp_yuv444_to_rgb, rgb_to_gbr, rgb_to_sharp_yuv420, - rgb_to_yuv420, rgb_to_yuv420_p16, rgb_to_yuv422, rgb_to_yuv422_p16, rgb_to_yuv444, - rgb_to_yuv444_p16, rgb_to_yuv_nv12, rgb_to_yuv_nv12_p16, rgb_to_yuv_nv16, rgb_to_yuv_nv16_p16, - rgb_to_yuv_nv24, rgb_to_yuv_nv24_p16, rgb_to_yuv_nv61_p16, yuv420_p16_to_rgb16, yuv420_to_rgb, - yuv422_p16_to_rgb16, yuv422_to_rgb, yuv444_p16_to_rgb16, yuv444_to_rgb, yuv_nv12_to_rgb, - yuv_nv12_to_rgb_p16, yuv_nv12_to_rgba, yuv_nv16_to_rgb, yuv_nv16_to_rgb_p16, yuv_nv24_to_rgb, - yuv_nv24_to_rgb_p16, yuv_nv61_to_rgb_p16, SharpYuvGammaTransfer, YuvBiPlanarImageMut, - YuvBytesPacking, YuvChromaSubsample, YuvEndianness, YuvPlanarImage, YuvPlanarImageMut, - YuvRange, YuvStandardMatrix, + rgb_to_yuv444, yuv444_to_yuyv422, yuyv422_to_rgb, yuyv422_to_yuv444, YuvBiPlanarImageMut, + YuvChromaSubsample, YuvPackedImage, YuvPlanarImageMut, YuvRange, YuvStandardMatrix, }; fn read_file_bytes(file_path: &str) -> Result, String> { @@ -98,12 +91,19 @@ fn main() { YuvBiPlanarImageMut::::alloc(width as u32, height as u32, YuvChromaSubsample::Yuv420); let mut planar_image = - YuvPlanarImageMut::::alloc(width as u32, height as u32, YuvChromaSubsample::Yuv444); + YuvPlanarImageMut::::alloc(width as u32, height as u32, YuvChromaSubsample::Yuv444); // let mut bytes_16: Vec = src_bytes.iter().map(|&x| (x as u16) << 2).collect(); let start_time = Instant::now(); - rdp_rgb_to_yuv444(&mut planar_image, &src_bytes, rgba_stride as u32).unwrap(); + rgb_to_yuv444( + &mut planar_image, + &src_bytes, + rgba_stride as u32, + YuvRange::Limited, + YuvStandardMatrix::Bt601, + ) + .unwrap(); // bytes_16.fill(0); // println!("rgb_to_yuv_nv12 time: {:?}", start_time.elapsed()); @@ -111,68 +111,55 @@ fn main() { let end_time = Instant::now().sub(start_time); println!("Forward time: {:?}", end_time); // // - // let full_size = if width % 2 == 0 { - // 2 * width as usize * height as usize - // } else { - // 2 * (width as usize + 1) * height as usize - // }; + let full_size = if width % 2 == 0 { + 2 * width as usize * height as usize + } else { + 2 * (width as usize + 1) * height as usize + }; // // // println!("Full YUY2 {}", full_size); // - // let yuy2_stride = if width % 2 == 0 { - // 2 * width as usize - // } else { - // 2 * (width as usize + 1) - // }; - // - // let mut yuy2_plane = vec![0u8; full_size]; + let yuy2_stride = if width % 2 == 0 { + 2 * width as usize + } else { + 2 * (width as usize + 1) + }; + + let mut yuy2_plane = vec![0u8; full_size]; // // // let start_time = Instant::now(); // // - // yuv420_to_yuyv422( - // &y_plane, - // y_stride as u32, - // &u_plane, - // y_stride as u32, - // &v_plane, - // y_stride as u32, - // &mut yuy2_plane, - // yuy2_stride as u32, - // width, - // height, - // ); + let plane = planar_image.to_fixed(); + yuv444_to_yuyv422(&plane, &mut yuy2_plane, yuy2_stride as u32).unwrap(); // let end_time = Instant::now().sub(start_time); // println!("yuv420_to_yuyv422 time: {:?}", end_time); // rgba.fill(0); // let start_time = Instant::now(); - // yuyv422_to_rgb( - // &yuy2_plane, - // yuy2_stride as u32, - // &mut rgba, - // rgba_stride as u32, - // width, - // height, - // YuvRange::TV, - // YuvStandardMatrix::Bt709, - // ); + yuyv422_to_rgb( + &yuy2_plane, + yuy2_stride as u32, + &mut rgba, + rgba_stride as u32, + width, + height, + YuvRange::Limited, + YuvStandardMatrix::Bt709, + ); // // let end_time = Instant::now().sub(start_time); // println!("yuyv422_to_rgb time: {:?}", end_time); // let start_time = Instant::now(); // - // yuyv422_to_yuv420( - // &mut y_plane, - // y_stride as u32, - // &mut u_plane, - // y_stride as u32, - // &mut v_plane, - // y_stride as u32, - // &yuy2_plane, - // yuy2_stride as u32, - // width, - // height, - // ); + + let packed_image = YuvPackedImage { + yuy: &yuy2_plane, + yuy_stride: yuy2_stride as u32, + width, + height, + }; + + yuyv422_to_yuv444(&mut planar_image, &packed_image).unwrap(); // // let end_time = Instant::now().sub(start_time); // println!("yuyv422_to_yuv444 time: {:?}", end_time); @@ -201,7 +188,7 @@ fn main() { // bytes_16.fill(0); let start_time = Instant::now(); - rdp_yuv444_to_rgb(&fixed_planar, &mut rgba, rgba_stride as u32).unwrap(); + // yuv444_to_rgb(&fixed_planar, &mut rgba, rgba_stride as u32, YuvRange::Limited, YuvStandardMatrix::Bt601).unwrap(); println!("Backward time: {:?}", start_time.elapsed()); diff --git a/src/images.rs b/src/images.rs index 3171be0..e7f11b7 100644 --- a/src/images.rs +++ b/src/images.rs @@ -26,7 +26,9 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -use crate::yuv_error::{check_chroma_channel, check_interleaved_chroma_channel, check_y8_channel}; +use crate::yuv_error::{ + check_chroma_channel, check_interleaved_chroma_channel, check_y8_channel, check_yuv_packed, +}; use crate::yuv_support::YuvChromaSubsample; use crate::YuvError; use std::fmt::Debug; @@ -465,3 +467,49 @@ where Ok(()) } } + +#[derive(Debug)] +/// Non-mutable representation of Packed YUV image +pub struct YuvPackedImage<'a, T> +where + T: Copy + Debug, +{ + pub yuy: &'a [T], + /// Stride here always means components per row. + pub yuy_stride: u32, + pub width: u32, + pub height: u32, +} + +impl YuvPackedImage<'_, T> +where + T: Copy + Debug, +{ + pub fn check_constraints(&self) -> Result<(), YuvError> { + check_yuv_packed(self.yuy, self.yuy_stride, self.width, self.height)?; + Ok(()) + } +} + +#[derive(Debug)] +/// Mutable representation of Packed YUV image +pub struct YuvPackedImageMut<'a, T> +where + T: Copy + Debug, +{ + pub yuy: BufferStoreMut<'a, T>, + /// Stride here always means components per row. + pub yuy_stride: u32, + pub width: u32, + pub height: u32, +} + +impl YuvPackedImageMut<'_, T> +where + T: Copy + Debug, +{ + pub fn check_constraints(&self) -> Result<(), YuvError> { + check_yuv_packed(self.yuy.borrow(), self.yuy_stride, self.width, self.height)?; + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index 67117ec..8e9e926 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -422,7 +422,8 @@ pub use sharpyuv::SharpYuvGammaTransfer; pub use images::{ BufferStoreMut, YuvBiPlanarImage, YuvBiPlanarImageMut, YuvGrayAlphaImage, YuvGrayImage, - YuvGrayImageMut, YuvPlanarImage, YuvPlanarImageMut, YuvPlanarImageWithAlpha, + YuvGrayImageMut, YuvPackedImage, YuvPackedImageMut, YuvPlanarImage, YuvPlanarImageMut, + YuvPlanarImageWithAlpha, }; #[cfg(feature = "rdp")] pub use rdp::*; diff --git a/src/yuv_error.rs b/src/yuv_error.rs index 5e61423..c1bad65 100644 --- a/src/yuv_error.rs +++ b/src/yuv_error.rs @@ -46,11 +46,20 @@ pub enum YuvError { LumaPlaneMinimumSizeMismatch(MismatchedSize), ChromaPlaneMinimumSizeMismatch(MismatchedSize), ChromaPlaneSizeMismatch(MismatchedSize), + PackedFrameSizeMismatch(MismatchedSize), + ImagesSizesNotMatch, } impl Display for YuvError { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { + YuvError::ImagesSizesNotMatch => { + f.write_str("All images size must match in one function") + } + YuvError::PackedFrameSizeMismatch(size) => f.write_fmt(format_args!( + "Packed YUV frame has invalid size, it must be {}, but it was {}", + size.expected, size.received + )), YuvError::ChromaPlaneSizeMismatch(size) => f.write_fmt(format_args!( "Chroma plane have invalid size, it must be {}, but it was {}", size.expected, size.received @@ -113,6 +122,9 @@ pub(crate) fn check_rgba_destination( height: u32, channels: usize, ) -> Result<(), YuvError> { + if width == 0 || height == 0 { + return Err(YuvError::ZeroBaseSize); + } check_overflow_v3(width as usize, height as usize, channels)?; if arr.len() != rgba_stride as usize * height as usize { return Err(YuvError::DestinationSizeMismatch(MismatchedSize { @@ -129,6 +141,32 @@ pub(crate) fn check_rgba_destination( Ok(()) } +#[inline] +pub(crate) fn check_yuv_packed( + data: &[V], + stride: u32, + width: u32, + height: u32, +) -> Result<(), YuvError> { + if width == 0 || height == 0 { + return Err(YuvError::ZeroBaseSize); + } + check_overflow_v2(stride as usize, height as usize)?; + check_overflow_v2(width as usize, height as usize)?; + let full_size = if width % 2 == 0 { + 2 * width as usize * height as usize + } else { + 2 * (width as usize + 1) * height as usize + }; + if data.len() != full_size { + return Err(YuvError::PackedFrameSizeMismatch(MismatchedSize { + expected: stride as usize * height as usize, + received: data.len(), + })); + } + Ok(()) +} + #[inline] pub(crate) fn check_y8_channel( data: &[V], @@ -136,6 +174,9 @@ pub(crate) fn check_y8_channel( width: u32, height: u32, ) -> Result<(), YuvError> { + if width == 0 || height == 0 { + return Err(YuvError::ZeroBaseSize); + } check_overflow_v2(stride as usize, height as usize)?; check_overflow_v2(width as usize, height as usize)?; if (stride as usize * height as usize) < (width as usize * height as usize) { @@ -161,6 +202,9 @@ pub(crate) fn check_chroma_channel( image_height: u32, sampling: YuvChromaSubsample, ) -> Result<(), YuvError> { + if image_width == 0 || image_height == 0 { + return Err(YuvError::ZeroBaseSize); + } let chroma_min_width = match sampling { YuvChromaSubsample::Yuv420 | YuvChromaSubsample::Yuv422 => (image_width + 1) / 2, YuvChromaSubsample::Yuv444 => image_width, @@ -196,6 +240,9 @@ pub(crate) fn check_interleaved_chroma_channel( image_height: u32, sampling: YuvChromaSubsample, ) -> Result<(), YuvError> { + if image_width == 0 || image_height == 0 { + return Err(YuvError::ZeroBaseSize); + } let chroma_min_width = match sampling { YuvChromaSubsample::Yuv420 | YuvChromaSubsample::Yuv422 => ((image_width + 1) / 2) * 2, YuvChromaSubsample::Yuv444 => image_width * 2, diff --git a/src/yuy2_to_yuv.rs b/src/yuy2_to_yuv.rs index 89b31ff..1143153 100644 --- a/src/yuy2_to_yuv.rs +++ b/src/yuy2_to_yuv.rs @@ -28,6 +28,7 @@ */ #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] use crate::avx2::yuy2_to_yuv_avx; +use crate::images::YuvPackedImage; #[cfg(all(target_arch = "aarch64", target_feature = "neon"))] use crate::neon::yuy2_to_yuv_neon_impl; #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] @@ -43,13 +44,18 @@ use rayon::prelude::{ParallelSlice, ParallelSliceMut}; fn yuy2_to_yuv_impl( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u8], - yuy2_stride: u32, + yuv_packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { let yuy2_target: Yuy2Description = YUY2_TARGET.into(); let chroma_subsampling: YuvChromaSubsample = SAMPLING.into(); planar_image.check_constraints(chroma_subsampling)?; + yuv_packed_image.check_constraints()?; + if planar_image.width != yuv_packed_image.width + || planar_image.height != yuv_packed_image.height + { + return Err(YuvError::ImagesSizesNotMatch); + } #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] let mut _use_sse = std::arch::is_x86_feature_detected!("sse4.1"); @@ -114,7 +120,11 @@ fn yuy2_to_yuv_impl( .par_chunks_exact_mut(y_stride as usize) .zip(u_plane.par_chunks_exact_mut(u_stride as usize)) .zip(v_plane.par_chunks_exact_mut(v_stride as usize)) - .zip(yuy2_store.par_chunks_exact(yuy2_stride as usize)); + .zip( + yuv_packed_image + .yuy + .par_chunks_exact(yuv_packed_image.yuy_stride as usize), + ); } #[cfg(not(feature = "rayon"))] { @@ -122,7 +132,11 @@ fn yuy2_to_yuv_impl( .chunks_exact_mut(y_stride as usize) .zip(u_plane.chunks_exact_mut(u_stride as usize)) .zip(v_plane.chunks_exact_mut(v_stride as usize)) - .zip(yuy2_store.chunks_exact(yuy2_stride as usize)); + .zip( + yuv_packed_image + .yuy + .chunks_exact(yuv_packed_image.yuy_stride as usize), + ); } iter.for_each(|(((y_dst, u_dst), v_dst), yuy2_src)| { let p_offset = process_wide_row(y_dst, u_dst, v_dst, yuy2_src); @@ -150,7 +164,7 @@ fn yuy2_to_yuv_impl( let y_dst = y_dst.last_mut().unwrap(); let u_dst = u_dst.last_mut().unwrap(); let v_dst = v_dst.last_mut().unwrap(); - let yuy2 = yuy2_src.chunks_exact(4).remainder(); + let yuy2 = yuy2_src.chunks_exact(4).last().unwrap(); let yuy2 = &yuy2[0..4]; *y_dst = yuy2[yuy2_target.get_first_y_position()]; *u_dst = yuy2[yuy2_target.get_u_position()]; @@ -165,7 +179,11 @@ fn yuy2_to_yuv_impl( .par_chunks_exact_mut(y_stride as usize) .zip(u_plane.par_chunks_exact_mut(u_stride as usize)) .zip(v_plane.par_chunks_exact_mut(v_stride as usize)) - .zip(yuy2_store.par_chunks_exact(yuy2_stride as usize)); + .zip( + yuv_packed_image + .yuy + .par_chunks_exact(yuv_packed_image.yuy_stride as usize), + ); } #[cfg(not(feature = "rayon"))] { @@ -173,7 +191,11 @@ fn yuy2_to_yuv_impl( .chunks_exact_mut(y_stride as usize) .zip(u_plane.chunks_exact_mut(u_stride as usize)) .zip(v_plane.chunks_exact_mut(v_stride as usize)) - .zip(yuy2_store.chunks_exact(yuy2_stride as usize)); + .zip( + yuv_packed_image + .yuy + .chunks_exact(yuv_packed_image.yuy_stride as usize), + ); } iter.for_each(|(((y_dst, u_dst), v_dst), yuy2_src)| { let p_offset = process_wide_row(y_dst, u_dst, v_dst, yuy2_src); @@ -199,7 +221,7 @@ fn yuy2_to_yuv_impl( let y_dst = y_dst.last_mut().unwrap(); let u_dst = u_dst.last_mut().unwrap(); let v_dst = v_dst.last_mut().unwrap(); - let yuy2 = yuy2_src.chunks_exact(4).remainder(); + let yuy2 = yuy2_src.chunks_exact(4).last().unwrap(); let yuy2 = &yuy2[0..4]; *y_dst = yuy2[yuy2_target.get_first_y_position()]; *u_dst = yuy2[yuy2_target.get_u_position()]; @@ -214,7 +236,11 @@ fn yuy2_to_yuv_impl( .par_chunks_exact_mut(y_stride as usize * 2) .zip(u_plane.par_chunks_exact_mut(u_stride as usize)) .zip(v_plane.par_chunks_exact_mut(v_stride as usize)) - .zip(yuy2_store.par_chunks_exact(yuy2_stride as usize * 2)); + .zip( + yuv_packed_image + .yuy + .par_chunks_exact(yuv_packed_image.yuy_stride as usize * 2), + ); } #[cfg(not(feature = "rayon"))] { @@ -222,12 +248,16 @@ fn yuy2_to_yuv_impl( .chunks_exact_mut(y_stride as usize * 2) .zip(u_plane.chunks_exact_mut(u_stride as usize)) .zip(v_plane.chunks_exact_mut(v_stride as usize)) - .zip(yuy2_store.chunks_exact(yuy2_stride as usize * 2)); + .zip( + yuv_packed_image + .yuy + .chunks_exact(yuv_packed_image.yuy_stride as usize * 2), + ); } iter.for_each(|(((y_dst, u_dst), v_dst), yuy2_src)| { for (y, (y_dst, yuy2)) in y_dst .chunks_exact_mut(y_stride as usize) - .zip(yuy2_src.chunks_exact(yuy2_stride as usize)) + .zip(yuy2_src.chunks_exact(yuv_packed_image.yuy_stride as usize)) .enumerate() { let p_offset = process_wide_row(y_dst, u_dst, v_dst, yuy2); @@ -255,7 +285,7 @@ fn yuy2_to_yuv_impl( if width & 1 != 0 { let y_dst = y_dst.last_mut().unwrap(); - let yuy2 = yuy2_src.chunks_exact(4).remainder(); + let yuy2 = yuy2_src.chunks_exact(4).last().unwrap(); let yuy2 = &yuy2[0..4]; *y_dst = yuy2[yuy2_target.get_first_y_position()]; if process_chroma { @@ -280,8 +310,7 @@ fn yuy2_to_yuv_impl( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted YUYV data. -/// * `yuy2_stride` - The stride (components per row) for the YUYV plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -290,13 +319,11 @@ fn yuy2_to_yuv_impl( /// pub fn yuyv422_to_yuv444( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u8], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv444 as u8 }, { Yuy2Description::YUYV as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -308,8 +335,7 @@ pub fn yuyv422_to_yuv444( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted YUYV data. -/// * `yuy2_stride` - The stride (components per row) for the YUYV plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -318,13 +344,11 @@ pub fn yuyv422_to_yuv444( /// pub fn yuyv422_to_yuv420( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u8], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv420 as u8 }, { Yuy2Description::YUYV as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -336,8 +360,7 @@ pub fn yuyv422_to_yuv420( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted YUYV data. -/// * `yuy2_stride` - The stride (components per row) for the YUYV plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -346,13 +369,11 @@ pub fn yuyv422_to_yuv420( /// pub fn yuyv422_to_yuv422( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u8], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv422 as u8 }, { Yuy2Description::YUYV as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -364,8 +385,7 @@ pub fn yuyv422_to_yuv422( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted YVYU data. -/// * `yuy2_stride` - The stride (components per row) for the YVYU plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -374,13 +394,11 @@ pub fn yuyv422_to_yuv422( /// pub fn yvyu422_to_yuv444( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u8], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv444 as u8 }, { Yuy2Description::YVYU as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -392,8 +410,7 @@ pub fn yvyu422_to_yuv444( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted YVYU data. -/// * `yuy2_stride` - The stride (components per row) for the YVYU plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -402,13 +419,11 @@ pub fn yvyu422_to_yuv444( /// pub fn yvyu422_to_yuv420( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u8], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv420 as u8 }, { Yuy2Description::YVYU as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -420,8 +435,7 @@ pub fn yvyu422_to_yuv420( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted YVYU data. -/// * `yuy2_stride` - The stride (components per row) for the YVYU plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -430,13 +444,11 @@ pub fn yvyu422_to_yuv420( /// pub fn yvyu422_to_yuv422( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u8], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv422 as u8 }, { Yuy2Description::YVYU as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -448,8 +460,7 @@ pub fn yvyu422_to_yuv422( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted VYUY data. -/// * `yuy2_stride` - The stride (components per row) for the VYUY plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -458,13 +469,11 @@ pub fn yvyu422_to_yuv422( /// pub fn vyuy422_to_yuv444( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u8], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv444 as u8 }, { Yuy2Description::VYUY as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -476,8 +485,7 @@ pub fn vyuy422_to_yuv444( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted VYUY data. -/// * `yuy2_stride` - The stride (components per row) for the VYUY plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -486,13 +494,11 @@ pub fn vyuy422_to_yuv444( /// pub fn vyuy422_to_yuv420( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u8], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv420 as u8 }, { Yuy2Description::VYUY as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -504,8 +510,7 @@ pub fn vyuy422_to_yuv420( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted VYUY data. -/// * `yuy2_stride` - The stride (components per row) for the VYUY plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -514,13 +519,11 @@ pub fn vyuy422_to_yuv420( /// pub fn vyuy422_to_yuv422( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u8], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv422 as u8 }, { Yuy2Description::VYUY as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -532,8 +535,7 @@ pub fn vyuy422_to_yuv422( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted UYVY data. -/// * `yuy2_stride` - The stride (components per row) for the UYVY plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -542,13 +544,11 @@ pub fn vyuy422_to_yuv422( /// pub fn uyvy422_to_yuv444( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u8], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv444 as u8 }, { Yuy2Description::UYVY as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -560,8 +560,7 @@ pub fn uyvy422_to_yuv444( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted UYVY data. -/// * `yuy2_stride` - The stride (components per row) for the UYVY plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -570,13 +569,11 @@ pub fn uyvy422_to_yuv444( /// pub fn uyvy422_to_yuv420( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u8], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv420 as u8 }, { Yuy2Description::UYVY as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -598,12 +595,10 @@ pub fn uyvy422_to_yuv420( /// pub fn uyvy422_to_yuv422( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u8], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv422 as u8 }, { Yuy2Description::UYVY as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } diff --git a/src/yuy2_to_yuv_p16.rs b/src/yuy2_to_yuv_p16.rs index c19b845..a006fe2 100644 --- a/src/yuy2_to_yuv_p16.rs +++ b/src/yuy2_to_yuv_p16.rs @@ -27,7 +27,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ use crate::yuv_support::{YuvChromaSubsample, Yuy2Description}; -use crate::{YuvError, YuvPlanarImageMut}; +use crate::{YuvError, YuvPackedImage, YuvPlanarImageMut}; #[cfg(feature = "rayon")] use rayon::iter::{IndexedParallelIterator, ParallelIterator}; #[cfg(feature = "rayon")] @@ -35,13 +35,16 @@ use rayon::prelude::{ParallelSlice, ParallelSliceMut}; fn yuy2_to_yuv_impl( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u16], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { let yuy2_target: Yuy2Description = YUY2_TARGET.into(); let chroma_subsampling: YuvChromaSubsample = SAMPLING.into(); planar_image.check_constraints(chroma_subsampling)?; + packed_image.check_constraints()?; + if planar_image.width != packed_image.width || planar_image.height != packed_image.height { + return Err(YuvError::ImagesSizesNotMatch); + } let width = planar_image.width; let y_plane = planar_image.y_plane.borrow_mut(); @@ -59,7 +62,11 @@ fn yuy2_to_yuv_impl( .par_chunks_exact_mut(y_stride as usize) .zip(u_plane.par_chunks_exact_mut(u_stride as usize)) .zip(v_plane.par_chunks_exact_mut(v_stride as usize)) - .zip(yuy2_store.par_chunks_exact(yuy2_stride as usize)); + .zip( + packed_image + .yuy + .par_chunks_exact(packed_image.yuy_stride as usize), + ); } #[cfg(not(feature = "rayon"))] { @@ -67,7 +74,11 @@ fn yuy2_to_yuv_impl( .chunks_exact_mut(y_stride as usize) .zip(u_plane.chunks_exact_mut(u_stride as usize)) .zip(v_plane.chunks_exact_mut(v_stride as usize)) - .zip(yuy2_store.chunks_exact(yuy2_stride as usize)); + .zip( + packed_image + .yuy + .chunks_exact(packed_image.yuy_stride as usize), + ); } iter.for_each(|(((y_dst, u_dst), v_dst), yuy2_src)| { for (((y_dst, u_dst), v_dst), yuy2) in y_dst @@ -92,7 +103,7 @@ fn yuy2_to_yuv_impl( let y_dst = y_dst.last_mut().unwrap(); let u_dst = u_dst.last_mut().unwrap(); let v_dst = v_dst.last_mut().unwrap(); - let yuy2 = yuy2_src.chunks_exact(4).remainder(); + let yuy2 = yuy2_src.chunks_exact(4).last().unwrap(); let yuy2 = &yuy2[0..4]; *y_dst = yuy2[yuy2_target.get_first_y_position()]; *u_dst = yuy2[yuy2_target.get_u_position()]; @@ -107,7 +118,11 @@ fn yuy2_to_yuv_impl( .par_chunks_exact_mut(y_stride as usize) .zip(u_plane.par_chunks_exact_mut(u_stride as usize)) .zip(v_plane.par_chunks_exact_mut(v_stride as usize)) - .zip(yuy2_store.par_chunks_exact(yuy2_stride as usize)); + .zip( + packed_image + .yuy + .par_chunks_exact(packed_image.yuy_stride as usize), + ); } #[cfg(not(feature = "rayon"))] { @@ -115,7 +130,11 @@ fn yuy2_to_yuv_impl( .chunks_exact_mut(y_stride as usize) .zip(u_plane.chunks_exact_mut(u_stride as usize)) .zip(v_plane.chunks_exact_mut(v_stride as usize)) - .zip(yuy2_store.chunks_exact(yuy2_stride as usize)); + .zip( + packed_image + .yuy + .chunks_exact(packed_image.yuy_stride as usize), + ); } iter.for_each(|(((y_dst, u_dst), v_dst), yuy2_src)| { for (((y_dst, u_dst), v_dst), yuy2) in y_dst @@ -138,7 +157,7 @@ fn yuy2_to_yuv_impl( let y_dst = y_dst.last_mut().unwrap(); let u_dst = u_dst.last_mut().unwrap(); let v_dst = v_dst.last_mut().unwrap(); - let yuy2 = yuy2_src.chunks_exact(4).remainder(); + let yuy2 = yuy2_src.chunks_exact(4).last().unwrap(); let yuy2 = &yuy2[0..4]; *y_dst = yuy2[yuy2_target.get_first_y_position()]; *u_dst = yuy2[yuy2_target.get_u_position()]; @@ -153,7 +172,11 @@ fn yuy2_to_yuv_impl( .par_chunks_exact_mut(y_stride as usize * 2) .zip(u_plane.par_chunks_exact_mut(u_stride as usize)) .zip(v_plane.par_chunks_exact_mut(v_stride as usize)) - .zip(yuy2_store.par_chunks_exact(yuy2_stride as usize * 2)); + .zip( + packed_image + .yuy + .par_chunks_exact(packed_image.yuy_stride as usize * 2), + ); } #[cfg(not(feature = "rayon"))] { @@ -161,12 +184,16 @@ fn yuy2_to_yuv_impl( .chunks_exact_mut(y_stride as usize * 2) .zip(u_plane.chunks_exact_mut(u_stride as usize)) .zip(v_plane.chunks_exact_mut(v_stride as usize)) - .zip(yuy2_store.chunks_exact(yuy2_stride as usize * 2)); + .zip( + packed_image + .yuy + .chunks_exact(packed_image.yuy_stride as usize * 2), + ); } iter.for_each(|(((y_dst, u_dst), v_dst), yuy2_src)| { for (y, (y_dst, yuy2)) in y_dst .chunks_exact_mut(y_stride as usize) - .zip(yuy2_src.chunks_exact(yuy2_stride as usize)) + .zip(yuy2_src.chunks_exact(packed_image.yuy_stride as usize)) .enumerate() { let process_chroma = y & 1 == 0; @@ -191,7 +218,7 @@ fn yuy2_to_yuv_impl( if width & 1 != 0 { let y_dst = y_dst.last_mut().unwrap(); - let yuy2 = yuy2_src.chunks_exact(4).remainder(); + let yuy2 = yuy2_src.chunks_exact(4).last().unwrap(); let yuy2 = &yuy2[0..4]; *y_dst = yuy2[yuy2_target.get_first_y_position()]; if process_chroma { @@ -216,8 +243,7 @@ fn yuy2_to_yuv_impl( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted YUYV data. -/// * `yuy2_stride` - The stride (elements per row) for the YUYV plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -226,13 +252,11 @@ fn yuy2_to_yuv_impl( /// pub fn yuyv422_to_yuv444_p16( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u16], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv444 as u8 }, { Yuy2Description::YUYV as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -244,8 +268,7 @@ pub fn yuyv422_to_yuv444_p16( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted YUYV data. -/// * `yuy2_stride` - The stride (elements per row) for the YUYV plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -254,13 +277,11 @@ pub fn yuyv422_to_yuv444_p16( /// pub fn yuyv422_to_yuv420_p16( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u16], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv420 as u8 }, { Yuy2Description::YUYV as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -272,8 +293,7 @@ pub fn yuyv422_to_yuv420_p16( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted YUYV data. -/// * `yuy2_stride` - The stride (elements per row) for the YUYV plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -282,13 +302,11 @@ pub fn yuyv422_to_yuv420_p16( /// pub fn yuyv422_to_yuv422_p16( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u16], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv422 as u8 }, { Yuy2Description::YUYV as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -300,8 +318,7 @@ pub fn yuyv422_to_yuv422_p16( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted YVYU data. -/// * `yuy2_stride` - The stride (elements per row) for the YVYU plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -310,13 +327,11 @@ pub fn yuyv422_to_yuv422_p16( /// pub fn yvyu422_to_yuv444_p16( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u16], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv444 as u8 }, { Yuy2Description::YVYU as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -328,8 +343,7 @@ pub fn yvyu422_to_yuv444_p16( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted YVYU data. -/// * `yuy2_stride` - The stride (elements per row) for the YVYU plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -338,13 +352,11 @@ pub fn yvyu422_to_yuv444_p16( /// pub fn yvyu422_to_yuv420_p16( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u16], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv420 as u8 }, { Yuy2Description::YVYU as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -356,8 +368,7 @@ pub fn yvyu422_to_yuv420_p16( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted YVYU data. -/// * `yuy2_stride` - The stride (elements per row) for the YVYU plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -366,13 +377,11 @@ pub fn yvyu422_to_yuv420_p16( /// pub fn yvyu422_to_yuv422_p16( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u16], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv422 as u8 }, { Yuy2Description::YVYU as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -384,8 +393,7 @@ pub fn yvyu422_to_yuv422_p16( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted VYUY data. -/// * `yuy2_stride` - The stride (elements per row) for the VYUY plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -394,13 +402,11 @@ pub fn yvyu422_to_yuv422_p16( /// pub fn vyuy422_to_yuv444_p16( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u16], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv444 as u8 }, { Yuy2Description::VYUY as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -412,8 +418,7 @@ pub fn vyuy422_to_yuv444_p16( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted VYUY data. -/// * `yuy2_stride` - The stride (elements per row) for the VYUY plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -422,13 +427,11 @@ pub fn vyuy422_to_yuv444_p16( /// pub fn vyuy422_to_yuv420_p16( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u16], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv420 as u8 }, { Yuy2Description::VYUY as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -440,8 +443,7 @@ pub fn vyuy422_to_yuv420_p16( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted VYUY data. -/// * `yuy2_stride` - The stride (elements per row) for the VYUY plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -450,13 +452,11 @@ pub fn vyuy422_to_yuv420_p16( /// pub fn vyuy422_to_yuv422_p16( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u16], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv422 as u8 }, { Yuy2Description::VYUY as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -468,8 +468,7 @@ pub fn vyuy422_to_yuv422_p16( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted UYVY data. -/// * `yuy2_stride` - The stride (elements per row) for the UYVY plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -478,13 +477,11 @@ pub fn vyuy422_to_yuv422_p16( /// pub fn uyvy422_to_yuv444_p16( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u16], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv444 as u8 }, { Yuy2Description::UYVY as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -496,8 +493,7 @@ pub fn uyvy422_to_yuv444_p16( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted UYVY data. -/// * `yuy2_stride` - The stride (elements per row) for the UYVY plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -506,13 +502,11 @@ pub fn uyvy422_to_yuv444_p16( /// pub fn uyvy422_to_yuv420_p16( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u16], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv420 as u8 }, { Yuy2Description::UYVY as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) } @@ -524,8 +518,7 @@ pub fn uyvy422_to_yuv420_p16( /// # Arguments /// /// * `planar_image` - Target planar image. -/// * `yuy2_store` - A slice to store the converted UYVY data. -/// * `yuy2_stride` - The stride (elements per row) for the UYVY plane. +/// * `packed_image` - Source packed image. /// /// # Panics /// @@ -534,12 +527,10 @@ pub fn uyvy422_to_yuv420_p16( /// pub fn uyvy422_to_yuv422_p16( planar_image: &mut YuvPlanarImageMut, - yuy2_store: &[u16], - yuy2_stride: u32, + packed_image: &YuvPackedImage, ) -> Result<(), YuvError> { yuy2_to_yuv_impl::<{ YuvChromaSubsample::Yuv422 as u8 }, { Yuy2Description::UYVY as usize }>( planar_image, - yuy2_store, - yuy2_stride, + packed_image, ) }