1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2013 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/codec/SkCodec.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/codec/SkEncodedOrigin.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorType.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPixmap.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkYUVAInfo.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkYUVAPixmaps.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkColorMatrix.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/encode/SkJpegEncoder.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "tools/Resources.h"
25*c8dee2aaSAndroid Build Coastguard Worker
26*c8dee2aaSAndroid Build Coastguard Worker #include <cmath>
27*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
28*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
29*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
30*c8dee2aaSAndroid Build Coastguard Worker
codec_yuv(skiatest::Reporter * reporter,const char path[],const SkYUVAInfo * expectedInfo)31*c8dee2aaSAndroid Build Coastguard Worker static void codec_yuv(skiatest::Reporter* reporter,
32*c8dee2aaSAndroid Build Coastguard Worker const char path[],
33*c8dee2aaSAndroid Build Coastguard Worker const SkYUVAInfo* expectedInfo) {
34*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkStream> stream(GetResourceAsStream(path));
35*c8dee2aaSAndroid Build Coastguard Worker if (!stream) {
36*c8dee2aaSAndroid Build Coastguard Worker return;
37*c8dee2aaSAndroid Build Coastguard Worker }
38*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(std::move(stream)));
39*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, codec);
40*c8dee2aaSAndroid Build Coastguard Worker if (!codec) {
41*c8dee2aaSAndroid Build Coastguard Worker return;
42*c8dee2aaSAndroid Build Coastguard Worker }
43*c8dee2aaSAndroid Build Coastguard Worker
44*c8dee2aaSAndroid Build Coastguard Worker // Test queryYUBAInfo()
45*c8dee2aaSAndroid Build Coastguard Worker SkYUVAPixmapInfo yuvaPixmapInfo;
46*c8dee2aaSAndroid Build Coastguard Worker
47*c8dee2aaSAndroid Build Coastguard Worker static constexpr auto kAllTypes = SkYUVAPixmapInfo::SupportedDataTypes::All();
48*c8dee2aaSAndroid Build Coastguard Worker static constexpr auto kNoTypes = SkYUVAPixmapInfo::SupportedDataTypes();
49*c8dee2aaSAndroid Build Coastguard Worker
50*c8dee2aaSAndroid Build Coastguard Worker // SkYUVAInfo param is required to be non-null.
51*c8dee2aaSAndroid Build Coastguard Worker bool success = codec->queryYUVAInfo(kAllTypes, nullptr);
52*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !success);
53*c8dee2aaSAndroid Build Coastguard Worker // Fails when there is no support for YUVA planes.
54*c8dee2aaSAndroid Build Coastguard Worker success = codec->queryYUVAInfo(kNoTypes, &yuvaPixmapInfo);
55*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !success);
56*c8dee2aaSAndroid Build Coastguard Worker
57*c8dee2aaSAndroid Build Coastguard Worker success = codec->queryYUVAInfo(kAllTypes, &yuvaPixmapInfo);
58*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, SkToBool(expectedInfo) == success);
59*c8dee2aaSAndroid Build Coastguard Worker if (!success) {
60*c8dee2aaSAndroid Build Coastguard Worker return;
61*c8dee2aaSAndroid Build Coastguard Worker }
62*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, *expectedInfo == yuvaPixmapInfo.yuvaInfo());
63*c8dee2aaSAndroid Build Coastguard Worker
64*c8dee2aaSAndroid Build Coastguard Worker int numPlanes = yuvaPixmapInfo.numPlanes();
65*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, numPlanes <= SkYUVAInfo::kMaxPlanes);
66*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < numPlanes; ++i) {
67*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo& planeInfo = yuvaPixmapInfo.planeInfo(i);
68*c8dee2aaSAndroid Build Coastguard Worker SkColorType planeCT = planeInfo.colorType();
69*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !planeInfo.isEmpty());
70*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, planeCT != kUnknown_SkColorType);
71*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, planeInfo.validRowBytes(yuvaPixmapInfo.rowBytes(i)));
72*c8dee2aaSAndroid Build Coastguard Worker // Currently all planes must share a data type, gettable as SkYUVAPixmapInfo::dataType().
73*c8dee2aaSAndroid Build Coastguard Worker auto [numChannels, planeDataType] = SkYUVAPixmapInfo::NumChannelsAndDataType(planeCT);
74*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, planeDataType == yuvaPixmapInfo.dataType());
75*c8dee2aaSAndroid Build Coastguard Worker }
76*c8dee2aaSAndroid Build Coastguard Worker for (int i = numPlanes; i < SkYUVAInfo::kMaxPlanes; ++i) {
77*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo& planeInfo = yuvaPixmapInfo.planeInfo(i);
78*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, planeInfo.dimensions().isEmpty());
79*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, planeInfo.colorType() == kUnknown_SkColorType);
80*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, yuvaPixmapInfo.rowBytes(i) == 0);
81*c8dee2aaSAndroid Build Coastguard Worker }
82*c8dee2aaSAndroid Build Coastguard Worker
83*c8dee2aaSAndroid Build Coastguard Worker // Allocate the memory for the YUV decode.
84*c8dee2aaSAndroid Build Coastguard Worker auto pixmaps = SkYUVAPixmaps::Allocate(yuvaPixmapInfo);
85*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, pixmaps.isValid());
86*c8dee2aaSAndroid Build Coastguard Worker
87*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < SkYUVAPixmaps::kMaxPlanes; ++i) {
88*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, pixmaps.plane(i).info() == yuvaPixmapInfo.planeInfo(i));
89*c8dee2aaSAndroid Build Coastguard Worker }
90*c8dee2aaSAndroid Build Coastguard Worker for (int i = numPlanes; i < SkYUVAInfo::kMaxPlanes; ++i) {
91*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, pixmaps.plane(i).rowBytes() == 0);
92*c8dee2aaSAndroid Build Coastguard Worker }
93*c8dee2aaSAndroid Build Coastguard Worker
94*c8dee2aaSAndroid Build Coastguard Worker // Test getYUVAPlanes()
95*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, SkCodec::kSuccess == codec->getYUVAPlanes(pixmaps));
96*c8dee2aaSAndroid Build Coastguard Worker }
97*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(Jpeg_YUV_Codec,r)98*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Jpeg_YUV_Codec, r) {
99*c8dee2aaSAndroid Build Coastguard Worker auto setExpectations = [](SkISize dims, SkYUVAInfo::Subsampling subsampling) {
100*c8dee2aaSAndroid Build Coastguard Worker return SkYUVAInfo(dims,
101*c8dee2aaSAndroid Build Coastguard Worker SkYUVAInfo::PlaneConfig::kY_U_V,
102*c8dee2aaSAndroid Build Coastguard Worker subsampling,
103*c8dee2aaSAndroid Build Coastguard Worker kJPEG_Full_SkYUVColorSpace,
104*c8dee2aaSAndroid Build Coastguard Worker kTopLeft_SkEncodedOrigin,
105*c8dee2aaSAndroid Build Coastguard Worker SkYUVAInfo::Siting::kCentered,
106*c8dee2aaSAndroid Build Coastguard Worker SkYUVAInfo::Siting::kCentered);
107*c8dee2aaSAndroid Build Coastguard Worker };
108*c8dee2aaSAndroid Build Coastguard Worker
109*c8dee2aaSAndroid Build Coastguard Worker SkYUVAInfo expectations = setExpectations({128, 128}, SkYUVAInfo::Subsampling::k420);
110*c8dee2aaSAndroid Build Coastguard Worker codec_yuv(r, "images/color_wheel.jpg", &expectations);
111*c8dee2aaSAndroid Build Coastguard Worker
112*c8dee2aaSAndroid Build Coastguard Worker // H2V2
113*c8dee2aaSAndroid Build Coastguard Worker expectations = setExpectations({512, 512}, SkYUVAInfo::Subsampling::k420);
114*c8dee2aaSAndroid Build Coastguard Worker codec_yuv(r, "images/mandrill_512_q075.jpg", &expectations);
115*c8dee2aaSAndroid Build Coastguard Worker
116*c8dee2aaSAndroid Build Coastguard Worker // H1V1
117*c8dee2aaSAndroid Build Coastguard Worker expectations = setExpectations({512, 512}, SkYUVAInfo::Subsampling::k444);
118*c8dee2aaSAndroid Build Coastguard Worker codec_yuv(r, "images/mandrill_h1v1.jpg", &expectations);
119*c8dee2aaSAndroid Build Coastguard Worker
120*c8dee2aaSAndroid Build Coastguard Worker // H2V1
121*c8dee2aaSAndroid Build Coastguard Worker expectations = setExpectations({512, 512}, SkYUVAInfo::Subsampling::k422);
122*c8dee2aaSAndroid Build Coastguard Worker codec_yuv(r, "images/mandrill_h2v1.jpg", &expectations);
123*c8dee2aaSAndroid Build Coastguard Worker
124*c8dee2aaSAndroid Build Coastguard Worker // Non-power of two dimensions
125*c8dee2aaSAndroid Build Coastguard Worker expectations = setExpectations({439, 154}, SkYUVAInfo::Subsampling::k420);
126*c8dee2aaSAndroid Build Coastguard Worker codec_yuv(r, "images/cropped_mandrill.jpg", &expectations);
127*c8dee2aaSAndroid Build Coastguard Worker
128*c8dee2aaSAndroid Build Coastguard Worker expectations = setExpectations({8, 8}, SkYUVAInfo::Subsampling::k420);
129*c8dee2aaSAndroid Build Coastguard Worker codec_yuv(r, "images/randPixels.jpg", &expectations);
130*c8dee2aaSAndroid Build Coastguard Worker
131*c8dee2aaSAndroid Build Coastguard Worker // Progressive images
132*c8dee2aaSAndroid Build Coastguard Worker expectations = setExpectations({512, 512}, SkYUVAInfo::Subsampling::k444);
133*c8dee2aaSAndroid Build Coastguard Worker codec_yuv(r, "images/brickwork-texture.jpg", &expectations);
134*c8dee2aaSAndroid Build Coastguard Worker codec_yuv(r, "images/brickwork_normal-map.jpg", &expectations);
135*c8dee2aaSAndroid Build Coastguard Worker
136*c8dee2aaSAndroid Build Coastguard Worker // A CMYK encoded image should fail.
137*c8dee2aaSAndroid Build Coastguard Worker codec_yuv(r, "images/CMYK.jpg", nullptr);
138*c8dee2aaSAndroid Build Coastguard Worker // A grayscale encoded image should fail.
139*c8dee2aaSAndroid Build Coastguard Worker codec_yuv(r, "images/grayscale.jpg", nullptr);
140*c8dee2aaSAndroid Build Coastguard Worker // A PNG should fail.
141*c8dee2aaSAndroid Build Coastguard Worker codec_yuv(r, "images/arrow.png", nullptr);
142*c8dee2aaSAndroid Build Coastguard Worker }
143*c8dee2aaSAndroid Build Coastguard Worker
decode_yuva(skiatest::Reporter * r,std::unique_ptr<SkStream> stream)144*c8dee2aaSAndroid Build Coastguard Worker SkYUVAPixmaps decode_yuva(skiatest::Reporter* r, std::unique_ptr<SkStream> stream) {
145*c8dee2aaSAndroid Build Coastguard Worker static constexpr auto kAllTypes = SkYUVAPixmapInfo::SupportedDataTypes::All();
146*c8dee2aaSAndroid Build Coastguard Worker SkYUVAPixmaps result;
147*c8dee2aaSAndroid Build Coastguard Worker
148*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(std::move(stream)));
149*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, codec);
150*c8dee2aaSAndroid Build Coastguard Worker
151*c8dee2aaSAndroid Build Coastguard Worker SkYUVAPixmapInfo yuvaPixmapInfo;
152*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, codec->queryYUVAInfo(kAllTypes, &yuvaPixmapInfo));
153*c8dee2aaSAndroid Build Coastguard Worker result = SkYUVAPixmaps::Allocate(yuvaPixmapInfo);
154*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, result.isValid());
155*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, SkCodec::kSuccess == codec->getYUVAPlanes(result));
156*c8dee2aaSAndroid Build Coastguard Worker return result;
157*c8dee2aaSAndroid Build Coastguard Worker }
158*c8dee2aaSAndroid Build Coastguard Worker
verify_same(skiatest::Reporter * r,const SkYUVAPixmaps a,const SkYUVAPixmaps & b)159*c8dee2aaSAndroid Build Coastguard Worker static void verify_same(skiatest::Reporter* r, const SkYUVAPixmaps a, const SkYUVAPixmaps& b) {
160*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, a.yuvaInfo() == b.yuvaInfo());
161*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, a.numPlanes() == b.numPlanes());
162*c8dee2aaSAndroid Build Coastguard Worker for (int plane = 0; plane < a.numPlanes(); ++plane) {
163*c8dee2aaSAndroid Build Coastguard Worker const SkPixmap& aPlane = a.plane(plane);
164*c8dee2aaSAndroid Build Coastguard Worker const SkPixmap& bPlane = b.plane(plane);
165*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, aPlane.computeByteSize() == bPlane.computeByteSize());
166*c8dee2aaSAndroid Build Coastguard Worker const uint8_t* aData = reinterpret_cast<const uint8_t*>(aPlane.addr());
167*c8dee2aaSAndroid Build Coastguard Worker const uint8_t* bData = reinterpret_cast<const uint8_t*>(bPlane.addr());
168*c8dee2aaSAndroid Build Coastguard Worker for (int row = 0; row < aPlane.height(); ++row) {
169*c8dee2aaSAndroid Build Coastguard Worker for (int col = 0; col < aPlane.width() * aPlane.info().bytesPerPixel(); ++col) {
170*c8dee2aaSAndroid Build Coastguard Worker int32_t aByte = aData[col];
171*c8dee2aaSAndroid Build Coastguard Worker int32_t bByte = bData[col];
172*c8dee2aaSAndroid Build Coastguard Worker // Allow at most one bit of difference.
173*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, std::abs(aByte - bByte) <= 1);
174*c8dee2aaSAndroid Build Coastguard Worker }
175*c8dee2aaSAndroid Build Coastguard Worker aData += aPlane.rowBytes();
176*c8dee2aaSAndroid Build Coastguard Worker bData += bPlane.rowBytes();
177*c8dee2aaSAndroid Build Coastguard Worker }
178*c8dee2aaSAndroid Build Coastguard Worker }
179*c8dee2aaSAndroid Build Coastguard Worker }
180*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(Jpeg_YUV_Encode,r)181*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Jpeg_YUV_Encode, r) {
182*c8dee2aaSAndroid Build Coastguard Worker const char* paths[] = {
183*c8dee2aaSAndroid Build Coastguard Worker "images/color_wheel.jpg",
184*c8dee2aaSAndroid Build Coastguard Worker "images/mandrill_512_q075.jpg",
185*c8dee2aaSAndroid Build Coastguard Worker "images/mandrill_h1v1.jpg",
186*c8dee2aaSAndroid Build Coastguard Worker "images/mandrill_h2v1.jpg",
187*c8dee2aaSAndroid Build Coastguard Worker "images/cropped_mandrill.jpg",
188*c8dee2aaSAndroid Build Coastguard Worker "images/randPixels.jpg",
189*c8dee2aaSAndroid Build Coastguard Worker };
190*c8dee2aaSAndroid Build Coastguard Worker for (const auto* path : paths) {
191*c8dee2aaSAndroid Build Coastguard Worker SkYUVAPixmaps decoded;
192*c8dee2aaSAndroid Build Coastguard Worker {
193*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkStream> stream(GetResourceAsStream(path));
194*c8dee2aaSAndroid Build Coastguard Worker decoded = decode_yuva(r, std::move(stream));
195*c8dee2aaSAndroid Build Coastguard Worker }
196*c8dee2aaSAndroid Build Coastguard Worker
197*c8dee2aaSAndroid Build Coastguard Worker SkYUVAPixmaps roundtrip;
198*c8dee2aaSAndroid Build Coastguard Worker {
199*c8dee2aaSAndroid Build Coastguard Worker SkJpegEncoder::Options options;
200*c8dee2aaSAndroid Build Coastguard Worker SkDynamicMemoryWStream encodeStream;
201*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, SkJpegEncoder::Encode(&encodeStream, decoded, nullptr, options));
202*c8dee2aaSAndroid Build Coastguard Worker auto encodedData = encodeStream.detachAsData();
203*c8dee2aaSAndroid Build Coastguard Worker roundtrip = decode_yuva(r, SkMemoryStream::Make(encodedData));
204*c8dee2aaSAndroid Build Coastguard Worker }
205*c8dee2aaSAndroid Build Coastguard Worker
206*c8dee2aaSAndroid Build Coastguard Worker verify_same(r, decoded, roundtrip);
207*c8dee2aaSAndroid Build Coastguard Worker }
208*c8dee2aaSAndroid Build Coastguard Worker }
209*c8dee2aaSAndroid Build Coastguard Worker
210*c8dee2aaSAndroid Build Coastguard Worker // Be sure that the two matrices are inverses of each other
211*c8dee2aaSAndroid Build Coastguard Worker // (i.e. rgb2yuv and yuv2rgb
DEF_TEST(YUVMath,reporter)212*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(YUVMath, reporter) {
213*c8dee2aaSAndroid Build Coastguard Worker const SkYUVColorSpace spaces[] = {
214*c8dee2aaSAndroid Build Coastguard Worker kJPEG_SkYUVColorSpace,
215*c8dee2aaSAndroid Build Coastguard Worker kRec601_SkYUVColorSpace,
216*c8dee2aaSAndroid Build Coastguard Worker kRec709_SkYUVColorSpace,
217*c8dee2aaSAndroid Build Coastguard Worker kBT2020_SkYUVColorSpace,
218*c8dee2aaSAndroid Build Coastguard Worker kIdentity_SkYUVColorSpace,
219*c8dee2aaSAndroid Build Coastguard Worker };
220*c8dee2aaSAndroid Build Coastguard Worker
221*c8dee2aaSAndroid Build Coastguard Worker // Not sure what the theoretical precision we can hope for is, so pick a big value that
222*c8dee2aaSAndroid Build Coastguard Worker // passes (when I think we're correct).
223*c8dee2aaSAndroid Build Coastguard Worker const float tolerance = 1.0f/(1 << 18);
224*c8dee2aaSAndroid Build Coastguard Worker
225*c8dee2aaSAndroid Build Coastguard Worker for (auto cs : spaces) {
226*c8dee2aaSAndroid Build Coastguard Worker SkColorMatrix r2ym = SkColorMatrix::RGBtoYUV(cs),
227*c8dee2aaSAndroid Build Coastguard Worker y2rm = SkColorMatrix::YUVtoRGB(cs);
228*c8dee2aaSAndroid Build Coastguard Worker r2ym.postConcat(y2rm);
229*c8dee2aaSAndroid Build Coastguard Worker
230*c8dee2aaSAndroid Build Coastguard Worker float tmp[20];
231*c8dee2aaSAndroid Build Coastguard Worker r2ym.getRowMajor(tmp);
232*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 20; ++i) {
233*c8dee2aaSAndroid Build Coastguard Worker float expected = 0;
234*c8dee2aaSAndroid Build Coastguard Worker if (i % 6 == 0) { // diagonal
235*c8dee2aaSAndroid Build Coastguard Worker expected = 1;
236*c8dee2aaSAndroid Build Coastguard Worker }
237*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, SkScalarNearlyEqual(tmp[i], expected, tolerance));
238*c8dee2aaSAndroid Build Coastguard Worker }
239*c8dee2aaSAndroid Build Coastguard Worker }
240*c8dee2aaSAndroid Build Coastguard Worker }
241