| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #import "ios/chrome/common/ui/util/image_util.h" |
| |
| #import "testing/gtest/include/gtest/gtest.h" |
| #import "testing/gtest_mac.h" |
| #import "testing/platform_test.h" |
| |
| using ImageUtilTest = PlatformTest; |
| |
| #define EXPECT_EQ_RECT(a, b) \ |
| EXPECT_NSEQ(NSStringFromCGRect(a), NSStringFromCGRect(b)) |
| #define EXPECT_EQ_SIZE(a, b) \ |
| EXPECT_NSEQ(NSStringFromCGSize(a), NSStringFromCGSize(b)) |
| |
| TEST_F(ImageUtilTest, TestProjectionFill) { |
| CGSize originalSize, targetSize, expectedRevisedSize, revisedSize; |
| CGRect expectedProjection, projection; |
| |
| // Resize with same aspect ratio. |
| originalSize = CGSizeMake(100, 100); |
| targetSize = CGSizeMake(50, 50); |
| expectedRevisedSize = targetSize; |
| expectedProjection = CGRectMake(0, 0, 50, 50); |
| CalculateProjection(originalSize, targetSize, ProjectionMode::kFill, |
| revisedSize, projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Resize with different aspect ratio. |
| originalSize = CGSizeMake(100, 100); |
| targetSize = CGSizeMake(60, 40); |
| expectedRevisedSize = targetSize; |
| expectedProjection = CGRectMake(0, 0, 60, 40); |
| CalculateProjection(originalSize, targetSize, ProjectionMode::kFill, |
| revisedSize, projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Stretch the other way. |
| originalSize = CGSizeMake(100, 100); |
| targetSize = CGSizeMake(40, 60); |
| expectedRevisedSize = targetSize; |
| expectedProjection = CGRectMake(0, 0, 40, 60); |
| CalculateProjection(originalSize, targetSize, ProjectionMode::kFill, |
| revisedSize, projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| } |
| |
| TEST_F(ImageUtilTest, TestProjectionFit) { |
| CGSize originalSize, targetSize, expectedRevisedSize, revisedSize; |
| CGRect expectedProjection, projection; |
| |
| // Landscape resize to 50x50, but squeezed into 50x25. |
| originalSize = CGSizeMake(100, 50); |
| targetSize = CGSizeMake(50, 50); |
| expectedRevisedSize = CGSizeMake(50, 25); |
| expectedProjection = CGRectMake(0, 0, 50, 25); |
| CalculateProjection(originalSize, targetSize, ProjectionMode::kAspectFit, |
| revisedSize, projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Landscape resize to 60x40, but squeezed into 60x30. |
| originalSize = CGSizeMake(100, 50); |
| targetSize = CGSizeMake(60, 40); |
| expectedRevisedSize = CGSizeMake(60, 30); |
| expectedProjection = CGRectMake(0, 0, 60, 30); |
| CalculateProjection(originalSize, targetSize, ProjectionMode::kAspectFit, |
| revisedSize, projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Landscape resize to 40x60, but squeezed into 40x20. |
| originalSize = CGSizeMake(100, 50); |
| targetSize = CGSizeMake(40, 60); |
| expectedRevisedSize = CGSizeMake(40, 20); |
| expectedProjection = CGRectMake(0, 0, 40, 20); |
| CalculateProjection(originalSize, targetSize, ProjectionMode::kAspectFit, |
| revisedSize, projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Portrait resize to 50x50, but squeezed into 25x50. |
| originalSize = CGSizeMake(50, 100); |
| targetSize = CGSizeMake(50, 50); |
| expectedRevisedSize = CGSizeMake(25, 50); |
| expectedProjection = CGRectMake(0, 0, 25, 50); |
| CalculateProjection(originalSize, targetSize, ProjectionMode::kAspectFit, |
| revisedSize, projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Portrait resize to 60x40, but squeezed into 20x40. |
| originalSize = CGSizeMake(50, 100); |
| targetSize = CGSizeMake(60, 40); |
| expectedRevisedSize = CGSizeMake(20, 40); |
| expectedProjection = CGRectMake(0, 0, 20, 40); |
| CalculateProjection(originalSize, targetSize, ProjectionMode::kAspectFit, |
| revisedSize, projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Portrait resize to 40x60, but squeezed into 30x60. |
| originalSize = CGSizeMake(50, 100); |
| targetSize = CGSizeMake(40, 60); |
| expectedRevisedSize = CGSizeMake(30, 60); |
| expectedProjection = CGRectMake(0, 0, 30, 60); |
| CalculateProjection(originalSize, targetSize, ProjectionMode::kAspectFit, |
| revisedSize, projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| } |
| |
| TEST_F(ImageUtilTest, TestProjectionAspectFill) { |
| CGSize originalSize, targetSize, expectedRevisedSize, revisedSize; |
| CGRect expectedProjection, projection; |
| |
| // Landscape resize to 50x50 |
| originalSize = CGSizeMake(100, 50); |
| targetSize = CGSizeMake(50, 50); |
| expectedRevisedSize = targetSize; |
| expectedProjection = CGRectMake(-25, 0, 100, 50); |
| CalculateProjection(originalSize, targetSize, ProjectionMode::kAspectFill, |
| revisedSize, projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Landscape resize to 60x40, but squeezed into 60x30. |
| originalSize = CGSizeMake(100, 50); |
| targetSize = CGSizeMake(60, 40); |
| expectedRevisedSize = targetSize; |
| expectedProjection = CGRectMake(-10, 0, 80, 40); |
| CalculateProjection(originalSize, targetSize, ProjectionMode::kAspectFill, |
| revisedSize, projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Landscape resize to 40x60, but squeezed into 40x20. |
| originalSize = CGSizeMake(100, 50); |
| targetSize = CGSizeMake(40, 60); |
| expectedRevisedSize = targetSize; |
| expectedProjection = CGRectMake(-40, 0, 120, 60); |
| CalculateProjection(originalSize, targetSize, ProjectionMode::kAspectFill, |
| revisedSize, projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Portrait resize to 50x50, but squeezed into 25x50. |
| originalSize = CGSizeMake(50, 100); |
| targetSize = CGSizeMake(50, 50); |
| expectedRevisedSize = targetSize; |
| expectedProjection = CGRectMake(0, -25, 50, 100); |
| CalculateProjection(originalSize, targetSize, ProjectionMode::kAspectFill, |
| revisedSize, projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Portrait resize to 60x40, but clipped to 20x40. |
| originalSize = CGSizeMake(50, 100); |
| targetSize = CGSizeMake(60, 40); |
| expectedRevisedSize = targetSize; |
| expectedProjection = CGRectMake(0, -40, 60, 120); |
| CalculateProjection(originalSize, targetSize, ProjectionMode::kAspectFill, |
| revisedSize, projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Portrait resize to 40x60, but clipped to 30x60. |
| originalSize = CGSizeMake(50, 100); |
| targetSize = CGSizeMake(40, 60); |
| expectedRevisedSize = targetSize; |
| expectedProjection = CGRectMake(0, -10, 40, 80); |
| CalculateProjection(originalSize, targetSize, ProjectionMode::kAspectFill, |
| revisedSize, projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| } |
| |
| TEST_F(ImageUtilTest, TestProjectionAspectFillAlignTop) { |
| CGSize originalSize, targetSize, expectedRevisedSize, revisedSize; |
| CGRect expectedProjection, projection; |
| |
| // Landscape resize to 100x100 |
| originalSize = CGSizeMake(400, 200); |
| targetSize = CGSizeMake(100, 100); |
| expectedRevisedSize = targetSize; |
| expectedProjection = CGRectMake(-50, 0, 200, 100); |
| CalculateProjection(originalSize, targetSize, |
| ProjectionMode::kAspectFillAlignTop, revisedSize, |
| projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Portrait resize to 100x100 and aligned to top |
| originalSize = CGSizeMake(200, 400); |
| targetSize = CGSizeMake(100, 100); |
| expectedRevisedSize = targetSize; |
| expectedProjection = CGRectMake(0, 0, 100, 200); |
| CalculateProjection(originalSize, targetSize, |
| ProjectionMode::kAspectFillAlignTop, revisedSize, |
| projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| } |
| |
| TEST_F(ImageUtilTest, TestProjectionAspectFillNoClipping) { |
| CGSize originalSize, targetSize, expectedRevisedSize, revisedSize; |
| CGRect expectedProjection, projection; |
| |
| // Landscape resize to 50x50 |
| originalSize = CGSizeMake(100, 50); |
| targetSize = CGSizeMake(50, 50); |
| expectedProjection = CGRectMake(0, 0, 100, 50); |
| expectedRevisedSize = expectedProjection.size; |
| CalculateProjection(originalSize, targetSize, |
| ProjectionMode::kAspectFillNoClipping, revisedSize, |
| projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Landscape resize to 60x40. |
| originalSize = CGSizeMake(100, 50); |
| targetSize = CGSizeMake(60, 40); |
| expectedProjection = CGRectMake(0, 0, 80, 40); |
| expectedRevisedSize = expectedProjection.size; |
| CalculateProjection(originalSize, targetSize, |
| ProjectionMode::kAspectFillNoClipping, revisedSize, |
| projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Landscape resize to 40x60. |
| originalSize = CGSizeMake(100, 50); |
| targetSize = CGSizeMake(40, 60); |
| expectedProjection = CGRectMake(0, 0, 120, 60); |
| expectedRevisedSize = expectedProjection.size; |
| CalculateProjection(originalSize, targetSize, |
| ProjectionMode::kAspectFillNoClipping, revisedSize, |
| projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Portrait resize to 50x50. |
| originalSize = CGSizeMake(50, 100); |
| targetSize = CGSizeMake(50, 50); |
| expectedProjection = CGRectMake(0, 0, 50, 100); |
| expectedRevisedSize = expectedProjection.size; |
| CalculateProjection(originalSize, targetSize, |
| ProjectionMode::kAspectFillNoClipping, revisedSize, |
| projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Portrait resize to 60x40. |
| originalSize = CGSizeMake(50, 100); |
| targetSize = CGSizeMake(60, 40); |
| expectedProjection = CGRectMake(0, 0, 60, 120); |
| expectedRevisedSize = expectedProjection.size; |
| CalculateProjection(originalSize, targetSize, |
| ProjectionMode::kAspectFillNoClipping, revisedSize, |
| projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| |
| // Portrait resize to 40x60. |
| originalSize = CGSizeMake(50, 100); |
| targetSize = CGSizeMake(40, 60); |
| expectedProjection = CGRectMake(0, 0, 40, 80); |
| expectedRevisedSize = expectedProjection.size; |
| CalculateProjection(originalSize, targetSize, |
| ProjectionMode::kAspectFillNoClipping, revisedSize, |
| projection); |
| EXPECT_EQ_RECT(expectedProjection, projection); |
| EXPECT_EQ_SIZE(expectedRevisedSize, revisedSize); |
| } |
| |
| // Returns an image of random color in the same scale as the device main |
| // screen. |
| UIImage* testImage(CGSize imageSize) { |
| UIGraphicsImageRendererFormat* format = |
| [UIGraphicsImageRendererFormat preferredFormat]; |
| format.opaque = NO; |
| |
| UIGraphicsImageRenderer* renderer = |
| [[UIGraphicsImageRenderer alloc] initWithSize:imageSize format:format]; |
| |
| return |
| [renderer imageWithActions:^(UIGraphicsImageRendererContext* UIContext) { |
| CGContextRef context = UIContext.CGContext; |
| CGContextSetRGBStrokeColor(context, 0, 0, 0, 1.0); |
| CGContextSetRGBFillColor(context, 0, 0, 0, 1.0); |
| CGContextFillRect( |
| context, CGRectMake(0.0, 0.0, imageSize.width, imageSize.height)); |
| }]; |
| } |
| |
| TEST_F(ImageUtilTest, TestResizeImageOpacity) { |
| UIImage* actual; |
| UIImage* image = testImage(CGSizeMake(100, 100)); |
| actual = |
| ResizeImage(image, CGSizeMake(50, 50), ProjectionMode::kAspectFit, YES); |
| EXPECT_TRUE(actual); |
| |
| actual = |
| ResizeImage(image, CGSizeMake(50, 50), ProjectionMode::kAspectFit, NO); |
| EXPECT_TRUE(actual); |
| } |
| |
| TEST_F(ImageUtilTest, TestResizeImageInvalidInput) { |
| UIImage* actual; |
| UIImage* image = testImage(CGSizeMake(100, 50)); |
| actual = ResizeImage(image, CGSizeZero, ProjectionMode::kAspectFit); |
| EXPECT_FALSE(actual); |
| |
| actual = ResizeImage(image, CGSizeMake(0.1, 0.1), ProjectionMode::kAspectFit); |
| EXPECT_FALSE(actual); |
| |
| actual = |
| ResizeImage(image, CGSizeMake(-100, -100), ProjectionMode::kAspectFit); |
| EXPECT_FALSE(actual); |
| |
| actual = ResizeImage(nil, CGSizeMake(100, 100), ProjectionMode::kAspectFit); |
| EXPECT_FALSE(actual); |
| } |