• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
8 #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"
15 
codec_yuv(skiatest::Reporter * reporter,const char path[],SkISize expectedSizes[4])16 static void codec_yuv(skiatest::Reporter* reporter,
17                       const char path[],
18                       SkISize expectedSizes[4]) {
19     std::unique_ptr<SkStream> stream(GetResourceAsStream(path));
20     if (!stream) {
21         return;
22     }
23     std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(std::move(stream)));
24     REPORTER_ASSERT(reporter, codec);
25     if (!codec) {
26         return;
27     }
28 
29     // Test queryYUV8()
30     SkYUVASizeInfo info;
31 
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 
41         for (int i = 0; i < SkYUVASizeInfo::kMaxCount; ++i) {
42             REPORTER_ASSERT(reporter, info.fSizes[i] == expectedSizes[i]);
43             REPORTER_ASSERT(reporter,
44                             info.fWidthBytes[i] == (uint32_t) SkAlign8(info.fSizes[i].width()));
45         }
46     }
47 
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 
56         for (int i = 0; i < SkYUVASizeInfo::kMaxCount; ++i) {
57             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     }
63 
64     // Allocate the memory for the YUV decode
65     size_t totalBytes = info.computeTotalBytes();
66 
67     SkAutoMalloc storage(totalBytes);
68     void* planes[SkYUVASizeInfo::kMaxCount];
69 
70     info.computePlanes(storage.get(), planes);
71 
72     // Test getYUV8Planes()
73     REPORTER_ASSERT(reporter, SkCodec::kInvalidInput == codec->getYUV8Planes(info, nullptr));
74     REPORTER_ASSERT(reporter, SkCodec::kSuccess == codec->getYUV8Planes(info, planes));
75 }
76 
DEF_TEST(Jpeg_YUV_Codec,r)77 DEF_TEST(Jpeg_YUV_Codec, r) {
78     SkISize sizes[4];
79 
80     sizes[0].set(128, 128);
81     sizes[1].set(64, 64);
82     sizes[2].set(64, 64);
83     sizes[3].set(0, 0);
84     codec_yuv(r, "images/color_wheel.jpg", sizes);
85 
86     // H2V2
87     sizes[0].set(512, 512);
88     sizes[1].set(256, 256);
89     sizes[2].set(256, 256);
90     codec_yuv(r, "images/mandrill_512_q075.jpg", sizes);
91 
92     // H1V1
93     sizes[1].set(512, 512);
94     sizes[2].set(512, 512);
95     codec_yuv(r, "images/mandrill_h1v1.jpg", sizes);
96 
97     // H2V1
98     sizes[1].set(256, 512);
99     sizes[2].set(256, 512);
100     codec_yuv(r, "images/mandrill_h2v1.jpg", sizes);
101 
102     // Non-power of two dimensions
103     sizes[0].set(439, 154);
104     sizes[1].set(220, 77);
105     sizes[2].set(220, 77);
106     codec_yuv(r, "images/cropped_mandrill.jpg", sizes);
107 
108     sizes[0].set(8, 8);
109     sizes[1].set(4, 4);
110     sizes[2].set(4, 4);
111     codec_yuv(r, "images/randPixels.jpg", sizes);
112 
113     // Progressive images
114     sizes[0].set(512, 512);
115     sizes[1].set(512, 512);
116     sizes[2].set(512, 512);
117     codec_yuv(r, "images/brickwork-texture.jpg", sizes);
118     codec_yuv(r, "images/brickwork_normal-map.jpg", sizes);
119 
120     // A CMYK encoded image should fail.
121     codec_yuv(r, "images/CMYK.jpg", nullptr);
122     // A grayscale encoded image should fail.
123     codec_yuv(r, "images/grayscale.jpg", nullptr);
124     // A PNG should fail.
125     codec_yuv(r, "images/arrow.png", nullptr);
126 }
127 
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
DEF_TEST(YUVMath,reporter)133 DEF_TEST(YUVMath, reporter) {
134     const SkYUVColorSpace spaces[] = {
135         kJPEG_SkYUVColorSpace,
136         kRec601_SkYUVColorSpace,
137         kRec709_SkYUVColorSpace,
138         kBT2020_SkYUVColorSpace,
139         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 }
167