mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +00:00
Shared media improvements
This commit is contained in:
@@ -6,6 +6,7 @@ import UIKit
|
||||
import TinyThumbnail
|
||||
import Display
|
||||
import FastBlur
|
||||
import MozjpegBinding
|
||||
|
||||
private func generateBlurredThumbnail(image: UIImage) -> UIImage? {
|
||||
let thumbnailContextSize = CGSize(width: 32.0, height: 32.0)
|
||||
@@ -22,6 +23,84 @@ private func generateBlurredThumbnail(image: UIImage) -> UIImage? {
|
||||
return thumbnailContext.generateImage()
|
||||
}
|
||||
|
||||
private func storeImage(context: DrawingContext, to path: String) -> UIImage? {
|
||||
if context.size.width <= 70.0 && context.size.height <= 70.0 {
|
||||
guard let file = ManagedFile(queue: nil, path: path, mode: .readwrite) else {
|
||||
return nil
|
||||
}
|
||||
var header: UInt32 = 0xcaf1
|
||||
let _ = file.write(&header, count: 4)
|
||||
var width: UInt16 = UInt16(context.size.width)
|
||||
let _ = file.write(&width, count: 2)
|
||||
var height: UInt16 = UInt16(context.size.height)
|
||||
let _ = file.write(&height, count: 2)
|
||||
var bytesPerRow: UInt16 = UInt16(context.bytesPerRow)
|
||||
let _ = file.write(&bytesPerRow, count: 2)
|
||||
|
||||
let _ = file.write(context.bytes, count: context.length)
|
||||
|
||||
return context.generateImage()
|
||||
} else {
|
||||
guard let image = context.generateImage(), let resultData = image.jpegData(compressionQuality: 0.7) else {
|
||||
return nil
|
||||
}
|
||||
let _ = try? resultData.write(to: URL(fileURLWithPath: path))
|
||||
return image
|
||||
}
|
||||
}
|
||||
|
||||
private func loadImage(data: Data) -> UIImage? {
|
||||
if data.count > 4 + 2 + 2 + 2 {
|
||||
var header: UInt32 = 0
|
||||
withUnsafeMutableBytes(of: &header, { header in
|
||||
data.copyBytes(to: header.baseAddress!.assumingMemoryBound(to: UInt8.self), from: 0 ..< 4)
|
||||
})
|
||||
if header == 0xcaf1 {
|
||||
var width: UInt16 = 0
|
||||
withUnsafeMutableBytes(of: &width, { width in
|
||||
data.copyBytes(to: width.baseAddress!.assumingMemoryBound(to: UInt8.self), from: 4 ..< (4 + 2))
|
||||
})
|
||||
var height: UInt16 = 0
|
||||
withUnsafeMutableBytes(of: &height, { height in
|
||||
data.copyBytes(to: height.baseAddress!.assumingMemoryBound(to: UInt8.self), from: (4 + 2) ..< (4 + 2 + 2))
|
||||
})
|
||||
var bytesPerRow: UInt16 = 0
|
||||
withUnsafeMutableBytes(of: &bytesPerRow, { bytesPerRow in
|
||||
data.copyBytes(to: bytesPerRow.baseAddress!.assumingMemoryBound(to: UInt8.self), from: (4 + 2 + 2) ..< (4 + 2 + 2 + 2))
|
||||
})
|
||||
|
||||
let imageData = data.subdata(in: (4 + 2 + 2 + 2) ..< data.count)
|
||||
guard let dataProvider = CGDataProvider(data: imageData as CFData) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
if let image = CGImage(
|
||||
width: Int(width),
|
||||
height: Int(height),
|
||||
bitsPerComponent: DeviceGraphicsContextSettings.shared.bitsPerComponent,
|
||||
bitsPerPixel: DeviceGraphicsContextSettings.shared.bitsPerPixel,
|
||||
bytesPerRow: Int(bytesPerRow),
|
||||
space: DeviceGraphicsContextSettings.shared.colorSpace,
|
||||
bitmapInfo: DeviceGraphicsContextSettings.shared.opaqueBitmapInfo,
|
||||
provider: dataProvider,
|
||||
decode: nil,
|
||||
shouldInterpolate: true,
|
||||
intent: .defaultIntent
|
||||
) {
|
||||
return UIImage(cgImage: image, scale: 1.0, orientation: .up)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let decompressedImage = decompressImage(data) {
|
||||
return decompressedImage
|
||||
}
|
||||
|
||||
return UIImage(data: data)
|
||||
}
|
||||
|
||||
public final class DirectMediaImageCache {
|
||||
public final class GetMediaResult {
|
||||
public let image: UIImage?
|
||||
@@ -65,16 +144,17 @@ public final class DirectMediaImageCache {
|
||||
}
|
||||
|> take(1)).start(next: { data in
|
||||
if let dataValue = try? Data(contentsOf: URL(fileURLWithPath: data.path)), let image = UIImage(data: dataValue) {
|
||||
if let scaledImage = generateImage(CGSize(width: CGFloat(width), height: CGFloat(width)), contextGenerator: { size, context in
|
||||
let filledSize = image.size.aspectFilled(size)
|
||||
let imageRect = CGRect(origin: CGPoint(x: (size.width - filledSize.width) / 2.0, y: (size.height - filledSize.height) / 2.0), size: filledSize)
|
||||
let scaledSize = CGSize(width: CGFloat(width), height: CGFloat(width))
|
||||
let scaledContext = DrawingContext(size: scaledSize, scale: 1.0, opaque: true)
|
||||
scaledContext.withFlippedContext { context in
|
||||
let filledSize = image.size.aspectFilled(scaledSize)
|
||||
let imageRect = CGRect(origin: CGPoint(x: (scaledSize.width - filledSize.width) / 2.0, y: (scaledSize.height - filledSize.height) / 2.0), size: filledSize)
|
||||
context.draw(image.cgImage!, in: imageRect)
|
||||
}, scale: 1.0) {
|
||||
if let resultData = scaledImage.jpegData(compressionQuality: 0.7) {
|
||||
let _ = try? resultData.write(to: URL(fileURLWithPath: cachePath))
|
||||
subscriber.putNext(scaledImage)
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
}
|
||||
|
||||
if let scaledImage = storeImage(context: scaledContext, to: cachePath) {
|
||||
subscriber.putNext(scaledImage)
|
||||
subscriber.putCompletion()
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -113,14 +193,14 @@ public final class DirectMediaImageCache {
|
||||
}
|
||||
|
||||
if let resource = resource {
|
||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: self.getCachePath(resourceId: resource.resource.id, imageType: .square(width: width)))), let image = UIImage(data: data) {
|
||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: self.getCachePath(resourceId: resource.resource.id, imageType: .square(width: width)))), let image = loadImage(data: data) {
|
||||
return GetMediaResult(image: image, loadSignal: nil)
|
||||
}
|
||||
|
||||
var blurredImage: UIImage?
|
||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: self.getCachePath(resourceId: resource.resource.id, imageType: .blurredThumbnail))), let image = UIImage(data: data) {
|
||||
if let data = try? Data(contentsOf: URL(fileURLWithPath: self.getCachePath(resourceId: resource.resource.id, imageType: .blurredThumbnail))), let image = loadImage(data: data) {
|
||||
blurredImage = image
|
||||
} else if let data = immediateThumbnailData.flatMap(decodeTinyThumbnail), let image = UIImage(data: data) {
|
||||
} else if let data = immediateThumbnailData.flatMap(decodeTinyThumbnail), let image = loadImage(data: data) {
|
||||
if let blurredImageValue = generateBlurredThumbnail(image: image) {
|
||||
blurredImage = blurredImageValue
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user