File: composebox_image_helper_ios_unittest.mm

package info (click to toggle)
chromium 141.0.7390.122-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,246,384 kB
  • sloc: cpp: 35,265,044; ansic: 7,169,920; javascript: 4,250,185; python: 1,460,635; asm: 950,788; xml: 751,771; pascal: 187,972; sh: 89,459; perl: 88,691; objc: 79,953; sql: 53,924; cs: 44,622; fortran: 24,137; makefile: 22,313; tcl: 15,277; php: 14,018; yacc: 8,995; ruby: 7,553; awk: 3,720; lisp: 3,096; lex: 1,330; ada: 727; jsp: 228; sed: 36
file content (122 lines) | stat: -rw-r--r-- 5,209 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "components/omnibox/composebox/ios/composebox_image_helper_ios.h"

#import <UIKit/UIKit.h>

#include "base/memory/ref_counted_memory.h"
#include "components/lens/lens_bitmap_processing.h"
#include "components/lens/ref_counted_lens_overlay_client_logs.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
#include "third_party/lens_server_proto/lens_overlay_image_data.pb.h"
#include "ui/gfx/image/image.h"

namespace composebox {

namespace {

constexpr int kImageCompressionQuality = 30;
constexpr int kImageMaxArea = 1000000;
constexpr int kImageMaxHeight = 1000;
constexpr int kImageMaxWidth = 1000;

}  // namespace

class ComposeboxImageHelperIosTest : public PlatformTest {
 protected:
  // Creates a solid color UIImage of a given size in points.
  UIImage* CreateImage(CGSize point_size, bool opaque) {
    CGRect rect = CGRectMake(0, 0, point_size.width, point_size.height);
    // UIGraphicsBeginImageContextWithOptions with a scale of 0.0 will use the
    // device's main screen scale, which is what we want to simulate reality.
    UIGraphicsBeginImageContextWithOptions(rect.size, opaque, 0.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [[UIColor greenColor] setFill];
    CGContextFillRect(context, rect);
    UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
  }

  lens::ImageData DownscaleAndEncodeUiImage(UIImage* ui_image,
                                            bool enable_webp_encoding = true) {
    lens::ImageEncodingOptions image_options{
        .enable_webp_encoding = enable_webp_encoding,
        .max_size = kImageMaxArea,
        .max_height = kImageMaxHeight,
        .max_width = kImageMaxWidth,
        .compression_quality = kImageCompressionQuality,
    };
    scoped_refptr<lens::RefCountedLensOverlayClientLogs> ref_counted_logs =
        base::MakeRefCounted<lens::RefCountedLensOverlayClientLogs>();
    return composebox::DownscaleAndEncodeImage(ui_image, ref_counted_logs,
                                               image_options);
  }

  // Verifies the encoded image data by decoding it and checking its properties.
  void VerifyEncodedData(const lens::ImageData& image_data,
                         int expected_pixel_width,
                         int expected_pixel_height) {
    // Check that the metadata correctly reports the expected pixel dimensions.
    EXPECT_EQ(expected_pixel_width, image_data.image_metadata().width());
    EXPECT_EQ(expected_pixel_height, image_data.image_metadata().height());

    // Perform a round-trip check to ensure the encoded bytes are valid.
    const std::string& bytes = image_data.payload().image_bytes();
    ASSERT_FALSE(bytes.empty());
    NSData* data = [NSData dataWithBytes:bytes.data() length:bytes.size()];
    UIImage* decoded_image = [UIImage imageWithData:data];
    ASSERT_TRUE(decoded_image);

    // The decoded image should have a scale of 1.0, so its point size should
    // match the pixel size in the metadata.
    EXPECT_EQ(image_data.image_metadata().width(),
              round(decoded_image.size.width));
    EXPECT_EQ(image_data.image_metadata().height(),
              round(decoded_image.size.height));
  }
};

TEST_F(ComposeboxImageHelperIosTest, DownscaleAndEncodeImageSmallSize) {
  UIImage* image = CreateImage(CGSizeMake(100, 100), /*opaque=*/true);
  lens::ImageData image_data = DownscaleAndEncodeUiImage(image);
  VerifyEncodedData(image_data, /*expected_pixel_width=*/100 * image.scale,
                    /*expected_pixel_height=*/100 * image.scale);
}

TEST_F(ComposeboxImageHelperIosTest, DownscaleAndEncodeImageLargeSize) {
  const int scale = 2;
  UIImage* image =
      CreateImage(CGSizeMake(kImageMaxWidth * scale, kImageMaxHeight * scale),
                  /*opaque=*/true);
  lens::ImageData image_data = DownscaleAndEncodeUiImage(image);
  VerifyEncodedData(image_data, kImageMaxWidth, kImageMaxHeight);
}

TEST_F(ComposeboxImageHelperIosTest, DownscaleAndEncodeImageHeightTooLarge) {
  const int scale = 2;
  UIImage* image = CreateImage(
      CGSizeMake(kImageMaxWidth, kImageMaxHeight * scale), /*opaque=*/true);
  lens::ImageData image_data = DownscaleAndEncodeUiImage(image);
  VerifyEncodedData(image_data, kImageMaxWidth / scale, kImageMaxHeight);
}

TEST_F(ComposeboxImageHelperIosTest, DownscaleAndEncodeImageWidthTooLarge) {
  const int scale = 2;
  UIImage* image = CreateImage(
      CGSizeMake(kImageMaxWidth * scale, kImageMaxHeight), /*opaque=*/true);
  lens::ImageData image_data = DownscaleAndEncodeUiImage(image);
  VerifyEncodedData(image_data, kImageMaxWidth, kImageMaxHeight / scale);
}

TEST_F(ComposeboxImageHelperIosTest, DownscaleAndEncodeImageTransparent) {
  UIImage* image = CreateImage(CGSizeMake(100, 100), /*opaque=*/false);
  lens::ImageData image_data = DownscaleAndEncodeUiImage(image);
  VerifyEncodedData(image_data, /*expected_pixel_width=*/100 * image.scale,
                    /*expected_pixel_height=*/100 * image.scale);
}

}  // namespace composebox