mirror of
https://chromium.googlesource.com/libyuv/libyuv
synced 2025-12-08 01:36:47 +08:00
I444ToI420 etc use ScalePlane on Y to allow mirroring.
BUG=291 TESTED=unittests still pass. R=tpsiaki@google.com Review URL: https://webrtc-codereview.appspot.com/4979004 git-svn-id: http://libyuv.googlecode.com/svn/trunk@893 16f28f9a-4ce2-e073-06de-1de4eb20be90
This commit is contained in:
parent
a8e4dcb5d5
commit
99a1298c54
@ -22,7 +22,43 @@ namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s)
|
||||
static __inline int Abs(int v) {
|
||||
return v >= 0 ? v : -v;
|
||||
}
|
||||
|
||||
// Any I4xx To I420 format with mirroring.
|
||||
static int I4xxToI420(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int src_y_width, int src_y_height,
|
||||
int src_uv_width, int src_uv_height) {
|
||||
if (src_y_width == 0 || src_y_height == 0 ||
|
||||
src_uv_width == 0 || src_uv_height == 0) {
|
||||
return -1;
|
||||
}
|
||||
const int dst_y_width = Abs(src_y_width);
|
||||
const int dst_y_height = Abs(src_y_height);
|
||||
const int dst_uv_width = SUBSAMPLE(dst_y_width, 1, 1);
|
||||
const int dst_uv_height = SUBSAMPLE(dst_y_height, 1, 1);
|
||||
ScalePlane(src_y, src_stride_y, src_y_width, src_y_height,
|
||||
dst_y, dst_stride_y, dst_y_width, dst_y_height,
|
||||
kFilterBilinear);
|
||||
ScalePlane(src_u, src_stride_u, src_uv_width, src_uv_height,
|
||||
dst_u, dst_stride_u, dst_uv_width, dst_uv_height,
|
||||
kFilterBilinear);
|
||||
ScalePlane(src_v, src_stride_v, src_uv_width, src_uv_height,
|
||||
dst_v, dst_stride_v, dst_uv_width, dst_uv_height,
|
||||
kFilterBilinear);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Copy I420 with optional flipping
|
||||
// TODO(fbarchard): Use Scale plane which supports mirroring, but ensure
|
||||
// is does row coalescing.
|
||||
LIBYUV_API
|
||||
int I420Copy(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
@ -69,37 +105,15 @@ int I422ToI420(const uint8* src_y, int src_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height) {
|
||||
if (!src_y || !src_u || !src_v ||
|
||||
!dst_y || !dst_u || !dst_v ||
|
||||
width <= 0 || height == 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
// Copy Y plane
|
||||
if (dst_y) {
|
||||
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
|
||||
}
|
||||
|
||||
// Resample UV planes.
|
||||
const int halfwidth = (width + 1) >> 1;
|
||||
const int halfheight = (height + 1) >> 1;
|
||||
ScalePlane(src_u, src_stride_u, halfwidth, height,
|
||||
dst_u, dst_stride_u, halfwidth, halfheight,
|
||||
kFilterBilinear);
|
||||
ScalePlane(src_v, src_stride_v, halfwidth, height,
|
||||
dst_v, dst_stride_v, halfwidth, halfheight,
|
||||
kFilterBilinear);
|
||||
return 0;
|
||||
const int src_uv_width = SUBSAMPLE(width, 1, 1);
|
||||
return I4xxToI420(src_y, src_stride_y,
|
||||
src_u, src_stride_u,
|
||||
src_v, src_stride_v,
|
||||
dst_y, dst_stride_y,
|
||||
dst_u, dst_stride_u,
|
||||
dst_v, dst_stride_v,
|
||||
width, height,
|
||||
src_uv_width, height);
|
||||
}
|
||||
|
||||
// 444 chroma is 1x width, 1x height
|
||||
@ -112,37 +126,14 @@ int I444ToI420(const uint8* src_y, int src_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height) {
|
||||
if (!src_y || !src_u || !src_v ||
|
||||
!dst_y || !dst_u || !dst_v ||
|
||||
width <= 0 || height == 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
// Copy Y plane
|
||||
if (dst_y) {
|
||||
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
|
||||
}
|
||||
|
||||
// Resample UV planes.
|
||||
const int halfwidth = (width + 1) >> 1;
|
||||
const int halfheight = (height + 1) >> 1;
|
||||
ScalePlane(src_u, src_stride_u, width, height,
|
||||
dst_u, dst_stride_u, halfwidth, halfheight,
|
||||
kFilterBilinear);
|
||||
ScalePlane(src_v, src_stride_v, width, height,
|
||||
dst_v, dst_stride_v, halfwidth, halfheight,
|
||||
kFilterBilinear);
|
||||
return 0;
|
||||
return I4xxToI420(src_y, src_stride_y,
|
||||
src_u, src_stride_u,
|
||||
src_v, src_stride_v,
|
||||
dst_y, dst_stride_y,
|
||||
dst_u, dst_stride_u,
|
||||
dst_v, dst_stride_v,
|
||||
width, height,
|
||||
width, height);
|
||||
}
|
||||
|
||||
// 411 chroma is 1/4 width, 1x height
|
||||
@ -155,38 +146,15 @@ int I411ToI420(const uint8* src_y, int src_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height) {
|
||||
if (!src_y || !src_u || !src_v ||
|
||||
!dst_y || !dst_u || !dst_v ||
|
||||
width <= 0 || height == 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
// Copy Y plane
|
||||
if (dst_y) {
|
||||
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
|
||||
}
|
||||
|
||||
// Resample UV planes.
|
||||
const int halfwidth = (width + 1) >> 1;
|
||||
const int halfheight = (height + 1) >> 1;
|
||||
const int quarterwidth = (width + 3) >> 2;
|
||||
ScalePlane(src_u, src_stride_u, quarterwidth, height,
|
||||
dst_u, dst_stride_u, halfwidth, halfheight,
|
||||
kFilterNone);
|
||||
ScalePlane(src_v, src_stride_v, quarterwidth, height,
|
||||
dst_v, dst_stride_v, halfwidth, halfheight,
|
||||
kFilterNone);
|
||||
return 0;
|
||||
const int src_uv_width = SUBSAMPLE(width, 3, 2);
|
||||
return I4xxToI420(src_y, src_stride_y,
|
||||
src_u, src_stride_u,
|
||||
src_v, src_stride_v,
|
||||
dst_y, dst_stride_y,
|
||||
dst_u, dst_stride_u,
|
||||
dst_v, dst_stride_v,
|
||||
width, height,
|
||||
src_uv_width, height);
|
||||
}
|
||||
|
||||
// I400 is greyscale typically used in MJPG
|
||||
@ -232,7 +200,6 @@ static void CopyPlane2(const uint8* src, int src_stride_0, int src_stride_1,
|
||||
}
|
||||
#endif
|
||||
#if defined(HAS_COPYROW_ERMS)
|
||||
// TODO(fbarchard): Detect Fast String support.
|
||||
if (TestCpuFlag(kCpuHasERMS)) {
|
||||
CopyRow = CopyRow_ERMS;
|
||||
}
|
||||
|
||||
@ -25,6 +25,40 @@ namespace libyuv {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s)
|
||||
static __inline int Abs(int v) {
|
||||
return v >= 0 ? v : -v;
|
||||
}
|
||||
|
||||
// I420 To any I4xx YUV format with mirroring.
|
||||
static int I420ToI4xx(const uint8* src_y, int src_stride_y,
|
||||
const uint8* src_u, int src_stride_u,
|
||||
const uint8* src_v, int src_stride_v,
|
||||
uint8* dst_y, int dst_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int src_y_width, int src_y_height,
|
||||
int dst_uv_width, int dst_uv_height) {
|
||||
if (src_y_width == 0 || src_y_height == 0 ||
|
||||
dst_uv_width <= 0 || dst_uv_height <= 0) {
|
||||
return -1;
|
||||
}
|
||||
const int dst_y_width = Abs(src_y_width);
|
||||
const int dst_y_height = Abs(src_y_height);
|
||||
const int src_uv_width = SUBSAMPLE(src_y_width, 1, 1);
|
||||
const int src_uv_height = SUBSAMPLE(src_y_height, 1, 1);
|
||||
ScalePlane(src_y, src_stride_y, src_y_width, src_y_height,
|
||||
dst_y, dst_stride_y, dst_y_width, dst_y_height,
|
||||
kFilterBilinear);
|
||||
ScalePlane(src_u, src_stride_u, src_uv_width, src_uv_height,
|
||||
dst_u, dst_stride_u, dst_uv_width, dst_uv_height,
|
||||
kFilterBilinear);
|
||||
ScalePlane(src_v, src_stride_v, src_uv_width, src_uv_height,
|
||||
dst_v, dst_stride_v, dst_uv_width, dst_uv_height,
|
||||
kFilterBilinear);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 420 chroma is 1/2 width, 1/2 height
|
||||
// 422 chroma is 1/2 width, 1x height
|
||||
LIBYUV_API
|
||||
@ -35,38 +69,16 @@ int I420ToI422(const uint8* src_y, int src_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height) {
|
||||
if (!src_y || !src_u || !src_v ||
|
||||
!dst_y || !dst_u || !dst_v ||
|
||||
width <= 0 || height == 0) {
|
||||
return -1;
|
||||
}
|
||||
// Negative height means invert the image.
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
dst_y = dst_y + (height - 1) * dst_stride_y;
|
||||
dst_u = dst_u + (height - 1) * dst_stride_u;
|
||||
dst_v = dst_v + (height - 1) * dst_stride_v;
|
||||
dst_stride_y = -dst_stride_y;
|
||||
dst_stride_u = -dst_stride_u;
|
||||
dst_stride_v = -dst_stride_v;
|
||||
}
|
||||
|
||||
// Copy Y plane.
|
||||
// TODO(fbarchard): Scale Y plane, which will do a copy, but allows mirror.
|
||||
if (dst_y) {
|
||||
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
|
||||
}
|
||||
|
||||
// Resample UV planes.
|
||||
const int halfwidth = (width + 1) >> 1;
|
||||
const int halfheight = (height + 1) >> 1;
|
||||
ScalePlane(src_u, src_stride_u, halfwidth, halfheight,
|
||||
dst_u, dst_stride_u, halfwidth, height,
|
||||
kFilterBilinear);
|
||||
ScalePlane(src_v, src_stride_v, halfwidth, halfheight,
|
||||
dst_v, dst_stride_v, halfwidth, height,
|
||||
kFilterBilinear);
|
||||
return 0;
|
||||
const int dst_uv_width = (Abs(width) + 1) >> 1;
|
||||
const int dst_uv_height = Abs(height);
|
||||
return I420ToI4xx(src_y, src_stride_y,
|
||||
src_u, src_stride_u,
|
||||
src_v, src_stride_v,
|
||||
dst_y, dst_stride_y,
|
||||
dst_u, dst_stride_u,
|
||||
dst_v, dst_stride_v,
|
||||
width, height,
|
||||
dst_uv_width, dst_uv_height);
|
||||
}
|
||||
|
||||
// 420 chroma is 1/2 width, 1/2 height
|
||||
@ -79,37 +91,16 @@ int I420ToI444(const uint8* src_y, int src_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height) {
|
||||
if (!src_y || !src_u|| !src_v ||
|
||||
!dst_y || !dst_u || !dst_v ||
|
||||
width <= 0 || height == 0) {
|
||||
return -1;
|
||||
}
|
||||
// Negative height means invert the image.
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
dst_y = dst_y + (height - 1) * dst_stride_y;
|
||||
dst_u = dst_u + (height - 1) * dst_stride_u;
|
||||
dst_v = dst_v + (height - 1) * dst_stride_v;
|
||||
dst_stride_y = -dst_stride_y;
|
||||
dst_stride_u = -dst_stride_u;
|
||||
dst_stride_v = -dst_stride_v;
|
||||
}
|
||||
|
||||
// Copy Y plane
|
||||
if (dst_y) {
|
||||
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
|
||||
}
|
||||
|
||||
// Resample UV planes.
|
||||
const int halfwidth = (width + 1) >> 1;
|
||||
const int halfheight = (height + 1) >> 1;
|
||||
ScalePlane(src_u, src_stride_u, halfwidth, halfheight,
|
||||
dst_u, dst_stride_u, width, height,
|
||||
kFilterBilinear);
|
||||
ScalePlane(src_v, src_stride_v, halfwidth, halfheight,
|
||||
dst_v, dst_stride_v, width, height,
|
||||
kFilterBilinear);
|
||||
return 0;
|
||||
const int dst_uv_width = Abs(width);
|
||||
const int dst_uv_height = Abs(height);
|
||||
return I420ToI4xx(src_y, src_stride_y,
|
||||
src_u, src_stride_u,
|
||||
src_v, src_stride_v,
|
||||
dst_y, dst_stride_y,
|
||||
dst_u, dst_stride_u,
|
||||
dst_v, dst_stride_v,
|
||||
width, height,
|
||||
dst_uv_width, dst_uv_height);
|
||||
}
|
||||
|
||||
// 420 chroma is 1/2 width, 1/2 height
|
||||
@ -122,38 +113,16 @@ int I420ToI411(const uint8* src_y, int src_stride_y,
|
||||
uint8* dst_u, int dst_stride_u,
|
||||
uint8* dst_v, int dst_stride_v,
|
||||
int width, int height) {
|
||||
if (!src_y || !src_u || !src_v ||
|
||||
!dst_y || !dst_u || !dst_v ||
|
||||
width <= 0 || height == 0) {
|
||||
return -1;
|
||||
}
|
||||
// Negative height means invert the image.
|
||||
if (height < 0) {
|
||||
height = -height;
|
||||
dst_y = dst_y + (height - 1) * dst_stride_y;
|
||||
dst_u = dst_u + (height - 1) * dst_stride_u;
|
||||
dst_v = dst_v + (height - 1) * dst_stride_v;
|
||||
dst_stride_y = -dst_stride_y;
|
||||
dst_stride_u = -dst_stride_u;
|
||||
dst_stride_v = -dst_stride_v;
|
||||
}
|
||||
|
||||
// Copy Y plane
|
||||
if (dst_y) {
|
||||
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
|
||||
}
|
||||
|
||||
// Resample UV planes.
|
||||
const int halfwidth = (width + 1) >> 1;
|
||||
const int halfheight = (height + 1) >> 1;
|
||||
const int quarterwidth = (width + 3) >> 2;
|
||||
ScalePlane(src_u, src_stride_u, halfwidth, halfheight,
|
||||
dst_u, dst_stride_u, quarterwidth, height,
|
||||
kFilterBilinear);
|
||||
ScalePlane(src_v, src_stride_v, halfwidth, halfheight,
|
||||
dst_v, dst_stride_v, quarterwidth, height,
|
||||
kFilterBilinear);
|
||||
return 0;
|
||||
const int dst_uv_width = (Abs(width) + 3) >> 2;
|
||||
const int dst_uv_height = Abs(height);
|
||||
return I420ToI4xx(src_y, src_stride_y,
|
||||
src_u, src_stride_u,
|
||||
src_v, src_stride_v,
|
||||
dst_y, dst_stride_y,
|
||||
dst_u, dst_stride_u,
|
||||
dst_v, dst_stride_v,
|
||||
width, height,
|
||||
dst_uv_width, dst_uv_height);
|
||||
}
|
||||
|
||||
// Copy to I400. Source can be I420,422,444,400,NV12,NV21
|
||||
|
||||
140
source/scale.cc
140
source/scale.cc
@ -30,10 +30,7 @@ static __inline int Abs(int v) {
|
||||
return v >= 0 ? v : -v;
|
||||
}
|
||||
|
||||
static __inline int Half(int v) {
|
||||
return v >= 0 ? ((v + 1) >> 1) : -((-v + 1) >> 1);
|
||||
}
|
||||
|
||||
#define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s)
|
||||
|
||||
// Scale plane, 1/2
|
||||
// This is an optimized version for scaling down a plane to 1/2 of
|
||||
@ -763,8 +760,7 @@ static void ScalePlaneSimple(int src_width, int src_height,
|
||||
}
|
||||
|
||||
// Scale a plane.
|
||||
// This function in turn calls a scaling function suitable for handling
|
||||
// the desired resolutions.
|
||||
// This function dispatches to a specialized scaler based on scale factor.
|
||||
|
||||
LIBYUV_API
|
||||
void ScalePlane(const uint8* src, int src_stride,
|
||||
@ -772,6 +768,13 @@ void ScalePlane(const uint8* src, int src_stride,
|
||||
uint8* dst, int dst_stride,
|
||||
int dst_width, int dst_height,
|
||||
FilterMode filtering) {
|
||||
// Negative height means invert the image.
|
||||
if (src_height < 0) {
|
||||
src_height = -src_height;
|
||||
src = src + (src_height - 1) * src_stride;
|
||||
src_stride = -src_stride;
|
||||
}
|
||||
|
||||
// Use specialized scales to improve performance for common resolutions.
|
||||
// For example, all the 1/2 scalings will use ScalePlaneDown2()
|
||||
if (dst_width == src_width && dst_height == src_height) {
|
||||
@ -841,8 +844,6 @@ void ScalePlane(const uint8* src, int src_stride,
|
||||
|
||||
// Scale an I420 image.
|
||||
// This function in turn calls a scaling function for each plane.
|
||||
// TODO(fbarchard): Disable UNDER_ALLOCATED_HACK
|
||||
#define UNDER_ALLOCATED_HACK 1
|
||||
|
||||
LIBYUV_API
|
||||
int I420Scale(const uint8* src_y, int src_stride_y,
|
||||
@ -858,43 +859,10 @@ int I420Scale(const uint8* src_y, int src_stride_y,
|
||||
!dst_y || !dst_u || !dst_v || dst_width <= 0 || dst_height <= 0) {
|
||||
return -1;
|
||||
}
|
||||
// Negative height means invert the image.
|
||||
if (src_height < 0) {
|
||||
src_height = -src_height;
|
||||
int halfheight = Half(src_height);
|
||||
src_y = src_y + (src_height - 1) * src_stride_y;
|
||||
src_u = src_u + (halfheight - 1) * src_stride_u;
|
||||
src_v = src_v + (halfheight - 1) * src_stride_v;
|
||||
src_stride_y = -src_stride_y;
|
||||
src_stride_u = -src_stride_u;
|
||||
src_stride_v = -src_stride_v;
|
||||
}
|
||||
int src_halfwidth = Half(src_width);
|
||||
int src_halfheight = Half(src_height);
|
||||
int dst_halfwidth = Half(dst_width);
|
||||
int dst_halfheight = Half(dst_height);
|
||||
|
||||
#ifdef UNDER_ALLOCATED_HACK
|
||||
// If caller passed width / 2 for stride, adjust halfwidth to match.
|
||||
if ((src_width & 1) && src_stride_u && src_halfwidth > Abs(src_stride_u)) {
|
||||
src_halfwidth = src_width >> 1;
|
||||
}
|
||||
if ((dst_width & 1) && dst_stride_u && dst_halfwidth > Abs(dst_stride_u)) {
|
||||
dst_halfwidth = dst_width >> 1;
|
||||
}
|
||||
// If caller used height / 2 when computing src_v, it will point into what
|
||||
// should be the src_u plane. Detect this and reduce halfheight to match.
|
||||
int uv_src_plane_size = src_halfwidth * src_halfheight;
|
||||
if ((src_height & 1) &&
|
||||
(src_v > src_u) && (src_v < (src_u + uv_src_plane_size))) {
|
||||
src_halfheight = src_height >> 1;
|
||||
}
|
||||
int uv_dst_plane_size = dst_halfwidth * dst_halfheight;
|
||||
if ((dst_height & 1) &&
|
||||
(dst_v > dst_u) && (dst_v < (dst_u + uv_dst_plane_size))) {
|
||||
dst_halfheight = dst_height >> 1;
|
||||
}
|
||||
#endif
|
||||
int src_halfwidth = SUBSAMPLE(src_width, 1, 1);
|
||||
int src_halfheight = SUBSAMPLE(src_height, 1, 1);
|
||||
int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1);
|
||||
int dst_halfheight = SUBSAMPLE(dst_height, 1, 1);
|
||||
|
||||
ScalePlane(src_y, src_stride_y, src_width, src_height,
|
||||
dst_y, dst_stride_y, dst_width, dst_height,
|
||||
@ -917,59 +885,15 @@ int Scale(const uint8* src_y, const uint8* src_u, const uint8* src_v,
|
||||
int dst_stride_y, int dst_stride_u, int dst_stride_v,
|
||||
int dst_width, int dst_height,
|
||||
bool interpolate) {
|
||||
if (!src_y || !src_u || !src_v || src_width <= 0 || src_height == 0 ||
|
||||
!dst_y || !dst_u || !dst_v || dst_width <= 0 || dst_height <= 0) {
|
||||
return -1;
|
||||
}
|
||||
// Negative height means invert the image.
|
||||
if (src_height < 0) {
|
||||
src_height = -src_height;
|
||||
int halfheight = Half(src_height);
|
||||
src_y = src_y + (src_height - 1) * src_stride_y;
|
||||
src_u = src_u + (halfheight - 1) * src_stride_u;
|
||||
src_v = src_v + (halfheight - 1) * src_stride_v;
|
||||
src_stride_y = -src_stride_y;
|
||||
src_stride_u = -src_stride_u;
|
||||
src_stride_v = -src_stride_v;
|
||||
}
|
||||
int src_halfwidth = Half(src_width);
|
||||
int src_halfheight = Half(src_height);
|
||||
int dst_halfwidth = Half(dst_width);
|
||||
int dst_halfheight = Half(dst_height);
|
||||
FilterMode filtering = interpolate ? kFilterBox : kFilterNone;
|
||||
|
||||
#ifdef UNDER_ALLOCATED_HACK
|
||||
// If caller passed width / 2 for stride, adjust halfwidth to match.
|
||||
if ((src_width & 1) && src_stride_u && src_halfwidth > Abs(src_stride_u)) {
|
||||
src_halfwidth = src_width >> 1;
|
||||
}
|
||||
if ((dst_width & 1) && dst_stride_u && dst_halfwidth > Abs(dst_stride_u)) {
|
||||
dst_halfwidth = dst_width >> 1;
|
||||
}
|
||||
// If caller used height / 2 when computing src_v, it will point into what
|
||||
// should be the src_u plane. Detect this and reduce halfheight to match.
|
||||
int uv_src_plane_size = src_halfwidth * src_halfheight;
|
||||
if ((src_height & 1) &&
|
||||
(src_v > src_u) && (src_v < (src_u + uv_src_plane_size))) {
|
||||
src_halfheight = src_height >> 1;
|
||||
}
|
||||
int uv_dst_plane_size = dst_halfwidth * dst_halfheight;
|
||||
if ((dst_height & 1) &&
|
||||
(dst_v > dst_u) && (dst_v < (dst_u + uv_dst_plane_size))) {
|
||||
dst_halfheight = dst_height >> 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
ScalePlane(src_y, src_stride_y, src_width, src_height,
|
||||
dst_y, dst_stride_y, dst_width, dst_height,
|
||||
filtering);
|
||||
ScalePlane(src_u, src_stride_u, src_halfwidth, src_halfheight,
|
||||
dst_u, dst_stride_u, dst_halfwidth, dst_halfheight,
|
||||
filtering);
|
||||
ScalePlane(src_v, src_stride_v, src_halfwidth, src_halfheight,
|
||||
dst_v, dst_stride_v, dst_halfwidth, dst_halfheight,
|
||||
filtering);
|
||||
return 0;
|
||||
return I420Scale(src_y, src_stride_y,
|
||||
src_u, src_stride_u,
|
||||
src_v, src_stride_v,
|
||||
src_width, src_height,
|
||||
dst_y, dst_stride_y,
|
||||
dst_u, dst_stride_u,
|
||||
dst_v, dst_stride_v,
|
||||
dst_width, dst_height,
|
||||
interpolate ? kFilterBox : kFilterNone);
|
||||
}
|
||||
|
||||
// Deprecated api
|
||||
@ -983,10 +907,10 @@ int ScaleOffset(const uint8* src, int src_width, int src_height,
|
||||
return -1;
|
||||
}
|
||||
dst_yoffset = dst_yoffset & ~1; // chroma requires offset to multiple of 2.
|
||||
int src_halfwidth = Half(src_width);
|
||||
int src_halfheight = Half(src_height);
|
||||
int dst_halfwidth = Half(dst_width);
|
||||
int dst_halfheight = Half(dst_height);
|
||||
int src_halfwidth = SUBSAMPLE(src_width, 1, 1);
|
||||
int src_halfheight = SUBSAMPLE(src_height, 1, 1);
|
||||
int dst_halfwidth = SUBSAMPLE(dst_width, 1, 1);
|
||||
int dst_halfheight = SUBSAMPLE(dst_height, 1, 1);
|
||||
int aheight = dst_height - dst_yoffset * 2; // actual output height
|
||||
const uint8* src_y = src;
|
||||
const uint8* src_u = src + src_width * src_height;
|
||||
@ -997,9 +921,15 @@ int ScaleOffset(const uint8* src, int src_width, int src_height,
|
||||
(dst_yoffset >> 1) * dst_halfwidth;
|
||||
uint8* dst_v = dst + dst_width * dst_height + dst_halfwidth * dst_halfheight +
|
||||
(dst_yoffset >> 1) * dst_halfwidth;
|
||||
return Scale(src_y, src_u, src_v, src_width, src_halfwidth, src_halfwidth,
|
||||
src_width, src_height, dst_y, dst_u, dst_v, dst_width,
|
||||
dst_halfwidth, dst_halfwidth, dst_width, aheight, interpolate);
|
||||
return I420Scale(src_y, src_width,
|
||||
src_u, src_halfwidth,
|
||||
src_v, src_halfwidth,
|
||||
src_width, src_height,
|
||||
dst_y, dst_width,
|
||||
dst_u, dst_halfwidth,
|
||||
dst_v, dst_halfwidth,
|
||||
dst_width, aheight,
|
||||
interpolate ? kFilterBox : kFilterNone);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@ -462,7 +462,7 @@ void ScalePlaneVertical(int src_height,
|
||||
int bpp, FilterMode filtering) {
|
||||
int dst_widthx4 = dst_width * bpp;
|
||||
src_argb += (x >> 16) * bpp;
|
||||
assert(src_height > 0);
|
||||
assert(src_height != 0);
|
||||
assert(dst_width > 0);
|
||||
assert(dst_height > 0);
|
||||
void (*InterpolateRow)(uint8* dst_argb, const uint8* src_argb,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user