blob: 070403ac36352be652c80cc35547f322da379cd4 [file] [log] [blame]
msarett829caa22016-02-11 14:17:17 -08001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/codec/SkCodec.h"
9#include "include/core/SkStream.h"
10#include "include/core/SkYUVASizeInfo.h"
11#include "include/private/SkTemplates.h"
12#include "src/core/SkAutoMalloc.h"
13#include "tests/Test.h"
14#include "tools/Resources.h"
msarett829caa22016-02-11 14:17:17 -080015
msarett829caa22016-02-11 14:17:17 -080016static void codec_yuv(skiatest::Reporter* reporter,
Jim Van Verth8f11e432018-10-18 14:36:59 -040017 const char path[],
18 SkISize expectedSizes[4]) {
Ben Wagner145dbcd2016-11-03 14:40:50 -040019 std::unique_ptr<SkStream> stream(GetResourceAsStream(path));
msarett829caa22016-02-11 14:17:17 -080020 if (!stream) {
msarett829caa22016-02-11 14:17:17 -080021 return;
22 }
Mike Reedede7bac2017-07-23 15:30:02 -040023 std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(std::move(stream)));
msarett829caa22016-02-11 14:17:17 -080024 REPORTER_ASSERT(reporter, codec);
25 if (!codec) {
26 return;
27 }
28
29 // Test queryYUV8()
Jim Van Verthe24b5872018-10-29 16:26:02 -040030 SkYUVASizeInfo info;
Jim Van Verth8f11e432018-10-18 14:36:59 -040031
32 {
33 bool success = codec->queryYUV8(nullptr, nullptr);
34 REPORTER_ASSERT(reporter, !success);
35 success = codec->queryYUV8(&info, nullptr);
36 REPORTER_ASSERT(reporter, (expectedSizes == nullptr) == !success);
37 if (!success) {
38 return;
39 }
40
Jim Van Verthe24b5872018-10-29 16:26:02 -040041 for (int i = 0; i < SkYUVASizeInfo::kMaxCount; ++i) {
Jim Van Verth8f11e432018-10-18 14:36:59 -040042 REPORTER_ASSERT(reporter, info.fSizes[i] == expectedSizes[i]);
43 REPORTER_ASSERT(reporter,
44 info.fWidthBytes[i] == (uint32_t) SkAlign8(info.fSizes[i].width()));
45 }
msarett829caa22016-02-11 14:17:17 -080046 }
Jim Van Verth8f11e432018-10-18 14:36:59 -040047
48 {
49 SkYUVColorSpace colorSpace;
50 bool success = codec->queryYUV8(&info, &colorSpace);
51 REPORTER_ASSERT(reporter, (expectedSizes == nullptr) == !success);
52 if (!success) {
53 return;
54 }
55
Jim Van Verthe24b5872018-10-29 16:26:02 -040056 for (int i = 0; i < SkYUVASizeInfo::kMaxCount; ++i) {
Jim Van Verth8f11e432018-10-18 14:36:59 -040057 REPORTER_ASSERT(reporter, info.fSizes[i] == expectedSizes[i]);
58 REPORTER_ASSERT(reporter,
59 info.fWidthBytes[i] == (uint32_t) SkAlign8(info.fSizes[i].width()));
60 }
61 REPORTER_ASSERT(reporter, kJPEG_SkYUVColorSpace == colorSpace);
62 }
msarett829caa22016-02-11 14:17:17 -080063
64 // Allocate the memory for the YUV decode
Jim Van Verth8f11e432018-10-18 14:36:59 -040065 size_t totalBytes = info.computeTotalBytes();
66
msarett829caa22016-02-11 14:17:17 -080067 SkAutoMalloc storage(totalBytes);
Jim Van Verthe24b5872018-10-29 16:26:02 -040068 void* planes[SkYUVASizeInfo::kMaxCount];
Jim Van Verth8f11e432018-10-18 14:36:59 -040069
70 info.computePlanes(storage.get(), planes);
msarett829caa22016-02-11 14:17:17 -080071
72 // Test getYUV8Planes()
Jim Van Verth8f11e432018-10-18 14:36:59 -040073 REPORTER_ASSERT(reporter, SkCodec::kInvalidInput == codec->getYUV8Planes(info, nullptr));
74 REPORTER_ASSERT(reporter, SkCodec::kSuccess == codec->getYUV8Planes(info, planes));
msarett829caa22016-02-11 14:17:17 -080075}
76
77DEF_TEST(Jpeg_YUV_Codec, r) {
Jim Van Verth8f11e432018-10-18 14:36:59 -040078 SkISize sizes[4];
msarett829caa22016-02-11 14:17:17 -080079
80 sizes[0].set(128, 128);
81 sizes[1].set(64, 64);
82 sizes[2].set(64, 64);
Jim Van Verth8f11e432018-10-18 14:36:59 -040083 sizes[3].set(0, 0);
Hal Canaryc465d132017-12-08 10:21:31 -050084 codec_yuv(r, "images/color_wheel.jpg", sizes);
msarett829caa22016-02-11 14:17:17 -080085
86 // H2V2
87 sizes[0].set(512, 512);
88 sizes[1].set(256, 256);
89 sizes[2].set(256, 256);
Hal Canaryc465d132017-12-08 10:21:31 -050090 codec_yuv(r, "images/mandrill_512_q075.jpg", sizes);
msarett829caa22016-02-11 14:17:17 -080091
92 // H1V1
93 sizes[1].set(512, 512);
94 sizes[2].set(512, 512);
Hal Canaryc465d132017-12-08 10:21:31 -050095 codec_yuv(r, "images/mandrill_h1v1.jpg", sizes);
msarett829caa22016-02-11 14:17:17 -080096
97 // H2V1
98 sizes[1].set(256, 512);
99 sizes[2].set(256, 512);
Hal Canaryc465d132017-12-08 10:21:31 -0500100 codec_yuv(r, "images/mandrill_h2v1.jpg", sizes);
msarett829caa22016-02-11 14:17:17 -0800101
102 // Non-power of two dimensions
103 sizes[0].set(439, 154);
104 sizes[1].set(220, 77);
105 sizes[2].set(220, 77);
Hal Canaryc465d132017-12-08 10:21:31 -0500106 codec_yuv(r, "images/cropped_mandrill.jpg", sizes);
msarett829caa22016-02-11 14:17:17 -0800107
108 sizes[0].set(8, 8);
109 sizes[1].set(4, 4);
110 sizes[2].set(4, 4);
Hal Canaryc465d132017-12-08 10:21:31 -0500111 codec_yuv(r, "images/randPixels.jpg", sizes);
msarett829caa22016-02-11 14:17:17 -0800112
113 // Progressive images
114 sizes[0].set(512, 512);
115 sizes[1].set(512, 512);
116 sizes[2].set(512, 512);
Hal Canaryc465d132017-12-08 10:21:31 -0500117 codec_yuv(r, "images/brickwork-texture.jpg", sizes);
118 codec_yuv(r, "images/brickwork_normal-map.jpg", sizes);
msarett829caa22016-02-11 14:17:17 -0800119
120 // A CMYK encoded image should fail.
Hal Canaryc465d132017-12-08 10:21:31 -0500121 codec_yuv(r, "images/CMYK.jpg", nullptr);
msarett829caa22016-02-11 14:17:17 -0800122 // A grayscale encoded image should fail.
Hal Canaryc465d132017-12-08 10:21:31 -0500123 codec_yuv(r, "images/grayscale.jpg", nullptr);
msarett829caa22016-02-11 14:17:17 -0800124 // A PNG should fail.
Hal Canaryc465d132017-12-08 10:21:31 -0500125 codec_yuv(r, "images/arrow.png", nullptr);
msarett829caa22016-02-11 14:17:17 -0800126}
Mike Reed6a5f7e22019-05-23 15:30:07 -0400127
128#include "include/effects/SkColorMatrix.h"
129#include "src/core/SkYUVMath.h"
130
131// Be sure that the two matrices are inverses of each other
132// (i.e. rgb2yuv and yuv2rgb
133DEF_TEST(YUVMath, reporter) {
134 const SkYUVColorSpace spaces[] = {
135 kJPEG_SkYUVColorSpace,
136 kRec601_SkYUVColorSpace,
137 kRec709_SkYUVColorSpace,
Brian Osman2b73e662019-11-01 10:02:24 -0400138 kBT2020_SkYUVColorSpace,
Mike Reed6a5f7e22019-05-23 15:30:07 -0400139 kIdentity_SkYUVColorSpace,
140 };
141
142 // Not sure what the theoretical precision we can hope for is, so pick a big value that
143 // passes (when I think we're correct).
144 const float tolerance = 1.0f/(1 << 18);
145
146 for (auto cs : spaces) {
147 float r2y[20], y2r[20];
148 SkColorMatrix_RGB2YUV(cs, r2y);
149 SkColorMatrix_YUV2RGB(cs, y2r);
150
151 SkColorMatrix r2ym, y2rm;
152 r2ym.setRowMajor(r2y);
153 y2rm.setRowMajor(y2r);
154 r2ym.postConcat(y2rm);
155
156 float tmp[20];
157 r2ym.getRowMajor(tmp);
158 for (int i = 0; i < 20; ++i) {
159 float expected = 0;
160 if (i % 6 == 0) { // diagonal
161 expected = 1;
162 }
163 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(tmp[i], expected, tolerance));
164 }
165 }
166}