xref: /third_party/skia/tests/YUVTest.cpp (revision cb93a386)
1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2013 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/codec/SkCodec.h"
9cb93a386Sopenharmony_ci#include "include/core/SkPixmap.h"
10cb93a386Sopenharmony_ci#include "include/core/SkStream.h"
11cb93a386Sopenharmony_ci#include "include/private/SkTemplates.h"
12cb93a386Sopenharmony_ci#include "src/core/SkAutoMalloc.h"
13cb93a386Sopenharmony_ci#include "tests/Test.h"
14cb93a386Sopenharmony_ci#include "tools/Resources.h"
15cb93a386Sopenharmony_ci
16cb93a386Sopenharmony_cistatic void codec_yuv(skiatest::Reporter* reporter,
17cb93a386Sopenharmony_ci                      const char path[],
18cb93a386Sopenharmony_ci                      const SkYUVAInfo* expectedInfo) {
19cb93a386Sopenharmony_ci    std::unique_ptr<SkStream> stream(GetResourceAsStream(path));
20cb93a386Sopenharmony_ci    if (!stream) {
21cb93a386Sopenharmony_ci        return;
22cb93a386Sopenharmony_ci    }
23cb93a386Sopenharmony_ci    std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(std::move(stream)));
24cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, codec);
25cb93a386Sopenharmony_ci    if (!codec) {
26cb93a386Sopenharmony_ci        return;
27cb93a386Sopenharmony_ci    }
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ci    // Test queryYUBAInfo()
30cb93a386Sopenharmony_ci    SkYUVAPixmapInfo yuvaPixmapInfo;
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ci    static constexpr auto kAllTypes = SkYUVAPixmapInfo::SupportedDataTypes::All();
33cb93a386Sopenharmony_ci    static constexpr auto kNoTypes  = SkYUVAPixmapInfo::SupportedDataTypes();
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_ci    // SkYUVAInfo param is required to be non-null.
36cb93a386Sopenharmony_ci    bool success = codec->queryYUVAInfo(kAllTypes, nullptr);
37cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !success);
38cb93a386Sopenharmony_ci    // Fails when there is no support for YUVA planes.
39cb93a386Sopenharmony_ci    success = codec->queryYUVAInfo(kNoTypes, &yuvaPixmapInfo);
40cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, !success);
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_ci    success = codec->queryYUVAInfo(kAllTypes, &yuvaPixmapInfo);
43cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, SkToBool(expectedInfo) == success);
44cb93a386Sopenharmony_ci    if (!success) {
45cb93a386Sopenharmony_ci        return;
46cb93a386Sopenharmony_ci    }
47cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, *expectedInfo == yuvaPixmapInfo.yuvaInfo());
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_ci    int numPlanes = yuvaPixmapInfo.numPlanes();
50cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, numPlanes <= SkYUVAInfo::kMaxPlanes);
51cb93a386Sopenharmony_ci    for (int i = 0; i < numPlanes; ++i) {
52cb93a386Sopenharmony_ci        const SkImageInfo& planeInfo = yuvaPixmapInfo.planeInfo(i);
53cb93a386Sopenharmony_ci        SkColorType planeCT = planeInfo.colorType();
54cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !planeInfo.isEmpty());
55cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, planeCT != kUnknown_SkColorType);
56cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, planeInfo.validRowBytes(yuvaPixmapInfo.rowBytes(i)));
57cb93a386Sopenharmony_ci        // Currently all planes must share a data type, gettable as SkYUVAPixmapInfo::dataType().
58cb93a386Sopenharmony_ci        auto [numChannels, planeDataType] = SkYUVAPixmapInfo::NumChannelsAndDataType(planeCT);
59cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, planeDataType == yuvaPixmapInfo.dataType());
60cb93a386Sopenharmony_ci    }
61cb93a386Sopenharmony_ci    for (int i = numPlanes; i < SkYUVAInfo::kMaxPlanes; ++i) {
62cb93a386Sopenharmony_ci        const SkImageInfo& planeInfo = yuvaPixmapInfo.planeInfo(i);
63cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, planeInfo.dimensions().isEmpty());
64cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, planeInfo.colorType() == kUnknown_SkColorType);
65cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, yuvaPixmapInfo.rowBytes(i) == 0);
66cb93a386Sopenharmony_ci    }
67cb93a386Sopenharmony_ci
68cb93a386Sopenharmony_ci    // Allocate the memory for the YUV decode.
69cb93a386Sopenharmony_ci    auto pixmaps = SkYUVAPixmaps::Allocate(yuvaPixmapInfo);
70cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, pixmaps.isValid());
71cb93a386Sopenharmony_ci
72cb93a386Sopenharmony_ci    for (int i = 0; i < SkYUVAPixmaps::kMaxPlanes; ++i) {
73cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, pixmaps.plane(i).info() == yuvaPixmapInfo.planeInfo(i));
74cb93a386Sopenharmony_ci    }
75cb93a386Sopenharmony_ci    for (int i = numPlanes; i < SkYUVAInfo::kMaxPlanes; ++i) {
76cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, pixmaps.plane(i).rowBytes() == 0);
77cb93a386Sopenharmony_ci    }
78cb93a386Sopenharmony_ci
79cb93a386Sopenharmony_ci    // Test getYUVAPlanes()
80cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, SkCodec::kSuccess == codec->getYUVAPlanes(pixmaps));
81cb93a386Sopenharmony_ci}
82cb93a386Sopenharmony_ci
83cb93a386Sopenharmony_ciDEF_TEST(Jpeg_YUV_Codec, r) {
84cb93a386Sopenharmony_ci    auto setExpectations = [](SkISize dims, SkYUVAInfo::Subsampling subsampling) {
85cb93a386Sopenharmony_ci        return SkYUVAInfo(dims,
86cb93a386Sopenharmony_ci                          SkYUVAInfo::PlaneConfig::kY_U_V,
87cb93a386Sopenharmony_ci                          subsampling,
88cb93a386Sopenharmony_ci                          kJPEG_Full_SkYUVColorSpace,
89cb93a386Sopenharmony_ci                          kTopLeft_SkEncodedOrigin,
90cb93a386Sopenharmony_ci                          SkYUVAInfo::Siting::kCentered,
91cb93a386Sopenharmony_ci                          SkYUVAInfo::Siting::kCentered);
92cb93a386Sopenharmony_ci    };
93cb93a386Sopenharmony_ci
94cb93a386Sopenharmony_ci    SkYUVAInfo expectations = setExpectations({128, 128}, SkYUVAInfo::Subsampling::k420);
95cb93a386Sopenharmony_ci    codec_yuv(r, "images/color_wheel.jpg", &expectations);
96cb93a386Sopenharmony_ci
97cb93a386Sopenharmony_ci    // H2V2
98cb93a386Sopenharmony_ci    expectations = setExpectations({512, 512}, SkYUVAInfo::Subsampling::k420);
99cb93a386Sopenharmony_ci    codec_yuv(r, "images/mandrill_512_q075.jpg", &expectations);
100cb93a386Sopenharmony_ci
101cb93a386Sopenharmony_ci    // H1V1
102cb93a386Sopenharmony_ci    expectations = setExpectations({512, 512}, SkYUVAInfo::Subsampling::k444);
103cb93a386Sopenharmony_ci    codec_yuv(r, "images/mandrill_h1v1.jpg", &expectations);
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_ci    // H2V1
106cb93a386Sopenharmony_ci    expectations = setExpectations({512, 512}, SkYUVAInfo::Subsampling::k422);
107cb93a386Sopenharmony_ci    codec_yuv(r, "images/mandrill_h2v1.jpg", &expectations);
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_ci    // Non-power of two dimensions
110cb93a386Sopenharmony_ci    expectations = setExpectations({439, 154}, SkYUVAInfo::Subsampling::k420);
111cb93a386Sopenharmony_ci    codec_yuv(r, "images/cropped_mandrill.jpg", &expectations);
112cb93a386Sopenharmony_ci
113cb93a386Sopenharmony_ci    expectations = setExpectations({8, 8}, SkYUVAInfo::Subsampling::k420);
114cb93a386Sopenharmony_ci    codec_yuv(r, "images/randPixels.jpg", &expectations);
115cb93a386Sopenharmony_ci
116cb93a386Sopenharmony_ci    // Progressive images
117cb93a386Sopenharmony_ci    expectations = setExpectations({512, 512}, SkYUVAInfo::Subsampling::k444);
118cb93a386Sopenharmony_ci    codec_yuv(r, "images/brickwork-texture.jpg", &expectations);
119cb93a386Sopenharmony_ci    codec_yuv(r, "images/brickwork_normal-map.jpg", &expectations);
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_ci    // A CMYK encoded image should fail.
122cb93a386Sopenharmony_ci    codec_yuv(r, "images/CMYK.jpg", nullptr);
123cb93a386Sopenharmony_ci    // A grayscale encoded image should fail.
124cb93a386Sopenharmony_ci    codec_yuv(r, "images/grayscale.jpg", nullptr);
125cb93a386Sopenharmony_ci    // A PNG should fail.
126cb93a386Sopenharmony_ci    codec_yuv(r, "images/arrow.png", nullptr);
127cb93a386Sopenharmony_ci}
128cb93a386Sopenharmony_ci
129cb93a386Sopenharmony_ci#include "include/effects/SkColorMatrix.h"
130cb93a386Sopenharmony_ci#include "src/core/SkYUVMath.h"
131cb93a386Sopenharmony_ci
132cb93a386Sopenharmony_ci// Be sure that the two matrices are inverses of each other
133cb93a386Sopenharmony_ci// (i.e. rgb2yuv and yuv2rgb
134cb93a386Sopenharmony_ciDEF_TEST(YUVMath, reporter) {
135cb93a386Sopenharmony_ci    const SkYUVColorSpace spaces[] = {
136cb93a386Sopenharmony_ci        kJPEG_SkYUVColorSpace,
137cb93a386Sopenharmony_ci        kRec601_SkYUVColorSpace,
138cb93a386Sopenharmony_ci        kRec709_SkYUVColorSpace,
139cb93a386Sopenharmony_ci        kBT2020_SkYUVColorSpace,
140cb93a386Sopenharmony_ci        kIdentity_SkYUVColorSpace,
141cb93a386Sopenharmony_ci    };
142cb93a386Sopenharmony_ci
143cb93a386Sopenharmony_ci    // Not sure what the theoretical precision we can hope for is, so pick a big value that
144cb93a386Sopenharmony_ci    // passes (when I think we're correct).
145cb93a386Sopenharmony_ci    const float tolerance = 1.0f/(1 << 18);
146cb93a386Sopenharmony_ci
147cb93a386Sopenharmony_ci    for (auto cs : spaces) {
148cb93a386Sopenharmony_ci        SkColorMatrix r2ym = SkColorMatrix::RGBtoYUV(cs),
149cb93a386Sopenharmony_ci                      y2rm = SkColorMatrix::YUVtoRGB(cs);
150cb93a386Sopenharmony_ci        r2ym.postConcat(y2rm);
151cb93a386Sopenharmony_ci
152cb93a386Sopenharmony_ci        float tmp[20];
153cb93a386Sopenharmony_ci        r2ym.getRowMajor(tmp);
154cb93a386Sopenharmony_ci        for (int i = 0; i < 20; ++i) {
155cb93a386Sopenharmony_ci            float expected = 0;
156cb93a386Sopenharmony_ci            if (i % 6 == 0) {   // diagonal
157cb93a386Sopenharmony_ci                expected = 1;
158cb93a386Sopenharmony_ci            }
159cb93a386Sopenharmony_ci            REPORTER_ASSERT(reporter, SkScalarNearlyEqual(tmp[i], expected, tolerance));
160cb93a386Sopenharmony_ci        }
161cb93a386Sopenharmony_ci    }
162cb93a386Sopenharmony_ci}
163