| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 The LibYuv Project Authors. All rights reserved. | 2 * Copyright 2012 The LibYuv Project Authors. All rights reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "libyuv/rotate.h" | 11 #include "libyuv/rotate.h" |
| 12 | 12 |
| 13 #include "libyuv/cpu_id.h" | 13 #include "libyuv/cpu_id.h" |
| 14 #include "libyuv/convert.h" | 14 #include "libyuv/convert.h" |
| 15 #include "libyuv/planar_functions.h" | 15 #include "libyuv/planar_functions.h" |
| 16 #include "libyuv/row.h" | 16 #include "libyuv/row.h" |
| 17 | 17 |
| 18 #ifdef __cplusplus | 18 #ifdef __cplusplus |
| 19 namespace libyuv { | 19 namespace libyuv { |
| 20 extern "C" { | 20 extern "C" { |
| 21 #endif | 21 #endif |
| 22 | 22 |
| 23 // ARGBScale has a function to copy pixels to a row, striding each source | 23 // ARGBScale has a function to copy pixels to a row, striding each source |
| 24 // pixel by a constant. | 24 // pixel by a constant. |
| 25 #if !defined(LIBYUV_DISABLE_X86) && \ | 25 #if !defined(LIBYUV_DISABLE_X86) && \ |
| 26 (defined(_M_IX86) || \ | 26 (defined(_M_IX86) || \ |
| 27 (defined(__x86_64__) && !defined(__native_client__)) || defined(__i386__)) | 27 (defined(__x86_64__) && !defined(__native_client__)) || defined(__i386__)) |
| 28 #define HAS_SCALEARGBROWDOWNEVEN_SSE2 | 28 #define HAS_SCALEARGBROWDOWNEVEN_SSE2 |
| 29 void ScaleARGBRowDownEven_SSE2(const uint8* src_ptr, int src_stride, | 29 void ScaleARGBRowDownEven_SSE2(const uint8* src_ptr, int src_stride, |
| 30 int src_stepx, | 30 int src_stepx, uint8* dst_ptr, int dst_width); |
| 31 uint8* dst_ptr, int dst_width); | |
| 32 #endif | 31 #endif |
| 33 #if !defined(LIBYUV_DISABLE_NEON) && !defined(__native_client__) && \ | 32 #if !defined(LIBYUV_DISABLE_NEON) && !defined(__native_client__) && \ |
| 34 (defined(__ARM_NEON__) || defined(LIBYUV_NEON) || defined(__aarch64__)) | 33 (defined(__ARM_NEON__) || defined(LIBYUV_NEON) || defined(__aarch64__)) |
| 35 #define HAS_SCALEARGBROWDOWNEVEN_NEON | 34 #define HAS_SCALEARGBROWDOWNEVEN_NEON |
| 36 void ScaleARGBRowDownEven_NEON(const uint8* src_ptr, int src_stride, | 35 void ScaleARGBRowDownEven_NEON(const uint8* src_ptr, int src_stride, |
| 37 int src_stepx, | 36 int src_stepx, uint8* dst_ptr, int dst_width); |
| 38 uint8* dst_ptr, int dst_width); | |
| 39 #endif | 37 #endif |
| 40 | 38 |
| 41 void ScaleARGBRowDownEven_C(const uint8* src_ptr, int, | 39 void ScaleARGBRowDownEven_C(const uint8* src_ptr, int, |
| 42 int src_stepx, | 40 int src_stepx, uint8* dst_ptr, int dst_width); |
| 43 uint8* dst_ptr, int dst_width); | |
| 44 | 41 |
| 45 static void ARGBTranspose(const uint8* src, int src_stride, | 42 static void ARGBTranspose(const uint8* src, int src_stride, |
| 46 uint8* dst, int dst_stride, | 43 uint8* dst, int dst_stride, int width, int height) { |
| 47 int width, int height) { | |
| 48 int i; | 44 int i; |
| 49 int src_pixel_step = src_stride >> 2; | 45 int src_pixel_step = src_stride >> 2; |
| 50 void (*ScaleARGBRowDownEven)(const uint8* src_ptr, int src_stride, | 46 void (*ScaleARGBRowDownEven)(const uint8* src_ptr, int src_stride, |
| 51 int src_step, uint8* dst_ptr, int dst_width) = ScaleARGBRowDownEven_C; | 47 int src_step, uint8* dst_ptr, int dst_width) = ScaleARGBRowDownEven_C; |
| 52 #if defined(HAS_SCALEARGBROWDOWNEVEN_SSE2) | 48 #if defined(HAS_SCALEARGBROWDOWNEVEN_SSE2) |
| 53 if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(height, 4)) { // Width of dest. | 49 if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(height, 4)) { // Width of dest. |
| 54 ScaleARGBRowDownEven = ScaleARGBRowDownEven_SSE2; | 50 ScaleARGBRowDownEven = ScaleARGBRowDownEven_SSE2; |
| 55 } | 51 } |
| 56 #endif | 52 #endif |
| 57 #if defined(HAS_SCALEARGBROWDOWNEVEN_NEON) | 53 #if defined(HAS_SCALEARGBROWDOWNEVEN_NEON) |
| 58 if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(height, 4)) { // Width of dest. | 54 if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(height, 4)) { // Width of dest. |
| 59 ScaleARGBRowDownEven = ScaleARGBRowDownEven_NEON; | 55 ScaleARGBRowDownEven = ScaleARGBRowDownEven_NEON; |
| 60 } | 56 } |
| 61 #endif | 57 #endif |
| 62 | 58 |
| 63 for (i = 0; i < width; ++i) { // column of source to row of dest. | 59 for (i = 0; i < width; ++i) { // column of source to row of dest. |
| 64 ScaleARGBRowDownEven(src, 0, src_pixel_step, dst, height); | 60 ScaleARGBRowDownEven(src, 0, src_pixel_step, dst, height); |
| 65 dst += dst_stride; | 61 dst += dst_stride; |
| 66 src += 4; | 62 src += 4; |
| 67 } | 63 } |
| 68 } | 64 } |
| 69 | 65 |
| 70 void ARGBRotate90(const uint8* src, int src_stride, | 66 void ARGBRotate90(const uint8* src, int src_stride, |
| 71 uint8* dst, int dst_stride, | 67 uint8* dst, int dst_stride, int width, int height) { |
| 72 int width, int height) { | |
| 73 // Rotate by 90 is a ARGBTranspose with the source read | 68 // Rotate by 90 is a ARGBTranspose with the source read |
| 74 // from bottom to top. So set the source pointer to the end | 69 // from bottom to top. So set the source pointer to the end |
| 75 // of the buffer and flip the sign of the source stride. | 70 // of the buffer and flip the sign of the source stride. |
| 76 src += src_stride * (height - 1); | 71 src += src_stride * (height - 1); |
| 77 src_stride = -src_stride; | 72 src_stride = -src_stride; |
| 78 ARGBTranspose(src, src_stride, dst, dst_stride, width, height); | 73 ARGBTranspose(src, src_stride, dst, dst_stride, width, height); |
| 79 } | 74 } |
| 80 | 75 |
| 81 void ARGBRotate270(const uint8* src, int src_stride, | 76 void ARGBRotate270(const uint8* src, int src_stride, |
| 82 uint8* dst, int dst_stride, | 77 uint8* dst, int dst_stride, int width, int height) { |
| 83 int width, int height) { | |
| 84 // Rotate by 270 is a ARGBTranspose with the destination written | 78 // Rotate by 270 is a ARGBTranspose with the destination written |
| 85 // from bottom to top. So set the destination pointer to the end | 79 // from bottom to top. So set the destination pointer to the end |
| 86 // of the buffer and flip the sign of the destination stride. | 80 // of the buffer and flip the sign of the destination stride. |
| 87 dst += dst_stride * (width - 1); | 81 dst += dst_stride * (width - 1); |
| 88 dst_stride = -dst_stride; | 82 dst_stride = -dst_stride; |
| 89 ARGBTranspose(src, src_stride, dst, dst_stride, width, height); | 83 ARGBTranspose(src, src_stride, dst, dst_stride, width, height); |
| 90 } | 84 } |
| 91 | 85 |
| 92 void ARGBRotate180(const uint8* src, int src_stride, | 86 void ARGBRotate180(const uint8* src, int src_stride, |
| 93 uint8* dst, int dst_stride, | 87 uint8* dst, int dst_stride, int width, int height) { |
| 94 int width, int height) { | |
| 95 // Swap first and last row and mirror the content. Uses a temporary row. | 88 // Swap first and last row and mirror the content. Uses a temporary row. |
| 96 align_buffer_64(row, width * 4); | 89 align_buffer_64(row, width * 4); |
| 97 const uint8* src_bot = src + src_stride * (height - 1); | 90 const uint8* src_bot = src + src_stride * (height - 1); |
| 98 uint8* dst_bot = dst + dst_stride * (height - 1); | 91 uint8* dst_bot = dst + dst_stride * (height - 1); |
| 99 int half_height = (height + 1) >> 1; | 92 int half_height = (height + 1) >> 1; |
| 100 int y; | 93 int y; |
| 101 void (*ARGBMirrorRow)(const uint8* src, uint8* dst, int width) = | 94 void (*ARGBMirrorRow)(const uint8* src, uint8* dst, int width) = |
| 102 ARGBMirrorRow_C; | 95 ARGBMirrorRow_C; |
| 103 void (*CopyRow)(const uint8* src, uint8* dst, int width) = CopyRow_C; | 96 void (*CopyRow)(const uint8* src, uint8* dst, int width) = CopyRow_C; |
| 104 #if defined(HAS_ARGBMIRRORROW_NEON) | 97 #if defined(HAS_ARGBMIRRORROW_NEON) |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 src += src_stride; | 152 src += src_stride; |
| 160 dst += dst_stride; | 153 dst += dst_stride; |
| 161 src_bot -= src_stride; | 154 src_bot -= src_stride; |
| 162 dst_bot -= dst_stride; | 155 dst_bot -= dst_stride; |
| 163 } | 156 } |
| 164 free_aligned_buffer_64(row); | 157 free_aligned_buffer_64(row); |
| 165 } | 158 } |
| 166 | 159 |
| 167 LIBYUV_API | 160 LIBYUV_API |
| 168 int ARGBRotate(const uint8* src_argb, int src_stride_argb, | 161 int ARGBRotate(const uint8* src_argb, int src_stride_argb, |
| 169 uint8* dst_argb, int dst_stride_argb, | 162 uint8* dst_argb, int dst_stride_argb, int width, int height, |
| 170 int width, int height, | |
| 171 enum RotationMode mode) { | 163 enum RotationMode mode) { |
| 172 if (!src_argb || width <= 0 || height == 0 || !dst_argb) { | 164 if (!src_argb || width <= 0 || height == 0 || !dst_argb) { |
| 173 return -1; | 165 return -1; |
| 174 } | 166 } |
| 175 | 167 |
| 176 // Negative height means invert the image. | 168 // Negative height means invert the image. |
| 177 if (height < 0) { | 169 if (height < 0) { |
| 178 height = -height; | 170 height = -height; |
| 179 src_argb = src_argb + (height - 1) * src_stride_argb; | 171 src_argb = src_argb + (height - 1) * src_stride_argb; |
| 180 src_stride_argb = -src_stride_argb; | 172 src_stride_argb = -src_stride_argb; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 204 default: | 196 default: |
| 205 break; | 197 break; |
| 206 } | 198 } |
| 207 return -1; | 199 return -1; |
| 208 } | 200 } |
| 209 | 201 |
| 210 #ifdef __cplusplus | 202 #ifdef __cplusplus |
| 211 } // extern "C" | 203 } // extern "C" |
| 212 } // namespace libyuv | 204 } // namespace libyuv |
| 213 #endif | 205 #endif |
| OLD | NEW |