xref: /aosp_15_r20/external/skia/tests/ImageGeneratorOrientationTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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