TestDownscalingFilter.cpp (9493B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "gtest/gtest.h" 8 9 #include "mozilla/gfx/2D.h" 10 #include "Common.h" 11 #include "Decoder.h" 12 #include "DecoderFactory.h" 13 #include "SourceBuffer.h" 14 #include "SurfaceFilters.h" 15 #include "SurfacePipe.h" 16 17 using namespace mozilla; 18 using namespace mozilla::gfx; 19 using namespace mozilla::image; 20 21 template <typename Func> 22 void WithDownscalingFilter(const IntSize& aInputSize, 23 const IntSize& aOutputSize, Func aFunc) { 24 RefPtr<image::Decoder> decoder = CreateTrivialDecoder(); 25 ASSERT_TRUE(decoder != nullptr); 26 27 WithFilterPipeline( 28 decoder, std::forward<Func>(aFunc), 29 DownscalingConfig{aInputSize, SurfaceFormat::OS_RGBA}, 30 SurfaceConfig{decoder, aOutputSize, SurfaceFormat::OS_RGBA, false}); 31 } 32 33 void AssertConfiguringDownscalingFilterFails(const IntSize& aInputSize, 34 const IntSize& aOutputSize) { 35 RefPtr<image::Decoder> decoder = CreateTrivialDecoder(); 36 ASSERT_TRUE(decoder != nullptr); 37 38 AssertConfiguringPipelineFails( 39 decoder, DownscalingConfig{aInputSize, SurfaceFormat::OS_RGBA}, 40 SurfaceConfig{decoder, aOutputSize, SurfaceFormat::OS_RGBA, false}); 41 } 42 43 TEST(ImageDownscalingFilter, WritePixels100_100to99_99) 44 { 45 WithDownscalingFilter(IntSize(100, 100), IntSize(99, 99), 46 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 47 CheckWritePixels( 48 aDecoder, aFilter, 49 /* aOutputRect = */ Some(IntRect(0, 0, 99, 99))); 50 }); 51 } 52 53 TEST(ImageDownscalingFilter, WritePixels100_100to33_33) 54 { 55 WithDownscalingFilter(IntSize(100, 100), IntSize(33, 33), 56 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 57 CheckWritePixels( 58 aDecoder, aFilter, 59 /* aOutputRect = */ Some(IntRect(0, 0, 33, 33))); 60 }); 61 } 62 63 TEST(ImageDownscalingFilter, WritePixels100_100to1_1) 64 { 65 WithDownscalingFilter(IntSize(100, 100), IntSize(1, 1), 66 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 67 CheckWritePixels( 68 aDecoder, aFilter, 69 /* aOutputRect = */ Some(IntRect(0, 0, 1, 1))); 70 }); 71 } 72 73 TEST(ImageDownscalingFilter, WritePixels100_100to33_99) 74 { 75 WithDownscalingFilter(IntSize(100, 100), IntSize(33, 99), 76 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 77 CheckWritePixels( 78 aDecoder, aFilter, 79 /* aOutputRect = */ Some(IntRect(0, 0, 33, 99))); 80 }); 81 } 82 83 TEST(ImageDownscalingFilter, WritePixels100_100to99_33) 84 { 85 WithDownscalingFilter(IntSize(100, 100), IntSize(99, 33), 86 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 87 CheckWritePixels( 88 aDecoder, aFilter, 89 /* aOutputRect = */ Some(IntRect(0, 0, 99, 33))); 90 }); 91 } 92 93 TEST(ImageDownscalingFilter, WritePixels100_100to99_1) 94 { 95 WithDownscalingFilter(IntSize(100, 100), IntSize(99, 1), 96 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 97 CheckWritePixels( 98 aDecoder, aFilter, 99 /* aOutputRect = */ Some(IntRect(0, 0, 99, 1))); 100 }); 101 } 102 103 TEST(ImageDownscalingFilter, WritePixels100_100to1_99) 104 { 105 WithDownscalingFilter(IntSize(100, 100), IntSize(1, 99), 106 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 107 CheckWritePixels( 108 aDecoder, aFilter, 109 /* aOutputRect = */ Some(IntRect(0, 0, 1, 99))); 110 }); 111 } 112 113 TEST(ImageDownscalingFilter, DownscalingFailsFor100_100to101_101) 114 { 115 // Upscaling is disallowed. 116 AssertConfiguringDownscalingFilterFails(IntSize(100, 100), IntSize(101, 101)); 117 } 118 119 TEST(ImageDownscalingFilter, DownscalingFailsFor100_100to100_100) 120 { 121 // "Scaling" to the same size is disallowed. 122 AssertConfiguringDownscalingFilterFails(IntSize(100, 100), IntSize(100, 100)); 123 } 124 125 TEST(ImageDownscalingFilter, DownscalingFailsFor0_0toMinus1_Minus1) 126 { 127 // A 0x0 input size is disallowed. 128 AssertConfiguringDownscalingFilterFails(IntSize(0, 0), IntSize(-1, -1)); 129 } 130 131 TEST(ImageDownscalingFilter, DownscalingFailsForMinus1_Minus1toMinus2_Minus2) 132 { 133 // A negative input size is disallowed. 134 AssertConfiguringDownscalingFilterFails(IntSize(-1, -1), IntSize(-2, -2)); 135 } 136 137 TEST(ImageDownscalingFilter, DownscalingFailsFor100_100to0_0) 138 { 139 // A 0x0 output size is disallowed. 140 AssertConfiguringDownscalingFilterFails(IntSize(100, 100), IntSize(0, 0)); 141 } 142 143 TEST(ImageDownscalingFilter, DownscalingFailsFor100_100toMinus1_Minus1) 144 { 145 // A negative output size is disallowed. 146 AssertConfiguringDownscalingFilterFails(IntSize(100, 100), IntSize(-1, -1)); 147 } 148 149 TEST(ImageDownscalingFilter, WritePixelsOutput100_100to20_20) 150 { 151 WithDownscalingFilter( 152 IntSize(100, 100), IntSize(20, 20), 153 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 154 // Fill the image. It consists of 25 lines of green, followed by 25 155 // lines of red, followed by 25 lines of green, followed by 25 more 156 // lines of red. 157 uint32_t count = 0; 158 auto result = 159 aFilter->WritePixels<uint32_t>([&]() -> NextPixel<uint32_t> { 160 uint32_t color = 161 (count <= 25 * 100) || (count > 50 * 100 && count <= 75 * 100) 162 ? BGRAColor::Green().AsPixel() 163 : BGRAColor::Red().AsPixel(); 164 ++count; 165 return AsVariant(color); 166 }); 167 EXPECT_EQ(WriteState::FINISHED, result); 168 EXPECT_EQ(100u * 100u, count); 169 170 AssertCorrectPipelineFinalState(aFilter, IntRect(0, 0, 100, 100), 171 IntRect(0, 0, 20, 20)); 172 173 // Check that the generated image is correct. Note that we skip rows 174 // near the transitions between colors, since the downscaler does not 175 // produce a sharp boundary at these points. Even some of the rows we 176 // test need a small amount of fuzz; this is just the nature of Lanczos 177 // downscaling. 178 RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); 179 RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface(); 180 EXPECT_TRUE(RowsAreSolidColor(surface, 0, 4, BGRAColor::Green(), 181 /* aFuzz = */ 2)); 182 EXPECT_TRUE(RowsAreSolidColor(surface, 6, 3, BGRAColor::Red(), 183 /* aFuzz = */ 3)); 184 EXPECT_TRUE(RowsAreSolidColor(surface, 11, 3, BGRAColor::Green(), 185 /* aFuzz = */ 3)); 186 EXPECT_TRUE(RowsAreSolidColor(surface, 16, 4, BGRAColor::Red(), 187 /* aFuzz = */ 3)); 188 }); 189 } 190 191 TEST(ImageDownscalingFilter, WritePixelsOutput100_100to10_20) 192 { 193 WithDownscalingFilter( 194 IntSize(100, 100), IntSize(10, 20), 195 [](image::Decoder* aDecoder, SurfaceFilter* aFilter) { 196 // Fill the image. It consists of 25 lines of green, followed by 25 197 // lines of red, followed by 25 lines of green, followed by 25 more 198 // lines of red. 199 uint32_t count = 0; 200 auto result = 201 aFilter->WritePixels<uint32_t>([&]() -> NextPixel<uint32_t> { 202 uint32_t color = 203 (count <= 25 * 100) || (count > 50 * 100 && count <= 75 * 100) 204 ? BGRAColor::Green().AsPixel() 205 : BGRAColor::Red().AsPixel(); 206 ++count; 207 return AsVariant(color); 208 }); 209 EXPECT_EQ(WriteState::FINISHED, result); 210 EXPECT_EQ(100u * 100u, count); 211 212 AssertCorrectPipelineFinalState(aFilter, IntRect(0, 0, 100, 100), 213 IntRect(0, 0, 10, 20)); 214 215 // Check that the generated image is correct. Note that we skip rows 216 // near the transitions between colors, since the downscaler does not 217 // produce a sharp boundary at these points. Even some of the rows we 218 // test need a small amount of fuzz; this is just the nature of Lanczos 219 // downscaling. 220 RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef(); 221 RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface(); 222 EXPECT_TRUE(RowsAreSolidColor(surface, 0, 4, BGRAColor::Green(), 223 /* aFuzz = */ 2)); 224 EXPECT_TRUE(RowsAreSolidColor(surface, 6, 3, BGRAColor::Red(), 225 /* aFuzz = */ 3)); 226 EXPECT_TRUE(RowsAreSolidColor(surface, 11, 3, BGRAColor::Green(), 227 /* aFuzz = */ 3)); 228 EXPECT_TRUE(RowsAreSolidColor(surface, 16, 4, BGRAColor::Red(), 229 /* aFuzz = */ 3)); 230 }); 231 }