| /* | |
| * Copyright 2024 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "include/codec/SkCodec.h" | |
| #include "include/core/SkBitmap.h" | |
| #include "include/core/SkColor.h" | |
| #include "include/core/SkData.h" | |
| #include "include/core/SkImage.h" | |
| #include "include/core/SkImageGenerator.h" | |
| #include "include/core/SkImageInfo.h" | |
| #include "include/core/SkM44.h" | |
| #include "include/core/SkRefCnt.h" | |
| #include "include/core/SkStream.h" | |
| #include "src/codec/SkCodecImageGenerator.h" | |
| #include "src/codec/SkPixmapUtilsPriv.h" | |
| #include "src/core/SkAutoMalloc.h" | |
| #include "src/image/SkImageGeneratorPriv.h" | |
| #include "tests/Test.h" | |
| #include "tools/Resources.h" | |
| #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) | |
| #include "include/ports/SkImageGeneratorCG.h" | |
| #elif defined(SK_BUILD_FOR_WIN) | |
| #include "include/ports/SkImageGeneratorWIC.h" | |
| #include "src/utils/win/SkAutoCoInitialize.h" | |
| #elif defined(SK_ENABLE_NDK_IMAGES) | |
| #include "include/ports/SkImageGeneratorNDK.h" | |
| #endif | |
| static bool nearly_equal(SkColor4f a, SkColor4f b) { | |
| float d = SkV3{a.fR - b.fR, a.fG - b.fG, a.fB - b.fB}.length(); | |
| static constexpr float kTol = 0.02f; | |
| return d <= kTol; | |
| } | |
| DEF_TEST(ImageGeneratorOrientationTest, reporter) { | |
| #if defined(SK_BUILD_FOR_WIN) | |
| SkAutoCoInitialize com; | |
| REPORTER_ASSERT(reporter, com.succeeded()); | |
| #endif | |
| for (char i = '1'; i <= '8'; i++) { | |
| SkString path = SkStringPrintf("images/orientation/%c_444.jpg", i); | |
| // Get the image as data | |
| sk_sp<SkData> data(GetResourceAsData(path.c_str())); | |
| std::unique_ptr<SkImageGenerator> gen; | |
| #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) | |
| gen = SkImageGeneratorCG::MakeFromEncodedCG(data); | |
| #elif defined(SK_BUILD_FOR_WIN) | |
| gen = SkImageGeneratorWIC::MakeFromEncodedWIC(data); | |
| #elif defined(SK_ENABLE_NDK_IMAGES) | |
| gen = SkImageGeneratorNDK::MakeFromEncodedNDK(data); | |
| #else | |
| gen = SkCodecImageGenerator::MakeFromEncodedCodec(data); | |
| #endif | |
| REPORTER_ASSERT(reporter, gen); | |
| bool success; | |
| // Get bitmap from image generator. | |
| SkImageInfo genInfo = gen->getInfo(); | |
| SkBitmap genBitmap; | |
| success = genBitmap.tryAllocPixels(genInfo); | |
| SkPixmap genPM = genBitmap.pixmap(); | |
| REPORTER_ASSERT(reporter, genPM.addr()); | |
| success = gen->getPixels(genPM); | |
| REPORTER_ASSERT(reporter, success); | |
| // Get bitmap from codec. SkCodec::getPixels does not automatically apply | |
| // the origin so we rotate it manually. | |
| SkBitmap codecBitmap; | |
| std::unique_ptr<SkStream> stream(GetResourceAsStream(path.c_str())); | |
| std::unique_ptr<SkCodec> codec(SkCodec::MakeFromStream(std::move(stream))); | |
| REPORTER_ASSERT(reporter, codec); | |
| SkImageInfo codecInfo = codec->getInfo(); | |
| SkEncodedOrigin origin = codec->getOrigin(); | |
| success = codecBitmap.tryAllocPixels(codecInfo); | |
| REPORTER_ASSERT(reporter, success); | |
| SkCodec::Result result = codec->getPixels(codecInfo, codecBitmap.getPixels(), | |
| codecBitmap.rowBytes()); | |
| REPORTER_ASSERT(reporter, result == SkCodec::kSuccess); | |
| SkBitmap tmpBitmap; | |
| if (SkEncodedOriginSwapsWidthHeight(origin)) { | |
| codecInfo = SkPixmapUtils::SwapWidthHeight(codecInfo); | |
| } | |
| success = tmpBitmap.tryAllocPixels(codecInfo); | |
| REPORTER_ASSERT(reporter, success); | |
| success = SkPixmapUtils::Orient(tmpBitmap.pixmap(), codecBitmap.pixmap(), origin); | |
| REPORTER_ASSERT(reporter, success); | |
| codecBitmap.swap(tmpBitmap); | |
| // Compare the decoded SkCodec and the bits from the SkImageGenerator. | |
| // They should be the same because both should respect orientation. | |
| if (codecBitmap.dimensions() != genInfo.dimensions()) { | |
| ERRORF(reporter, "Bitmaps do not have the same dimentions.\n" | |
| "\tgenBitmap: (%i, %i)\tcodecBitmap: (%i, %i)", | |
| codecBitmap.dimensions().fWidth, codecBitmap.dimensions().fHeight, | |
| genBitmap.dimensions().fWidth, genBitmap.dimensions().fHeight); | |
| } | |
| for (int k = 0; k < codecBitmap.width(); ++k) { | |
| for (int j = 0; j < codecBitmap.height(); ++j) { | |
| SkColor4f c1 = genBitmap.getColor4f(k, j); | |
| SkColor4f c2 = codecBitmap.getColor4f(k, j); | |
| if (!nearly_equal(c1, c2)) { | |
| ERRORF(reporter, "Bitmaps for %s do not match starting at position %i, %i\n" | |
| "\tgenBitmap: %x\tcodecBitmap: %x", path.c_str(), i, j, | |
| c1.toSkColor(), c2.toSkColor()); | |
| return; | |
| } | |
| } | |
| } | |
| } | |
| } |