diff options
author | Sergio Garcia Murillo <sergio.garcia.murillo@gmail.com> | 2022-04-06 20:57:53 +0200 |
---|---|---|
committer | libyuv LUCI CQ <libyuv-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-04-06 23:49:35 +0000 |
commit | a77d615e1067fe5bb48444a073f7ee08fd273b8a (patch) | |
tree | 6f85baa2f8a3d60a40b31f317e1d10663e2b6f72 /source/rotate.cc | |
parent | 4589081cea3dc5364dc433f9a20e67706fd3e29c (diff) | |
download | libyuv-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.cc | 84 |
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, |