【问题标题】:How to resize a UIImage without antialiasing?如何在没有抗锯齿的情况下调整 UIImage 的大小?
【发布时间】:2018-07-05 08:08:05
【问题描述】:

我正在开发一款 iOS 棋盘游戏。我试图给董事会一种“质感”。

我所做的是我创建了这个非常小的图像(真的很小,一定要仔细看):

我将此图像传递给UIColor.init(patternImage:) 初始化程序以创建一个UIColor 即此图像。我用这个UIColor填充了一些正方形UIBezierPaths,结果是这样的:

该图像的所有副本都完美排列,并形成许多对角直线。到目前为止一切顺利。

现在在 iPad 上,我画的方块会变大,而且这些方块的边框也会变大。我已经成功计算出正方形的笔画宽度和大小应该是多少,所以这不是问题。

但是,由于 iPad 上的正方形更大,每个正方形的对角线会更多。我不要那个。我需要将非常小的图像调整为更大的图像,并且大小取决于正方形的笔画宽度。具体来说,调整后图片的宽度应该是笔划宽度的两倍。

我写了这个扩展来调整图像大小,改编自post:

extension UIImage {
    func resized(toWidth newWidth: CGFloat) -> UIImage {

        let scale = newWidth / size.width
        let newHeight = size.height * scale
        UIGraphicsBeginImageContextWithOptions(CGSize(width: newWidth, height: newHeight), false, 0)
        self.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage!
    }
}

并这样称呼它:

// this is the code I used to draw a single square
let path = UIBezierPath(rect: CGRect(origin: point(for: Position(x, y)), size: CGSize(width: squareLength, height: squareLength)))
UIColor.black.setStroke()
path.lineWidth = strokeWidth
// this is the line that's important!
UIColor(patternImage: #imageLiteral(resourceName: 

"纹理").resized(toWidth: strokeWidth * 2)).setFill() path.fill() path.stroke()

现在游戏板在 iPhone 上是这样的:

您可能需要将网页放大一点才能明白我的意思。董事会现在看起来非常难看。您可以看到图像的每个副本的“边框”。我不想要这个。不过,在 iPad 上,电路板看起来不错。我怀疑这只会在我缩小图像时发生。

我认为这可能是由于我使用扩展程序时发生的抗锯齿。我发现this post 和this post 关于删除抗锯齿,但前者似乎在图像视图中执行此操作,而我在自定义GameBoardView 的draw(_:) 方法中执行此操作。后者的解决方案似乎和我使用的完全一样。

如何在没有抗锯齿的情况下调整大小?或者在更高的抽象层次上,我怎样才能让我的电路板看起来很漂亮?

【问题讨论】:

    标签: ios swift drawing image-resizing


    【解决方案1】:
    class Ruled: UIView {
    
        override func draw(_ rect: CGRect) {
    
            let T: CGFloat = 15     // desired thickness of lines
            let G: CGFloat = 30     // desired gap between lines
            let W = rect.size.width
            let H = rect.size.height
    
            guard let c = UIGraphicsGetCurrentContext() else { return }
            c.setStrokeColor(UIColor.orange.cgColor)
            c.setLineWidth(T)
    
            var p = -(W > H ? W : H) - T
            while p <= W {
    
                c.move( to: CGPoint(x: p-T, y: -T) )
                c.addLine( to: CGPoint(x: p+T+H, y: T+H) )
                c.strokePath()
                p += G + T + T
            }
        }
    }
    

    享受吧。

    请注意,您显然会剪切该视图。

    如果您想在屏幕上或以某种模式显示它们的数量,那就这样做吧。


    剪切到给定的矩形:

    上面的类只是将它绘制成“UIView 的大小”。

    但是,通常,您希望在视图中的不同坐标处实际绘制多个“框”。 (一个很好的例子是日历)。

    此外,此示例显式绘制“两条条纹”,而不是在背景颜色上绘制一条条纹:

    func simpleStripes(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat) {
         
        let stripeWidth: CGFloat = 20.0 // whatever you want
        let m = stripeWidth / 2.0
        
        guard let c = UIGraphicsGetCurrentContext() else { return }
        c.setLineWidth(stripeWidth)
        
        let r = CGRect(x: x, y: y, width: width, height: height)
        let longerSide = width > height ? width : height
        
        c.saveGState()
        c.clip(to: r)
            
            var p = x - longerSide
            while p <= x + width {
                
                c.setStrokeColor(pale blue)
                c.move( to: CGPoint(x: p-m, y: y-m) )
                c.addLine( to: CGPoint(x: p+m+height, y: y+m+height) )
                c.strokePath()
                
                p += stripeWidth
                
                c.setStrokeColor(pale gray)
                c.move( to: CGPoint(x: p-m, y: y-m) )
                c.addLine( to: CGPoint(x: p+m+height, y: y+m+height) )
                c.strokePath()
                
                p += stripeWidth
            }
            
        c.restoreGState()
    }
    

    【讨论】:

    • 这不适用于我的具体情况。所有的方块都不是UIViews 本身。我在充当“父级”的大UIView 中绘制了带有路径的正方形。广场没有填满大视野,周围有一些空间。您的代码将在每个正方形的边界之外绘制。这导致正方形周围的空白也被对角线覆盖。你可以修改它,只在每个正方形的边界内绘制对角线吗?
    • 嘿,你只是在小视图上设置了剪辑,@sweeper。但我有另一个版本,我将包括在内。但是,您需要对与此或其他答案一样多的工作投“赞成”任何答案。
    • 您编辑的代码有效。谢谢你。我会给你赏金,除非其他人可以在没有抗锯齿的情况下调整图像大小,因为这是最初的问题。
    • 嘿好一个@Sweeper,希望对您有所帮助。 (不幸的是,没有办法像那样抗锯齿。)顺便说一句,你会很喜欢:paintcodeapp.com 这是做这种事情的更现代的方式。干杯!
    【解决方案2】:
    extension UIImage {
    
        func ResizeImage(targetSize: CGSize) -> UIImage
        {
            let size = self.size
    
            let widthRatio  = targetSize.width  / self.size.width
            let heightRatio = targetSize.height / self.size.height
    
            // Figure out what our orientation is, and use that to form the rectangle
            var newSize: CGSize
            if(widthRatio > heightRatio) {
                newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
            } else {
                newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
            }
            // This is the rect that we've calculated out and this is what is actually used below
            let rect = CGRect(x: 0, y: 0, width: newSize.width,height: newSize.height)
    
            // Actually do the resizing to the rect using the ImageContext stuff
            UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
            self.draw(in: rect)
            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
    
            return newImage!
        }
    }
    

    【讨论】:

    • @Sweeper 可能是您将 targetSize 设置为小到您需要的图像大小
    猜你喜欢
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 2013-10-12
    • 1970-01-01
    • 2012-01-25
    • 2011-11-29
    • 1970-01-01
    • 2020-10-21
    相关资源
    最近更新 更多