diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoEditorUtils.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoEditorUtils.h index f5837b4dd0..948ccab2ff 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoEditorUtils.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGPhotoEditorUtils.h @@ -14,9 +14,11 @@ CGFloat TGRadiansToDegrees(CGFloat radians); UIImage *TGPhotoEditorCrop(UIImage *image, UIImage *paintingImage, UIImageOrientation orientation, CGFloat rotation, CGRect rect, bool mirrored, CGSize maxSize, CGSize originalSize, bool shouldResize); UIImage *TGPhotoEditorVideoCrop(UIImage *image, UIImage *paintingImage, UIImageOrientation orientation, CGFloat rotation, CGRect rect, bool mirrored, CGSize maxSize, CGSize originalSize, bool shouldResize, bool useImageSize); -UIImage *TGPhotoEditorVideoExtCrop(UIImage *inputImage, UIImage *paintingImage, UIImageOrientation orientation, CGFloat rotation, CGRect rect, bool mirrored, CGSize maxSize, CGSize originalSize, bool shouldResize, bool useImageSize, bool skipImageTransform); +UIImage *TGPhotoEditorVideoExtCrop(UIImage *inputImage, UIImage *paintingImage, UIImageOrientation orientation, CGFloat rotation, CGRect rect, bool mirrored, CGSize maxSize, CGSize originalSize, bool shouldResize, bool useImageSize, bool skipImageTransform, bool fillPainting); UIImage *TGPhotoEditorFitImage(UIImage *image, CGSize maxSize); CGSize TGRotatedContentSize(CGSize contentSize, CGFloat rotation); + +UIImage *TGPhotoEditorPaintingCrop(UIImage *paintingImage, UIImageOrientation orientation, CGFloat rotation, CGRect rect, bool mirrored, CGSize maxSize, CGSize originalSize, bool shouldResize, bool useImageSize, bool skipImageTransform); UIImageOrientation TGNextCWOrientationForOrientation(UIImageOrientation orientation); UIImageOrientation TGNextCCWOrientationForOrientation(UIImageOrientation orientation); diff --git a/submodules/LegacyComponents/Sources/TGAttachmentCarouselItemView.m b/submodules/LegacyComponents/Sources/TGAttachmentCarouselItemView.m index 37da1a71a1..3aa9bcda19 100644 --- a/submodules/LegacyComponents/Sources/TGAttachmentCarouselItemView.m +++ b/submodules/LegacyComponents/Sources/TGAttachmentCarouselItemView.m @@ -928,7 +928,8 @@ const NSUInteger TGAttachmentDisplayedAssetLimit = 500; if (paintingImage == nil) { paintingImage = adjustments.paintingData.image; } - UIImage *thumbnailImage = TGPhotoEditorVideoExtCrop(resultImage, paintingImage, adjustments.cropOrientation, adjustments.cropRotation, adjustments.cropRect, adjustments.cropMirrored, TGScaleToFill(asset.dimensions, CGSizeMake(800, 800)), adjustments.originalSize, true, true, true); + UIImage *croppedPaintingImage = TGPhotoEditorPaintingCrop(paintingImage, adjustments.cropOrientation, adjustments.cropRotation, adjustments.cropRect, adjustments.cropMirrored, resultImage.size, adjustments.originalSize, true, true, false); + UIImage *thumbnailImage = TGPhotoEditorVideoExtCrop(resultImage, croppedPaintingImage, adjustments.cropOrientation, adjustments.cropRotation, adjustments.cropRect, adjustments.cropMirrored, TGScaleToFill(asset.dimensions, CGSizeMake(800, 800)), adjustments.originalSize, true, true, true, true); if (thumbnailImage != nil) { previewImage = thumbnailImage; } diff --git a/submodules/LegacyComponents/Sources/TGCameraController.m b/submodules/LegacyComponents/Sources/TGCameraController.m index 638153c61f..8482896730 100644 --- a/submodules/LegacyComponents/Sources/TGCameraController.m +++ b/submodules/LegacyComponents/Sources/TGCameraController.m @@ -1751,9 +1751,34 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus TGDispatchOnMainThread(^ { - if (strongSelf.finishedWithPhoto != nil) - strongSelf.finishedWithPhoto(nil, resultImage, nil, nil, nil, nil); - + if (editorValues.paintingData.hasAnimation) { + TGVideoEditAdjustments *adjustments = [TGVideoEditAdjustments editAdjustmentsWithPhotoEditorValues:(PGPhotoEditorValues *)editorValues preset:TGMediaVideoConversionPresetProfileVeryHigh]; + + NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSString alloc] initWithFormat:@"gifvideo_%x.jpg", (int)arc4random()]]; + NSData *data = UIImageJPEGRepresentation(resultImage, 0.8); + [data writeToFile:filePath atomically:true]; + + UIImage *previewImage = resultImage; + if ([adjustments cropAppliedForAvatar:false] || adjustments.hasPainting || adjustments.toolsApplied) + { + UIImage *paintingImage = adjustments.paintingData.stillImage; + if (paintingImage == nil) { + paintingImage = adjustments.paintingData.image; + } + UIImage *croppedPaintingImage = TGPhotoEditorPaintingCrop(paintingImage, adjustments.cropOrientation, adjustments.cropRotation, adjustments.cropRect, adjustments.cropMirrored, resultImage.size, adjustments.originalSize, true, true, false); + UIImage *thumbnailImage = TGPhotoEditorVideoExtCrop(resultImage, croppedPaintingImage, adjustments.cropOrientation, adjustments.cropRotation, adjustments.cropRect, adjustments.cropMirrored, TGScaleToFill(resultImage.size, CGSizeMake(800, 800)), adjustments.originalSize, true, true, true, true); + if (thumbnailImage != nil) { + previewImage = thumbnailImage; + } + } + + if (strongSelf.finishedWithVideo != nil) + strongSelf.finishedWithVideo(nil, [NSURL fileURLWithPath:filePath], previewImage, 0, CGSizeZero, adjustments, nil, nil, nil, nil); + } else { + if (strongSelf.finishedWithPhoto != nil) + strongSelf.finishedWithPhoto(nil, resultImage, nil, nil, nil, nil); + } + if (strongSelf.shouldStoreCapturedAssets && [input isKindOfClass:[UIImage class]]) { [strongSelf _savePhotoToCameraRollWithOriginalImage:image editedImage:[editorValues toolsApplied] ? resultImage : nil]; @@ -2608,7 +2633,7 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus if (paintingImage == nil) { paintingImage = adjustments.paintingData.image; } - UIImage *thumbnailImage = TGPhotoEditorVideoExtCrop(image, paintingImage, adjustments.cropOrientation, adjustments.cropRotation, adjustments.cropRect, adjustments.cropMirrored, TGScaleToFill(image.size, CGSizeMake(512, 512)), adjustments.originalSize, true, true, true); + UIImage *thumbnailImage = TGPhotoEditorVideoExtCrop(image, paintingImage, adjustments.cropOrientation, adjustments.cropRotation, adjustments.cropRect, adjustments.cropMirrored, TGScaleToFill(image.size, CGSizeMake(512, 512)), adjustments.originalSize, true, true, true, false); if (thumbnailImage != nil) { dict[@"previewImage"] = thumbnailImage; } diff --git a/submodules/LegacyComponents/Sources/TGMediaAssetsController.m b/submodules/LegacyComponents/Sources/TGMediaAssetsController.m index 7c295a7652..956d31fb69 100644 --- a/submodules/LegacyComponents/Sources/TGMediaAssetsController.m +++ b/submodules/LegacyComponents/Sources/TGMediaAssetsController.m @@ -920,7 +920,7 @@ if (paintingImage == nil) { paintingImage = adjustments.paintingData.image; } - UIImage *thumbnailImage = TGPhotoEditorVideoExtCrop(image, paintingImage, adjustments.cropOrientation, adjustments.cropRotation, adjustments.cropRect, adjustments.cropMirrored, TGScaleToFill(asset.dimensions, CGSizeMake(512, 512)), adjustments.originalSize, true, true, true); + UIImage *thumbnailImage = TGPhotoEditorVideoExtCrop(image, paintingImage, adjustments.cropOrientation, adjustments.cropRotation, adjustments.cropRect, adjustments.cropMirrored, TGScaleToFill(asset.dimensions, CGSizeMake(512, 512)), adjustments.originalSize, true, true, true, false); if (thumbnailImage != nil) { dict[@"previewImage"] = thumbnailImage; } diff --git a/submodules/LegacyComponents/Sources/TGMediaAssetsPickerController.m b/submodules/LegacyComponents/Sources/TGMediaAssetsPickerController.m index 28e2407007..61c68aec85 100644 --- a/submodules/LegacyComponents/Sources/TGMediaAssetsPickerController.m +++ b/submodules/LegacyComponents/Sources/TGMediaAssetsPickerController.m @@ -442,7 +442,8 @@ if (paintingImage == nil) { paintingImage = adjustments.paintingData.image; } - UIImage *thumbnailImage = TGPhotoEditorVideoExtCrop(resultImage, paintingImage, adjustments.cropOrientation, adjustments.cropRotation, adjustments.cropRect, adjustments.cropMirrored, TGScaleToFill(asset.dimensions, CGSizeMake(800, 800)), adjustments.originalSize, true, true, true); + UIImage *croppedPaintingImage = TGPhotoEditorPaintingCrop(paintingImage, adjustments.cropOrientation, adjustments.cropRotation, adjustments.cropRect, adjustments.cropMirrored, resultImage.size, adjustments.originalSize, true, true, false); + UIImage *thumbnailImage = TGPhotoEditorVideoExtCrop(resultImage, croppedPaintingImage, adjustments.cropOrientation, adjustments.cropRotation, adjustments.cropRect, adjustments.cropMirrored, TGScaleToFill(asset.dimensions, CGSizeMake(800, 800)), adjustments.originalSize, true, true, true, true); if (thumbnailImage != nil) { previewImage = thumbnailImage; } diff --git a/submodules/LegacyComponents/Sources/TGPhotoEditorUtils.m b/submodules/LegacyComponents/Sources/TGPhotoEditorUtils.m index 91dd667420..c2a2882fe3 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoEditorUtils.m +++ b/submodules/LegacyComponents/Sources/TGPhotoEditorUtils.m @@ -218,10 +218,10 @@ UIImage *TGPhotoEditorCrop(UIImage *inputImage, UIImage *paintingImage, UIImageO } UIImage *TGPhotoEditorVideoCrop(UIImage *inputImage, UIImage *paintingImage, UIImageOrientation orientation, CGFloat rotation, CGRect rect, bool mirrored, CGSize maxSize, CGSize originalSize, bool shouldResize, bool useImageSize) { - return TGPhotoEditorVideoExtCrop(inputImage, paintingImage, orientation, rotation, rect, mirrored, maxSize, originalSize, shouldResize, useImageSize, false); + return TGPhotoEditorVideoExtCrop(inputImage, paintingImage, orientation, rotation, rect, mirrored, maxSize, originalSize, shouldResize, useImageSize, false, false); } -UIImage *TGPhotoEditorVideoExtCrop(UIImage *inputImage, UIImage *paintingImage, UIImageOrientation orientation, CGFloat rotation, CGRect rect, bool mirrored, CGSize maxSize, CGSize originalSize, bool shouldResize, bool useImageSize, bool skipImageTransform) +UIImage *TGPhotoEditorVideoExtCrop(UIImage *inputImage, UIImage *paintingImage, UIImageOrientation orientation, CGFloat rotation, CGRect rect, bool mirrored, CGSize maxSize, CGSize originalSize, bool shouldResize, bool useImageSize, bool skipImageTransform, bool fillPainting) { if (iosMajorVersion() < 7) return TGPhotoEditorLegacyCrop(inputImage, paintingImage, orientation, rotation, rect, mirrored, maxSize, shouldResize); @@ -251,6 +251,9 @@ UIImage *TGPhotoEditorVideoExtCrop(UIImage *inputImage, UIImage *paintingImage, UIGraphicsBeginImageContextWithOptions(CGSizeMake(outputImageSize.width, outputImageSize.height), true, 1.0f); CGContextRef context = UIGraphicsGetCurrentContext(); + + CGContextSaveGState(context); + CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor); CGContextFillRect(context, CGRectMake(0, 0, outputImageSize.width, outputImageSize.height)); CGContextSetInterpolationQuality(context, kCGInterpolationHigh); @@ -297,6 +300,97 @@ UIImage *TGPhotoEditorVideoExtCrop(UIImage *inputImage, UIImage *paintingImage, [image drawAtPoint:CGPointMake(-image.size.width / 2, -image.size.height / 2)]; } + if (paintingImage != nil) + { + if (fillPainting) { + CGContextRestoreGState(context); + [paintingImage drawInRect:CGRectMake(0.0, 0.0, outputImageSize.width, outputImageSize.height)]; + } else { + if (mirrored) + CGContextScaleCTM(context, -1.0f, 1.0f); + + [paintingImage drawInRect:CGRectMake(-imageSize.width / 2, -imageSize.height / 2, imageSize.width, imageSize.height)]; + } + } + + UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return croppedImage; +} + +UIImage *TGPhotoEditorPaintingCrop(UIImage *paintingImage, UIImageOrientation orientation, CGFloat rotation, CGRect rect, bool mirrored, CGSize maxSize, CGSize originalSize, bool shouldResize, bool useImageSize, bool skipImageTransform) +{ + CGSize fittedOriginalSize = originalSize; + if (useImageSize) + { + CGFloat ratio = paintingImage.size.width / originalSize.width; + if (skipImageTransform) { + + } + rect.origin.x = rect.origin.x * ratio; + rect.origin.y = rect.origin.y * ratio; + rect.size.width = rect.size.width * ratio; + rect.size.height = rect.size.height * ratio; + + fittedOriginalSize = CGSizeMake(originalSize.width * ratio, originalSize.height * ratio); + } + + CGSize fittedImageSize = shouldResize ? TGFitSize(rect.size, maxSize) : rect.size; + + CGSize outputImageSize = fittedImageSize; + outputImageSize.width = CGFloor(outputImageSize.width); + outputImageSize.height = CGFloor(outputImageSize.height); + if (TGOrientationIsSideward(orientation, NULL)) + outputImageSize = CGSizeMake(outputImageSize.height, outputImageSize.width); + + UIGraphicsBeginImageContextWithOptions(CGSizeMake(outputImageSize.width, outputImageSize.height), false, 1.0f); + CGContextRef context = UIGraphicsGetCurrentContext(); + + UIImage *image = nil; + CGSize imageSize = paintingImage.size; + if (shouldResize) + { + CGSize referenceSize = useImageSize ? paintingImage.size : originalSize; + CGSize resizedSize = CGSizeMake(referenceSize.width * fittedImageSize.width / rect.size.width, referenceSize.height * fittedImageSize.height / rect.size.height); + + UIGraphicsBeginImageContextWithOptions(resizedSize, false, 1.0f); + [image drawInRect:CGRectMake(0, 0, resizedSize.width, resizedSize.height) blendMode:kCGBlendModeCopy alpha:1.0f]; + image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + if (skipImageTransform) { + imageSize = CGSizeMake(image.size.width * fittedOriginalSize.width / rect.size.width, image.size.height * fittedOriginalSize.height / rect.size.height); + } else { + imageSize = image.size; + } + } + else + { + image = paintingImage; + imageSize = image.size; + } + + if (skipImageTransform) { + [image drawInRect:CGRectMake(0.0, 0.0, outputImageSize.width, outputImageSize.height)]; + } + + CGSize scales = CGSizeMake(fittedImageSize.width / rect.size.width, fittedImageSize.height / rect.size.height); + CGSize rotatedContentSize = TGRotatedContentSize(paintingImage.size, rotation); + CGAffineTransform transform = CGAffineTransformIdentity; + transform = CGAffineTransformTranslate(transform, outputImageSize.width / 2, outputImageSize.height / 2); + transform = CGAffineTransformRotate(transform, TGRotationForOrientation(orientation)); + transform = CGAffineTransformTranslate(transform, (rotatedContentSize.width / 2 - CGRectGetMidX(rect)) * scales.width, (rotatedContentSize.height / 2 - CGRectGetMidY(rect)) * scales.height); + transform = CGAffineTransformRotate(transform, rotation); + CGContextConcatCTM(context, transform); + + if (mirrored) + CGContextScaleCTM(context, -1.0f, 1.0f); + + if (!skipImageTransform) { + [image drawAtPoint:CGPointMake(-image.size.width / 2, -image.size.height / 2)]; + } + if (paintingImage != nil) { if (mirrored) diff --git a/submodules/PhotoResources/Sources/PhotoResources.swift b/submodules/PhotoResources/Sources/PhotoResources.swift index bde7d61772..53316eba0e 100644 --- a/submodules/PhotoResources/Sources/PhotoResources.swift +++ b/submodules/PhotoResources/Sources/PhotoResources.swift @@ -2218,16 +2218,14 @@ public func chatAvatarGalleryPhoto(account: Account, representations: [ImageRepr blurredThumbnailImage = UIImage(cgImage: thumbnailImage) } else { let thumbnailSize = CGSize(width: thumbnailImage.width, height: thumbnailImage.height) - - let initialThumbnailContextFittingSize = fittedSize.fitted(CGSize(width: 100.0, height: 100.0)) + let initialThumbnailContextFittingSize = fittedSize.fitted(CGSize(width: 90.0, height: 90.0)) let thumbnailContextSize = thumbnailSize.aspectFitted(initialThumbnailContextFittingSize) - let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0, clear: false) + let thumbnailContext = DrawingContext(size: thumbnailContextSize, scale: 1.0) thumbnailContext.withFlippedContext { c in - c.interpolationQuality = .none c.draw(thumbnailImage, in: CGRect(origin: CGPoint(), size: thumbnailContextSize)) } - imageFastBlur(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes) + telegramFastBlurMore(Int32(thumbnailContextSize.width), Int32(thumbnailContextSize.height), Int32(thumbnailContext.bytesPerRow), thumbnailContext.bytes) var thumbnailContextFittingSize = CGSize(width: floor(arguments.drawingSize.width * 0.5), height: floor(arguments.drawingSize.width * 0.5)) if thumbnailContextFittingSize.width < 150.0 || thumbnailContextFittingSize.height < 150.0 { @@ -2236,7 +2234,7 @@ public func chatAvatarGalleryPhoto(account: Account, representations: [ImageRepr if thumbnailContextFittingSize.width > thumbnailContextSize.width { let additionalContextSize = thumbnailContextFittingSize - let additionalBlurContext = DrawingContext(size: additionalContextSize, scale: 1.0, clear: false) + let additionalBlurContext = DrawingContext(size: additionalContextSize, scale: 1.0) additionalBlurContext.withFlippedContext { c in c.interpolationQuality = .default if let image = thumbnailContext.generateImage()?.cgImage { @@ -2261,7 +2259,7 @@ public func chatAvatarGalleryPhoto(account: Account, representations: [ImageRepr c.setBlendMode(.copy) if let blurredThumbnailImage = blurredThumbnailImage, let cgImage = blurredThumbnailImage.cgImage { - c.interpolationQuality = .medium + c.interpolationQuality = .default drawImage(context: c, image: cgImage, orientation: imageOrientation, in: fittedRect) c.setBlendMode(.normal) } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 364109e5e5..2f9da9a78d 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -5070,7 +5070,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.preloadAvatarDisposable.set((peerInfoProfilePhotosWithCache(context: context, peerId: peerId) |> mapToSignal { result -> Signal in var signals: [Signal] = [.complete()] - for i in 0 ..< min(5, result.count) { + for i in 0 ..< min(1, result.count) { if let video = result[i].videoRepresentations.first { let duration: Double = (video.representation.startTimestamp ?? 0.0) + (i == 0 ? 4.0 : 2.0) signals.append(preloadVideoResource(postbox: context.account.postbox, resourceReference: video.reference, duration: duration)) diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift index e58d4507ff..567095af9c 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift @@ -1706,13 +1706,7 @@ final class PeerInfoAvatarListNode: ASDisplayNode { func animateAvatarCollapse(transition: ContainedViewLayoutTransition) { if let currentItemNode = self.listContainerNode.currentItemNode, case .animated = transition { if let _ = self.avatarContainerNode.videoNode { -// if self.listContainerNode.currentIndex > 0 { -// transition.updateAlpha(node: currentItemNode, alpha: 0.0, completion: { _ in -// Queue.mainQueue().after(0.1, { -// currentItemNode.alpha = 1.0 -// }) -// }) -// } + } else if let unroundedImage = self.avatarContainerNode.avatarNode.unroundedImage { let avatarCopyView = UIImageView() avatarCopyView.image = unroundedImage @@ -2858,7 +2852,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { titleFrame = CGRect(origin: CGPoint(x: floor((width - titleSize.width) / 2.0), y: avatarFrame.maxY + 10.0 + (subtitleSize.height.isZero ? 11.0 : 0.0)), size: titleSize) let totalSubtitleWidth = subtitleSize.width + usernameSpacing + usernameSize.width - twoLineInfo = true // totalSubtitleWidth > width - textSideInset * 2.0 + twoLineInfo = true if usernameSize.width == 0.0 || twoLineInfo { subtitleFrame = CGRect(origin: CGPoint(x: floor((width - subtitleSize.width) / 2.0), y: titleFrame.maxY + 1.0), size: subtitleSize) usernameFrame = CGRect(origin: CGPoint(x: floor((width - usernameSize.width) / 2.0), y: subtitleFrame.maxY + 1.0), size: usernameSize) diff --git a/submodules/WebSearchUI/Sources/LegacyWebSearchGallery.swift b/submodules/WebSearchUI/Sources/LegacyWebSearchGallery.swift index 99e7fab29a..3d5f8e1149 100644 --- a/submodules/WebSearchUI/Sources/LegacyWebSearchGallery.swift +++ b/submodules/WebSearchUI/Sources/LegacyWebSearchGallery.swift @@ -459,7 +459,7 @@ public func legacyEnqueueWebSearchMessages(_ selectionState: TGMediaSelectionCon paintingImage = adjustments.paintingData?.image } - let thumbnailImage = TGPhotoEditorVideoExtCrop(image, paintingImage, adjustments.cropOrientation, adjustments.cropRotation, adjustments.cropRect, adjustments.cropMirrored, TGScaleToFill(image.size, CGSize(width: 512.0, height: 512.0)), adjustments.originalSize, true, true, true) + let thumbnailImage = TGPhotoEditorVideoExtCrop(image, paintingImage, adjustments.cropOrientation, adjustments.cropRotation, adjustments.cropRect, adjustments.cropMirrored, TGScaleToFill(image.size, CGSize(width: 512.0, height: 512.0)), adjustments.originalSize, true, true, true, false) if let thumbnailImage = thumbnailImage { dict["previewImage"] = thumbnailImage }