aboutsummaryrefslogtreecommitdiff
path: root/source/rotate.cc
diff options
context:
space:
mode:
authorSergio Garcia Murillo <sergio.garcia.murillo@gmail.com>2022-04-06 20:57:53 +0200
committerlibyuv LUCI CQ <libyuv-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-04-06 23:49:35 +0000
commita77d615e1067fe5bb48444a073f7ee08fd273b8a (patch)
tree6f85baa2f8a3d60a40b31f317e1d10663e2b6f72 /source/rotate.cc
parent4589081cea3dc5364dc433f9a20e67706fd3e29c (diff)
downloadlibyuv-a77d615e1067fe5bb48444a073f7ee08fd273b8a.tar.gz
Add tentative I422Rotate.
When doing 90 or 270 degrees rotation we need to do a rotate&scale of the UV planes, as there are no helper optimized functions to do this, we use the Y plane as temporal memory and perform each of the transforms independently: First U plane is rotated, putting the result in the Y plane. After the rotation, the output has double the samples horizontally and half the samples vertically, so it is scaled into the final U plane. Same process is done with the V plane. Last the Y plane that can be just rotated without scaling. It would be great to have an optimized version for this, but maybe this is helpfull for triggering the discussions. Bug: libyuv:926 Change-Id: I188af103c4d0e3f9522021b4bf2b63c9d5de8b93 Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/3568424 Reviewed-by: Frank Barchard <fbarchard@chromium.org> Commit-Queue: Frank Barchard <fbarchard@chromium.org>
Diffstat (limited to 'source/rotate.cc')
-rw-r--r--source/rotate.cc84
1 files changed, 84 insertions, 0 deletions
diff --git a/source/rotate.cc b/source/rotate.cc
index b274e8db..f193bad7 100644
--- a/source/rotate.cc
+++ b/source/rotate.cc
@@ -545,6 +545,90 @@ int I420Rotate(const uint8_t* src_y,
}
LIBYUV_API
+int I422Rotate(const uint8_t* src_y,
+ int src_stride_y,
+ const uint8_t* src_u,
+ int src_stride_u,
+ const uint8_t* src_v,
+ int src_stride_v,
+ uint8_t* dst_y,
+ int dst_stride_y,
+ uint8_t* dst_u,
+ int dst_stride_u,
+ uint8_t* dst_v,
+ int dst_stride_v,
+ int width,
+ int height,
+ enum libyuv::RotationMode mode) {
+ int halfwidth = (width + 1) >> 1;
+ int halfheight = (height + 1) >> 1;
+ if (!src_y || !src_u || !src_v || width <= 0 || height == 0 || !dst_y ||
+ !dst_u || !dst_v) {
+ return -1;
+ }
+ // Negative height means invert the image.
+ if (height < 0) {
+ height = -height;
+ src_y = src_y + (height - 1) * src_stride_y;
+ src_u = src_u + (height - 1) * src_stride_u;
+ src_v = src_v + (height - 1) * src_stride_v;
+ src_stride_y = -src_stride_y;
+ src_stride_u = -src_stride_u;
+ src_stride_v = -src_stride_v;
+ }
+
+ switch (mode) {
+ case libyuv::kRotate0:
+ // copy frame
+ libyuv::CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width,
+ height);
+ libyuv::CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth,
+ height);
+ libyuv::CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth,
+ height);
+ return 0;
+ case libyuv::kRotate90:
+ // We need to rotate and rescale, we use plane Y as temporal storage.
+ libyuv::RotatePlane90(src_u, src_stride_u, dst_y, height, halfwidth,
+ height);
+ libyuv::ScalePlane(dst_y, height, height, halfwidth, dst_u, halfheight,
+ halfheight, width, libyuv::kFilterBilinear);
+ libyuv::RotatePlane90(src_v, src_stride_v, dst_y, height, halfwidth,
+ height);
+ libyuv::ScalePlane(dst_y, height, height, halfwidth, dst_v, halfheight,
+ halfheight, width, libyuv::kFilterLinear);
+ libyuv::RotatePlane90(src_y, src_stride_y, dst_y, dst_stride_y, width,
+ height);
+ return 0;
+ case libyuv::kRotate270:
+ // We need to rotate and rescale, we use plane Y as temporal storage.
+ libyuv::RotatePlane270(src_u, src_stride_u, dst_y, height, halfwidth,
+ height);
+ libyuv::ScalePlane(dst_y, height, height, halfwidth, dst_u, halfheight,
+ halfheight, width, libyuv::kFilterBilinear);
+ libyuv::RotatePlane270(src_v, src_stride_v, dst_y, height, halfwidth,
+ height);
+ libyuv::ScalePlane(dst_y, height, height, halfwidth, dst_v, halfheight,
+ halfheight, width, libyuv::kFilterLinear);
+ libyuv::RotatePlane270(src_y, src_stride_y, dst_y, dst_stride_y, width,
+ height);
+
+ return 0;
+ case libyuv::kRotate180:
+ libyuv::RotatePlane180(src_y, src_stride_y, dst_y, dst_stride_y, width,
+ height);
+ libyuv::RotatePlane180(src_u, src_stride_u, dst_u, dst_stride_u,
+ halfwidth, height);
+ libyuv::RotatePlane180(src_v, src_stride_v, dst_v, dst_stride_v,
+ halfwidth, height);
+ return 0;
+ default:
+ break;
+ }
+ return -1;
+}
+
+LIBYUV_API
int I444Rotate(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_u,