Skip to main content

Zooming Images with Text in an iOS Scroll View

You have an image containing text. As such, there’s lots of sharp edges. You want to put this image into a scroll view and allow the user to zoom in with a pinch gesture. This is very easy to implement in iOS. Technically, you don’t even need to write code. This can all be done in Interface Builder. However, the further the image is zoomed the blurrier it looks.

Solution 1

Start with a fully zoomed of the image and scale it down when initially adding it to the scroll view. After all, it’s much easier to scale an image down and keep it looking good than it is to scale it up. So during the whole zoom operation the image being displayed is a scaled down version of the original. This would work great except that iOS doesn’t apply the right interpolation when scaling the original large down to fit into the initial smaller frame. You would think self.imageView.layer.minificationFilter = kCAFilterTrilinear; would do the trick but it doesn’t. I could be doing it wrong but I haven’t been able to get this to work yet.

Solution 2

This is a variation of the previous solution. We still start with a large image at the size of its maximum zoom level. We keep a reference to this image on hand so we can create smaller versions of it whenever we need to. We’ll programatically resize the image down to its minimum zoom level and add that to our scroll view as the initial image. We’re using Core Graphics code to do the resizing so the interpolation is done correctly. Credit: variations of this method have appeared in several answers on StackOverflow.

- (UIImage*)resizeImage:(UIImage*)image newSize:(CGSize)newSize
{
    CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
    CGImageRef imageRef = image.CGImage;

    UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
    CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, newSize.height);

    CGContextConcatCTM(context, flipVertical);
    CGContextDrawImage(context, newRect, imageRef);

    CGImageRef newImageRef = CGBitmapContextCreateImage(context);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];

    CGImageRelease(newImageRef);
    UIGraphicsEndImageContext();

    return newImage;
}

We use this method in two different places. First, when the image is initially added to the scroll view. Second, when the user releases a pinch-zoom gesture. This approach may be a little heavy handed but it ensures a good-looking image at any point the pinch-zoom gesture is released.

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.originalImage = [UIImage imageNamed:@"continuo_display"];

    self.imageView.layer.minificationFilter = kCAFilterTrilinear;
    self.imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"continuo_display"]];
    self.imageView.frame = CGRectMake(0, 0, ORIGINAL_WIDTH, ORIGINAL_HEIGHT);
    self.imageView.image = [self resizeImage:self.originalImage newSize:CGSizeMake(ORIGINAL_WIDTH, ORIGINAL_HEIGHT)];

    self.scrollView.minimumZoomScale = 1.0f;
    self.scrollView.maximumZoomScale = 2.0f;
    [self.scrollView addSubview:self.imageView];
}

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale
{
    int new_width = ORIGINAL_WIDTH * self.scrollView.zoomScale;
    int new_height = ORIGINAL_HEIGHT * self.scrollView.zoomScale;
    self.imageView.image = [self resizeImage:self.originalImage newSize:CGSizeMake(new_width, new_height)];
}

The performance of this measured on an entrey-level iPad is pretty smooth.


The above solution and content was initially published by mluton on his own website which was left to decay and domain expiration and was recovered by projTek - an AI-powered R&D project. The GitHub repo of the original author: https://github.com/mluton 

Comments

Popular posts from this blog

Integrating SwiftUI into Existing AppKit Cocoa Projects: A Step-by-Step Guide

As Apple continues to push SwiftUI as the future of app development across its platforms, many developers find themselves in a position where they need to integrate this modern framework into their existing AppKit Cocoa projects. This integration can breathe new life into older applications, allowing developers to take advantage of SwiftUI's declarative syntax and powerful features while maintaining their existing codebase. In this guide, we'll walk through the process of adding SwiftUI to an existing AppKit Cocoa project, providing you with the knowledge to modernize your macOS applications.

Tips to improve performance of database-driven Java applications

Here are four tips, not really super cool or something you never heard and I rather say fundamentals but in practice many programmers  just missed these, you may also called this database performance tips but I prefer to keep them as Java because I mostly used this when I access database from Java application. Java database performance tips 1: Reduce the number of calls you make to the database server. Believe it or not if you see performance in seconds than in most cases culprit is database access code. since connecting to database requires connections to be prepared, network round trip and processing on database side, its best to avoid database call if you can work with cached value. even if your application has quite dynamic data having a short time cache can save many database round trip which can boost your java application performance by almost 20-50% based on how many calls got reduced. In order to find out database calls just put logging for each db call in DAO layer, e...

How to Use OUIEditableFrame with the OmniGroup Framework

TLDR: This blog post provides a detailed tutorial on how to implement OmniGroup’s OUIEditableFrame in an iOS project to render text with proper kerning, which cannot be achieved with standard UIKit controls due to a bug. The guide walks through creating and configuring an Xcode workspace, cloning the OmniGroup project from GitHub, adding necessary frameworks and dependencies, and writing the required view controller code. Learn to implement OmniGroup's OUIEditableFrame for proper text kerning in iOS projects with this step-by-step Xcode tutorial. Table of Contents: Introduction Create and Configure Xcode Workspace Clone the OmniGroup Project from GitHub Add the FixStringsFile Project Add OmniBase Add the Rest of the Frameworks Write View Controller Code Making It Work in iOS 5 Get Rid of the Static Analyzer Message If you need a UITextField that renders text with proper kerning you don’t have many of options. Writing al...