调整NSImage的大小会改变其原点并产生错误的结果

时间:2018-01-28 04:20:18

标签: swift xcode macos nsimage

我正在使用以下代码调整图像大小(保持宽高比)。当我尝试将大小为 2432X3648像素的图像调整为时1800X2700像素 输出图像原点被移位。

extension NSImage {   


  func resizeTo(width: CGFloat, height: CGFloat) -> NSImage {
    let ratioX = width / size.width
    let ratioY = height / size.height
    var ratio = ratioX < ratioY ? ratioX : ratioY
    let newHeight = size.height * ratio
    let newWidth = size.width * ratio
    let canvasSize = CGSize(width: newWidth, height: newHeight)
    let img = NSImage(size: canvasSize)
    img.lockFocus()
    let context = NSGraphicsContext.current()
    context?.imageInterpolation = .high
    draw(in: NSRect(origin: .zero, size: NSSize(width: newWidth,height: newHeight)), from: NSRect(origin: .zero, size: size) , operation: .copy, fraction: 1)
    img.unlockFocus()
    return img
    }


}

请查看调整后的样本图像。我已经标记了图像。调整大小代码似乎在其他情况下正常工作。请咨询..

enter image description here

更新: @LeoDabus我已经使用了你的代码,它产生类似的输出大小1084X2086像素的结果。我不得不稍微修改你的代码 - 只在一行,因为它不会编译。编译器自动建议它。    NSGraphicsContext.current()?. imageInterpolation = .high

 func resizeTo(width: CGFloat, height: CGFloat) -> NSImage {
        let ratioX = width / size.width
        let ratioY = height / size.height
        let ratio = ratioX < ratioY ? ratioX : ratioY
        let newHeight = size.height * ratio
        let newWidth = size.width * ratio
        let canvasSize = CGSize(width: width, height: CGFloat(ceil(width/size.width * size.height)))
        let img = NSImage(size: canvasSize)
        img.lockFocus()
        NSGraphicsContext.current()?.imageInterpolation = .high
        draw(in: NSRect(origin: CGPoint(x: (canvasSize.width - (size.width * ratio)) / 2, y: (canvasSize.height - (size.height * ratio)) / 2), size: NSSize(width: newWidth,height: newHeight)), from: NSRect(origin: .zero, size: size), operation: .copy, fraction: 1)
        img.unlockFocus()
        return img

}

1 个答案:

答案 0 :(得分:3)

实际上错误的只是画布尺寸应该使用新的宽度和高度:

<canvas id="canvas"></canvas>
<script id="vertex-shader" type="shader">
  // an attribute will receive data from a buffer
  attribute vec4 a_position;
attribute vec2 a_texcoord;
varying vec2 v_texcoord;

// all shaders have a main function
void main() {

  // gl_Position is a special variable a vertex shader
  // is responsible for setting
  gl_Position = a_position;
  v_texcoord = a_texcoord;
}
</script>
<script id="fragment-shader" type="shader">
  // fragment shaders don't have a default precision so we need
  // to pick one. mediump is a good default. It means "medium precision"
  precision mediump float;
  varying vec2 v_texcoord;
  uniform sampler2D u_texture;

  void main() {
  // gl_FragColor is a special variable a fragment shader
  // is responsible for setting
  // gl_FragColor = vec4(1, 0, 0.5, 1); // return redish-purple
  gl_FragColor = texture2D(u_texture, v_texcoord);
}
</script>