File: image_util_ios.mm

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (135 lines) | stat: -rw-r--r-- 4,628 bytes parent folder | download | duplicates (6)
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
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/gfx/image/image_util.h"

#import <UIKit/UIKit.h>

#include <optional>

#include "base/apple/foundation_util.h"
#include "base/containers/to_vector.h"
#include "build/blink_buildflags.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/resize_image_dimensions.h"

#if BUILDFLAG(USE_BLINK)
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/jpeg_codec.h"
#endif  // BUILDFLAG(USE_BLINK)

namespace {
// Copied from GTMUIImage+Resize in //third_party/google_toolbox_for_mac to
// avoid depending on other GTM* classes unnecessarily.
UIImage* ResizeUIImage(UIImage* image,
                       CGSize target_size,
                       BOOL preserve_aspect_ratio,
                       BOOL trim_to_fit) {
  CGSize imageSize = image.size;
  if (imageSize.height < 1 || imageSize.width < 1) {
    return nil;
  }
  if (target_size.height < 1 || target_size.width < 1) {
    return nil;
  }
  CGFloat aspectRatio = imageSize.width / imageSize.height;
  CGFloat targetAspectRatio = target_size.width / target_size.height;
  CGRect projectTo = CGRectZero;
  if (preserve_aspect_ratio) {
    if (trim_to_fit) {
      // Scale and clip image so that the aspect ratio is preserved and the
      // target size is filled.
      if (targetAspectRatio < aspectRatio) {
        // clip the x-axis.
        projectTo.size.width = target_size.height * aspectRatio;
        projectTo.size.height = target_size.height;
        projectTo.origin.x = (target_size.width - projectTo.size.width) / 2;
        projectTo.origin.y = 0;
      } else {
        // clip the y-axis.
        projectTo.size.width = target_size.width;
        projectTo.size.height = target_size.width / aspectRatio;
        projectTo.origin.x = 0;
        projectTo.origin.y = (target_size.height - projectTo.size.height) / 2;
      }
    } else {
      // Scale image to ensure it fits inside the specified target_size.
      if (targetAspectRatio < aspectRatio) {
        // target is less wide than the original.
        projectTo.size.width = target_size.width;
        projectTo.size.height = projectTo.size.width / aspectRatio;
        target_size = projectTo.size;
      } else {
        // target is wider than the original.
        projectTo.size.height = target_size.height;
        projectTo.size.width = projectTo.size.height * aspectRatio;
        target_size = projectTo.size;
      }
    }  // if (clip)
  } else {
    // Don't preserve the aspect ratio.
    projectTo.size = target_size;
  }

  projectTo = CGRectIntegral(projectTo);
  // There's no CGSizeIntegral, so we fake our own.
  CGRect integralRect = CGRectZero;
  integralRect.size = target_size;
  target_size = CGRectIntegral(integralRect).size;

  // Resize photo. Use UIImage drawing methods because they respect
  // UIImageOrientation as opposed to CGContextDrawImage().
  UIGraphicsBeginImageContext(target_size);
  [image drawInRect:projectTo];
  UIImage* resizedPhoto = UIGraphicsGetImageFromCurrentImageContext();
  UIGraphicsEndImageContext();
  return resizedPhoto;
}
}  // namespace

namespace gfx {

std::optional<std::vector<uint8_t>> JPEG1xEncodedDataFromImage(
    const Image& image,
    int quality) {
  NSData* data = UIImageJPEGRepresentation(image.ToUIImage(), quality / 100.0);

  if (data.length == 0) {
    return std::nullopt;
  }

  return base::ToVector(base::apple::NSDataToSpan(data));
}

Image ResizedImageForSearchByImage(const Image& image) {
  if (image.IsEmpty()) {
    return image;
  }
  UIImage* ui_image = image.ToUIImage();

  if (ui_image &&
      ui_image.size.height * ui_image.size.width > kSearchByImageMaxImageArea &&
      (ui_image.size.width > kSearchByImageMaxImageWidth ||
       ui_image.size.height > kSearchByImageMaxImageHeight)) {
    CGSize new_image_size =
        CGSizeMake(kSearchByImageMaxImageWidth, kSearchByImageMaxImageHeight);
    ui_image = ResizeUIImage(ui_image, new_image_size,
                             /*preserve_aspect_ratio=*/YES, /*trim_to_fit=*/NO);
  }
  return Image(ui_image);
}

#if BUILDFLAG(USE_BLINK)
Image ImageFrom1xJPEGEncodedData(base::span<const uint8_t> input) {
  return Image::CreateFrom1xBitmap(gfx::JPEGCodec::Decode(input));
}
#endif  // BUILDFLAG(USE_BLINK)

Image ResizedImage(const Image& image, const gfx::Size& size) {
  UIImage* ui_image =
      ResizeUIImage(image.ToUIImage(), size.ToCGSize(),
       /*preserve_aspect_ratio=*/NO, /*trim_to_fit=*/NO);
  return Image(ui_image);
}
}  // end namespace gfx