1 /*
2 * Copyright 2024 Google LLC.
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/SkBitmap.h"
10 #include "include/core/SkColor.h"
11 #include "include/core/SkData.h"
12 #include "include/core/SkImage.h"
13 #include "include/core/SkImageGenerator.h"
14 #include "include/core/SkImageInfo.h"
15 #include "include/core/SkM44.h"
16 #include "include/core/SkRefCnt.h"
17 #include "include/core/SkStream.h"
18 #include "src/base/SkAutoMalloc.h"
19 #include "src/codec/SkCodecImageGenerator.h"
20 #include "src/codec/SkPixmapUtilsPriv.h"
21 #include "src/image/SkImageGeneratorPriv.h"
22 #include "tests/Test.h"
23 #include "tools/Resources.h"
24
25 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
26 #include "include/ports/SkImageGeneratorCG.h"
27 #elif defined(SK_BUILD_FOR_WIN)
28 #include "include/ports/SkImageGeneratorWIC.h"
29 #include "src/utils/win/SkAutoCoInitialize.h"
30 #elif defined(SK_ENABLE_NDK_IMAGES)
31 #include "include/ports/SkImageGeneratorNDK.h"
32 #endif
33
nearly_equal(SkColor4f a,SkColor4f b)34 static bool nearly_equal(SkColor4f a, SkColor4f b) {
35 float d = SkV3{a.fR - b.fR, a.fG - b.fG, a.fB - b.fB}.length();
36 static constexpr float kTol = 0.02f;
37 return d <= kTol;
38 }
39
DEF_TEST(ImageGeneratorOrientationTest,reporter)40 DEF_TEST(ImageGeneratorOrientationTest, reporter) {
41 #if defined(SK_BUILD_FOR_WIN)
42 SkAutoCoInitialize com;
43 REPORTER_ASSERT(reporter, com.succeeded());
44 #endif
45
46 for (char i = '1'; i <= '8'; i++) {
47 SkString path = SkStringPrintf("images/orientation/%c_444.jpg", i);
48 // Get the image as data
49 sk_sp<SkData> data(GetResourceAsData(path.c_str()));
50
51 std::unique_ptr<SkImageGenerator> gen;
52 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
53 gen = SkImageGeneratorCG::MakeFromEncodedCG(data);
54 #elif defined(SK_BUILD_FOR_WIN)
55 gen = SkImageGeneratorWIC::MakeFromEncodedWIC(data);
56 #elif defined(SK_ENABLE_NDK_IMAGES)
57 gen = SkImageGeneratorNDK::MakeFromEncodedNDK(data);
58 #else
59 gen = SkCodecImageGenerator::MakeFromEncodedCodec(data);
60 #endif
61
62 REPORTER_ASSERT(reporter, gen);
63
64 bool success;
65 // Get bitmap from image generator.
66 SkImageInfo genInfo = gen->getInfo();
67 SkBitmap genBitmap;
68 success = genBitmap.tryAllocPixels(genInfo);
69 SkPixmap genPM = genBitmap.pixmap();
70 REPORTER_ASSERT(reporter, genPM.addr());
71 success = gen->getPixels(genPM);
72 REPORTER_ASSERT(reporter, success);
73
74 // Get bitmap from codec. SkCodec::getPixels does not automatically apply
75 // the origin so we rotate it manually.
76 SkBitmap codecBitmap;
77 std::unique_ptr<SkStream> stream(GetResourceAsStream(path.c_str()));
78 std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(std::move(stream)));
79 REPORTER_ASSERT(reporter, codec);
80
81 SkImageInfo codecInfo = codec->getInfo();
82 SkEncodedOrigin origin = codec->getOrigin();
83
84 success = codecBitmap.tryAllocPixels(codecInfo);
85 REPORTER_ASSERT(reporter, success);
86 SkCodec::Result result = codec->getPixels(codecInfo, codecBitmap.getPixels(),
87 codecBitmap.rowBytes());
88 REPORTER_ASSERT(reporter, result == SkCodec::kSuccess);
89
90
91 SkBitmap tmpBitmap;
92 if (SkEncodedOriginSwapsWidthHeight(origin)) {
93 codecInfo = SkPixmapUtils::SwapWidthHeight(codecInfo);
94 }
95 success = tmpBitmap.tryAllocPixels(codecInfo);
96 REPORTER_ASSERT(reporter, success);
97
98 success = SkPixmapUtils::Orient(tmpBitmap.pixmap(), codecBitmap.pixmap(), origin);
99 REPORTER_ASSERT(reporter, success);
100
101 codecBitmap.swap(tmpBitmap);
102
103 // Compare the decoded SkCodec and the bits from the SkImageGenerator.
104 // They should be the same because both should respect orientation.
105 if (codecBitmap.dimensions() != genInfo.dimensions()) {
106 ERRORF(reporter, "Bitmaps do not have the same dimentions.\n"
107 "\tgenBitmap: (%i, %i)\tcodecBitmap: (%i, %i)",
108 codecBitmap.dimensions().fWidth, codecBitmap.dimensions().fHeight,
109 genBitmap.dimensions().fWidth, genBitmap.dimensions().fHeight);
110 }
111 for (int k = 0; k < codecBitmap.width(); ++k) {
112 for (int j = 0; j < codecBitmap.height(); ++j) {
113 SkColor4f c1 = genBitmap.getColor4f(k, j);
114 SkColor4f c2 = codecBitmap.getColor4f(k, j);
115 if (!nearly_equal(c1, c2)) {
116 ERRORF(reporter, "Bitmaps for %s do not match starting at position %i, %i\n"
117 "\tgenBitmap: %x\tcodecBitmap: %x", path.c_str(), i, j,
118 c1.toSkColor(), c2.toSkColor());
119 return;
120 }
121 }
122 }
123 }
124 }
125