在后台使用 Cocoa 进行 9 切片缩放/拉伸

Posted

技术标签:

【中文标题】在后台使用 Cocoa 进行 9 切片缩放/拉伸【英文标题】:9-slice scaling/stretching in the background, using Cocoa on iOS 【发布时间】:2011-06-17 13:27:47 【问题描述】:

我想使用“9 切片”缩放来拉伸图像,其中仅缩放图像的中心。就像 UIImage 的stretchableImageWithLeftCapWidth 方法一样,但是我想在后台线程中执行此操作。我知道这个方法只能在gui线程中使用。

我正在 ios / iPad / iPhone 上开发。

有没有人有代码 sn-p,或者知道可以做到这一点的库?我正在努力不重新发明***!

我发现一些有用的相关参考资料:

CGContext 文档:

http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/CGContext/Reference/reference.html

关于后台绘图的好博文:

http://joris.kluivers.nl/iphone-dev/?p=BackgroundImageProcessing

使用 CGContext 旋转图像:

http://blog.coriolis.ch/2009/09/04/arbitrary-rotation-of-a-cgimage/

【问题讨论】:

【参考方案1】:

从 iOS 4 开始,UIKit 的某些部分是线程安全的;我相信 UIGraphics 函数和 UIImage 绘图应该可以工作。

如果你需要支持 iOS 3,那就有点困难了。如果你想完全避免 UIKit(可能是明智的),那么你需要向后台线程传递一个 CGImageRef。您可能还需要担心其他一些事情;我假设scale 是 1 而imageOrientation 是纵向。

    创建上下文:CGBitmapContextCreate() 创建您的子图像:CGImageCreateWithImageInRect()。 将每个子图像绘制到正确的位置:CGContextDrawImage() 从上下文中获取图像:CGBitmapContextCreateImage() 释放必要的东西并将CGImageRef返回给主线程。 在主线程中,使用+[UIImage imageWithCGImage:]+imageWithCGImage:scale:orientation:(请注意,在后一种情况下,比例为2 的图像似乎只支持纵向;我不知道为什么)。

另外请注意,最好将图像粘贴在 UIImageView 中并适当设置 contentStretch,因为这样缩放是在 GPU 上完成的。

【讨论】:

【参考方案2】:

AppKit 有一个很好的NSDrawNinePartImage() 函数。我在网上找到了这段代码,它为 iOS 提供了类似的功能。

http://pastie.org/1147077/

//
//  UIImageAdditions.m
//  Newspress
//
//  Created by Kyle Van Essen on 10-04-10.
//  Copyright 2010 Vibealicious. All rights reserved.
//

#import "UIImageAdditions.h"


@implementation UIImage (Additions)

+(void)drawNinePartImage:(NSArray *)images inRect:(CGRect)rect

    CGPoint origin = rect.origin;
    CGSize size = rect.size;

    NSInteger partCount = 9;

    if ([images count] < partCount)
        return;

    CGRect rects[partCount];
    UIImage *image;

    // Top Row
    image = [images objectAtIndex:0];
    rects[0] = CGRectMake(origin.x, origin.y, image.size.width, image.size.height);

    image = [images objectAtIndex:2];
    rects[2] = CGRectMake(origin.x + size.width - image.size.width, origin.y, image.size.width, image.size.height);

    image = [images objectAtIndex:1];
    rects[1] = CGRectMake(rects[0].size.width + rects[0].origin.x, origin.y, size.width - rects[0].size.width - rects[2].size.width, image.size.height);

    // Bottom Row
    image = [images objectAtIndex:6];
    rects[6] = CGRectMake(origin.x, origin.y + size.height - image.size.height, image.size.width, image.size.height);

    image = [images objectAtIndex:8];
    rects[8] = CGRectMake(origin.x + size.width - image.size.width, origin.y + size.height - image.size.height, image.size.width, image.size.height);

    image = [images objectAtIndex:7];
    rects[7] = CGRectMake(rects[6].size.width + rects[6].origin.x, origin.y + size.height - image.size.height, size.width - rects[6].size.width - rects[8].size.width, image.size.height);

    // Middle Row
    image = [images objectAtIndex:3];
    rects[3] = CGRectMake(origin.x, origin.y + rects[0].size.height, image.size.width, size.height - rects[0].size.height - rects[6].size.height);

    image = [images objectAtIndex:5];
    rects[5] = CGRectMake(origin.x + size.width - image.size.width, origin.y + rects[0].size.height, image.size.width, size.height - rects[2].size.height - rects[8].size.height);

    image = [images objectAtIndex:4];
    rects[4] = CGRectMake(rects[3].size.width + rects[3].origin.x, origin.y + rects[0].size.height, size.width - rects[0].size.width - rects[2].size.width, size.height - rects[1].size.height - rects[7].size.height);

    for (NSInteger index = 0; index < partCount; index++)
                   
        UIColor *pattern = [[UIColor alloc] initWithPatternImage:[images objectAtIndex:index]];

        //NSLog(@"Frame: %f, %f, %f, %f", rects[index].origin.x, rects[index].origin.y, rects[index].size.width, rects[index].size.height);

        [pattern set];
        CGContextSetPatternPhase(UIGraphicsGetCurrentContext(), CGSizeMake(rects[index].origin.x, rects[index].origin.y));
        UIRectFill(rects[index]);

        [pattern release];
    

    [[UIColor clearColor] set];


@end

【讨论】:

谢谢亚历山大。好的起点!这个答案需要一个已经分成 9 个部分的图像,而不是拉伸单个图像。我仍然需要找到/编写一个拆分器。 不幸的是,sn-p 也使用 UIGraphicsGetCurrentContext(),它只能从主线程调用。

以上是关于在后台使用 Cocoa 进行 9 切片缩放/拉伸的主要内容,如果未能解决你的问题,请参考以下文章

在资产目录中切片 PDF 资源是不是损坏?

Cocoa 查看自动缩放内容

尝试在 React 中进行排序和切片时,如何保留整个 geojson?

大文件上传实现总结

我要用C#实现对图像的缩放、鼠标拖曳和灰度拉伸等功能,且图像可能非常大,请问我该使用picturebox控件吗

求用flex实现图片缩放拉伸和旋转功能