1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2016 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/codec/SkWebpDecoder.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/encode/SkJpegEncoder.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/SkExif.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "tools/Resources.h"
19*c8dee2aaSAndroid Build Coastguard Worker
20*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
21*c8dee2aaSAndroid Build Coastguard Worker #include <tuple>
22*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
23*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(ExifOrientation,r)24*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(ExifOrientation, r) {
25*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkStream> stream(GetResourceAsStream("images/exif-orientation-2-ur.jpg"));
26*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, nullptr != stream);
27*c8dee2aaSAndroid Build Coastguard Worker if (!stream) {
28*c8dee2aaSAndroid Build Coastguard Worker return;
29*c8dee2aaSAndroid Build Coastguard Worker }
30*c8dee2aaSAndroid Build Coastguard Worker
31*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(std::move(stream)));
32*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, nullptr != codec);
33*c8dee2aaSAndroid Build Coastguard Worker SkEncodedOrigin origin = codec->getOrigin();
34*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, kTopRight_SkEncodedOrigin == origin);
35*c8dee2aaSAndroid Build Coastguard Worker
36*c8dee2aaSAndroid Build Coastguard Worker codec = SkCodec::MakeFromStream(GetResourceAsStream("images/mandrill_512_q075.jpg"));
37*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, nullptr != codec);
38*c8dee2aaSAndroid Build Coastguard Worker origin = codec->getOrigin();
39*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, kTopLeft_SkEncodedOrigin == origin);
40*c8dee2aaSAndroid Build Coastguard Worker }
41*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(GetImageRespectsExif,r)42*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(GetImageRespectsExif, r) {
43*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkStream> stream(GetResourceAsStream("images/orientation/6.webp"));
44*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, nullptr != stream);
45*c8dee2aaSAndroid Build Coastguard Worker if (!stream) {
46*c8dee2aaSAndroid Build Coastguard Worker return;
47*c8dee2aaSAndroid Build Coastguard Worker }
48*c8dee2aaSAndroid Build Coastguard Worker
49*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkCodec> codec(SkWebpDecoder::Decode(std::move(stream), nullptr));
50*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, nullptr != codec);
51*c8dee2aaSAndroid Build Coastguard Worker SkEncodedOrigin origin = codec->getOrigin();
52*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, kRightTop_SkEncodedOrigin == origin,
53*c8dee2aaSAndroid Build Coastguard Worker "Actual origin %d", origin);
54*c8dee2aaSAndroid Build Coastguard Worker
55*c8dee2aaSAndroid Build Coastguard Worker auto result = codec->getImage();
56*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, std::get<1>(result) == SkCodec::Result::kSuccess,
57*c8dee2aaSAndroid Build Coastguard Worker "Not success %d", std::get<1>(result));
58*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> frame = std::get<0>(result);
59*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, frame);
60*c8dee2aaSAndroid Build Coastguard Worker SkISize dims = frame->dimensions();
61*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, dims.fWidth == 100, "width %d != 100", dims.fWidth);
62*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, dims.fHeight == 80, "height %d != 80", dims.fHeight);
63*c8dee2aaSAndroid Build Coastguard Worker }
64*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(ExifOrientationInExif,r)65*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(ExifOrientationInExif, r) {
66*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkStream> stream(GetResourceAsStream("images/orientation/exif.jpg"));
67*c8dee2aaSAndroid Build Coastguard Worker
68*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkCodec> codec = SkCodec::MakeFromStream(std::move(stream));
69*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, nullptr != codec);
70*c8dee2aaSAndroid Build Coastguard Worker SkEncodedOrigin origin = codec->getOrigin();
71*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, kLeftBottom_SkEncodedOrigin == origin);
72*c8dee2aaSAndroid Build Coastguard Worker }
73*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(ExifOrientationInSubIFD,r)74*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(ExifOrientationInSubIFD, r) {
75*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkStream> stream(GetResourceAsStream("images/orientation/subifd.jpg"));
76*c8dee2aaSAndroid Build Coastguard Worker
77*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkCodec> codec = SkCodec::MakeFromStream(std::move(stream));
78*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, nullptr != codec);
79*c8dee2aaSAndroid Build Coastguard Worker SkEncodedOrigin origin = codec->getOrigin();
80*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, kLeftBottom_SkEncodedOrigin == origin);
81*c8dee2aaSAndroid Build Coastguard Worker }
82*c8dee2aaSAndroid Build Coastguard Worker
approx_eq(float x,float y,float epsilon)83*c8dee2aaSAndroid Build Coastguard Worker static bool approx_eq(float x, float y, float epsilon) { return std::abs(x - y) < epsilon; }
84*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(ExifParse,r)85*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(ExifParse, r) {
86*c8dee2aaSAndroid Build Coastguard Worker const float kEpsilon = 0.001f;
87*c8dee2aaSAndroid Build Coastguard Worker
88*c8dee2aaSAndroid Build Coastguard Worker {
89*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data = GetResourceAsData("images/test0-hdr.exif");
90*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, nullptr != data);
91*c8dee2aaSAndroid Build Coastguard Worker SkExif::Metadata exif;
92*c8dee2aaSAndroid Build Coastguard Worker SkExif::Parse(exif, data.get());
93*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fHdrHeadroom.has_value());
94*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, approx_eq(exif.fHdrHeadroom.value(), 3.755296f, kEpsilon));
95*c8dee2aaSAndroid Build Coastguard Worker
96*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fResolutionUnit.has_value());
97*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 2 == exif.fResolutionUnit.value());
98*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fXResolution.has_value());
99*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 72.f == exif.fXResolution.value());
100*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fYResolution.has_value());
101*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 72.f == exif.fYResolution.value());
102*c8dee2aaSAndroid Build Coastguard Worker
103*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fPixelXDimension.has_value());
104*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 4032 == exif.fPixelXDimension.value());
105*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fPixelYDimension.has_value());
106*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 3024 == exif.fPixelYDimension.value());
107*c8dee2aaSAndroid Build Coastguard Worker }
108*c8dee2aaSAndroid Build Coastguard Worker
109*c8dee2aaSAndroid Build Coastguard Worker {
110*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data = GetResourceAsData("images/test1-pixel32.exif");
111*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, nullptr != data);
112*c8dee2aaSAndroid Build Coastguard Worker SkExif::Metadata exif;
113*c8dee2aaSAndroid Build Coastguard Worker SkExif::Parse(exif, data.get());
114*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, !exif.fHdrHeadroom.has_value());
115*c8dee2aaSAndroid Build Coastguard Worker
116*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fResolutionUnit.value());
117*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 2 == exif.fResolutionUnit.value());
118*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fXResolution.has_value());
119*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 72.f == exif.fXResolution.value());
120*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fYResolution.has_value());
121*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 72.f == exif.fYResolution.value());
122*c8dee2aaSAndroid Build Coastguard Worker
123*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fPixelXDimension.has_value());
124*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 200 == exif.fPixelXDimension.value());
125*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fPixelYDimension.has_value());
126*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 100 == exif.fPixelYDimension.value());
127*c8dee2aaSAndroid Build Coastguard Worker }
128*c8dee2aaSAndroid Build Coastguard Worker
129*c8dee2aaSAndroid Build Coastguard Worker {
130*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data = GetResourceAsData("images/test2-nonuniform.exif");
131*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, nullptr != data);
132*c8dee2aaSAndroid Build Coastguard Worker SkExif::Metadata exif;
133*c8dee2aaSAndroid Build Coastguard Worker SkExif::Parse(exif, data.get());
134*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, !exif.fHdrHeadroom.has_value());
135*c8dee2aaSAndroid Build Coastguard Worker
136*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fResolutionUnit.value());
137*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 2 == exif.fResolutionUnit.value());
138*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fXResolution.has_value());
139*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 144.f == exif.fXResolution.value());
140*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fYResolution.has_value());
141*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 36.f == exif.fYResolution.value());
142*c8dee2aaSAndroid Build Coastguard Worker
143*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fPixelXDimension.has_value());
144*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 50 == exif.fPixelXDimension.value());
145*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fPixelYDimension.has_value());
146*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 100 == exif.fPixelYDimension.value());
147*c8dee2aaSAndroid Build Coastguard Worker }
148*c8dee2aaSAndroid Build Coastguard Worker
149*c8dee2aaSAndroid Build Coastguard Worker {
150*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data = GetResourceAsData("images/test3-little-endian.exif");
151*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, nullptr != data);
152*c8dee2aaSAndroid Build Coastguard Worker SkExif::Metadata exif;
153*c8dee2aaSAndroid Build Coastguard Worker SkExif::Parse(exif, data.get());
154*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, !exif.fHdrHeadroom.has_value());
155*c8dee2aaSAndroid Build Coastguard Worker
156*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fResolutionUnit.value());
157*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 2 == exif.fResolutionUnit.value());
158*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fXResolution.has_value());
159*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 350.f == exif.fXResolution.value());
160*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fYResolution.has_value());
161*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 350.f == exif.fYResolution.value());
162*c8dee2aaSAndroid Build Coastguard Worker
163*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, !exif.fPixelXDimension.has_value());
164*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, !exif.fPixelYDimension.has_value());
165*c8dee2aaSAndroid Build Coastguard Worker }
166*c8dee2aaSAndroid Build Coastguard Worker
167*c8dee2aaSAndroid Build Coastguard Worker {
168*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data = GetResourceAsData("images/test0-hdr.exif");
169*c8dee2aaSAndroid Build Coastguard Worker
170*c8dee2aaSAndroid Build Coastguard Worker // Zero out the denominators of signed and unsigned rationals, to verify that we do not
171*c8dee2aaSAndroid Build Coastguard Worker // divide by zero.
172*c8dee2aaSAndroid Build Coastguard Worker data = SkData::MakeWithCopy(data->bytes(), data->size());
173*c8dee2aaSAndroid Build Coastguard Worker memset(static_cast<uint8_t*>(data->writable_data()) + 186, 0, 4);
174*c8dee2aaSAndroid Build Coastguard Worker memset(static_cast<uint8_t*>(data->writable_data()) + 2171, 0, 4);
175*c8dee2aaSAndroid Build Coastguard Worker memset(static_cast<uint8_t*>(data->writable_data()) + 2240, 0, 4);
176*c8dee2aaSAndroid Build Coastguard Worker
177*c8dee2aaSAndroid Build Coastguard Worker // Parse the corrupted Exif.
178*c8dee2aaSAndroid Build Coastguard Worker SkExif::Metadata exif;
179*c8dee2aaSAndroid Build Coastguard Worker SkExif::Parse(exif, data.get());
180*c8dee2aaSAndroid Build Coastguard Worker
181*c8dee2aaSAndroid Build Coastguard Worker // HDR headroom signed denominators are destroyed.
182*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fHdrHeadroom.has_value());
183*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, approx_eq(exif.fHdrHeadroom.value(), 3.482202f, kEpsilon));
184*c8dee2aaSAndroid Build Coastguard Worker
185*c8dee2aaSAndroid Build Coastguard Worker // The X resolution should be zero.
186*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fXResolution.has_value());
187*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 0.f == exif.fXResolution.value());
188*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fYResolution.has_value());
189*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, 72.f == exif.fYResolution.value());
190*c8dee2aaSAndroid Build Coastguard Worker }
191*c8dee2aaSAndroid Build Coastguard Worker }
192*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(ExifTruncate,r)193*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(ExifTruncate, r) {
194*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data = GetResourceAsData("images/test0-hdr.exif");
195*c8dee2aaSAndroid Build Coastguard Worker
196*c8dee2aaSAndroid Build Coastguard Worker // At 545 bytes, we do not have either value yet.
197*c8dee2aaSAndroid Build Coastguard Worker {
198*c8dee2aaSAndroid Build Coastguard Worker SkExif::Metadata exif;
199*c8dee2aaSAndroid Build Coastguard Worker SkExif::Parse(exif, SkData::MakeWithCopy(data->bytes(), 545).get());
200*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, !exif.fPixelXDimension.has_value());
201*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, !exif.fPixelYDimension.has_value());
202*c8dee2aaSAndroid Build Coastguard Worker }
203*c8dee2aaSAndroid Build Coastguard Worker
204*c8dee2aaSAndroid Build Coastguard Worker // At 546 bytes, we have one.
205*c8dee2aaSAndroid Build Coastguard Worker {
206*c8dee2aaSAndroid Build Coastguard Worker SkExif::Metadata exif;
207*c8dee2aaSAndroid Build Coastguard Worker SkExif::Parse(exif, SkData::MakeWithCopy(data->bytes(), 546).get());
208*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fPixelXDimension.has_value());
209*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, !exif.fPixelYDimension.has_value());
210*c8dee2aaSAndroid Build Coastguard Worker }
211*c8dee2aaSAndroid Build Coastguard Worker
212*c8dee2aaSAndroid Build Coastguard Worker // At 558 bytes (12 bytes later, one tag), we have both.
213*c8dee2aaSAndroid Build Coastguard Worker {
214*c8dee2aaSAndroid Build Coastguard Worker SkExif::Metadata exif;
215*c8dee2aaSAndroid Build Coastguard Worker SkExif::Parse(exif, SkData::MakeWithCopy(data->bytes(), 558).get());
216*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fPixelXDimension.has_value());
217*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, exif.fPixelYDimension.has_value());
218*c8dee2aaSAndroid Build Coastguard Worker }
219*c8dee2aaSAndroid Build Coastguard Worker }
220*c8dee2aaSAndroid Build Coastguard Worker
metadata_are_equal(const SkExif::Metadata & m1,const SkExif::Metadata & m2)221*c8dee2aaSAndroid Build Coastguard Worker bool metadata_are_equal(const SkExif::Metadata& m1, const SkExif::Metadata& m2) {
222*c8dee2aaSAndroid Build Coastguard Worker return m1.fOrigin == m2.fOrigin &&
223*c8dee2aaSAndroid Build Coastguard Worker m1.fHdrHeadroom == m2.fHdrHeadroom &&
224*c8dee2aaSAndroid Build Coastguard Worker m1.fResolutionUnit == m2.fResolutionUnit &&
225*c8dee2aaSAndroid Build Coastguard Worker m1.fXResolution == m2.fXResolution &&
226*c8dee2aaSAndroid Build Coastguard Worker m1.fYResolution == m2.fYResolution &&
227*c8dee2aaSAndroid Build Coastguard Worker m1.fPixelXDimension == m2.fPixelXDimension &&
228*c8dee2aaSAndroid Build Coastguard Worker m1.fPixelYDimension == m2.fPixelYDimension;
229*c8dee2aaSAndroid Build Coastguard Worker }
230*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(ExifWriteOrientation,r)231*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(ExifWriteOrientation, r) {
232*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bm;
233*c8dee2aaSAndroid Build Coastguard Worker bm.allocPixels(SkImageInfo::MakeN32Premul(100, 100));
234*c8dee2aaSAndroid Build Coastguard Worker bm.eraseColor(SK_ColorBLUE);
235*c8dee2aaSAndroid Build Coastguard Worker SkPixmap pm;
236*c8dee2aaSAndroid Build Coastguard Worker if (!bm.peekPixels(&pm)) {
237*c8dee2aaSAndroid Build Coastguard Worker ERRORF(r, "failed to peek pixels");
238*c8dee2aaSAndroid Build Coastguard Worker return;
239*c8dee2aaSAndroid Build Coastguard Worker }
240*c8dee2aaSAndroid Build Coastguard Worker for (auto o : { kTopLeft_SkEncodedOrigin,
241*c8dee2aaSAndroid Build Coastguard Worker kTopRight_SkEncodedOrigin,
242*c8dee2aaSAndroid Build Coastguard Worker kBottomRight_SkEncodedOrigin,
243*c8dee2aaSAndroid Build Coastguard Worker kBottomLeft_SkEncodedOrigin,
244*c8dee2aaSAndroid Build Coastguard Worker kLeftTop_SkEncodedOrigin,
245*c8dee2aaSAndroid Build Coastguard Worker kRightTop_SkEncodedOrigin,
246*c8dee2aaSAndroid Build Coastguard Worker kRightBottom_SkEncodedOrigin,
247*c8dee2aaSAndroid Build Coastguard Worker kLeftBottom_SkEncodedOrigin }) {
248*c8dee2aaSAndroid Build Coastguard Worker SkDynamicMemoryWStream stream;
249*c8dee2aaSAndroid Build Coastguard Worker SkJpegEncoder::Options options;
250*c8dee2aaSAndroid Build Coastguard Worker options.fOrigin = o;
251*c8dee2aaSAndroid Build Coastguard Worker if (!SkJpegEncoder::Encode(&stream, pm, options)) {
252*c8dee2aaSAndroid Build Coastguard Worker ERRORF(r, "Failed to encode with orientation %i", o);
253*c8dee2aaSAndroid Build Coastguard Worker return;
254*c8dee2aaSAndroid Build Coastguard Worker }
255*c8dee2aaSAndroid Build Coastguard Worker
256*c8dee2aaSAndroid Build Coastguard Worker auto data = stream.detachAsData();
257*c8dee2aaSAndroid Build Coastguard Worker auto codec = SkCodec::MakeFromData(std::move(data));
258*c8dee2aaSAndroid Build Coastguard Worker if (!codec) {
259*c8dee2aaSAndroid Build Coastguard Worker ERRORF(r, "Failed to create a codec with orientation %i", o);
260*c8dee2aaSAndroid Build Coastguard Worker return;
261*c8dee2aaSAndroid Build Coastguard Worker }
262*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, codec->getOrigin() == o);
263*c8dee2aaSAndroid Build Coastguard Worker }
264*c8dee2aaSAndroid Build Coastguard Worker }
265*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(ExifWriteTest,r)266*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(ExifWriteTest, r) {
267*c8dee2aaSAndroid Build Coastguard Worker {
268*c8dee2aaSAndroid Build Coastguard Worker // Parse exif data
269*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data = GetResourceAsData("images/test2-nonuniform.exif");
270*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, nullptr != data);
271*c8dee2aaSAndroid Build Coastguard Worker SkExif::Metadata exif;
272*c8dee2aaSAndroid Build Coastguard Worker SkExif::Parse(exif, data.get());
273*c8dee2aaSAndroid Build Coastguard Worker
274*c8dee2aaSAndroid Build Coastguard Worker // Write parsed data back to exif
275*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> writeData = SkExif::WriteExif(exif);
276*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, nullptr != writeData);
277*c8dee2aaSAndroid Build Coastguard Worker
278*c8dee2aaSAndroid Build Coastguard Worker // Parse the new exif data that was written
279*c8dee2aaSAndroid Build Coastguard Worker SkExif::Metadata writeExif;
280*c8dee2aaSAndroid Build Coastguard Worker SkExif::Parse(writeExif, writeData.get());
281*c8dee2aaSAndroid Build Coastguard Worker
282*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, metadata_are_equal(writeExif, exif));
283*c8dee2aaSAndroid Build Coastguard Worker }
284*c8dee2aaSAndroid Build Coastguard Worker }
285*c8dee2aaSAndroid Build Coastguard Worker
286*c8dee2aaSAndroid Build Coastguard Worker // We are not able to write HDRheadroom data from a Metadata instance so WriteExif
287*c8dee2aaSAndroid Build Coastguard Worker // should fail and return nullptr when fHdrHeadroom is present.
DEF_TEST(ExifWriteFailsHDRheadroom,r)288*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(ExifWriteFailsHDRheadroom, r) {
289*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data = GetResourceAsData("images/test0-hdr.exif");
290*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, nullptr != data);
291*c8dee2aaSAndroid Build Coastguard Worker SkExif::Metadata exif;
292*c8dee2aaSAndroid Build Coastguard Worker SkExif::Parse(exif, data.get());
293*c8dee2aaSAndroid Build Coastguard Worker
294*c8dee2aaSAndroid Build Coastguard Worker // Write parsed data back to exif
295*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> writeData = SkExif::WriteExif(exif);
296*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, nullptr == writeData);
297*c8dee2aaSAndroid Build Coastguard Worker }
298*c8dee2aaSAndroid Build Coastguard Worker
299