From 3ba35d0e491ad7f58d6f0e38d8cbaacb4c6bf2d4 Mon Sep 17 00:00:00 2001 From: Vegard Matthey Date: Mon, 4 Aug 2025 22:11:43 +0200 Subject: [PATCH] fix regression where images were only scaled for portrait mode --- ImageViewer/ViewController.swift | 112 ++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 30 deletions(-) diff --git a/ImageViewer/ViewController.swift b/ImageViewer/ViewController.swift index 8884834..86401f5 100644 --- a/ImageViewer/ViewController.swift +++ b/ImageViewer/ViewController.swift @@ -912,24 +912,19 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { var text = "\(metadata.title)\n" if let chapterTitle = metadata.chapters[currentChapter - 1].title { - text = - text + "\(chapterTitle)\n" - } - text = - text + """ - Volume \(Int(metadata.chapters[currentChapter - 1].volume)) of \(Int(metadata.last_volume)) - Chapter \(currentChapter!) of \(Int(metadata.last_chapter)) - Page \(currentPage!) of \(metadata.chapters[currentChapter - 1].pages) - """ - if let size = imageLoader.size[ - getImagePath( - chapter: currentChapter, volume: Int(metadata.chapters[currentChapter - 1].volume), - page: currentPage!, path: currentPath - ).path] - { - text = - text + "\nImage size: \(Int(size.width))x\(Int(size.height))" + text += + "\(chapterTitle)\n" } + text += + """ + Volume \(Int(metadata.chapters[currentChapter - 1].volume)) of \(Int(metadata.last_volume)) + Chapter \(currentChapter!) of \(Int(metadata.last_chapter)) + Page \(currentPage!) of \(metadata.chapters[currentChapter - 1].pages) + """ + // if let size = imageLoader.originalImage.cgImage { + // text += + // "\nImage size: \(Int(size.width))x\(Int(size.height))" + // } info.text = text } @@ -1060,6 +1055,23 @@ class ViewController: UIViewController, UIGestureRecognizerDelegate { } return nil } + + override func viewWillTransition( + to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator + ) { + super.viewWillTransition(to: size, with: coordinator) + + self.imageLoader.loadImage( + at: self.getImagePath( + chapter: self.currentChapter, + volume: Int(self.metadata.chapters[self.currentChapter - 1].volume), + page: self.currentPage, + path: self.currentPath), + scaling: .scaleAspectFit + ) { image in + self.imageView.image = image + } + } } func getGlobalState() -> GlobalState { @@ -1259,10 +1271,15 @@ class ComicImageCell: UICollectionViewCell { } } +enum Rotation { + case vertical + case horizontal +} + class ImageLoader { - private let cache = NSCache() + let cache = NSCache() + let horCache = NSCache() private var loadingTasks: [String: [((UIImage?) -> Void)]] = [:] - var size: [String: CGSize] = [:] init() { // 128 MiB @@ -1273,10 +1290,26 @@ class ImageLoader { loadImage(at: path, scaling: scaling, completion: nil) } - func loadImage(at path: URL, scaling: UIView.ContentMode, completion: ((UIImage?) -> Void)?) { - if let cached = cache.object(forKey: path.path as NSString) { - completion?(cached) - return + func loadImage( + at path: URL, scaling: UIView.ContentMode, + completion: ((UIImage?) -> Void)? + ) { + let screenSize = UIScreen.main.bounds.size + let rotation: Rotation = + if screenSize.width > screenSize.height { + .horizontal + } else { .vertical } + + if rotation == .vertical { + if let cached = cache.object(forKey: path.path as NSString) { + completion?(cached) + return + } + } else { + if let cached = horCache.object(forKey: path.path as NSString) { + completion?(cached) + return + } } if loadingTasks[path.path] != nil { @@ -1291,15 +1324,34 @@ class ImageLoader { queue.async { [weak self] in guard let self = self else { return } guard var image = UIImage(contentsOfFile: path.path) else { return } - self.size[path.path] = image.size - let scaledSize = aspectSize( - for: image.size, in: UIScreen.main.bounds.size, scaling: scaling) - image = resizeImage(image, to: scaledSize) - guard let cost = imageByteSize(image) else { return } - self.cache.setObject(image, forKey: path.path as NSString, cost: cost) + + // If you turn pages fast, completion will not be nil and as such only the needed scaled image should be prepared + if completion == nil || rotation == .vertical { + let vertical = CGSize( + width: min(screenSize.width, screenSize.height), + height: max(screenSize.height, screenSize.width)) + let vScaledSize = aspectSize( + for: image.size, in: vertical, scaling: scaling) + let vScaleImage = resizeImage(image, to: vScaledSize) + guard let cost = imageByteSize(vScaleImage) else { return } + self.cache.setObject(vScaleImage, forKey: path.path as NSString, cost: cost) + image = vScaleImage + } + + if completion == nil || rotation == .horizontal { + let horizontal = CGSize( + width: max(screenSize.width, screenSize.height), + height: min(screenSize.height, screenSize.width)) + let hScaledSize = aspectSize( + for: image.size, in: horizontal, scaling: scaling) + let hScaleImage = resizeImage(image, to: hScaledSize) + guard let cost = imageByteSize(hScaleImage) else { return } + self.horCache.setObject(hScaleImage, forKey: path.path as NSString, cost: cost) + image = hScaleImage + } DispatchQueue.main.async { - self.loadingTasks[path.path]?.forEach { $0(image) } + self.loadingTasks[path.path]?.forEach { $0((image)) } self.loadingTasks.removeValue(forKey: path.path) } }