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
|