• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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/codec/SkEncodedOrigin.h"
10 #include "include/codec/SkWebpDecoder.h"
11 #include "include/core/SkImage.h"
12 #include "include/core/SkSize.h"
13 #include "include/core/SkStream.h"
14 #include "include/private/SkExif.h"
15 #include "tests/Test.h"
16 #include "tools/Resources.h"
17 
18 #include <memory>
19 #include <tuple>
20 #include <utility>
21 
DEF_TEST(ExifOrientation,r)22 DEF_TEST(ExifOrientation, r) {
23     std::unique_ptr<SkStream> stream(GetResourceAsStream("images/exif-orientation-2-ur.jpg"));
24     REPORTER_ASSERT(r, nullptr != stream);
25     if (!stream) {
26         return;
27     }
28 
29     std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(std::move(stream)));
30     REPORTER_ASSERT(r, nullptr != codec);
31     SkEncodedOrigin origin = codec->getOrigin();
32     REPORTER_ASSERT(r, kTopRight_SkEncodedOrigin == origin);
33 
34     codec = SkCodec::MakeFromStream(GetResourceAsStream("images/mandrill_512_q075.jpg"));
35     REPORTER_ASSERT(r, nullptr != codec);
36     origin = codec->getOrigin();
37     REPORTER_ASSERT(r, kTopLeft_SkEncodedOrigin == origin);
38 }
39 
DEF_TEST(GetImageRespectsExif,r)40 DEF_TEST(GetImageRespectsExif, r) {
41     std::unique_ptr<SkStream> stream(GetResourceAsStream("images/orientation/6.webp"));
42     REPORTER_ASSERT(r, nullptr != stream);
43     if (!stream) {
44         return;
45     }
46 
47     std::unique_ptr<SkCodec> codec(SkWebpDecoder::Decode(std::move(stream), nullptr));
48     REPORTER_ASSERT(r, nullptr != codec);
49     SkEncodedOrigin origin = codec->getOrigin();
50     REPORTER_ASSERT(r, kRightTop_SkEncodedOrigin == origin,
51                     "Actual origin %d", origin);
52 
53     auto result = codec->getImage();
54     REPORTER_ASSERT(r, std::get<1>(result) == SkCodec::Result::kSuccess,
55                     "Not success %d", std::get<1>(result));
56     sk_sp<SkImage> frame = std::get<0>(result);
57     REPORTER_ASSERT(r, frame);
58     SkISize dims = frame->dimensions();
59     REPORTER_ASSERT(r, dims.fWidth == 100, "width %d != 100", dims.fWidth);
60     REPORTER_ASSERT(r, dims.fHeight == 80, "height %d != 80", dims.fHeight);
61 }
62 
DEF_TEST(ExifOrientationInExif,r)63 DEF_TEST(ExifOrientationInExif, r) {
64     std::unique_ptr<SkStream> stream(GetResourceAsStream("images/orientation/exif.jpg"));
65 
66     std::unique_ptr<SkCodec> codec = SkCodec::MakeFromStream(std::move(stream));
67     REPORTER_ASSERT(r, nullptr != codec);
68     SkEncodedOrigin origin = codec->getOrigin();
69     REPORTER_ASSERT(r, kLeftBottom_SkEncodedOrigin == origin);
70 }
71 
DEF_TEST(ExifOrientationInSubIFD,r)72 DEF_TEST(ExifOrientationInSubIFD, r) {
73     std::unique_ptr<SkStream> stream(GetResourceAsStream("images/orientation/subifd.jpg"));
74 
75     std::unique_ptr<SkCodec> codec = SkCodec::MakeFromStream(std::move(stream));
76     REPORTER_ASSERT(r, nullptr != codec);
77     SkEncodedOrigin origin = codec->getOrigin();
78     REPORTER_ASSERT(r, kLeftBottom_SkEncodedOrigin == origin);
79 }
80 
approx_eq(float x,float y,float epsilon)81 static bool approx_eq(float x, float y, float epsilon) { return std::abs(x - y) < epsilon; }
82 
DEF_TEST(ExifParse,r)83 DEF_TEST(ExifParse, r) {
84     const float kEpsilon = 0.001f;
85 
86     {
87         sk_sp<SkData> data = GetResourceAsData("images/test0-hdr.exif");
88         REPORTER_ASSERT(r, nullptr != data);
89         SkExif::Metadata exif;
90         SkExif::Parse(exif, data.get());
91         REPORTER_ASSERT(r, exif.fHdrHeadroom.has_value());
92         REPORTER_ASSERT(r, approx_eq(exif.fHdrHeadroom.value(), 3.755296f, kEpsilon));
93 
94         REPORTER_ASSERT(r, exif.fResolutionUnit.has_value());
95         REPORTER_ASSERT(r, 2 == exif.fResolutionUnit.value());
96         REPORTER_ASSERT(r, exif.fXResolution.has_value());
97         REPORTER_ASSERT(r, 72.f == exif.fXResolution.value());
98         REPORTER_ASSERT(r, exif.fYResolution.has_value());
99         REPORTER_ASSERT(r, 72.f == exif.fYResolution.value());
100 
101         REPORTER_ASSERT(r, exif.fPixelXDimension.has_value());
102         REPORTER_ASSERT(r, 4032 == exif.fPixelXDimension.value());
103         REPORTER_ASSERT(r, exif.fPixelYDimension.has_value());
104         REPORTER_ASSERT(r, 3024 == exif.fPixelYDimension.value());
105     }
106 
107     {
108         sk_sp<SkData> data = GetResourceAsData("images/test1-pixel32.exif");
109         REPORTER_ASSERT(r, nullptr != data);
110         SkExif::Metadata exif;
111         SkExif::Parse(exif, data.get());
112         REPORTER_ASSERT(r, !exif.fHdrHeadroom.has_value());
113 
114         REPORTER_ASSERT(r, exif.fResolutionUnit.value());
115         REPORTER_ASSERT(r, 2 == exif.fResolutionUnit.value());
116         REPORTER_ASSERT(r, exif.fXResolution.has_value());
117         REPORTER_ASSERT(r, 72.f == exif.fXResolution.value());
118         REPORTER_ASSERT(r, exif.fYResolution.has_value());
119         REPORTER_ASSERT(r, 72.f == exif.fYResolution.value());
120 
121         REPORTER_ASSERT(r, exif.fPixelXDimension.has_value());
122         REPORTER_ASSERT(r, 200 == exif.fPixelXDimension.value());
123         REPORTER_ASSERT(r, exif.fPixelYDimension.has_value());
124         REPORTER_ASSERT(r, 100 == exif.fPixelYDimension.value());
125     }
126 
127     {
128         sk_sp<SkData> data = GetResourceAsData("images/test2-nonuniform.exif");
129         REPORTER_ASSERT(r, nullptr != data);
130         SkExif::Metadata exif;
131         SkExif::Parse(exif, data.get());
132         REPORTER_ASSERT(r, !exif.fHdrHeadroom.has_value());
133 
134         REPORTER_ASSERT(r, exif.fResolutionUnit.value());
135         REPORTER_ASSERT(r, 2 == exif.fResolutionUnit.value());
136         REPORTER_ASSERT(r, exif.fXResolution.has_value());
137         REPORTER_ASSERT(r, 144.f == exif.fXResolution.value());
138         REPORTER_ASSERT(r, exif.fYResolution.has_value());
139         REPORTER_ASSERT(r, 36.f == exif.fYResolution.value());
140 
141         REPORTER_ASSERT(r, exif.fPixelXDimension.has_value());
142         REPORTER_ASSERT(r, 50 == exif.fPixelXDimension.value());
143         REPORTER_ASSERT(r, exif.fPixelYDimension.has_value());
144         REPORTER_ASSERT(r, 100 == exif.fPixelYDimension.value());
145     }
146 
147     {
148         sk_sp<SkData> data = GetResourceAsData("images/test3-little-endian.exif");
149         REPORTER_ASSERT(r, nullptr != data);
150         SkExif::Metadata exif;
151         SkExif::Parse(exif, data.get());
152         REPORTER_ASSERT(r, !exif.fHdrHeadroom.has_value());
153 
154         REPORTER_ASSERT(r, exif.fResolutionUnit.value());
155         REPORTER_ASSERT(r, 2 == exif.fResolutionUnit.value());
156         REPORTER_ASSERT(r, exif.fXResolution.has_value());
157         REPORTER_ASSERT(r, 350.f == exif.fXResolution.value());
158         REPORTER_ASSERT(r, exif.fYResolution.has_value());
159         REPORTER_ASSERT(r, 350.f == exif.fYResolution.value());
160 
161         REPORTER_ASSERT(r, !exif.fPixelXDimension.has_value());
162         REPORTER_ASSERT(r, !exif.fPixelYDimension.has_value());
163     }
164 
165     {
166         sk_sp<SkData> data = GetResourceAsData("images/test0-hdr.exif");
167 
168         // Zero out the denominators of signed and unsigned rationals, to verify that we do not
169         // divide by zero.
170         data = SkData::MakeWithCopy(data->bytes(), data->size());
171         memset(static_cast<uint8_t*>(data->writable_data()) + 186, 0, 4);
172         memset(static_cast<uint8_t*>(data->writable_data()) + 2171, 0, 4);
173         memset(static_cast<uint8_t*>(data->writable_data()) + 2240, 0, 4);
174 
175         // Parse the corrupted Exif.
176         SkExif::Metadata exif;
177         SkExif::Parse(exif, data.get());
178 
179         // HDR headroom signed denominators are destroyed.
180         REPORTER_ASSERT(r, exif.fHdrHeadroom.has_value());
181         REPORTER_ASSERT(r, approx_eq(exif.fHdrHeadroom.value(), 3.482202f, kEpsilon));
182 
183         // The X resolution should be zero.
184         REPORTER_ASSERT(r, exif.fXResolution.has_value());
185         REPORTER_ASSERT(r, 0.f == exif.fXResolution.value());
186         REPORTER_ASSERT(r, exif.fYResolution.has_value());
187         REPORTER_ASSERT(r, 72.f == exif.fYResolution.value());
188     }
189 }
190 
DEF_TEST(ExifTruncate,r)191 DEF_TEST(ExifTruncate, r) {
192     sk_sp<SkData> data = GetResourceAsData("images/test0-hdr.exif");
193 
194     // At 545 bytes, we do not have either value yet.
195     {
196         SkExif::Metadata exif;
197         SkExif::Parse(exif, SkData::MakeWithCopy(data->bytes(), 545).get());
198         REPORTER_ASSERT(r, !exif.fPixelXDimension.has_value());
199         REPORTER_ASSERT(r, !exif.fPixelYDimension.has_value());
200     }
201 
202     // At 546 bytes, we have one.
203     {
204         SkExif::Metadata exif;
205         SkExif::Parse(exif, SkData::MakeWithCopy(data->bytes(), 546).get());
206         REPORTER_ASSERT(r, exif.fPixelXDimension.has_value());
207         REPORTER_ASSERT(r, !exif.fPixelYDimension.has_value());
208     }
209 
210     // At 558 bytes (12 bytes later, one tag), we have both.
211     {
212         SkExif::Metadata exif;
213         SkExif::Parse(exif, SkData::MakeWithCopy(data->bytes(), 558).get());
214         REPORTER_ASSERT(r, exif.fPixelXDimension.has_value());
215         REPORTER_ASSERT(r, exif.fPixelYDimension.has_value());
216     }
217 }
218