1aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org/* 2b0c97975894a5eebebf9d93147cdd941a3accb63fbarchard@google.com * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org * 4aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org * Use of this source code is governed by a BSD-style license 5aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org * that can be found in the LICENSE file in the root of the source 6aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org * tree. An additional intellectual property rights grant can be found 7cde587092fef0dbed2c35602f30b79e7b892e766fbarchard@google.com * in the file PATENTS. All contributing project authors may 8aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org */ 10aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org 11a1280730c24b5c94ef16949777f65e597719488efbarchard@google.com#include "libyuv/planar_functions.h" 12aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org 130ab54406939b220e46eaee03f410ac88cc796762fbarchard@google.com#include <string.h> // for memset() 142842f2536d63eafb45f42052082225ab5fcb1e64fbarchard@google.com 15a1280730c24b5c94ef16949777f65e597719488efbarchard@google.com#include "libyuv/cpu_id.h" 167c8e16f82ae94e09c9657276a0ceedafbf036315fbarchard@google.com#ifdef HAVE_JPEG 177c8e16f82ae94e09c9657276a0ceedafbf036315fbarchard@google.com#include "libyuv/mjpeg_decoder.h" 187c8e16f82ae94e09c9657276a0ceedafbf036315fbarchard@google.com#endif 19142f6c4ed5eaeec0176f255e64bac8d8c70b42e1fbarchard@google.com#include "libyuv/row.h" 20aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org 21fe5ff7ed5451496281697bda9cb85084c532926cfbarchard@google.com#ifdef __cplusplus 22aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.orgnamespace libyuv { 23fe5ff7ed5451496281697bda9cb85084c532926cfbarchard@google.comextern "C" { 24fe5ff7ed5451496281697bda9cb85084c532926cfbarchard@google.com#endif 25aed1cc94c105736a5e6010e9c84cc32910b865d6mikhal@webrtc.org 262d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com// Copy a plane of data 27fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 282d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.comvoid CopyPlane(const uint8* src_y, int src_stride_y, 292d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com uint8* dst_y, int dst_stride_y, 302d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com int width, int height) { 3170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 3270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*CopyRow)(const uint8* src, uint8* dst, int width) = CopyRow_C; 33095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 34518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com if (src_stride_y == width && 35518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com dst_stride_y == width) { 36095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 37095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 38095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_y = dst_stride_y = 0; 39ba45bbff3419ad2004ebcb1ef7b878662341283bfbarchard@google.com } 40a9ff15b7bbd7b2a646f94328ff702091acde225afbarchard@google.com // Nothing to do. 41a9ff15b7bbd7b2a646f94328ff702091acde225afbarchard@google.com if (src_y == dst_y && src_stride_y == dst_stride_y) { 42a9ff15b7bbd7b2a646f94328ff702091acde225afbarchard@google.com return; 43a9ff15b7bbd7b2a646f94328ff702091acde225afbarchard@google.com } 44c5d44a0c5e3f67ebd64626a92d71478876ba4ff2fbarchard@google.com#if defined(HAS_COPYROW_X86) 45c5d44a0c5e3f67ebd64626a92d71478876ba4ff2fbarchard@google.com if (TestCpuFlag(kCpuHasX86) && IS_ALIGNED(width, 4)) { 462d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com CopyRow = CopyRow_X86; 47c5d44a0c5e3f67ebd64626a92d71478876ba4ff2fbarchard@google.com } 48ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com#endif 49c5d44a0c5e3f67ebd64626a92d71478876ba4ff2fbarchard@google.com#if defined(HAS_COPYROW_SSE2) 50c5d44a0c5e3f67ebd64626a92d71478876ba4ff2fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32) && 51c5d44a0c5e3f67ebd64626a92d71478876ba4ff2fbarchard@google.com IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) && 52c5d44a0c5e3f67ebd64626a92d71478876ba4ff2fbarchard@google.com IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { 53c5d44a0c5e3f67ebd64626a92d71478876ba4ff2fbarchard@google.com CopyRow = CopyRow_SSE2; 54ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com } 5519932f8dbc5ca3123d87b5b8369e7d7bf3469a97fbarchard@google.com#endif 56aa7988ff733b13d7bfd3c755bf0c18f93b9e8f6efbarchard@google.com#if defined(HAS_COPYROW_ERMS) 57aa7988ff733b13d7bfd3c755bf0c18f93b9e8f6efbarchard@google.com if (TestCpuFlag(kCpuHasERMS)) { 58aa7988ff733b13d7bfd3c755bf0c18f93b9e8f6efbarchard@google.com CopyRow = CopyRow_ERMS; 59b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com } 60b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#endif 61b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#if defined(HAS_COPYROW_NEON) 62b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 32)) { 63b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com CopyRow = CopyRow_NEON; 64b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com } 65b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#endif 666c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com#if defined(HAS_COPYROW_MIPS) 676c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com if (TestCpuFlag(kCpuHasMIPS)) { 686c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com CopyRow = CopyRow_MIPS; 696c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com } 706c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com#endif 719eefb2e8dd2c40a8b6bd0f02d794fe78332fc08ffbarchard@google.com 722d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com // Copy plane 7370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 742d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com CopyRow(src_y, dst_y, width); 75ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com src_y += src_stride_y; 762d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com dst_y += dst_stride_y; 77ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com } 78ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com} 79ecb3f4cc4e0a6e17daaebea1c1da63df9042984ffbarchard@google.com 80b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comLIBYUV_API 81b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.comvoid CopyPlane_16(const uint16* src_y, int src_stride_y, 82b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com uint16* dst_y, int dst_stride_y, 83b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com int width, int height) { 84b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com int y; 85b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com void (*CopyRow)(const uint16* src, uint16* dst, int width) = CopyRow_16_C; 86b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com // Coalesce rows. 87b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com if (src_stride_y == width && 88b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com dst_stride_y == width) { 89b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com width *= height; 90b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com height = 1; 91b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com src_stride_y = dst_stride_y = 0; 92b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com } 93b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#if defined(HAS_COPYROW_16_X86) 94b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com if (TestCpuFlag(kCpuHasX86) && IS_ALIGNED(width, 4)) { 95b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com CopyRow = CopyRow_16_X86; 96b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com } 97b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#endif 98b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#if defined(HAS_COPYROW_16_SSE2) 99b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32) && 100b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) && 101b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { 102b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com CopyRow = CopyRow_16_SSE2; 103b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com } 104b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#endif 105b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#if defined(HAS_COPYROW_16_ERMS) 106b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com if (TestCpuFlag(kCpuHasERMS)) { 107b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com CopyRow = CopyRow_16_ERMS; 108b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com } 109b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#endif 110b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#if defined(HAS_COPYROW_16_NEON) 111b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 32)) { 112b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com CopyRow = CopyRow_16_NEON; 113b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com } 114b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#endif 115b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#if defined(HAS_COPYROW_16_MIPS) 116b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com if (TestCpuFlag(kCpuHasMIPS)) { 117b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com CopyRow = CopyRow_16_MIPS; 118b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com } 119b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com#endif 120b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com 121b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com // Copy plane 122b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com for (y = 0; y < height; ++y) { 123b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com CopyRow(src_y, dst_y, width); 124b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com src_y += src_stride_y; 125b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com dst_y += dst_stride_y; 126b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com } 127b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com} 128b18413e568ae742114eabb8450b180db98a83be0fbarchard@google.com 129a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com// Copy I422. 130a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.comLIBYUV_API 131a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.comint I422Copy(const uint8* src_y, int src_stride_y, 132a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com const uint8* src_u, int src_stride_u, 133a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com const uint8* src_v, int src_stride_v, 134a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com uint8* dst_y, int dst_stride_y, 135a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com uint8* dst_u, int dst_stride_u, 136a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com uint8* dst_v, int dst_stride_v, 137a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com int width, int height) { 13870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int halfwidth = (width + 1) >> 1; 139a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com if (!src_y || !src_u || !src_v || 140a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com !dst_y || !dst_u || !dst_v || 141a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com width <= 0 || height == 0) { 142a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com return -1; 143a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com } 144a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com // Negative height means invert the image. 145a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com if (height < 0) { 146a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com height = -height; 147a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com src_y = src_y + (height - 1) * src_stride_y; 148a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com src_u = src_u + (height - 1) * src_stride_u; 149a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com src_v = src_v + (height - 1) * src_stride_v; 150a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com src_stride_y = -src_stride_y; 151a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com src_stride_u = -src_stride_u; 152a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com src_stride_v = -src_stride_v; 153a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com } 154a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); 155a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, height); 156a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, height); 157a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com return 0; 158a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com} 159a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com 160a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com// Copy I444. 161a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.comLIBYUV_API 162a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.comint I444Copy(const uint8* src_y, int src_stride_y, 163a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com const uint8* src_u, int src_stride_u, 164a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com const uint8* src_v, int src_stride_v, 165a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com uint8* dst_y, int dst_stride_y, 166a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com uint8* dst_u, int dst_stride_u, 167a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com uint8* dst_v, int dst_stride_v, 168a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com int width, int height) { 169a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com if (!src_y || !src_u || !src_v || 170a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com !dst_y || !dst_u || !dst_v || 171a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com width <= 0 || height == 0) { 172a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com return -1; 173a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com } 174a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com // Negative height means invert the image. 175a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com if (height < 0) { 176a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com height = -height; 177a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com src_y = src_y + (height - 1) * src_stride_y; 178a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com src_u = src_u + (height - 1) * src_stride_u; 179a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com src_v = src_v + (height - 1) * src_stride_v; 180a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com src_stride_y = -src_stride_y; 181a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com src_stride_u = -src_stride_u; 182a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com src_stride_v = -src_stride_v; 183a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com } 184a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com 185a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); 186a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, width, height); 187a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, width, height); 188a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com return 0; 189a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com} 190a00da62e52167966bde5bc11cc0470e87136b652fbarchard@google.com 1916b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.com// Copy I400. 1926b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.comLIBYUV_API 1936b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.comint I400ToI400(const uint8* src_y, int src_stride_y, 1946b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.com uint8* dst_y, int dst_stride_y, 1956b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.com int width, int height) { 1966b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.com if (!src_y || !dst_y || width <= 0 || height == 0) { 1976b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.com return -1; 1986b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.com } 1996b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.com // Negative height means invert the image. 2006b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.com if (height < 0) { 2016b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.com height = -height; 2026b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.com src_y = src_y + (height - 1) * src_stride_y; 2036b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.com src_stride_y = -src_stride_y; 2046b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.com } 2056b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.com CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); 2066b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.com return 0; 2076b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.com} 2086b5a8efff7759c941f5a11ead2f67330dea2f14cfbarchard@google.com 209bf8b0f0e2ba4e647efa88e44833c7fd383a1becefbarchard@google.com// Convert I420 to I400. 210fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 211e214fe3f070d47d34e3cfbf4431994f97c9e0d1bfbarchard@google.comint I420ToI400(const uint8* src_y, int src_stride_y, 2121f923e3ea6de7afd9380c73f60a2f3e7b0588811fbarchard@google.com const uint8* src_u, int src_stride_u, 2131f923e3ea6de7afd9380c73f60a2f3e7b0588811fbarchard@google.com const uint8* src_v, int src_stride_v, 214e214fe3f070d47d34e3cfbf4431994f97c9e0d1bfbarchard@google.com uint8* dst_y, int dst_stride_y, 215e214fe3f070d47d34e3cfbf4431994f97c9e0d1bfbarchard@google.com int width, int height) { 216c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com if (!src_y || !dst_y || width <= 0 || height == 0) { 217e214fe3f070d47d34e3cfbf4431994f97c9e0d1bfbarchard@google.com return -1; 218e214fe3f070d47d34e3cfbf4431994f97c9e0d1bfbarchard@google.com } 219e214fe3f070d47d34e3cfbf4431994f97c9e0d1bfbarchard@google.com // Negative height means invert the image. 220e214fe3f070d47d34e3cfbf4431994f97c9e0d1bfbarchard@google.com if (height < 0) { 221e214fe3f070d47d34e3cfbf4431994f97c9e0d1bfbarchard@google.com height = -height; 222e214fe3f070d47d34e3cfbf4431994f97c9e0d1bfbarchard@google.com src_y = src_y + (height - 1) * src_stride_y; 223e214fe3f070d47d34e3cfbf4431994f97c9e0d1bfbarchard@google.com src_stride_y = -src_stride_y; 224e214fe3f070d47d34e3cfbf4431994f97c9e0d1bfbarchard@google.com } 225e214fe3f070d47d34e3cfbf4431994f97c9e0d1bfbarchard@google.com CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); 226e214fe3f070d47d34e3cfbf4431994f97c9e0d1bfbarchard@google.com return 0; 227e214fe3f070d47d34e3cfbf4431994f97c9e0d1bfbarchard@google.com} 228e214fe3f070d47d34e3cfbf4431994f97c9e0d1bfbarchard@google.com 229aae7deb5cf7269144e04045d3e0fa05054759dbefbarchard@google.com// Mirror a plane of data. 2302d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.comvoid MirrorPlane(const uint8* src_y, int src_stride_y, 2312d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com uint8* dst_y, int dst_stride_y, 232ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com int width, int height) { 23370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 23470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*MirrorRow)(const uint8* src, uint8* dst, int width) = MirrorRow_C; 235aae7deb5cf7269144e04045d3e0fa05054759dbefbarchard@google.com // Negative height means invert the image. 236aae7deb5cf7269144e04045d3e0fa05054759dbefbarchard@google.com if (height < 0) { 237aae7deb5cf7269144e04045d3e0fa05054759dbefbarchard@google.com height = -height; 238aae7deb5cf7269144e04045d3e0fa05054759dbefbarchard@google.com src_y = src_y + (height - 1) * src_stride_y; 239aae7deb5cf7269144e04045d3e0fa05054759dbefbarchard@google.com src_stride_y = -src_stride_y; 240aae7deb5cf7269144e04045d3e0fa05054759dbefbarchard@google.com } 2412d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com#if defined(HAS_MIRRORROW_NEON) 2422d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16)) { 2432d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com MirrorRow = MirrorRow_NEON; 2440ab54406939b220e46eaee03f410ac88cc796762fbarchard@google.com } 2459eefb2e8dd2c40a8b6bd0f02d794fe78332fc08ffbarchard@google.com#endif 2462d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com#if defined(HAS_MIRRORROW_SSE2) 2472d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16)) { 2482d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com MirrorRow = MirrorRow_SSE2; 2493e46444727a0524d2f1d81117e0b1404148ac910fbarchard@google.com } 2503e46444727a0524d2f1d81117e0b1404148ac910fbarchard@google.com#endif 2510ab54406939b220e46eaee03f410ac88cc796762fbarchard@google.com#if defined(HAS_MIRRORROW_SSSE3) 252b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 16) && 253b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) && 254b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { 255b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com MirrorRow = MirrorRow_SSSE3; 256b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com } 2570ab54406939b220e46eaee03f410ac88cc796762fbarchard@google.com#endif 2582007dca6dcfee6828f604068d7d17842fbe5d646fbarchard@google.com#if defined(HAS_MIRRORROW_AVX2) 2592007dca6dcfee6828f604068d7d17842fbe5d646fbarchard@google.com if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 32)) { 2602007dca6dcfee6828f604068d7d17842fbe5d646fbarchard@google.com MirrorRow = MirrorRow_AVX2; 2612007dca6dcfee6828f604068d7d17842fbe5d646fbarchard@google.com } 2622007dca6dcfee6828f604068d7d17842fbe5d646fbarchard@google.com#endif 2639eefb2e8dd2c40a8b6bd0f02d794fe78332fc08ffbarchard@google.com 2642d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com // Mirror plane 26570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 2662d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com MirrorRow(src_y, dst_y, width); 267ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com src_y += src_stride_y; 2682d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com dst_y += dst_stride_y; 269ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com } 270ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com} 271ecb3f4cc4e0a6e17daaebea1c1da63df9042984ffbarchard@google.com 27264ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com// Convert YUY2 to I422. 27364ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.comLIBYUV_API 27464ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.comint YUY2ToI422(const uint8* src_yuy2, int src_stride_yuy2, 27564ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com uint8* dst_y, int dst_stride_y, 27664ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com uint8* dst_u, int dst_stride_u, 27764ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com uint8* dst_v, int dst_stride_v, 27864ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com int width, int height) { 27970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 28070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*YUY2ToUV422Row)(const uint8* src_yuy2, 28170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* dst_u, uint8* dst_v, int pix) = 28270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com YUY2ToUV422Row_C; 28370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*YUY2ToYRow)(const uint8* src_yuy2, uint8* dst_y, int pix) = 28470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com YUY2ToYRow_C; 28564ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com // Negative height means invert the image. 28664ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com if (height < 0) { 28764ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com height = -height; 28864ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2; 28964ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com src_stride_yuy2 = -src_stride_yuy2; 29064ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 291095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 292518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com if (src_stride_yuy2 == width * 2 && 29311a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com dst_stride_y == width && 294518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com dst_stride_u * 2 == width && 295518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com dst_stride_v * 2 == width) { 296095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 297095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 298095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_yuy2 = dst_stride_y = dst_stride_u = dst_stride_v = 0; 29911a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 30064ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com#if defined(HAS_YUY2TOYROW_SSE2) 301b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { 302b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com YUY2ToUV422Row = YUY2ToUV422Row_Any_SSE2; 303b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com YUY2ToYRow = YUY2ToYRow_Any_SSE2; 30464ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com if (IS_ALIGNED(width, 16)) { 30564ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com YUY2ToUV422Row = YUY2ToUV422Row_Unaligned_SSE2; 30664ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com YUY2ToYRow = YUY2ToYRow_Unaligned_SSE2; 30764ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com if (IS_ALIGNED(src_yuy2, 16) && IS_ALIGNED(src_stride_yuy2, 16)) { 30864ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com YUY2ToUV422Row = YUY2ToUV422Row_SSE2; 30964ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { 31064ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com YUY2ToYRow = YUY2ToYRow_SSE2; 31164ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 31264ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 31364ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 31464ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 315b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#endif 316b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#if defined(HAS_YUY2TOYROW_AVX2) 317b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com if (TestCpuFlag(kCpuHasAVX2) && width >= 32) { 318b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com YUY2ToUV422Row = YUY2ToUV422Row_Any_AVX2; 319b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com YUY2ToYRow = YUY2ToYRow_Any_AVX2; 320b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com if (IS_ALIGNED(width, 32)) { 321b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com YUY2ToUV422Row = YUY2ToUV422Row_AVX2; 322b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com YUY2ToYRow = YUY2ToYRow_AVX2; 323b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com } 324b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com } 325b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#endif 326b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#if defined(HAS_YUY2TOYROW_NEON) 327b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 328b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com YUY2ToYRow = YUY2ToYRow_Any_NEON; 329b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com if (width >= 16) { 330b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com YUY2ToUV422Row = YUY2ToUV422Row_Any_NEON; 33164ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 33264ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com if (IS_ALIGNED(width, 16)) { 33364ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com YUY2ToYRow = YUY2ToYRow_NEON; 33464ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com YUY2ToUV422Row = YUY2ToUV422Row_NEON; 33564ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 33664ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 33764ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com#endif 33864ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com 33970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 34064ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com YUY2ToUV422Row(src_yuy2, dst_u, dst_v, width); 34164ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com YUY2ToYRow(src_yuy2, dst_y, width); 34264ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com src_yuy2 += src_stride_yuy2; 34364ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com dst_y += dst_stride_y; 34464ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com dst_u += dst_stride_u; 34564ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com dst_v += dst_stride_v; 34664ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 34764ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com return 0; 34864ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com} 34964ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com 35064ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com// Convert UYVY to I422. 35164ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.comLIBYUV_API 35264ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.comint UYVYToI422(const uint8* src_uyvy, int src_stride_uyvy, 35364ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com uint8* dst_y, int dst_stride_y, 35464ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com uint8* dst_u, int dst_stride_u, 35564ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com uint8* dst_v, int dst_stride_v, 35664ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com int width, int height) { 35770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 35870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*UYVYToUV422Row)(const uint8* src_uyvy, 35970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* dst_u, uint8* dst_v, int pix) = 36070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com UYVYToUV422Row_C; 36170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*UYVYToYRow)(const uint8* src_uyvy, 36270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* dst_y, int pix) = UYVYToYRow_C; 36364ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com // Negative height means invert the image. 36464ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com if (height < 0) { 36564ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com height = -height; 36664ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy; 36764ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com src_stride_uyvy = -src_stride_uyvy; 36864ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 369095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 370518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com if (src_stride_uyvy == width * 2 && 37111a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com dst_stride_y == width && 372518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com dst_stride_u * 2 == width && 373518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com dst_stride_v * 2 == width) { 374095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 375095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 376095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_uyvy = dst_stride_y = dst_stride_u = dst_stride_v = 0; 37711a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 37864ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com#if defined(HAS_UYVYTOYROW_SSE2) 379b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { 380b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com UYVYToUV422Row = UYVYToUV422Row_Any_SSE2; 381b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com UYVYToYRow = UYVYToYRow_Any_SSE2; 38264ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com if (IS_ALIGNED(width, 16)) { 38364ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com UYVYToUV422Row = UYVYToUV422Row_Unaligned_SSE2; 38464ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com UYVYToYRow = UYVYToYRow_Unaligned_SSE2; 38564ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com if (IS_ALIGNED(src_uyvy, 16) && IS_ALIGNED(src_stride_uyvy, 16)) { 38664ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com UYVYToUV422Row = UYVYToUV422Row_SSE2; 38764ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { 38864ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com UYVYToYRow = UYVYToYRow_SSE2; 38964ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 39064ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 39164ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 39264ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 393b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#endif 394b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#if defined(HAS_UYVYTOYROW_AVX2) 395b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com if (TestCpuFlag(kCpuHasAVX2) && width >= 32) { 396b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com UYVYToUV422Row = UYVYToUV422Row_Any_AVX2; 397b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com UYVYToYRow = UYVYToYRow_Any_AVX2; 398b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com if (IS_ALIGNED(width, 32)) { 399b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com UYVYToUV422Row = UYVYToUV422Row_AVX2; 400b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com UYVYToYRow = UYVYToYRow_AVX2; 401b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com } 402b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com } 403b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#endif 404b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com#if defined(HAS_UYVYTOYROW_NEON) 405b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 406b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com UYVYToYRow = UYVYToYRow_Any_NEON; 407b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com if (width >= 16) { 408b444bae883e97c1e4579f2e1148cf14f9c7c18fbfbarchard@google.com UYVYToUV422Row = UYVYToUV422Row_Any_NEON; 40964ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 41064ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com if (IS_ALIGNED(width, 16)) { 41164ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com UYVYToYRow = UYVYToYRow_NEON; 41264ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com UYVYToUV422Row = UYVYToUV422Row_NEON; 41364ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 41464ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 41564ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com#endif 41664ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com 41770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 41864ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com UYVYToUV422Row(src_uyvy, dst_u, dst_v, width); 41964ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com UYVYToYRow(src_uyvy, dst_y, width); 42064ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com src_uyvy += src_stride_uyvy; 42164ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com dst_y += dst_stride_y; 42264ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com dst_u += dst_stride_u; 42364ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com dst_v += dst_stride_v; 42464ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com } 42564ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com return 0; 42664ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com} 42764ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com 4286bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com// Mirror I400 with optional flipping 4296bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.comLIBYUV_API 4306bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.comint I400Mirror(const uint8* src_y, int src_stride_y, 4316bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com uint8* dst_y, int dst_stride_y, 4326bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com int width, int height) { 4336bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com if (!src_y || !dst_y || 4346bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com width <= 0 || height == 0) { 4356bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com return -1; 4366bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com } 4376bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com // Negative height means invert the image. 4386bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com if (height < 0) { 4396bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com height = -height; 4406bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com src_y = src_y + (height - 1) * src_stride_y; 4416bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com src_stride_y = -src_stride_y; 4426bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com } 4436bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com 4446bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com MirrorPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); 4456bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com return 0; 4466bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com} 4476bb9f53f4fcf1d40fdb345323a084057e67a508dfbarchard@google.com 4482d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com// Mirror I420 with optional flipping 449fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 4502d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.comint I420Mirror(const uint8* src_y, int src_stride_y, 4512d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com const uint8* src_u, int src_stride_u, 4522d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com const uint8* src_v, int src_stride_v, 4532d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com uint8* dst_y, int dst_stride_y, 4542d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com uint8* dst_u, int dst_stride_u, 4552d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com uint8* dst_v, int dst_stride_v, 4562d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com int width, int height) { 45770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int halfwidth = (width + 1) >> 1; 45870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int halfheight = (height + 1) >> 1; 459c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com if (!src_y || !src_u || !src_v || !dst_y || !dst_u || !dst_v || 4602d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com width <= 0 || height == 0) { 4612d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com return -1; 4622d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com } 463ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com // Negative height means invert the image. 464ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com if (height < 0) { 465ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com height = -height; 46670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com halfheight = (height + 1) >> 1; 4672d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com src_y = src_y + (height - 1) * src_stride_y; 4682d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com src_u = src_u + (halfheight - 1) * src_stride_u; 4692d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com src_v = src_v + (halfheight - 1) * src_stride_v; 4702d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com src_stride_y = -src_stride_y; 4712d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com src_stride_u = -src_stride_u; 4722d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com src_stride_v = -src_stride_v; 473ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com } 4749eefb2e8dd2c40a8b6bd0f02d794fe78332fc08ffbarchard@google.com 4752d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com if (dst_y) { 4762d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com MirrorPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); 477ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com } 4782d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com MirrorPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, halfheight); 4792d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com MirrorPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, halfheight); 480ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com return 0; 481ba1f52692605bbf8fedb8a915275c71fa186d291fbarchard@google.com} 4829eefb2e8dd2c40a8b6bd0f02d794fe78332fc08ffbarchard@google.com 48327d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com// ARGB mirror. 484fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 48527d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.comint ARGBMirror(const uint8* src_argb, int src_stride_argb, 48627d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com uint8* dst_argb, int dst_stride_argb, 48727d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com int width, int height) { 48870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 48970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBMirrorRow)(const uint8* src, uint8* dst, int width) = 49070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com ARGBMirrorRow_C; 491c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com if (!src_argb || !dst_argb || width <= 0 || height == 0) { 49227d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com return -1; 49327d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com } 49427d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com // Negative height means invert the image. 49527d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com if (height < 0) { 49627d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com height = -height; 49727d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com src_argb = src_argb + (height - 1) * src_stride_argb; 49827d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com src_stride_argb = -src_stride_argb; 49927d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com } 50027d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com 50127d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com#if defined(HAS_ARGBMIRRORROW_SSSE3) 50227d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 4) && 50327d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && 50427d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { 50527d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com ARGBMirrorRow = ARGBMirrorRow_SSSE3; 50627d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com } 50751398e0be5004b8818df4a4ccda9fe77bcfaf141fbarchard@google.com#endif 50851398e0be5004b8818df4a4ccda9fe77bcfaf141fbarchard@google.com#if defined(HAS_ARGBMIRRORROW_AVX2) 50951398e0be5004b8818df4a4ccda9fe77bcfaf141fbarchard@google.com if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 8)) { 51051398e0be5004b8818df4a4ccda9fe77bcfaf141fbarchard@google.com ARGBMirrorRow = ARGBMirrorRow_AVX2; 51151398e0be5004b8818df4a4ccda9fe77bcfaf141fbarchard@google.com } 51251398e0be5004b8818df4a4ccda9fe77bcfaf141fbarchard@google.com#endif 51351398e0be5004b8818df4a4ccda9fe77bcfaf141fbarchard@google.com#if defined(HAS_ARGBMIRRORROW_NEON) 5143e46444727a0524d2f1d81117e0b1404148ac910fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 4)) { 5153e46444727a0524d2f1d81117e0b1404148ac910fbarchard@google.com ARGBMirrorRow = ARGBMirrorRow_NEON; 5163e46444727a0524d2f1d81117e0b1404148ac910fbarchard@google.com } 51727d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com#endif 51827d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com 51927d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com // Mirror plane 52070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 52127d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com ARGBMirrorRow(src_argb, dst_argb, width); 52227d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com src_argb += src_stride_argb; 52327d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com dst_argb += dst_stride_argb; 52427d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com } 52527d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com return 0; 52627d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com} 52727d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com 528d2f4413d29d15b94d971630ba555dd0cd8fcc8c2fbarchard@google.com// Get a blender that optimized for the CPU, alignment and pixel count. 529d2f4413d29d15b94d971630ba555dd0cd8fcc8c2fbarchard@google.com// As there are 6 blenders to choose from, the caller should try to use 530d2f4413d29d15b94d971630ba555dd0cd8fcc8c2fbarchard@google.com// the same blend function for all pixels if possible. 531fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 532bac5f2c3ee12535817448e606c7a7704bbae8321fbarchard@google.comARGBBlendRow GetARGBBlend() { 533d2f4413d29d15b94d971630ba555dd0cd8fcc8c2fbarchard@google.com void (*ARGBBlendRow)(const uint8* src_argb, const uint8* src_argb1, 534d2f4413d29d15b94d971630ba555dd0cd8fcc8c2fbarchard@google.com uint8* dst_argb, int width) = ARGBBlendRow_C; 5355ff3a8fec5fa54bca8905f1eb6eb69c14d5fb79ffbarchard@google.com#if defined(HAS_ARGBBLENDROW_SSSE3) 536bac5f2c3ee12535817448e606c7a7704bbae8321fbarchard@google.com if (TestCpuFlag(kCpuHasSSSE3)) { 537bac5f2c3ee12535817448e606c7a7704bbae8321fbarchard@google.com ARGBBlendRow = ARGBBlendRow_SSSE3; 5385ff3a8fec5fa54bca8905f1eb6eb69c14d5fb79ffbarchard@google.com return ARGBBlendRow; 5395ff3a8fec5fa54bca8905f1eb6eb69c14d5fb79ffbarchard@google.com } 5405ff3a8fec5fa54bca8905f1eb6eb69c14d5fb79ffbarchard@google.com#endif 541da5cc4274b69efe633293a489e7c9550733daf5cfbarchard@google.com#if defined(HAS_ARGBBLENDROW_SSE2) 542bac5f2c3ee12535817448e606c7a7704bbae8321fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2)) { 543bac5f2c3ee12535817448e606c7a7704bbae8321fbarchard@google.com ARGBBlendRow = ARGBBlendRow_SSE2; 544965fb914ea3f5057cd186763c9af5d3110c44acdfbarchard@google.com } 545965fb914ea3f5057cd186763c9af5d3110c44acdfbarchard@google.com#endif 5468f506332af217882648eed166a257557855b9fdbfbarchard@google.com#if defined(HAS_ARGBBLENDROW_NEON) 5478f506332af217882648eed166a257557855b9fdbfbarchard@google.com if (TestCpuFlag(kCpuHasNEON)) { 5488f506332af217882648eed166a257557855b9fdbfbarchard@google.com ARGBBlendRow = ARGBBlendRow_NEON; 5498f506332af217882648eed166a257557855b9fdbfbarchard@google.com } 5508f506332af217882648eed166a257557855b9fdbfbarchard@google.com#endif 551d2f4413d29d15b94d971630ba555dd0cd8fcc8c2fbarchard@google.com return ARGBBlendRow; 552c757f308eab211f9d5467a089052e7d84606f6c1fbarchard@google.com} 553c757f308eab211f9d5467a089052e7d84606f6c1fbarchard@google.com 554c757f308eab211f9d5467a089052e7d84606f6c1fbarchard@google.com// Alpha Blend 2 ARGB images and store to destination. 555fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 556d2f4413d29d15b94d971630ba555dd0cd8fcc8c2fbarchard@google.comint ARGBBlend(const uint8* src_argb0, int src_stride_argb0, 55727d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com const uint8* src_argb1, int src_stride_argb1, 55827d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com uint8* dst_argb, int dst_stride_argb, 55927d42c7ff6452c53643bc57ee8b7b17afbe8dfd0fbarchard@google.com int width, int height) { 56070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 56170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBBlendRow)(const uint8* src_argb, const uint8* src_argb1, 56270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* dst_argb, int width) = GetARGBBlend(); 563c757f308eab211f9d5467a089052e7d84606f6c1fbarchard@google.com if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) { 564c757f308eab211f9d5467a089052e7d84606f6c1fbarchard@google.com return -1; 565c757f308eab211f9d5467a089052e7d84606f6c1fbarchard@google.com } 566c757f308eab211f9d5467a089052e7d84606f6c1fbarchard@google.com // Negative height means invert the image. 567c757f308eab211f9d5467a089052e7d84606f6c1fbarchard@google.com if (height < 0) { 568c757f308eab211f9d5467a089052e7d84606f6c1fbarchard@google.com height = -height; 569c757f308eab211f9d5467a089052e7d84606f6c1fbarchard@google.com dst_argb = dst_argb + (height - 1) * dst_stride_argb; 570c757f308eab211f9d5467a089052e7d84606f6c1fbarchard@google.com dst_stride_argb = -dst_stride_argb; 571c757f308eab211f9d5467a089052e7d84606f6c1fbarchard@google.com } 572095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 57311a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com if (src_stride_argb0 == width * 4 && 57411a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com src_stride_argb1 == width * 4 && 57511a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com dst_stride_argb == width * 4) { 576095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 577095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 578095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0; 57911a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 580c757f308eab211f9d5467a089052e7d84606f6c1fbarchard@google.com 58170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 582d2f4413d29d15b94d971630ba555dd0cd8fcc8c2fbarchard@google.com ARGBBlendRow(src_argb0, src_argb1, dst_argb, width); 583c757f308eab211f9d5467a089052e7d84606f6c1fbarchard@google.com src_argb0 += src_stride_argb0; 584c757f308eab211f9d5467a089052e7d84606f6c1fbarchard@google.com src_argb1 += src_stride_argb1; 585c757f308eab211f9d5467a089052e7d84606f6c1fbarchard@google.com dst_argb += dst_stride_argb; 586965fb914ea3f5057cd186763c9af5d3110c44acdfbarchard@google.com } 587965fb914ea3f5057cd186763c9af5d3110c44acdfbarchard@google.com return 0; 588965fb914ea3f5057cd186763c9af5d3110c44acdfbarchard@google.com} 589965fb914ea3f5057cd186763c9af5d3110c44acdfbarchard@google.com 59051d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com// Multiply 2 ARGB images and store to destination. 5918fa76349948802d728dd244a7b54051d751d8696fbarchard@google.comLIBYUV_API 5928fa76349948802d728dd244a7b54051d751d8696fbarchard@google.comint ARGBMultiply(const uint8* src_argb0, int src_stride_argb0, 5938fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com const uint8* src_argb1, int src_stride_argb1, 5948fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com uint8* dst_argb, int dst_stride_argb, 5958fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com int width, int height) { 59670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 59770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBMultiplyRow)(const uint8* src0, const uint8* src1, uint8* dst, 59870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width) = ARGBMultiplyRow_C; 5998fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) { 6008fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com return -1; 6018fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com } 6028fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com // Negative height means invert the image. 6038fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com if (height < 0) { 6048fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com height = -height; 6058fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com dst_argb = dst_argb + (height - 1) * dst_stride_argb; 6068fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com dst_stride_argb = -dst_stride_argb; 6078fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com } 608095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 60951d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com if (src_stride_argb0 == width * 4 && 61051d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com src_stride_argb1 == width * 4 && 61151d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com dst_stride_argb == width * 4) { 612095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 613095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 614095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0; 61551d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com } 6168fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com#if defined(HAS_ARGBMULTIPLYROW_SSE2) 617bb92acade0cd17a83ad32177da6a449b2962066efbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && width >= 4) { 6188fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com ARGBMultiplyRow = ARGBMultiplyRow_Any_SSE2; 6198fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com if (IS_ALIGNED(width, 4)) { 6208fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com ARGBMultiplyRow = ARGBMultiplyRow_SSE2; 6218fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com } 6228fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com } 62351d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com#endif 62451d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com#if defined(HAS_ARGBMULTIPLYROW_AVX2) 62551d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com if (TestCpuFlag(kCpuHasAVX2) && width >= 8) { 62651d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com ARGBMultiplyRow = ARGBMultiplyRow_Any_AVX2; 62751d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com if (IS_ALIGNED(width, 8)) { 62851d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com ARGBMultiplyRow = ARGBMultiplyRow_AVX2; 62951d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com } 63051d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com } 63151d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com#endif 63251d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com#if defined(HAS_ARGBMULTIPLYROW_NEON) 6335b0f7e1132bbf79dc3d70dcf225646fcbc5875e2fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 6345b0f7e1132bbf79dc3d70dcf225646fcbc5875e2fbarchard@google.com ARGBMultiplyRow = ARGBMultiplyRow_Any_NEON; 6355b0f7e1132bbf79dc3d70dcf225646fcbc5875e2fbarchard@google.com if (IS_ALIGNED(width, 8)) { 6365b0f7e1132bbf79dc3d70dcf225646fcbc5875e2fbarchard@google.com ARGBMultiplyRow = ARGBMultiplyRow_NEON; 6375b0f7e1132bbf79dc3d70dcf225646fcbc5875e2fbarchard@google.com } 6388fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com } 6398fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com#endif 6408fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com 6418fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com // Multiply plane 64270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 6438fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com ARGBMultiplyRow(src_argb0, src_argb1, dst_argb, width); 6448fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com src_argb0 += src_stride_argb0; 6458fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com src_argb1 += src_stride_argb1; 6468fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com dst_argb += dst_stride_argb; 6478fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com } 6488fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com return 0; 6498fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com} 6508fa76349948802d728dd244a7b54051d751d8696fbarchard@google.com 65151d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com// Add 2 ARGB images and store to destination. 65283e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.comLIBYUV_API 65383e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.comint ARGBAdd(const uint8* src_argb0, int src_stride_argb0, 65483e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com const uint8* src_argb1, int src_stride_argb1, 65583e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com uint8* dst_argb, int dst_stride_argb, 65683e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com int width, int height) { 65770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 65870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBAddRow)(const uint8* src0, const uint8* src1, uint8* dst, 65970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width) = ARGBAddRow_C; 66083e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) { 66183e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com return -1; 66283e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com } 66383e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com // Negative height means invert the image. 66483e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com if (height < 0) { 66583e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com height = -height; 66683e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com dst_argb = dst_argb + (height - 1) * dst_stride_argb; 66783e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com dst_stride_argb = -dst_stride_argb; 66883e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com } 669095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 67051d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com if (src_stride_argb0 == width * 4 && 67151d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com src_stride_argb1 == width * 4 && 67251d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com dst_stride_argb == width * 4) { 673095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 674095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 675095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0; 67651d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com } 677bb92acade0cd17a83ad32177da6a449b2962066efbarchard@google.com#if defined(HAS_ARGBADDROW_SSE2) && defined(_MSC_VER) 678bb92acade0cd17a83ad32177da6a449b2962066efbarchard@google.com if (TestCpuFlag(kCpuHasSSE2)) { 679bb92acade0cd17a83ad32177da6a449b2962066efbarchard@google.com ARGBAddRow = ARGBAddRow_SSE2; 680bb92acade0cd17a83ad32177da6a449b2962066efbarchard@google.com } 681bb92acade0cd17a83ad32177da6a449b2962066efbarchard@google.com#endif 682bb92acade0cd17a83ad32177da6a449b2962066efbarchard@google.com#if defined(HAS_ARGBADDROW_SSE2) && !defined(_MSC_VER) 683bb92acade0cd17a83ad32177da6a449b2962066efbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && width >= 4) { 68483e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com ARGBAddRow = ARGBAddRow_Any_SSE2; 68583e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com if (IS_ALIGNED(width, 4)) { 68683e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com ARGBAddRow = ARGBAddRow_SSE2; 68783e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com } 68883e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com } 68951d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com#endif 69051d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com#if defined(HAS_ARGBADDROW_AVX2) 69151d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com if (TestCpuFlag(kCpuHasAVX2) && width >= 8) { 69251d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com ARGBAddRow = ARGBAddRow_Any_AVX2; 69351d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com if (IS_ALIGNED(width, 8)) { 69451d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com ARGBAddRow = ARGBAddRow_AVX2; 69551d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com } 69651d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com } 69751d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com#endif 69851d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com#if defined(HAS_ARGBADDROW_NEON) 6995b0f7e1132bbf79dc3d70dcf225646fcbc5875e2fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 7005b0f7e1132bbf79dc3d70dcf225646fcbc5875e2fbarchard@google.com ARGBAddRow = ARGBAddRow_Any_NEON; 7015b0f7e1132bbf79dc3d70dcf225646fcbc5875e2fbarchard@google.com if (IS_ALIGNED(width, 8)) { 7025b0f7e1132bbf79dc3d70dcf225646fcbc5875e2fbarchard@google.com ARGBAddRow = ARGBAddRow_NEON; 7035b0f7e1132bbf79dc3d70dcf225646fcbc5875e2fbarchard@google.com } 70483e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com } 70583e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com#endif 70683e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com 70783e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com // Add plane 70870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 70983e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com ARGBAddRow(src_argb0, src_argb1, dst_argb, width); 71083e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com src_argb0 += src_stride_argb0; 71183e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com src_argb1 += src_stride_argb1; 71283e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com dst_argb += dst_stride_argb; 71383e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com } 71483e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com return 0; 71583e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com} 71683e1b17cc0b1840c7b5e361fa19e7263fca2b32bfbarchard@google.com 717573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com// Subtract 2 ARGB images and store to destination. 718573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.comLIBYUV_API 719573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.comint ARGBSubtract(const uint8* src_argb0, int src_stride_argb0, 720573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com const uint8* src_argb1, int src_stride_argb1, 721573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com uint8* dst_argb, int dst_stride_argb, 722573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com int width, int height) { 72370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 72470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBSubtractRow)(const uint8* src0, const uint8* src1, uint8* dst, 72570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width) = ARGBSubtractRow_C; 726573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) { 727573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com return -1; 728573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com } 729573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com // Negative height means invert the image. 730573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com if (height < 0) { 731573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com height = -height; 732573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com dst_argb = dst_argb + (height - 1) * dst_stride_argb; 733573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com dst_stride_argb = -dst_stride_argb; 734573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com } 735095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 73651d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com if (src_stride_argb0 == width * 4 && 73751d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com src_stride_argb1 == width * 4 && 73851d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com dst_stride_argb == width * 4) { 739095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 740095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 741095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0; 74251d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com } 743573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com#if defined(HAS_ARGBSUBTRACTROW_SSE2) 744bb92acade0cd17a83ad32177da6a449b2962066efbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && width >= 4) { 745573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com ARGBSubtractRow = ARGBSubtractRow_Any_SSE2; 746573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com if (IS_ALIGNED(width, 4)) { 747573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com ARGBSubtractRow = ARGBSubtractRow_SSE2; 748573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com } 749573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com } 75051d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com#endif 75151d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com#if defined(HAS_ARGBSUBTRACTROW_AVX2) 75251d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com if (TestCpuFlag(kCpuHasAVX2) && width >= 8) { 75351d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com ARGBSubtractRow = ARGBSubtractRow_Any_AVX2; 75451d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com if (IS_ALIGNED(width, 8)) { 75551d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com ARGBSubtractRow = ARGBSubtractRow_AVX2; 75651d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com } 75751d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com } 75851d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com#endif 75951d3e236cb5923c60ba818b6e825c2658b565afefbarchard@google.com#if defined(HAS_ARGBSUBTRACTROW_NEON) 760573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 761573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com ARGBSubtractRow = ARGBSubtractRow_Any_NEON; 762573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com if (IS_ALIGNED(width, 8)) { 763573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com ARGBSubtractRow = ARGBSubtractRow_NEON; 764573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com } 765573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com } 766573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com#endif 767573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com 768573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com // Subtract plane 76970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 770573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com ARGBSubtractRow(src_argb0, src_argb1, dst_argb, width); 771573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com src_argb0 += src_stride_argb0; 772573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com src_argb1 += src_stride_argb1; 773573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com dst_argb += dst_stride_argb; 774573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com } 775573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com return 0; 776573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com} 777573a883dd65c94a10422e6e9e0d453e2a5d45227fbarchard@google.com 778cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com// Convert I422 to BGRA. 779fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 780cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.comint I422ToBGRA(const uint8* src_y, int src_stride_y, 781cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com const uint8* src_u, int src_stride_u, 782cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com const uint8* src_v, int src_stride_v, 783cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com uint8* dst_bgra, int dst_stride_bgra, 784cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com int width, int height) { 78570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 78670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*I422ToBGRARow)(const uint8* y_buf, 78770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com const uint8* u_buf, 78870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com const uint8* v_buf, 78970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* rgb_buf, 79070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width) = I422ToBGRARow_C; 791cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (!src_y || !src_u || !src_v || 792cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com !dst_bgra || 793cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com width <= 0 || height == 0) { 794cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com return -1; 795cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 796cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com // Negative height means invert the image. 797cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (height < 0) { 798cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com height = -height; 799cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com dst_bgra = dst_bgra + (height - 1) * dst_stride_bgra; 800cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com dst_stride_bgra = -dst_stride_bgra; 801cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 802095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 803518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com if (src_stride_y == width && 804518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com src_stride_u * 2 == width && 805518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com src_stride_v * 2 == width && 80611a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com dst_stride_bgra == width * 4) { 807095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 808095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 809095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_y = src_stride_u = src_stride_v = dst_stride_bgra = 0; 81011a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 811cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com#if defined(HAS_I422TOBGRAROW_NEON) 812cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (TestCpuFlag(kCpuHasNEON)) { 813cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToBGRARow = I422ToBGRARow_Any_NEON; 814cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (IS_ALIGNED(width, 16)) { 815cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToBGRARow = I422ToBGRARow_NEON; 816cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 817cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 818cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com#elif defined(HAS_I422TOBGRAROW_SSSE3) 819cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { 820cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToBGRARow = I422ToBGRARow_Any_SSSE3; 821cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (IS_ALIGNED(width, 8)) { 822cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToBGRARow = I422ToBGRARow_Unaligned_SSSE3; 823cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (IS_ALIGNED(dst_bgra, 16) && IS_ALIGNED(dst_stride_bgra, 16)) { 824cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToBGRARow = I422ToBGRARow_SSSE3; 825cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 826cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 827cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 8286c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com#elif defined(HAS_I422TOBGRAROW_MIPS_DSPR2) 8296c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) && 8306c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && 8316c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) && 8326c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) && 8336c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com IS_ALIGNED(dst_bgra, 4) && IS_ALIGNED(dst_stride_bgra, 4)) { 8346c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com I422ToBGRARow = I422ToBGRARow_MIPS_DSPR2; 8356c1b2d38c685e769cf7db2806e27c8ec4c028fe3fbarchard@google.com } 836cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com#endif 837cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com 83870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 839cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToBGRARow(src_y, src_u, src_v, dst_bgra, width); 840cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com dst_bgra += dst_stride_bgra; 841cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com src_y += src_stride_y; 842cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com src_u += src_stride_u; 843cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com src_v += src_stride_v; 844cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 845cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com return 0; 846cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com} 847cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com 848cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com// Convert I422 to ABGR. 849fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 850cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.comint I422ToABGR(const uint8* src_y, int src_stride_y, 851cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com const uint8* src_u, int src_stride_u, 852cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com const uint8* src_v, int src_stride_v, 853cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com uint8* dst_abgr, int dst_stride_abgr, 854cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com int width, int height) { 85570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 85670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*I422ToABGRRow)(const uint8* y_buf, 85770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com const uint8* u_buf, 85870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com const uint8* v_buf, 85970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* rgb_buf, 86070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width) = I422ToABGRRow_C; 861cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (!src_y || !src_u || !src_v || 862cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com !dst_abgr || 863cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com width <= 0 || height == 0) { 864cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com return -1; 865cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 866cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com // Negative height means invert the image. 867cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (height < 0) { 868cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com height = -height; 869cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com dst_abgr = dst_abgr + (height - 1) * dst_stride_abgr; 870cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com dst_stride_abgr = -dst_stride_abgr; 871cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 872095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 873518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com if (src_stride_y == width && 874518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com src_stride_u * 2 == width && 875518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com src_stride_v * 2 == width && 87611a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com dst_stride_abgr == width * 4) { 877095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 878095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 879095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_y = src_stride_u = src_stride_v = dst_stride_abgr = 0; 88011a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 881cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com#if defined(HAS_I422TOABGRROW_NEON) 882cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (TestCpuFlag(kCpuHasNEON)) { 883cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToABGRRow = I422ToABGRRow_Any_NEON; 884cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (IS_ALIGNED(width, 16)) { 885cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToABGRRow = I422ToABGRRow_NEON; 886cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 887cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 888cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com#elif defined(HAS_I422TOABGRROW_SSSE3) 889cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { 890cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToABGRRow = I422ToABGRRow_Any_SSSE3; 891cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (IS_ALIGNED(width, 8)) { 892cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToABGRRow = I422ToABGRRow_Unaligned_SSSE3; 893cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (IS_ALIGNED(dst_abgr, 16) && IS_ALIGNED(dst_stride_abgr, 16)) { 894cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToABGRRow = I422ToABGRRow_SSSE3; 895cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 896cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 897cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 898cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com#endif 899cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com 90070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 901cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToABGRRow(src_y, src_u, src_v, dst_abgr, width); 902cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com dst_abgr += dst_stride_abgr; 903cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com src_y += src_stride_y; 904cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com src_u += src_stride_u; 905cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com src_v += src_stride_v; 906cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 907cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com return 0; 908cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com} 909cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com 910cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com// Convert I422 to RGBA. 911fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 912cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.comint I422ToRGBA(const uint8* src_y, int src_stride_y, 913cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com const uint8* src_u, int src_stride_u, 914cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com const uint8* src_v, int src_stride_v, 915cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com uint8* dst_rgba, int dst_stride_rgba, 916cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com int width, int height) { 91770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 91870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*I422ToRGBARow)(const uint8* y_buf, 91970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com const uint8* u_buf, 92070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com const uint8* v_buf, 92170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* rgb_buf, 92270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width) = I422ToRGBARow_C; 923cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (!src_y || !src_u || !src_v || 924cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com !dst_rgba || 925cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com width <= 0 || height == 0) { 926cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com return -1; 927cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 928cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com // Negative height means invert the image. 929cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (height < 0) { 930cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com height = -height; 931cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba; 932cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com dst_stride_rgba = -dst_stride_rgba; 933cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 934095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 935518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com if (src_stride_y == width && 936518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com src_stride_u * 2 == width && 937518833b9833a52b715b487445e6ccfe4f8881903fbarchard@google.com src_stride_v * 2 == width && 93811a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com dst_stride_rgba == width * 4) { 939095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 940095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 941095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_y = src_stride_u = src_stride_v = dst_stride_rgba = 0; 94211a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 943cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com#if defined(HAS_I422TORGBAROW_NEON) 944cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (TestCpuFlag(kCpuHasNEON)) { 945cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToRGBARow = I422ToRGBARow_Any_NEON; 946cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (IS_ALIGNED(width, 16)) { 947cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToRGBARow = I422ToRGBARow_NEON; 948cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 949cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 950cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com#elif defined(HAS_I422TORGBAROW_SSSE3) 951cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { 952cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToRGBARow = I422ToRGBARow_Any_SSSE3; 953cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (IS_ALIGNED(width, 8)) { 954cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToRGBARow = I422ToRGBARow_Unaligned_SSSE3; 955cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com if (IS_ALIGNED(dst_rgba, 16) && IS_ALIGNED(dst_stride_rgba, 16)) { 956cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToRGBARow = I422ToRGBARow_SSSE3; 957cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 958cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 959cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 960cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com#endif 961cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com 96270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 963cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com I422ToRGBARow(src_y, src_u, src_v, dst_rgba, width); 964cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com dst_rgba += dst_stride_rgba; 965cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com src_y += src_stride_y; 966cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com src_u += src_stride_u; 967cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com src_v += src_stride_v; 968cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com } 969cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com return 0; 970cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com} 971cad0ad303cc84195646fbb57014aa73bbe986c48fbarchard@google.com 9722d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com// Convert NV12 to RGB565. 973fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 9742d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.comint NV12ToRGB565(const uint8* src_y, int src_stride_y, 9752d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com const uint8* src_uv, int src_stride_uv, 9762d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com uint8* dst_rgb565, int dst_stride_rgb565, 9772d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com int width, int height) { 97870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 97970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*NV12ToRGB565Row)(const uint8* y_buf, 98070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com const uint8* uv_buf, 98170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* rgb_buf, 98270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width) = NV12ToRGB565Row_C; 9839f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com if (!src_y || !src_uv || !dst_rgb565 || 9849f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com width <= 0 || height == 0) { 985c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com return -1; 986c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com } 9872d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com // Negative height means invert the image. 9882d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com if (height < 0) { 9892d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com height = -height; 9902d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565; 9912d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com dst_stride_rgb565 = -dst_stride_rgb565; 9922d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com } 9939f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com#if defined(HAS_NV12TORGB565ROW_SSSE3) 994b2a51d042d9ccc49de6180880e5fed3d07067d95fbarchard@google.com if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { 9959f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com NV12ToRGB565Row = NV12ToRGB565Row_Any_SSSE3; 99615449263c4bba75bc396dc3d60266efee6ab6c66fbarchard@google.com if (IS_ALIGNED(width, 8)) { 9979f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com NV12ToRGB565Row = NV12ToRGB565Row_SSSE3; 99815449263c4bba75bc396dc3d60266efee6ab6c66fbarchard@google.com } 9992d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com } 10009f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com#elif defined(HAS_NV12TORGB565ROW_NEON) 100115449263c4bba75bc396dc3d60266efee6ab6c66fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 10029f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com NV12ToRGB565Row = NV12ToRGB565Row_Any_NEON; 100315449263c4bba75bc396dc3d60266efee6ab6c66fbarchard@google.com if (IS_ALIGNED(width, 8)) { 10049f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com NV12ToRGB565Row = NV12ToRGB565Row_NEON; 10058d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com } 1006fc99814a9271b1981fb21e8235f9d73161a4109ffbarchard@google.com } 10070ab54406939b220e46eaee03f410ac88cc796762fbarchard@google.com#endif 1008fc99814a9271b1981fb21e8235f9d73161a4109ffbarchard@google.com 100970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 10109f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com NV12ToRGB565Row(src_y, src_uv, dst_rgb565, width); 10112d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com dst_rgb565 += dst_stride_rgb565; 10122d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com src_y += src_stride_y; 10132d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com if (y & 1) { 1014fc99814a9271b1981fb21e8235f9d73161a4109ffbarchard@google.com src_uv += src_stride_uv; 1015fc99814a9271b1981fb21e8235f9d73161a4109ffbarchard@google.com } 10162d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com } 10172d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com return 0; 10182d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com} 10192d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com 10202d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com// Convert NV21 to RGB565. 1021fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 10222d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.comint NV21ToRGB565(const uint8* src_y, int src_stride_y, 10239f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com const uint8* src_vu, int src_stride_vu, 10242d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com uint8* dst_rgb565, int dst_stride_rgb565, 10252d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com int width, int height) { 102670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 102770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*NV21ToRGB565Row)(const uint8* y_buf, 102870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com const uint8* src_vu, 102970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* rgb_buf, 103070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width) = NV21ToRGB565Row_C; 10319f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com if (!src_y || !src_vu || !dst_rgb565 || 10329f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com width <= 0 || height == 0) { 1033c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com return -1; 1034c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com } 10352d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com // Negative height means invert the image. 10362d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com if (height < 0) { 10372d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com height = -height; 10382d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565; 10392d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com dst_stride_rgb565 = -dst_stride_rgb565; 10402d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com } 10419f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com#if defined(HAS_NV21TORGB565ROW_SSSE3) 1042b2a51d042d9ccc49de6180880e5fed3d07067d95fbarchard@google.com if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { 10439f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com NV21ToRGB565Row = NV21ToRGB565Row_Any_SSSE3; 104415449263c4bba75bc396dc3d60266efee6ab6c66fbarchard@google.com if (IS_ALIGNED(width, 8)) { 10459f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com NV21ToRGB565Row = NV21ToRGB565Row_SSSE3; 104615449263c4bba75bc396dc3d60266efee6ab6c66fbarchard@google.com } 10472d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com } 10489f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com#elif defined(HAS_NV21TORGB565ROW_NEON) 104915449263c4bba75bc396dc3d60266efee6ab6c66fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 10509f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com NV21ToRGB565Row = NV21ToRGB565Row_Any_NEON; 105115449263c4bba75bc396dc3d60266efee6ab6c66fbarchard@google.com if (IS_ALIGNED(width, 8)) { 10529f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com NV21ToRGB565Row = NV21ToRGB565Row_NEON; 10538d37dd5c205216e0ad13c5091061908cb981c5f9fbarchard@google.com } 10542d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com } 10552d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com#endif 10562d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com 105770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 10589f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com NV21ToRGB565Row(src_y, src_vu, dst_rgb565, width); 10592d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com dst_rgb565 += dst_stride_rgb565; 1060fc99814a9271b1981fb21e8235f9d73161a4109ffbarchard@google.com src_y += src_stride_y; 10612d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com if (y & 1) { 10629f2d404145e8a69d209eb130975442ab3f29d5a7fbarchard@google.com src_vu += src_stride_vu; 10632d9fe08225ab28f62b515b2b914accc6a7b060fbfbarchard@google.com } 1064fc99814a9271b1981fb21e8235f9d73161a4109ffbarchard@google.com } 1065fc99814a9271b1981fb21e8235f9d73161a4109ffbarchard@google.com return 0; 1066fc99814a9271b1981fb21e8235f9d73161a4109ffbarchard@google.com} 1067fc99814a9271b1981fb21e8235f9d73161a4109ffbarchard@google.com 1068fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 10692d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.comvoid SetPlane(uint8* dst_y, int dst_stride_y, 10702d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com int width, int height, 10712d11d43a6e21865b904705acce6535ae4c2d3caffbarchard@google.com uint32 value) { 107270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 107370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint32 v32 = value | (value << 8) | (value << 16) | (value << 24); 107470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*SetRow)(uint8* dst, uint32 value, int pix) = SetRow_C; 1075095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 107611a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com if (dst_stride_y == width) { 1077095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 1078095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 1079095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com dst_stride_y = 0; 108011a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 10813e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com#if defined(HAS_SETROW_NEON) 10823e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && 10833e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com IS_ALIGNED(width, 16) && 10843e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { 1085f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com SetRow = SetRow_NEON; 10860ab54406939b220e46eaee03f410ac88cc796762fbarchard@google.com } 1087c5d44a0c5e3f67ebd64626a92d71478876ba4ff2fbarchard@google.com#endif 1088c5d44a0c5e3f67ebd64626a92d71478876ba4ff2fbarchard@google.com#if defined(HAS_SETROW_X86) 1089c5d44a0c5e3f67ebd64626a92d71478876ba4ff2fbarchard@google.com if (TestCpuFlag(kCpuHasX86) && IS_ALIGNED(width, 4)) { 1090f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com SetRow = SetRow_X86; 1091c5d44a0c5e3f67ebd64626a92d71478876ba4ff2fbarchard@google.com } 1092c5d44a0c5e3f67ebd64626a92d71478876ba4ff2fbarchard@google.com#endif 10933e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com 10943e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com // Set plane 109570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 10963e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com SetRow(dst_y, v32, width); 10973e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com dst_y += dst_stride_y; 10983e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com } 10993e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com} 11003e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com 11013e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com// Draw a rectangle into I420 1102fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 11033e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.comint I420Rect(uint8* dst_y, int dst_stride_y, 11043e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com uint8* dst_u, int dst_stride_u, 11053e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com uint8* dst_v, int dst_stride_v, 11063e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com int x, int y, 11073e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com int width, int height, 11083e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com int value_y, int value_u, int value_v) { 110970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int halfwidth = (width + 1) >> 1; 111070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int halfheight = (height + 1) >> 1; 111170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* start_y = dst_y + y * dst_stride_y + x; 111270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* start_u = dst_u + (y / 2) * dst_stride_u + (x / 2); 111370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* start_v = dst_v + (y / 2) * dst_stride_v + (x / 2); 11143e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com if (!dst_y || !dst_u || !dst_v || 11153e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com width <= 0 || height <= 0 || 11163e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com x < 0 || y < 0 || 11173e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com value_y < 0 || value_y > 255 || 11183e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com value_u < 0 || value_u > 255 || 11193e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com value_v < 0 || value_v > 255) { 11203e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com return -1; 11213e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com } 11223e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com 11233e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com SetPlane(start_y, dst_stride_y, width, height, value_y); 11243e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com SetPlane(start_u, dst_stride_u, halfwidth, halfheight, value_u); 11253e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com SetPlane(start_v, dst_stride_v, halfwidth, halfheight, value_v); 11263e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com return 0; 11273e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com} 11283e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com 11293e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com// Draw a rectangle into ARGB 1130fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 11313e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.comint ARGBRect(uint8* dst_argb, int dst_stride_argb, 1132120b8d7ee72bb07c0f58fa2a2245cd6436736579fbarchard@google.com int dst_x, int dst_y, 11333e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com int width, int height, 11343e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com uint32 value) { 11353e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com if (!dst_argb || 11363e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com width <= 0 || height <= 0 || 1137120b8d7ee72bb07c0f58fa2a2245cd6436736579fbarchard@google.com dst_x < 0 || dst_y < 0) { 11383e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com return -1; 11393e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com } 1140095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com dst_argb += dst_y * dst_stride_argb + dst_x * 4; 1141095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 114211a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com if (dst_stride_argb == width * 4) { 1143095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 1144095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 1145095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com dst_stride_argb = 0; 114611a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 1147d2f4413d29d15b94d971630ba555dd0cd8fcc8c2fbarchard@google.com#if defined(HAS_SETROW_NEON) 11480ab54406939b220e46eaee03f410ac88cc796762fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16) && 1149095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { 1150095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com ARGBSetRows_NEON(dst_argb, value, width, dst_stride_argb, height); 11510ab54406939b220e46eaee03f410ac88cc796762fbarchard@google.com return 0; 11520ab54406939b220e46eaee03f410ac88cc796762fbarchard@google.com } 1153d2f4413d29d15b94d971630ba555dd0cd8fcc8c2fbarchard@google.com#endif 1154c5d44a0c5e3f67ebd64626a92d71478876ba4ff2fbarchard@google.com#if defined(HAS_SETROW_X86) 1155c5d44a0c5e3f67ebd64626a92d71478876ba4ff2fbarchard@google.com if (TestCpuFlag(kCpuHasX86)) { 1156095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com ARGBSetRows_X86(dst_argb, value, width, dst_stride_argb, height); 1157c5d44a0c5e3f67ebd64626a92d71478876ba4ff2fbarchard@google.com return 0; 1158c5d44a0c5e3f67ebd64626a92d71478876ba4ff2fbarchard@google.com } 11590ab54406939b220e46eaee03f410ac88cc796762fbarchard@google.com#endif 1160095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com ARGBSetRows_C(dst_argb, value, width, dst_stride_argb, height); 11614f59bcc102643b700102fe5e55c5fc0e1159a00cfbarchard@google.com return 0; 11623e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com} 11633e8a577bb383154f2a4e978ef615eaafed746e1dfbarchard@google.com 1164da5cc4274b69efe633293a489e7c9550733daf5cfbarchard@google.com// Convert unattentuated ARGB to preattenuated ARGB. 1165829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com// An unattenutated ARGB alpha blend uses the formula 1166829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com// p = a * f + (1 - a) * b 1167829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com// where 1168829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com// p is output pixel 1169829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com// f is foreground pixel 1170829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com// b is background pixel 1171829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com// a is alpha value from foreground pixel 1172829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com// An preattenutated ARGB alpha blend uses the formula 1173829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com// p = f + (1 - a) * b 1174829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com// where 1175829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com// f is foreground pixel premultiplied by alpha 1176829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com 1177fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 1178829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.comint ARGBAttenuate(const uint8* src_argb, int src_stride_argb, 1179829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com uint8* dst_argb, int dst_stride_argb, 1180829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com int width, int height) { 118170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 118270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBAttenuateRow)(const uint8* src_argb, uint8* dst_argb, 118370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width) = ARGBAttenuateRow_C; 1184c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com if (!src_argb || !dst_argb || width <= 0 || height == 0) { 1185c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com return -1; 1186c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com } 1187829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com if (height < 0) { 1188829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com height = -height; 1189829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com src_argb = src_argb + (height - 1) * src_stride_argb; 1190829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com src_stride_argb = -src_stride_argb; 1191829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com } 1192095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 119311a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com if (src_stride_argb == width * 4 && 119411a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com dst_stride_argb == width * 4) { 1195095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 1196095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 1197095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_argb = dst_stride_argb = 0; 119811a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 11991d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com#if defined(HAS_ARGBATTENUATEROW_SSE2) 12001d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && width >= 4 && 12018ed54222e723037322579f15c36d4faddb924e91fbarchard@google.com IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && 12028ed54222e723037322579f15c36d4faddb924e91fbarchard@google.com IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { 12031d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com ARGBAttenuateRow = ARGBAttenuateRow_Any_SSE2; 12041d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com if (IS_ALIGNED(width, 4)) { 12051d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com ARGBAttenuateRow = ARGBAttenuateRow_SSE2; 12061d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com } 12078ed54222e723037322579f15c36d4faddb924e91fbarchard@google.com } 12088ed54222e723037322579f15c36d4faddb924e91fbarchard@google.com#endif 1209eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com#if defined(HAS_ARGBATTENUATEROW_SSSE3) 121038157bdc719c403a620218bc2a35af0f9b4adc85fbarchard@google.com if (TestCpuFlag(kCpuHasSSSE3) && width >= 4) { 12111d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3; 12121d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com if (IS_ALIGNED(width, 4)) { 12131d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com ARGBAttenuateRow = ARGBAttenuateRow_SSSE3; 12141d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com } 12151d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com } 12161d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com#endif 1217d5ee3dc9123c9fa4e90ec6b90a5c45f8434cac3ffbarchard@google.com#if defined(HAS_ARGBATTENUATEROW_AVX2) 1218c0d9c3469062e20430685565a3e4bb1d7042d147fbarchard@google.com if (TestCpuFlag(kCpuHasAVX2) && width >= 8) { 1219c0d9c3469062e20430685565a3e4bb1d7042d147fbarchard@google.com ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2; 1220c0d9c3469062e20430685565a3e4bb1d7042d147fbarchard@google.com if (IS_ALIGNED(width, 8)) { 1221c0d9c3469062e20430685565a3e4bb1d7042d147fbarchard@google.com ARGBAttenuateRow = ARGBAttenuateRow_AVX2; 1222c0d9c3469062e20430685565a3e4bb1d7042d147fbarchard@google.com } 1223d5ee3dc9123c9fa4e90ec6b90a5c45f8434cac3ffbarchard@google.com } 1224d5ee3dc9123c9fa4e90ec6b90a5c45f8434cac3ffbarchard@google.com#endif 12251d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com#if defined(HAS_ARGBATTENUATEROW_NEON) 12261d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 12271d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON; 12281d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com if (IS_ALIGNED(width, 8)) { 12291d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com ARGBAttenuateRow = ARGBAttenuateRow_NEON; 12301d160cb99f2b05df80c4555bd769825ad1175dc9fbarchard@google.com } 1231f2c86d01cc46b0851e0bf88429dd064b8c8b0dbafbarchard@google.com } 1232f2c86d01cc46b0851e0bf88429dd064b8c8b0dbafbarchard@google.com#endif 1233829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com 123470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 12358ed54222e723037322579f15c36d4faddb924e91fbarchard@google.com ARGBAttenuateRow(src_argb, dst_argb, width); 1236829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com src_argb += src_stride_argb; 1237829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com dst_argb += dst_stride_argb; 1238829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com } 1239829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com return 0; 1240829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com} 1241829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com 1242da5cc4274b69efe633293a489e7c9550733daf5cfbarchard@google.com// Convert preattentuated ARGB to unattenuated ARGB. 1243fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 1244829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.comint ARGBUnattenuate(const uint8* src_argb, int src_stride_argb, 1245829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com uint8* dst_argb, int dst_stride_argb, 1246829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com int width, int height) { 124770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 124870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBUnattenuateRow)(const uint8* src_argb, uint8* dst_argb, 124970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width) = ARGBUnattenuateRow_C; 1250c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com if (!src_argb || !dst_argb || width <= 0 || height == 0) { 1251c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com return -1; 1252c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com } 1253829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com if (height < 0) { 1254829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com height = -height; 1255829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com src_argb = src_argb + (height - 1) * src_stride_argb; 1256829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com src_stride_argb = -src_stride_argb; 1257829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com } 1258095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 125911a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com if (src_stride_argb == width * 4 && 126011a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com dst_stride_argb == width * 4) { 1261095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 1262095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 1263095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_argb = dst_stride_argb = 0; 126411a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 1265eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com#if defined(HAS_ARGBUNATTENUATEROW_SSE2) 126638157bdc719c403a620218bc2a35af0f9b4adc85fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && width >= 4) { 1267c0d9c3469062e20430685565a3e4bb1d7042d147fbarchard@google.com ARGBUnattenuateRow = ARGBUnattenuateRow_Any_SSE2; 1268c0d9c3469062e20430685565a3e4bb1d7042d147fbarchard@google.com if (IS_ALIGNED(width, 4)) { 1269c0d9c3469062e20430685565a3e4bb1d7042d147fbarchard@google.com ARGBUnattenuateRow = ARGBUnattenuateRow_SSE2; 1270c0d9c3469062e20430685565a3e4bb1d7042d147fbarchard@google.com } 12718ed54222e723037322579f15c36d4faddb924e91fbarchard@google.com } 12728ed54222e723037322579f15c36d4faddb924e91fbarchard@google.com#endif 12733c7bb050bd54264f360ced29c1cd2777483bd6f0fbarchard@google.com#if defined(HAS_ARGBUNATTENUATEROW_AVX2) 1274c0d9c3469062e20430685565a3e4bb1d7042d147fbarchard@google.com if (TestCpuFlag(kCpuHasAVX2) && width >= 8) { 1275c0d9c3469062e20430685565a3e4bb1d7042d147fbarchard@google.com ARGBUnattenuateRow = ARGBUnattenuateRow_Any_AVX2; 1276c0d9c3469062e20430685565a3e4bb1d7042d147fbarchard@google.com if (IS_ALIGNED(width, 8)) { 1277c0d9c3469062e20430685565a3e4bb1d7042d147fbarchard@google.com ARGBUnattenuateRow = ARGBUnattenuateRow_AVX2; 1278c0d9c3469062e20430685565a3e4bb1d7042d147fbarchard@google.com } 12793c7bb050bd54264f360ced29c1cd2777483bd6f0fbarchard@google.com } 12803c7bb050bd54264f360ced29c1cd2777483bd6f0fbarchard@google.com#endif 12813c7bb050bd54264f360ced29c1cd2777483bd6f0fbarchard@google.com// TODO(fbarchard): Neon version. 1282829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com 128370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 12848ed54222e723037322579f15c36d4faddb924e91fbarchard@google.com ARGBUnattenuateRow(src_argb, dst_argb, width); 1285829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com src_argb += src_stride_argb; 1286829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com dst_argb += dst_stride_argb; 1287829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com } 1288829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com return 0; 1289829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com} 1290829e7ea402a06fa616e4c70ee91675318e00e134fbarchard@google.com 1291eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com// Convert ARGB to Grayed ARGB. 1292fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 1293eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.comint ARGBGrayTo(const uint8* src_argb, int src_stride_argb, 1294eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com uint8* dst_argb, int dst_stride_argb, 1295eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com int width, int height) { 129670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 129770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBGrayRow)(const uint8* src_argb, uint8* dst_argb, 129870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width) = ARGBGrayRow_C; 1299eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com if (!src_argb || !dst_argb || width <= 0 || height == 0) { 1300eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com return -1; 1301eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com } 1302eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com if (height < 0) { 1303eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com height = -height; 1304eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com src_argb = src_argb + (height - 1) * src_stride_argb; 1305eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com src_stride_argb = -src_stride_argb; 1306eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com } 1307095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 130811a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com if (src_stride_argb == width * 4 && 130911a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com dst_stride_argb == width * 4) { 1310095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 1311095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 1312095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_argb = dst_stride_argb = 0; 131311a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 1314eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com#if defined(HAS_ARGBGRAYROW_SSSE3) 1315eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8) && 1316eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && 1317eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { 1318eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com ARGBGrayRow = ARGBGrayRow_SSSE3; 1319eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com } 132082375d6de22e6fdc09f9b74dfe036ec172c3af73fbarchard@google.com#elif defined(HAS_ARGBGRAYROW_NEON) 132182375d6de22e6fdc09f9b74dfe036ec172c3af73fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { 132282375d6de22e6fdc09f9b74dfe036ec172c3af73fbarchard@google.com ARGBGrayRow = ARGBGrayRow_NEON; 132382375d6de22e6fdc09f9b74dfe036ec172c3af73fbarchard@google.com } 1324eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com#endif 1325eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com 132670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 1327eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com ARGBGrayRow(src_argb, dst_argb, width); 1328eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com src_argb += src_stride_argb; 1329eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com dst_argb += dst_stride_argb; 1330eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com } 1331eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com return 0; 1332eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com} 1333eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com 1334ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.com// Make a rectangle of ARGB gray scale. 1335fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 1336ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.comint ARGBGray(uint8* dst_argb, int dst_stride_argb, 1337ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.com int dst_x, int dst_y, 1338ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.com int width, int height) { 133970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 134070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBGrayRow)(const uint8* src_argb, uint8* dst_argb, 134170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width) = ARGBGrayRow_C; 134270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4; 1343ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.com if (!dst_argb || width <= 0 || height <= 0 || dst_x < 0 || dst_y < 0) { 1344ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.com return -1; 1345ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.com } 1346095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 134711a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com if (dst_stride_argb == width * 4) { 1348095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 1349095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 1350095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com dst_stride_argb = 0; 135111a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 1352ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.com#if defined(HAS_ARGBGRAYROW_SSSE3) 1353ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.com if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8) && 1354ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.com IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { 1355ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.com ARGBGrayRow = ARGBGrayRow_SSSE3; 1356ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.com } 135782375d6de22e6fdc09f9b74dfe036ec172c3af73fbarchard@google.com#elif defined(HAS_ARGBGRAYROW_NEON) 135882375d6de22e6fdc09f9b74dfe036ec172c3af73fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { 135982375d6de22e6fdc09f9b74dfe036ec172c3af73fbarchard@google.com ARGBGrayRow = ARGBGrayRow_NEON; 136082375d6de22e6fdc09f9b74dfe036ec172c3af73fbarchard@google.com } 1361ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.com#endif 136270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 1363eeac2903ef22110d475c50ef9bfd7826d3183a5efbarchard@google.com ARGBGrayRow(dst, dst, width); 1364ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.com dst += dst_stride_argb; 1365ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.com } 1366ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.com return 0; 1367ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.com} 1368ffaea7eee38e593a3e63553ffa90e554ba81fe30fbarchard@google.com 1369221e602f8a726f7457a0d521b5bcca05d89215bbfbarchard@google.com// Make a rectangle of ARGB Sepia tone. 1370fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 1371221e602f8a726f7457a0d521b5bcca05d89215bbfbarchard@google.comint ARGBSepia(uint8* dst_argb, int dst_stride_argb, 137281b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com int dst_x, int dst_y, int width, int height) { 137370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 137470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBSepiaRow)(uint8* dst_argb, int width) = ARGBSepiaRow_C; 137570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4; 1376221e602f8a726f7457a0d521b5bcca05d89215bbfbarchard@google.com if (!dst_argb || width <= 0 || height <= 0 || dst_x < 0 || dst_y < 0) { 1377221e602f8a726f7457a0d521b5bcca05d89215bbfbarchard@google.com return -1; 1378221e602f8a726f7457a0d521b5bcca05d89215bbfbarchard@google.com } 1379095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 138011a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com if (dst_stride_argb == width * 4) { 1381095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 1382095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 1383095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com dst_stride_argb = 0; 138411a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 1385221e602f8a726f7457a0d521b5bcca05d89215bbfbarchard@google.com#if defined(HAS_ARGBSEPIAROW_SSSE3) 1386221e602f8a726f7457a0d521b5bcca05d89215bbfbarchard@google.com if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8) && 1387221e602f8a726f7457a0d521b5bcca05d89215bbfbarchard@google.com IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { 1388221e602f8a726f7457a0d521b5bcca05d89215bbfbarchard@google.com ARGBSepiaRow = ARGBSepiaRow_SSSE3; 1389221e602f8a726f7457a0d521b5bcca05d89215bbfbarchard@google.com } 1390c247625d7fabfa6217111c0b6a2f0f30b99da204fbarchard@google.com#elif defined(HAS_ARGBSEPIAROW_NEON) 1391c247625d7fabfa6217111c0b6a2f0f30b99da204fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { 1392c247625d7fabfa6217111c0b6a2f0f30b99da204fbarchard@google.com ARGBSepiaRow = ARGBSepiaRow_NEON; 1393c247625d7fabfa6217111c0b6a2f0f30b99da204fbarchard@google.com } 1394221e602f8a726f7457a0d521b5bcca05d89215bbfbarchard@google.com#endif 139570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 1396221e602f8a726f7457a0d521b5bcca05d89215bbfbarchard@google.com ARGBSepiaRow(dst, width); 1397221e602f8a726f7457a0d521b5bcca05d89215bbfbarchard@google.com dst += dst_stride_argb; 1398221e602f8a726f7457a0d521b5bcca05d89215bbfbarchard@google.com } 1399221e602f8a726f7457a0d521b5bcca05d89215bbfbarchard@google.com return 0; 1400221e602f8a726f7457a0d521b5bcca05d89215bbfbarchard@google.com} 1401221e602f8a726f7457a0d521b5bcca05d89215bbfbarchard@google.com 1402c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com// Apply a 4x4 matrix to each ARGB pixel. 1403c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com// Note: Normally for shading, but can be used to swizzle or invert. 1404fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 1405c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.comint ARGBColorMatrix(const uint8* src_argb, int src_stride_argb, 1406c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com uint8* dst_argb, int dst_stride_argb, 1407e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com const int8* matrix_argb, 1408c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com int width, int height) { 140970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 141070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBColorMatrixRow)(const uint8* src_argb, uint8* dst_argb, 141170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com const int8* matrix_argb, int width) = ARGBColorMatrixRow_C; 1412c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com if (!src_argb || !dst_argb || !matrix_argb || width <= 0 || height == 0) { 1413e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com return -1; 1414e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com } 1415c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com if (height < 0) { 1416c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com height = -height; 1417c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com src_argb = src_argb + (height - 1) * src_stride_argb; 1418c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com src_stride_argb = -src_stride_argb; 1419c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com } 1420095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 1421c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com if (src_stride_argb == width * 4 && 1422c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com dst_stride_argb == width * 4) { 1423095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 1424095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 1425095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_argb = dst_stride_argb = 0; 142611a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 1427e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com#if defined(HAS_ARGBCOLORMATRIXROW_SSSE3) 1428e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 8) && 1429e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { 1430e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com ARGBColorMatrixRow = ARGBColorMatrixRow_SSSE3; 1431e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com } 143262154e53a2820136f6a8cab8cc029622e3b100c1fbarchard@google.com#elif defined(HAS_ARGBCOLORMATRIXROW_NEON) 143362154e53a2820136f6a8cab8cc029622e3b100c1fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { 143462154e53a2820136f6a8cab8cc029622e3b100c1fbarchard@google.com ARGBColorMatrixRow = ARGBColorMatrixRow_NEON; 143562154e53a2820136f6a8cab8cc029622e3b100c1fbarchard@google.com } 1436e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com#endif 143770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 1438c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com ARGBColorMatrixRow(src_argb, dst_argb, matrix_argb, width); 1439c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com src_argb += src_stride_argb; 1440c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com dst_argb += dst_stride_argb; 1441e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com } 1442e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com return 0; 1443e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com} 14447c8e16f82ae94e09c9657276a0ceedafbf036315fbarchard@google.com 1445c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com// Apply a 4x3 matrix to each ARGB pixel. 1446c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com// Deprecated. 1447d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.comLIBYUV_API 1448c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.comint RGBColorMatrix(uint8* dst_argb, int dst_stride_argb, 1449c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com const int8* matrix_rgb, 1450c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com int dst_x, int dst_y, int width, int height) { 145170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com SIMD_ALIGNED(int8 matrix_argb[16]); 145270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4; 1453c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com if (!dst_argb || !matrix_rgb || width <= 0 || height <= 0 || 1454c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com dst_x < 0 || dst_y < 0) { 1455c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com return -1; 1456c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com } 1457c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com 1458c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com // Convert 4x3 7 bit matrix to 4x4 6 bit matrix. 1459c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com matrix_argb[0] = matrix_rgb[0] / 2; 1460c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com matrix_argb[1] = matrix_rgb[1] / 2; 1461c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com matrix_argb[2] = matrix_rgb[2] / 2; 1462c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com matrix_argb[3] = matrix_rgb[3] / 2; 1463c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com matrix_argb[4] = matrix_rgb[4] / 2; 1464c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com matrix_argb[5] = matrix_rgb[5] / 2; 1465c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com matrix_argb[6] = matrix_rgb[6] / 2; 1466c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com matrix_argb[7] = matrix_rgb[7] / 2; 1467c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com matrix_argb[8] = matrix_rgb[8] / 2; 1468c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com matrix_argb[9] = matrix_rgb[9] / 2; 1469c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com matrix_argb[10] = matrix_rgb[10] / 2; 1470c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com matrix_argb[11] = matrix_rgb[11] / 2; 1471c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com matrix_argb[14] = matrix_argb[13] = matrix_argb[12] = 0; 1472c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com matrix_argb[15] = 64; // 1.0 1473c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com 1474a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com return ARGBColorMatrix((const uint8*)(dst), dst_stride_argb, 1475c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com dst, dst_stride_argb, 1476c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com &matrix_argb[0], width, height); 1477c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com} 1478c99db063e24d6180740d4adc29e84159096eef2dfbarchard@google.com 1479e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com// Apply a color table each ARGB pixel. 1480e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com// Table contains 256 ARGB values. 1481fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 1482e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.comint ARGBColorTable(uint8* dst_argb, int dst_stride_argb, 1483e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com const uint8* table_argb, 1484e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com int dst_x, int dst_y, int width, int height) { 148570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 148670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBColorTableRow)(uint8* dst_argb, const uint8* table_argb, 148770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width) = ARGBColorTableRow_C; 148870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4; 1489c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com if (!dst_argb || !table_argb || width <= 0 || height <= 0 || 1490c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com dst_x < 0 || dst_y < 0) { 1491e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com return -1; 1492e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com } 1493095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 149411a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com if (dst_stride_argb == width * 4) { 1495095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 1496095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 1497095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com dst_stride_argb = 0; 149811a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 1499e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com#if defined(HAS_ARGBCOLORTABLEROW_X86) 1500e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com if (TestCpuFlag(kCpuHasX86)) { 1501e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com ARGBColorTableRow = ARGBColorTableRow_X86; 1502e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com } 1503e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com#endif 150470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 1505e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com ARGBColorTableRow(dst, table_argb, width); 1506e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com dst += dst_stride_argb; 1507e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com } 1508e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com return 0; 1509e442dc4c2a896e85419628e3b7d97c4dfbe71c9dfbarchard@google.com} 151081b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com 15115520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com// Apply a color table each ARGB pixel but preserve destination alpha. 15125520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com// Table contains 256 ARGB values. 15135520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.comLIBYUV_API 15145520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.comint RGBColorTable(uint8* dst_argb, int dst_stride_argb, 15155520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com const uint8* table_argb, 15165520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com int dst_x, int dst_y, int width, int height) { 151770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 151870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*RGBColorTableRow)(uint8* dst_argb, const uint8* table_argb, 151970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width) = RGBColorTableRow_C; 152070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4; 15215520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com if (!dst_argb || !table_argb || width <= 0 || height <= 0 || 15225520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com dst_x < 0 || dst_y < 0) { 15235520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com return -1; 15245520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com } 1525095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 15265520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com if (dst_stride_argb == width * 4) { 1527095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 1528095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 1529095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com dst_stride_argb = 0; 15305520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com } 15315520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com#if defined(HAS_RGBCOLORTABLEROW_X86) 15325520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com if (TestCpuFlag(kCpuHasX86)) { 15335520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com RGBColorTableRow = RGBColorTableRow_X86; 15345520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com } 15355520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com#endif 153670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 15375520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com RGBColorTableRow(dst, table_argb, width); 15385520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com dst += dst_stride_argb; 15395520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com } 15405520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com return 0; 15415520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com} 15425520710ef7ce306357ab35c501f776b1fb0266e8fbarchard@google.com 154381b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com// ARGBQuantize is used to posterize art. 154481b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com// e.g. rgb / qvalue * qvalue + qvalue / 2 154581b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com// But the low levels implement efficiently with 3 parameters, and could be 154681b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com// used for other high level operations. 1547442b0ad0ac44825b9abbeacfa3940c32d0a5ca71fbarchard@google.com// dst_argb[0] = (b * scale >> 16) * interval_size + interval_offset; 1548442b0ad0ac44825b9abbeacfa3940c32d0a5ca71fbarchard@google.com// where scale is 1 / interval_size as a fixed point value. 154981b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com// The divide is replaces with a multiply by reciprocal fixed point multiply. 155081b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com// Caveat - although SSE2 saturates, the C function does not and should be used 155181b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com// with care if doing anything but quantization. 1552fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 155381b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.comint ARGBQuantize(uint8* dst_argb, int dst_stride_argb, 155481b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com int scale, int interval_size, int interval_offset, 155581b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com int dst_x, int dst_y, int width, int height) { 155670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 155770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBQuantizeRow)(uint8* dst_argb, int scale, int interval_size, 155870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int interval_offset, int width) = ARGBQuantizeRow_C; 155970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* dst = dst_argb + dst_y * dst_stride_argb + dst_x * 4; 156081b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com if (!dst_argb || width <= 0 || height <= 0 || dst_x < 0 || dst_y < 0 || 156181b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com interval_size < 1 || interval_size > 255) { 156281b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com return -1; 156381b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com } 1564095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 156511a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com if (dst_stride_argb == width * 4) { 1566095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 1567095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 1568095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com dst_stride_argb = 0; 156911a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 157081b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com#if defined(HAS_ARGBQUANTIZEROW_SSE2) 157181b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 4) && 157281b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { 157381b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com ARGBQuantizeRow = ARGBQuantizeRow_SSE2; 157481b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com } 1575ef60ab0db435c8e0bd1f63dc9aedb5ad880424a9fbarchard@google.com#elif defined(HAS_ARGBQUANTIZEROW_NEON) 1576ef60ab0db435c8e0bd1f63dc9aedb5ad880424a9fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { 1577ef60ab0db435c8e0bd1f63dc9aedb5ad880424a9fbarchard@google.com ARGBQuantizeRow = ARGBQuantizeRow_NEON; 1578ef60ab0db435c8e0bd1f63dc9aedb5ad880424a9fbarchard@google.com } 157981b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com#endif 158070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 158181b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com ARGBQuantizeRow(dst, scale, interval_size, interval_offset, width); 158281b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com dst += dst_stride_argb; 158381b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com } 158481b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com return 0; 158581b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com} 158681b804e35c0346ee2fc5f8d11945eab9a88fdb10fbarchard@google.com 1587f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com// Computes table of cumulative sum for image where the value is the sum 158864ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com// of all values above and to the left of the entry. Used by ARGBBlur. 1589fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 1590f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.comint ARGBComputeCumulativeSum(const uint8* src_argb, int src_stride_argb, 1591f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com int32* dst_cumsum, int dst_stride32_cumsum, 1592f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com int width, int height) { 159370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 159470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ComputeCumulativeSumRow)(const uint8* row, int32* cumsum, 159570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com const int32* previous_cumsum, int width) = ComputeCumulativeSumRow_C; 159670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int32* previous_cumsum = dst_cumsum; 1597f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com if (!dst_cumsum || !src_argb || width <= 0 || height <= 0) { 1598f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com return -1; 1599f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com } 1600f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com#if defined(HAS_CUMULATIVESUMTOAVERAGEROW_SSE2) 1601f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2)) { 1602f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com ComputeCumulativeSumRow = ComputeCumulativeSumRow_SSE2; 1603f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com } 1604f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com#endif 1605bac5f2c3ee12535817448e606c7a7704bbae8321fbarchard@google.com memset(dst_cumsum, 0, width * sizeof(dst_cumsum[0]) * 4); // 4 int per pixel. 160670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 1607f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com ComputeCumulativeSumRow(src_argb, dst_cumsum, previous_cumsum, width); 1608f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com previous_cumsum = dst_cumsum; 1609f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com dst_cumsum += dst_stride32_cumsum; 1610f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com src_argb += src_stride_argb; 1611f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com } 1612f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com return 0; 1613f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com} 1614f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com 1615f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com// Blur ARGB image. 1616133adc46470722b24fdac30d7537d5009e61ef0cfbarchard@google.com// Caller should allocate CumulativeSum table of width * height * 16 bytes 161764ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com// aligned to 16 byte boundary. height can be radius * 2 + 2 to save memory 1618133adc46470722b24fdac30d7537d5009e61ef0cfbarchard@google.com// as the buffer is treated as circular. 1619fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 1620f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.comint ARGBBlur(const uint8* src_argb, int src_stride_argb, 1621f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com uint8* dst_argb, int dst_stride_argb, 1622f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com int32* dst_cumsum, int dst_stride32_cumsum, 1623f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com int width, int height, int radius) { 162470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 162570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ComputeCumulativeSumRow)(const uint8 *row, int32 *cumsum, 162670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com const int32* previous_cumsum, int width) = ComputeCumulativeSumRow_C; 162770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*CumulativeSumToAverageRow)(const int32* topleft, const int32* botleft, 162870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width, int area, uint8* dst, int count) = CumulativeSumToAverageRow_C; 162970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int32* cumsum_bot_row; 163070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int32* max_cumsum_bot_row; 163170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int32* cumsum_top_row; 163270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com 1633c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com if (!src_argb || !dst_argb || width <= 0 || height == 0) { 1634c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com return -1; 1635c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com } 1636c4a70492c0f2f5b8da259046b951ae0a141bc60efbarchard@google.com if (height < 0) { 1637c4a70492c0f2f5b8da259046b951ae0a141bc60efbarchard@google.com height = -height; 1638c4a70492c0f2f5b8da259046b951ae0a141bc60efbarchard@google.com src_argb = src_argb + (height - 1) * src_stride_argb; 1639c4a70492c0f2f5b8da259046b951ae0a141bc60efbarchard@google.com src_stride_argb = -src_stride_argb; 1640c4a70492c0f2f5b8da259046b951ae0a141bc60efbarchard@google.com } 16412732591d461755bcacda0b93074839acb239cc03fbarchard@google.com if (radius > height) { 1642ba0eab9366a394d28fd3dce81fa9598af0f058d8fbarchard@google.com radius = height; 16432732591d461755bcacda0b93074839acb239cc03fbarchard@google.com } 1644ba0eab9366a394d28fd3dce81fa9598af0f058d8fbarchard@google.com if (radius > (width / 2 - 1)) { 1645ba0eab9366a394d28fd3dce81fa9598af0f058d8fbarchard@google.com radius = width / 2 - 1; 1646ba0eab9366a394d28fd3dce81fa9598af0f058d8fbarchard@google.com } 1647ba0eab9366a394d28fd3dce81fa9598af0f058d8fbarchard@google.com if (radius <= 0) { 1648ba0eab9366a394d28fd3dce81fa9598af0f058d8fbarchard@google.com return -1; 16492732591d461755bcacda0b93074839acb239cc03fbarchard@google.com } 1650f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com#if defined(HAS_CUMULATIVESUMTOAVERAGEROW_SSE2) 1651f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2)) { 1652f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com ComputeCumulativeSumRow = ComputeCumulativeSumRow_SSE2; 1653c4a70492c0f2f5b8da259046b951ae0a141bc60efbarchard@google.com CumulativeSumToAverageRow = CumulativeSumToAverageRow_SSE2; 1654f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com } 1655f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com#endif 165664ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com // Compute enough CumulativeSum for first row to be blurred. After this 1657133adc46470722b24fdac30d7537d5009e61ef0cfbarchard@google.com // one row of CumulativeSum is updated at a time. 1658f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com ARGBComputeCumulativeSum(src_argb, src_stride_argb, 1659f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com dst_cumsum, dst_stride32_cumsum, 1660f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com width, radius); 1661f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com 1662f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com src_argb = src_argb + radius * src_stride_argb; 166370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com cumsum_bot_row = &dst_cumsum[(radius - 1) * dst_stride32_cumsum]; 1664f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com 166570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com max_cumsum_bot_row = &dst_cumsum[(radius * 2 + 2) * dst_stride32_cumsum]; 166670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com cumsum_top_row = &dst_cumsum[0]; 1667f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com 166870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 1669f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com int top_y = ((y - radius - 1) >= 0) ? (y - radius - 1) : 0; 1670f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com int bot_y = ((y + radius) < height) ? (y + radius) : (height - 1); 1671f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com int area = radius * (bot_y - top_y); 167270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int boxwidth = radius * 4; 167370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int x; 167470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int n; 1675f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com 1676133adc46470722b24fdac30d7537d5009e61ef0cfbarchard@google.com // Increment cumsum_top_row pointer with circular buffer wrap around. 1677f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com if (top_y) { 1678f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com cumsum_top_row += dst_stride32_cumsum; 1679f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com if (cumsum_top_row >= max_cumsum_bot_row) { 1680f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com cumsum_top_row = dst_cumsum; 1681f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com } 1682f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com } 1683133adc46470722b24fdac30d7537d5009e61ef0cfbarchard@google.com // Increment cumsum_bot_row pointer with circular buffer wrap around and 1684133adc46470722b24fdac30d7537d5009e61ef0cfbarchard@google.com // then fill in a row of CumulativeSum. 1685f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com if ((y + radius) < height) { 1686133adc46470722b24fdac30d7537d5009e61ef0cfbarchard@google.com const int32* prev_cumsum_bot_row = cumsum_bot_row; 1687f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com cumsum_bot_row += dst_stride32_cumsum; 1688f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com if (cumsum_bot_row >= max_cumsum_bot_row) { 1689f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com cumsum_bot_row = dst_cumsum; 1690f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com } 1691f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com ComputeCumulativeSumRow(src_argb, cumsum_bot_row, prev_cumsum_bot_row, 1692f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com width); 1693f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com src_argb += src_stride_argb; 1694f38aefef4b66dc8ebe77ff37234be332731d47f6fbarchard@google.com } 1695f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com 1696f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com // Left clipped. 1697f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com for (x = 0; x < radius + 1; ++x) { 1698c4a70492c0f2f5b8da259046b951ae0a141bc60efbarchard@google.com CumulativeSumToAverageRow(cumsum_top_row, cumsum_bot_row, 1699b99bcab7f77ebc724ed451c04e72b589a3d4acbbfbarchard@google.com boxwidth, area, &dst_argb[x * 4], 1); 1700f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com area += (bot_y - top_y); 1701f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com boxwidth += 4; 1702f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com } 1703f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com 1704f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com // Middle unclipped. 170570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com n = (width - 1) - radius - x + 1; 1706c4a70492c0f2f5b8da259046b951ae0a141bc60efbarchard@google.com CumulativeSumToAverageRow(cumsum_top_row, cumsum_bot_row, 1707b99bcab7f77ebc724ed451c04e72b589a3d4acbbfbarchard@google.com boxwidth, area, &dst_argb[x * 4], n); 1708f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com 1709f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com // Right clipped. 1710f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com for (x += n; x <= width - 1; ++x) { 1711f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com area -= (bot_y - top_y); 1712f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com boxwidth -= 4; 1713c4a70492c0f2f5b8da259046b951ae0a141bc60efbarchard@google.com CumulativeSumToAverageRow(cumsum_top_row + (x - radius - 1) * 4, 1714b99bcab7f77ebc724ed451c04e72b589a3d4acbbfbarchard@google.com cumsum_bot_row + (x - radius - 1) * 4, 1715b99bcab7f77ebc724ed451c04e72b589a3d4acbbfbarchard@google.com boxwidth, area, &dst_argb[x * 4], 1); 1716f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com } 1717f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com dst_argb += dst_stride_argb; 1718f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com } 1719f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com return 0; 1720f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com} 1721f51e87912eebc959ac6b9d1ab44978e0e056ca74fbarchard@google.com 17220d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com// Multiply ARGB image by a specified ARGB value. 1723fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 1724c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.comint ARGBShade(const uint8* src_argb, int src_stride_argb, 1725c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com uint8* dst_argb, int dst_stride_argb, 1726c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com int width, int height, uint32 value) { 172770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 172870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBShadeRow)(const uint8* src_argb, uint8* dst_argb, 172970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width, uint32 value) = ARGBShadeRow_C; 1730c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com if (!src_argb || !dst_argb || width <= 0 || height == 0 || value == 0u) { 1731c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com return -1; 1732c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com } 1733c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com if (height < 0) { 1734c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com height = -height; 1735c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com src_argb = src_argb + (height - 1) * src_stride_argb; 1736c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com src_stride_argb = -src_stride_argb; 1737c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com } 1738095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 173911a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com if (src_stride_argb == width * 4 && 174011a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com dst_stride_argb == width * 4) { 1741095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 1742095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 1743095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_argb = dst_stride_argb = 0; 174411a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 1745f08ac6bb095348565b5259f2fab95f259ef47edefbarchard@google.com#if defined(HAS_ARGBSHADEROW_SSE2) 1746c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 4) && 1747c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && 1748c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { 1749c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com ARGBShadeRow = ARGBShadeRow_SSE2; 1750c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com } 1751b94b139e86635d40ed0d054bb66e30e6086ae7a3fbarchard@google.com#elif defined(HAS_ARGBSHADEROW_NEON) 1752b94b139e86635d40ed0d054bb66e30e6086ae7a3fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { 1753b94b139e86635d40ed0d054bb66e30e6086ae7a3fbarchard@google.com ARGBShadeRow = ARGBShadeRow_NEON; 1754b94b139e86635d40ed0d054bb66e30e6086ae7a3fbarchard@google.com } 1755c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com#endif 1756c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com 175770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 1758c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com ARGBShadeRow(src_argb, dst_argb, width, value); 1759c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com src_argb += src_stride_argb; 1760c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com dst_argb += dst_stride_argb; 1761c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com } 1762c4c578e327a9dbc9dafe113634612e9a349a8c1ffbarchard@google.com return 0; 1763c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com} 1764c4500c9f7957f24021250a056f099300aa6f0476fbarchard@google.com 17650d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com// Interpolate 2 ARGB images by specified amount (0 to 255). 1766fc7314e86bc7a1a88b38b815e881183521801ea9fbarchard@google.comLIBYUV_API 17670d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.comint ARGBInterpolate(const uint8* src_argb0, int src_stride_argb0, 17680d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com const uint8* src_argb1, int src_stride_argb1, 17690d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com uint8* dst_argb, int dst_stride_argb, 17700d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com int width, int height, int interpolation) { 177170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 177270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*InterpolateRow)(uint8* dst_ptr, const uint8* src_ptr, 177370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com ptrdiff_t src_stride, int dst_width, 177470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int source_y_fraction) = InterpolateRow_C; 17750d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com if (!src_argb0 || !src_argb1 || !dst_argb || width <= 0 || height == 0) { 17760d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com return -1; 17770d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com } 17780d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com // Negative height means invert the image. 17790d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com if (height < 0) { 17800d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com height = -height; 17810d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com dst_argb = dst_argb + (height - 1) * dst_stride_argb; 17820d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com dst_stride_argb = -dst_stride_argb; 17830d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com } 1784095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 178511a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com if (src_stride_argb0 == width * 4 && 178611a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com src_stride_argb1 == width * 4 && 178711a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com dst_stride_argb == width * 4) { 1788095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 1789095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 1790095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_argb0 = src_stride_argb1 = dst_stride_argb = 0; 179111a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com } 1792b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com#if defined(HAS_INTERPOLATEROW_SSE2) 1793cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && width >= 4) { 1794b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com InterpolateRow = InterpolateRow_Any_SSE2; 1795cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com if (IS_ALIGNED(width, 4)) { 1796b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com InterpolateRow = InterpolateRow_Unaligned_SSE2; 1797cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com if (IS_ALIGNED(src_argb0, 16) && IS_ALIGNED(src_stride_argb0, 16) && 1798cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com IS_ALIGNED(src_argb1, 16) && IS_ALIGNED(src_stride_argb1, 16) && 1799cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { 1800b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com InterpolateRow = InterpolateRow_SSE2; 1801cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com } 1802cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com } 18038811289be7ad257f16a6532aeec2cb5db331fa54fbarchard@google.com } 18048811289be7ad257f16a6532aeec2cb5db331fa54fbarchard@google.com#endif 1805b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com#if defined(HAS_INTERPOLATEROW_SSSE3) 1806cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com if (TestCpuFlag(kCpuHasSSSE3) && width >= 4) { 1807b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com InterpolateRow = InterpolateRow_Any_SSSE3; 1808cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com if (IS_ALIGNED(width, 4)) { 1809b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com InterpolateRow = InterpolateRow_Unaligned_SSSE3; 1810cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com if (IS_ALIGNED(src_argb0, 16) && IS_ALIGNED(src_stride_argb0, 16) && 1811cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com IS_ALIGNED(src_argb1, 16) && IS_ALIGNED(src_stride_argb1, 16) && 1812cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { 1813b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com InterpolateRow = InterpolateRow_SSSE3; 1814cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com } 1815cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com } 18160d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com } 1817cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com#endif 18182154de414c1ac41fb434348964c728ccc077ffd3fbarchard@google.com#if defined(HAS_INTERPOLATEROW_AVX2) 18192154de414c1ac41fb434348964c728ccc077ffd3fbarchard@google.com if (TestCpuFlag(kCpuHasAVX2) && width >= 8) { 18202154de414c1ac41fb434348964c728ccc077ffd3fbarchard@google.com InterpolateRow = InterpolateRow_Any_AVX2; 18212154de414c1ac41fb434348964c728ccc077ffd3fbarchard@google.com if (IS_ALIGNED(width, 8)) { 18222154de414c1ac41fb434348964c728ccc077ffd3fbarchard@google.com InterpolateRow = InterpolateRow_AVX2; 18232154de414c1ac41fb434348964c728ccc077ffd3fbarchard@google.com } 18242154de414c1ac41fb434348964c728ccc077ffd3fbarchard@google.com } 18252154de414c1ac41fb434348964c728ccc077ffd3fbarchard@google.com#endif 1826b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com#if defined(HAS_INTERPOLATEROW_NEON) 1827cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && width >= 4) { 1828b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com InterpolateRow = InterpolateRow_Any_NEON; 1829cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com if (IS_ALIGNED(width, 4)) { 1830b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com InterpolateRow = InterpolateRow_NEON; 1831cd6056c01cec8de0431390933537c9b8458bd472fbarchard@google.com } 1832b5491759b45de37df781d4408a0c46abf6d4ae08fbarchard@google.com } 18330d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com#endif 1834b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com#if defined(HAS_INTERPOLATEROWS_MIPS_DSPR2) 1835b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com if (TestCpuFlag(kCpuHasMIPS_DSPR2) && width >= 1 && 1836b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com IS_ALIGNED(src_argb0, 4) && IS_ALIGNED(src_stride_argb0, 4) && 1837b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com IS_ALIGNED(src_argb1, 4) && IS_ALIGNED(src_stride_argb1, 4) && 1838b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) { 1839b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com ScaleARGBFilterRows = InterpolateRow_MIPS_DSPR2; 1840b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com } 1841b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com#endif 1842b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com 184370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 1844b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com InterpolateRow(dst_argb, src_argb0, src_argb1 - src_argb0, 1845b911428afd3994f47e5780a80c876d05d1d4c590fbarchard@google.com width * 4, interpolation); 18460d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com src_argb0 += src_stride_argb0; 18470d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com src_argb1 += src_stride_argb1; 18480d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com dst_argb += dst_stride_argb; 18490d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com } 18500d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com return 0; 18510d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com} 18520d95d4775792c26117d803adbab0bef1cee18052fbarchard@google.com 18531096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com// Shuffle ARGB channel order. e.g. BGRA to ARGB. 18541096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.comLIBYUV_API 18551096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.comint ARGBShuffle(const uint8* src_bgra, int src_stride_bgra, 18561096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com uint8* dst_argb, int dst_stride_argb, 18571096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com const uint8* shuffler, int width, int height) { 185870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 185970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBShuffleRow)(const uint8* src_bgra, uint8* dst_argb, 186070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com const uint8* shuffler, int pix) = ARGBShuffleRow_C; 18611096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com if (!src_bgra || !dst_argb || 18621096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com width <= 0 || height == 0) { 18631096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com return -1; 18641096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com } 18651096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com // Negative height means invert the image. 18661096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com if (height < 0) { 18671096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com height = -height; 18681096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com src_bgra = src_bgra + (height - 1) * src_stride_bgra; 18691096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com src_stride_bgra = -src_stride_bgra; 18701096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com } 1871095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 187211a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com if (src_stride_bgra == width * 4 && 187311a524362d9ee48fb30c1a2e6098a566199550f9fbarchard@google.com dst_stride_argb == width * 4) { 1874095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 1875095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 1876095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_bgra = dst_stride_argb = 0; 18771096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com } 1878212a1a5000dbdd6bcff7ec355fa2bfa6a00183f8fbarchard@google.com#if defined(HAS_ARGBSHUFFLEROW_SSE2) 1879212a1a5000dbdd6bcff7ec355fa2bfa6a00183f8fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && width >= 4) { 1880212a1a5000dbdd6bcff7ec355fa2bfa6a00183f8fbarchard@google.com ARGBShuffleRow = ARGBShuffleRow_Any_SSE2; 1881212a1a5000dbdd6bcff7ec355fa2bfa6a00183f8fbarchard@google.com if (IS_ALIGNED(width, 4)) { 1882212a1a5000dbdd6bcff7ec355fa2bfa6a00183f8fbarchard@google.com ARGBShuffleRow = ARGBShuffleRow_SSE2; 1883212a1a5000dbdd6bcff7ec355fa2bfa6a00183f8fbarchard@google.com } 1884212a1a5000dbdd6bcff7ec355fa2bfa6a00183f8fbarchard@google.com } 1885212a1a5000dbdd6bcff7ec355fa2bfa6a00183f8fbarchard@google.com#endif 18861096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com#if defined(HAS_ARGBSHUFFLEROW_SSSE3) 18871096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { 18881096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com ARGBShuffleRow = ARGBShuffleRow_Any_SSSE3; 18891096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com if (IS_ALIGNED(width, 8)) { 18901096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com ARGBShuffleRow = ARGBShuffleRow_Unaligned_SSSE3; 18911096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com if (IS_ALIGNED(src_bgra, 16) && IS_ALIGNED(src_stride_bgra, 16) && 18921096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { 18931096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com ARGBShuffleRow = ARGBShuffleRow_SSSE3; 18941096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com } 18951096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com } 18961096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com } 18971096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com#endif 18981096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com#if defined(HAS_ARGBSHUFFLEROW_AVX2) 18991096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com if (TestCpuFlag(kCpuHasAVX2) && width >= 16) { 19001096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com ARGBShuffleRow = ARGBShuffleRow_Any_AVX2; 19011096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com if (IS_ALIGNED(width, 16)) { 19021096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com ARGBShuffleRow = ARGBShuffleRow_AVX2; 19031096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com } 19041096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com } 19051096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com#endif 19061096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com#if defined(HAS_ARGBSHUFFLEROW_NEON) 19071096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && width >= 4) { 19081096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com ARGBShuffleRow = ARGBShuffleRow_Any_NEON; 19091096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com if (IS_ALIGNED(width, 4)) { 19101096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com ARGBShuffleRow = ARGBShuffleRow_NEON; 19111096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com } 19121096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com } 19131096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com#endif 19141096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com 191570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 19161096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com ARGBShuffleRow(src_bgra, dst_argb, shuffler, width); 19171096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com src_bgra += src_stride_bgra; 19181096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com dst_argb += dst_stride_argb; 19191096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com } 19201096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com return 0; 19211096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com} 19221096543eaa1e596a93ba5d3863e637dc489e32ccfbarchard@google.com 19231e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com// Sobel ARGB effect. 1924d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.comstatic int ARGBSobelize(const uint8* src_argb, int src_stride_argb, 1925d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com uint8* dst_argb, int dst_stride_argb, 1926d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com int width, int height, 1927d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com void (*SobelRow)(const uint8* src_sobelx, 1928d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com const uint8* src_sobely, 1929d9c9f37ac482ac958519e02db8b7c5b47bf1816afbarchard@google.com uint8* dst, int width)) { 193070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 193170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBToBayerRow)(const uint8* src_argb, uint8* dst_bayer, 193270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint32 selector, int pix) = ARGBToBayerGGRow_C; 193370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*SobelYRow)(const uint8* src_y0, const uint8* src_y1, 193470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* dst_sobely, int width) = SobelYRow_C; 193570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*SobelXRow)(const uint8* src_y0, const uint8* src_y1, 193670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com const uint8* src_y2, uint8* dst_sobely, int width) = 193770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com SobelXRow_C; 19382732591d461755bcacda0b93074839acb239cc03fbarchard@google.com const int kEdge = 16; // Extra pixels at start of row for extrude/align. 1939b2a51d042d9ccc49de6180880e5fed3d07067d95fbarchard@google.com if (!src_argb || !dst_argb || width <= 0 || height == 0) { 19401e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com return -1; 19411e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com } 19421e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com // Negative height means invert the image. 19431e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com if (height < 0) { 19441e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com height = -height; 19451e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com src_argb = src_argb + (height - 1) * src_stride_argb; 19461e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com src_stride_argb = -src_stride_argb; 19471e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com } 1948e8df16bd7c44e58ea925c51ea82a34144ada3956fbarchard@google.com // ARGBToBayer used to select G channel from ARGB. 194908b24a4232600b2f9f21584f34f6868d8c15c215fbarchard@google.com#if defined(HAS_ARGBTOBAYERGGROW_SSE2) 195008b24a4232600b2f9f21584f34f6868d8c15c215fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && width >= 8 && 195108b24a4232600b2f9f21584f34f6868d8c15c215fbarchard@google.com IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { 195208b24a4232600b2f9f21584f34f6868d8c15c215fbarchard@google.com ARGBToBayerRow = ARGBToBayerGGRow_Any_SSE2; 195308b24a4232600b2f9f21584f34f6868d8c15c215fbarchard@google.com if (IS_ALIGNED(width, 8)) { 195408b24a4232600b2f9f21584f34f6868d8c15c215fbarchard@google.com ARGBToBayerRow = ARGBToBayerGGRow_SSE2; 195508b24a4232600b2f9f21584f34f6868d8c15c215fbarchard@google.com } 195608b24a4232600b2f9f21584f34f6868d8c15c215fbarchard@google.com } 195708b24a4232600b2f9f21584f34f6868d8c15c215fbarchard@google.com#endif 1958e8df16bd7c44e58ea925c51ea82a34144ada3956fbarchard@google.com#if defined(HAS_ARGBTOBAYERROW_SSSE3) 1959e8df16bd7c44e58ea925c51ea82a34144ada3956fbarchard@google.com if (TestCpuFlag(kCpuHasSSSE3) && width >= 8 && 1960e8df16bd7c44e58ea925c51ea82a34144ada3956fbarchard@google.com IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { 1961e8df16bd7c44e58ea925c51ea82a34144ada3956fbarchard@google.com ARGBToBayerRow = ARGBToBayerRow_Any_SSSE3; 1962e8df16bd7c44e58ea925c51ea82a34144ada3956fbarchard@google.com if (IS_ALIGNED(width, 8)) { 1963e8df16bd7c44e58ea925c51ea82a34144ada3956fbarchard@google.com ARGBToBayerRow = ARGBToBayerRow_SSSE3; 19641e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com } 19651e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com } 196608b24a4232600b2f9f21584f34f6868d8c15c215fbarchard@google.com#endif 196708b24a4232600b2f9f21584f34f6868d8c15c215fbarchard@google.com#if defined(HAS_ARGBTOBAYERGGROW_NEON) 1968c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 196908b24a4232600b2f9f21584f34f6868d8c15c215fbarchard@google.com ARGBToBayerRow = ARGBToBayerGGRow_Any_NEON; 1970c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com if (IS_ALIGNED(width, 8)) { 197108b24a4232600b2f9f21584f34f6868d8c15c215fbarchard@google.com ARGBToBayerRow = ARGBToBayerGGRow_NEON; 19721e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com } 19731e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com } 19741e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com#endif 1975092099507e44e9f429ec52956a20b28db634b910fbarchard@google.com#if defined(HAS_SOBELYROW_SSE2) 1976092099507e44e9f429ec52956a20b28db634b910fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2)) { 1977092099507e44e9f429ec52956a20b28db634b910fbarchard@google.com SobelYRow = SobelYRow_SSE2; 19781e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com } 19791e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com#endif 1980c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com#if defined(HAS_SOBELYROW_NEON) 1981c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com if (TestCpuFlag(kCpuHasNEON)) { 1982c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com SobelYRow = SobelYRow_NEON; 1983c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com } 1984c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com#endif 1985092099507e44e9f429ec52956a20b28db634b910fbarchard@google.com#if defined(HAS_SOBELXROW_SSE2) 1986092099507e44e9f429ec52956a20b28db634b910fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2)) { 1987092099507e44e9f429ec52956a20b28db634b910fbarchard@google.com SobelXRow = SobelXRow_SSE2; 19881e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com } 19891e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com#endif 1990c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com#if defined(HAS_SOBELXROW_NEON) 1991c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com if (TestCpuFlag(kCpuHasNEON)) { 1992c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com SobelXRow = SobelXRow_NEON; 1993c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com } 1994c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com#endif 199570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com { 199670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com // 3 rows with edges before/after. 199770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com const int kRowSize = (width + kEdge + 15) & ~15; 199870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com align_buffer_64(rows, kRowSize * 2 + (kEdge + kRowSize * 3 + kEdge)); 199970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* row_sobelx = rows; 200070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* row_sobely = rows + kRowSize; 200170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* row_y = rows + kRowSize * 2; 200270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com 200370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com // Convert first row. 200470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* row_y0 = row_y + kEdge; 200570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* row_y1 = row_y0 + kRowSize; 200670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* row_y2 = row_y1 + kRowSize; 200770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com ARGBToBayerRow(src_argb, row_y0, 0x0d090501, width); 200870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com row_y0[-1] = row_y0[0]; 200970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com memset(row_y0 + width, row_y0[width - 1], 16); // Extrude 16 for valgrind. 201070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com ARGBToBayerRow(src_argb, row_y1, 0x0d090501, width); 201170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com row_y1[-1] = row_y1[0]; 201270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com memset(row_y1 + width, row_y1[width - 1], 16); 201370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com memset(row_y2 + width, 0, 16); 201470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com 201570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 201670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com // Convert next row of ARGB to Y. 201770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com if (y < (height - 1)) { 201870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com src_argb += src_stride_argb; 201970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com } 202070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com ARGBToBayerRow(src_argb, row_y2, 0x0d090501, width); 202170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com row_y2[-1] = row_y2[0]; 202270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com row_y2[width] = row_y2[width - 1]; 202370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com 202470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com SobelXRow(row_y0 - 1, row_y1 - 1, row_y2 - 1, row_sobelx, width); 202570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com SobelYRow(row_y0 - 1, row_y2 - 1, row_sobely, width); 202670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com SobelRow(row_sobelx, row_sobely, dst_argb, width); 202770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com 202870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com // Cycle thru circular queue of 3 row_y buffers. 202970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com { 203070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* row_yt = row_y0; 203170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com row_y0 = row_y1; 203270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com row_y1 = row_y2; 203370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com row_y2 = row_yt; 203470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com } 20351e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com 203670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com dst_argb += dst_stride_argb; 203770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com } 203870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com free_aligned_buffer_64(rows); 20391e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com } 20401e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com return 0; 20411e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com} 20421e985bbc1607d52c6295c167de29cb2b736e9244fbarchard@google.com 20438be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com// Sobel ARGB effect. 2044610e012d56b1cce420369b82335bd178f7e39397fbarchard@google.comLIBYUV_API 20458be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.comint ARGBSobel(const uint8* src_argb, int src_stride_argb, 20468be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com uint8* dst_argb, int dst_stride_argb, 20478be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com int width, int height) { 20488be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com void (*SobelRow)(const uint8* src_sobelx, const uint8* src_sobely, 20498be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com uint8* dst_argb, int width) = SobelRow_C; 20508be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com#if defined(HAS_SOBELROW_SSE2) 20518be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16) && 20528be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { 20538be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com SobelRow = SobelRow_SSE2; 2054610e012d56b1cce420369b82335bd178f7e39397fbarchard@google.com } 2055610e012d56b1cce420369b82335bd178f7e39397fbarchard@google.com#endif 20568be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com#if defined(HAS_SOBELROW_NEON) 20578be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { 20588be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com SobelRow = SobelRow_NEON; 2059c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com } 2060c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com#endif 20618be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com return ARGBSobelize(src_argb, src_stride_argb, dst_argb, dst_stride_argb, 20628be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com width, height, SobelRow); 20638be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com} 20648be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com 20658be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com// Sobel ARGB effect with planar output. 20668be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.comLIBYUV_API 20678be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.comint ARGBSobelToPlane(const uint8* src_argb, int src_stride_argb, 20688be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com uint8* dst_y, int dst_stride_y, 20698be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com int width, int height) { 20708be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com void (*SobelToPlaneRow)(const uint8* src_sobelx, const uint8* src_sobely, 20718be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com uint8* dst_, int width) = SobelToPlaneRow_C; 20728be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com#if defined(HAS_SOBELTOPLANEROW_SSE2) 20738be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16) && 20748be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { 20758be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com SobelToPlaneRow = SobelToPlaneRow_SSE2; 2076610e012d56b1cce420369b82335bd178f7e39397fbarchard@google.com } 2077610e012d56b1cce420369b82335bd178f7e39397fbarchard@google.com#endif 20788be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com#if defined(HAS_SOBELTOPLANEROW_NEON) 20798be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 16)) { 20808be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com SobelToPlaneRow = SobelToPlaneRow_NEON; 2081c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com } 2082c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com#endif 20838be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com return ARGBSobelize(src_argb, src_stride_argb, dst_y, dst_stride_y, 20848be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com width, height, SobelToPlaneRow); 20858be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com} 20868be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com 20878be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com// SobelXY ARGB effect. 20888be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com// Similar to Sobel, but also stores Sobel X in R and Sobel Y in B. G = Sobel. 20898be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.comLIBYUV_API 20908be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.comint ARGBSobelXY(const uint8* src_argb, int src_stride_argb, 20918be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com uint8* dst_argb, int dst_stride_argb, 20928be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com int width, int height) { 2093610e012d56b1cce420369b82335bd178f7e39397fbarchard@google.com void (*SobelXYRow)(const uint8* src_sobelx, const uint8* src_sobely, 2094c93a137671e2e281dfb8d32561fed95caacf608bfbarchard@google.com uint8* dst_argb, int width) = SobelXYRow_C; 2095610e012d56b1cce420369b82335bd178f7e39397fbarchard@google.com#if defined(HAS_SOBELXYROW_SSE2) 2096610e012d56b1cce420369b82335bd178f7e39397fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 16) && 2097610e012d56b1cce420369b82335bd178f7e39397fbarchard@google.com IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { 2098610e012d56b1cce420369b82335bd178f7e39397fbarchard@google.com SobelXYRow = SobelXYRow_SSE2; 2099610e012d56b1cce420369b82335bd178f7e39397fbarchard@google.com } 2100610e012d56b1cce420369b82335bd178f7e39397fbarchard@google.com#endif 2101c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com#if defined(HAS_SOBELXYROW_NEON) 2102c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 8)) { 2103c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com SobelXYRow = SobelXYRow_NEON; 2104c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com } 2105c56a55fc7206a257eecc21969f94ab066dd80f2ffbarchard@google.com#endif 21068be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com return ARGBSobelize(src_argb, src_stride_argb, dst_argb, dst_stride_argb, 21078be4b289c799356d84c68c4eb4b5403285096693fbarchard@google.com width, height, SobelXYRow); 2108610e012d56b1cce420369b82335bd178f7e39397fbarchard@google.com} 2109610e012d56b1cce420369b82335bd178f7e39397fbarchard@google.com 2110ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com// Apply a 4x4 polynomial to each ARGB pixel. 2111ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.comLIBYUV_API 2112ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.comint ARGBPolynomial(const uint8* src_argb, int src_stride_argb, 2113ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com uint8* dst_argb, int dst_stride_argb, 2114ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com const float* poly, 2115ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com int width, int height) { 211670bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 211770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBPolynomialRow)(const uint8* src_argb, 211870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com uint8* dst_argb, const float* poly, 211970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width) = ARGBPolynomialRow_C; 21206f7e514caa3e1c57ab1fd765151c52b9156113befbarchard@google.com if (!src_argb || !dst_argb || !poly || width <= 0 || height == 0) { 2121ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com return -1; 2122ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com } 21236f7e514caa3e1c57ab1fd765151c52b9156113befbarchard@google.com // Negative height means invert the image. 21246f7e514caa3e1c57ab1fd765151c52b9156113befbarchard@google.com if (height < 0) { 21256f7e514caa3e1c57ab1fd765151c52b9156113befbarchard@google.com height = -height; 21266f7e514caa3e1c57ab1fd765151c52b9156113befbarchard@google.com src_argb = src_argb + (height - 1) * src_stride_argb; 21276f7e514caa3e1c57ab1fd765151c52b9156113befbarchard@google.com src_stride_argb = -src_stride_argb; 21286f7e514caa3e1c57ab1fd765151c52b9156113befbarchard@google.com } 2129095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 2130095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com if (src_stride_argb == width * 4 && 2131095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com dst_stride_argb == width * 4) { 2132095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 2133095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 2134095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_argb = dst_stride_argb = 0; 2135ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com } 2136ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com#if defined(HAS_ARGBPOLYNOMIALROW_SSE2) 2137c3c06ec328b5ea6c57012d3ca3ca442f22aad681fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 2)) { 2138ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com ARGBPolynomialRow = ARGBPolynomialRow_SSE2; 2139ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com } 2140ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com#endif 21416da76f3b34e80da2ffebff92d57fd08a93964942fbarchard@google.com#if defined(HAS_ARGBPOLYNOMIALROW_AVX2) 21422bbb64df2c997725ab1a024a0a21f1c63f895797fbarchard@google.com if (TestCpuFlag(kCpuHasAVX2) && TestCpuFlag(kCpuHasFMA3) && 21432bbb64df2c997725ab1a024a0a21f1c63f895797fbarchard@google.com IS_ALIGNED(width, 2)) { 21446da76f3b34e80da2ffebff92d57fd08a93964942fbarchard@google.com ARGBPolynomialRow = ARGBPolynomialRow_AVX2; 21456da76f3b34e80da2ffebff92d57fd08a93964942fbarchard@google.com } 21466da76f3b34e80da2ffebff92d57fd08a93964942fbarchard@google.com#endif 214770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com 214870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 2149ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com ARGBPolynomialRow(src_argb, dst_argb, poly, width); 2150ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com src_argb += src_stride_argb; 2151ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com dst_argb += dst_stride_argb; 2152ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com } 2153ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com return 0; 2154ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com} 2155ae0091e3a74603b23c91f417c8ea023cd43e7e9cfbarchard@google.com 2156b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.com// Apply a lumacolortable to each ARGB pixel. 2157b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.comLIBYUV_API 2158b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.comint ARGBLumaColorTable(const uint8* src_argb, int src_stride_argb, 2159b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.com uint8* dst_argb, int dst_stride_argb, 2160b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.com const uint8* luma, 2161b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.com int width, int height) { 216270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 216370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBLumaColorTableRow)(const uint8* src_argb, uint8* dst_argb, 216470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int width, const uint8* luma, const uint32 lumacoeff) = 216570bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com ARGBLumaColorTableRow_C; 21666f7e514caa3e1c57ab1fd765151c52b9156113befbarchard@google.com if (!src_argb || !dst_argb || !luma || width <= 0 || height == 0) { 2167b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.com return -1; 2168b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.com } 21696f7e514caa3e1c57ab1fd765151c52b9156113befbarchard@google.com // Negative height means invert the image. 21706f7e514caa3e1c57ab1fd765151c52b9156113befbarchard@google.com if (height < 0) { 21716f7e514caa3e1c57ab1fd765151c52b9156113befbarchard@google.com height = -height; 21726f7e514caa3e1c57ab1fd765151c52b9156113befbarchard@google.com src_argb = src_argb + (height - 1) * src_stride_argb; 21736f7e514caa3e1c57ab1fd765151c52b9156113befbarchard@google.com src_stride_argb = -src_stride_argb; 21746f7e514caa3e1c57ab1fd765151c52b9156113befbarchard@google.com } 2175095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 2176095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com if (src_stride_argb == width * 4 && 2177095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com dst_stride_argb == width * 4) { 2178095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com width *= height; 2179095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com height = 1; 2180095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com src_stride_argb = dst_stride_argb = 0; 2181b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.com } 2182b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.com#if defined(HAS_ARGBLUMACOLORTABLEROW_SSSE3) 2183afd1d6b4ec467aef31f4605bc7c6be2b130036fcfbarchard@google.com if (TestCpuFlag(kCpuHasSSSE3) && IS_ALIGNED(width, 4)) { 2184b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.com ARGBLumaColorTableRow = ARGBLumaColorTableRow_SSSE3; 2185b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.com } 2186b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.com#endif 218770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com 218870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 218911a0d48e45a7acd5aaf6b914caeee06432f06b6bfbarchard@google.com ARGBLumaColorTableRow(src_argb, dst_argb, width, luma, 0x00264b0f); 2190b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.com src_argb += src_stride_argb; 2191b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.com dst_argb += dst_stride_argb; 2192b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.com } 2193b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.com return 0; 2194b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.com} 2195b38b73d88cb63f41d943062aa579fc8c27544689fbarchard@google.com 2196adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com// Copy Alpha from one ARGB image to another. 21977f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.comLIBYUV_API 21987f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.comint ARGBCopyAlpha(const uint8* src_argb, int src_stride_argb, 21997f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com uint8* dst_argb, int dst_stride_argb, 22007f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com int width, int height) { 220170bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 220270bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBCopyAlphaRow)(const uint8* src_argb, uint8* dst_argb, int width) = 220370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com ARGBCopyAlphaRow_C; 2204adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com if (!src_argb || !dst_argb || width <= 0 || height == 0) { 22057f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com return -1; 22067f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com } 22077f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com // Negative height means invert the image. 22087f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com if (height < 0) { 22097f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com height = -height; 22107f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com src_argb = src_argb + (height - 1) * src_stride_argb; 22117f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com src_stride_argb = -src_stride_argb; 22127f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com } 2213095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 2214095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com if (src_stride_argb == width * 4 && 2215095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com dst_stride_argb == width * 4) { 2216adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com width *= height; 2217adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com height = 1; 2218adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com src_stride_argb = dst_stride_argb = 0; 22197f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com } 22207f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com#if defined(HAS_ARGBCOPYALPHAROW_SSE2) 2221f6631bb814600f841f74a9d8a626b528be2fd8bbfbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && 2222f6631bb814600f841f74a9d8a626b528be2fd8bbfbarchard@google.com IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && 2223f6631bb814600f841f74a9d8a626b528be2fd8bbfbarchard@google.com IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16) && 2224f6631bb814600f841f74a9d8a626b528be2fd8bbfbarchard@google.com IS_ALIGNED(width, 8)) { 22257f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com ARGBCopyAlphaRow = ARGBCopyAlphaRow_SSE2; 22267f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com } 22277f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com#endif 2228f6631bb814600f841f74a9d8a626b528be2fd8bbfbarchard@google.com#if defined(HAS_ARGBCOPYALPHAROW_AVX2) 2229f6631bb814600f841f74a9d8a626b528be2fd8bbfbarchard@google.com if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 16)) { 2230f6631bb814600f841f74a9d8a626b528be2fd8bbfbarchard@google.com ARGBCopyAlphaRow = ARGBCopyAlphaRow_AVX2; 2231f6631bb814600f841f74a9d8a626b528be2fd8bbfbarchard@google.com } 2232f6631bb814600f841f74a9d8a626b528be2fd8bbfbarchard@google.com#endif 223370bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com 223470bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 22357f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com ARGBCopyAlphaRow(src_argb, dst_argb, width); 22367f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com src_argb += src_stride_argb; 22377f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com dst_argb += dst_stride_argb; 22387f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com } 22397f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com return 0; 22407f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com} 22417f67961ec53f0ad12f827905fc4a4cc880f00931fbarchard@google.com 2242adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com// Copy a planar Y channel to the alpha channel of a destination ARGB image. 2243adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.comLIBYUV_API 2244adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.comint ARGBCopyYToAlpha(const uint8* src_y, int src_stride_y, 2245adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com uint8* dst_argb, int dst_stride_argb, 2246adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com int width, int height) { 224770bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com int y; 224870bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com void (*ARGBCopyYToAlphaRow)(const uint8* src_y, uint8* dst_argb, int width) = 224970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com ARGBCopyYToAlphaRow_C; 2250adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com if (!src_y || !dst_argb || width <= 0 || height == 0) { 2251adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com return -1; 2252adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com } 2253adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com // Negative height means invert the image. 2254adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com if (height < 0) { 2255adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com height = -height; 2256adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com src_y = src_y + (height - 1) * src_stride_y; 2257adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com src_stride_y = -src_stride_y; 2258adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com } 2259095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com // Coalesce rows. 2260095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com if (src_stride_y == width && 2261095f33d870bdc68773db05e75484cc2ed1fe7550fbarchard@google.com dst_stride_argb == width * 4) { 2262adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com width *= height; 2263adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com height = 1; 2264adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com src_stride_y = dst_stride_argb = 0; 2265adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com } 2266adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com#if defined(HAS_ARGBCOPYYTOALPHAROW_SSE2) 2267adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com if (TestCpuFlag(kCpuHasSSE2) && 2268adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) && 2269adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16) && 2270adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com IS_ALIGNED(width, 8)) { 2271adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com ARGBCopyYToAlphaRow = ARGBCopyYToAlphaRow_SSE2; 2272adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com } 2273adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com#endif 2274adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com#if defined(HAS_ARGBCOPYYTOALPHAROW_AVX2) 2275adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com if (TestCpuFlag(kCpuHasAVX2) && IS_ALIGNED(width, 16)) { 2276adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com ARGBCopyYToAlphaRow = ARGBCopyYToAlphaRow_AVX2; 2277adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com } 2278adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com#endif 227970bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com 228070bc4995a08336ec0328226512e9395cba6c36eafbarchard@google.com for (y = 0; y < height; ++y) { 2281adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com ARGBCopyYToAlphaRow(src_y, dst_argb, width); 2282adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com src_y += src_stride_y; 2283adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com dst_argb += dst_stride_argb; 2284adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com } 2285adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com return 0; 2286adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com} 2287adef267edfb3539cd773692d6fa4050ffd092f55fbarchard@google.com 2288fe5ff7ed5451496281697bda9cb85084c532926cfbarchard@google.com#ifdef __cplusplus 2289fe5ff7ed5451496281697bda9cb85084c532926cfbarchard@google.com} // extern "C" 22903faa0f15cb5a585e20c93f816d326df9452dbd65fbarchard@google.com} // namespace libyuv 2291fe5ff7ed5451496281697bda9cb85084c532926cfbarchard@google.com#endif 2292