Add view to Crop and scale avatar.

// FREEBIE
This commit is contained in:
Matthew Chen 2017-08-24 17:23:17 -04:00
parent 728028563c
commit 6b8e189f45
4 changed files with 66 additions and 48 deletions

View file

@ -31,6 +31,7 @@
#import "TSMessageAdapter.h"
#import "UIColor+OWS.h"
#import "UIFont+OWS.h"
#import "UIImage+normalizeImage.h"
#import "UIUtil.h"
#import "UIView+OWS.h"
#import "ViewControllerUtils.h"

View file

@ -4,6 +4,7 @@
#import "AvatarViewHelper.h"
#import "OWSContactsManager.h"
#import "OWSNavigationController.h"
#import "Signal-Swift.h"
#import "UIUtil.h"
#import <MobileCoreServices/UTCoreTypes.h>
@ -98,28 +99,6 @@ NS_ASSUME_NONNULL_BEGIN
}
}
- (void)showCropScaleUI
{
OWSAssert([NSThread isMainThread]);
OWSAssert(self.delegate);
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum]) {
picker.mediaTypes = [[NSArray alloc] initWithObjects:(NSString *)kUTTypeImage, nil];
[self.delegate.fromViewController presentViewController:picker
animated:YES
completion:[UIUtil modalCompletionBlock]];
}
}
//// We resize the avatar to fill a 210x210 square.
////
//// See: GroupCreateActivity.java in Signal-Android.java.
// UIImage *resizedAvatar = [rawAvatar resizedImageToFillPixelSize:CGSizeMake(210, 210)];
//[self.delegate avatarDidChange:resizedAvatar];
/*
* Dismissing UIImagePickerController
*/
@ -142,11 +121,25 @@ NS_ASSUME_NONNULL_BEGIN
UIImage *rawAvatar = [info objectForKey:UIImagePickerControllerOriginalImage];
if (rawAvatar) {
// [self showCropScaleUI:rawAvatar];
}
[self.delegate.fromViewController
dismissViewControllerAnimated:YES
completion:^{
if (rawAvatar) {
OWSAssert([NSThread isMainThread]);
[self.delegate.fromViewController dismissViewControllerAnimated:YES completion:nil];
CropScaleImageViewController *vc = [[CropScaleImageViewController alloc]
initWithSrcImage:rawAvatar
successCompletion:^(UIImage *_Nonnull dstImage) {
[self.delegate avatarDidChange:dstImage];
}];
OWSNavigationController *navigationController =
[[OWSNavigationController alloc] initWithRootViewController:vc];
[self.delegate.fromViewController
presentViewController:navigationController
animated:YES
completion:[UIUtil modalCompletionBlock]];
}
}];
}
@end

View file

@ -56,7 +56,14 @@ class CropScaleImageViewController: OWSViewController {
var dashedBorderLayer: CAShapeLayer?
// In width/height.
let dstAspectRatio: CGFloat = 1.0
//
// TODO: We could make this a parameter.
var dstSizePixels: CGSize {
return CGSize(width:210, height:210)
}
var dstAspectRatio: CGFloat {
return dstSizePixels.width / dstSizePixels.height
}
// The size of the src image in points.
var srcImageSizePoints: CGSize = CGSize.zero
@ -90,7 +97,8 @@ class CropScaleImageViewController: OWSViewController {
}
required init(srcImage: UIImage, successCompletion : @escaping (UIImage) -> Void) {
self.srcImage = srcImage
// normalized() can be slightly expensive but in practice this is fine.
self.srcImage = srcImage.normalized()
self.successCompletion = successCompletion
super.init(nibName: nil, bundle: nil)
@ -283,13 +291,7 @@ class CropScaleImageViewController: OWSViewController {
srcTranslation = CGPoint(x: max(minSrcTranslationPoints.x, min(maxSrcTranslationPoints.x, srcTranslation.x)),
y: max(minSrcTranslationPoints.y, min(maxSrcTranslationPoints.y, srcTranslation.y)))
let srcToViewRatio = viewSizePoints.width / srcCropSizePoints.width
let imageViewFrame = CGRect(origin: CGPoint(x:srcTranslation.x * -srcToViewRatio,
y:srcTranslation.y * -srcToViewRatio),
size: CGSize(width:srcImageSizePoints.width * +srcToViewRatio,
height:srcImageSizePoints.height * +srcToViewRatio
))
let imageViewFrame = imageRenderRect(forDstSize:viewSizePoints)
// Disable implicit animations.
CATransaction.begin()
@ -301,6 +303,20 @@ class CropScaleImageViewController: OWSViewController {
dashedBorderLayer.path = UIBezierPath(rect: imageView.bounds).cgPath
}
private func imageRenderRect(forDstSize dstSize: CGSize) -> CGRect {
let srcCropSizePoints = CGSize(width:srcDefaultCropSizePoints.width / imageScale,
height:srcDefaultCropSizePoints.height / imageScale)
let srcToViewRatio = dstSize.width / srcCropSizePoints.width
return CGRect(origin: CGPoint(x:srcTranslation.x * -srcToViewRatio,
y:srcTranslation.y * -srcToViewRatio),
size: CGSize(width:srcImageSizePoints.width * +srcToViewRatio,
height:srcImageSizePoints.height * +srcToViewRatio
))
}
var srcTranslationAtPinchStart: CGPoint = CGPoint.zero
var imageScaleAtPinchStart: CGFloat = 0
var lastPinchLocation: CGPoint = CGPoint.zero
@ -458,9 +474,28 @@ class CropScaleImageViewController: OWSViewController {
func donePressed(sender: UIButton) {
let successCompletion = self.successCompletion
dismiss(animated: true, completion: {
// TODO:
let dstImage = self.srcImage
guard let dstImage = self.generateDstImage() else {
return
}
successCompletion?(dstImage)
})
}
// MARK: - Output
func generateDstImage() -> UIImage? {
let hasAlpha = false
let dstScale: CGFloat = 1.0 // The size is specified in pixels, not in points.
UIGraphicsBeginImageContextWithOptions(dstSizePixels, !hasAlpha, dstScale)
let imageViewFrame = imageRenderRect(forDstSize:dstSizePixels)
srcImage.draw(in:imageViewFrame)
let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
if scaledImage == nil {
Logger.error("\(TAG) could not generate dst image.")
}
UIGraphicsEndImageContext()
return scaledImage
}
}

View file

@ -271,17 +271,6 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
}
[self updateBarButtonItems];
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *srcDmage = [UIImage imageNamed:@"IMG_4187.PNG"];
OWSAssert(srcDmage);
CropScaleImageViewController *vc =
[[CropScaleImageViewController alloc] initWithSrcImage:srcDmage
successCompletion:^(UIImage *_Nonnull dstImage){
}];
OWSNavigationController *navigationController = [[OWSNavigationController alloc] initWithRootViewController:vc];
[self presentTopLevelModalViewController:navigationController animateDismissal:NO animatePresentation:YES];
});
}
- (void)updateBarButtonItems {