获取 RMagick/ImageMagick 文本引力

Getting RMagick/ImageMagick gravity with text

这里是Ruby代码:

require 'rmagick'

include Magick

img = Image.new(300, 300)
draw = Draw.new

draw.line(0, 150, 300, 150)
draw.line(150, 0, 150, 300)

# for each of known gravity constants...
%w[NorthWestGravity NorthGravity NorthEastGravity WestGravity CenterGravity EastGravity SouthWestGravity SouthGravity SouthEastGravity].
each{|g|
  # set gravity to this value...
  draw.gravity Magick.const_get(g)
  # ...and draw text with this constant name
  draw.text 150, 150, g
}

draw.draw(img)

img.write('tmp/gravity.png')

这是它生成的图像:

对于 SouthEast/NorthWest 和类似的重力结果符合预期(文本接近 150,150,向所需方向移动)。但是对于南方,北方和其他人来说,结果真的很奇怪。

据我从代码中了解到,RMagick 只是将引力和文本命令转换为相应的 ImageMagick 绘图基元,因此,我想这是我无法理解的 ImageMagick 引力概念中的某些内容。

这是什么?

I suppose its something in ImageMagick's gravity concept that I can't get.

What is it?..

了解发生了什么的关键是找到 CenterGravity 文本。

向左移动 150px,向下移动 150px

现在比较NorthWestGravity位置。

也分别向左和向下翻译 150px。看到趋势了吗?

您的问题与此行有关...

draw.text 150, 150, g

Magick::Draw API 映射到 MVG 规范。使用 Magick::Draw.push & Magick::Draw.pop 控制绘图上下文。

根据评论编辑...

要设置要绘制的文本的 origin,您需要在评估 text/type 指标后计算位置。

示例。

require 'rmagick'

include Magick

img = Image.new(300, 300) {
  self.background_color = "palegreen"
}
draw = Draw.new
dotes = Draw.new # Dotes added for point of origin
dotes.fill = "red"

cursor = 1
# for each of known gravity constants...
%w[NorthWestGravity NorthGravity NorthEastGravity WestGravity CenterGravity EastGravity SouthWestGravity SouthGravity SouthEastGravity].
each{|g|
  offsetX = 150
  offsetY = cursor * 25
  dotes.circle offsetX, offsetY, offsetX+2, offsetY+2
  # Get metrics of text
  metrics = draw.get_type_metrics(img, g)
  # Full width
  if %w[NorthWestGravity WestGravity SouthWestGravity].include? g then
    offsetX -= metrics[:width]
  end
  # Full height
  if %w[SouthWestGravity SouthGravity SouthEastGravity].include? g then
    offsetY += metrics[:ascent]
  end
  # Half width
  if %w[NorthGravity SouthGravity CenterGravity].include? g then
    offsetX -= metrics[:width] / 2
  end
  # Half height
  if %w[WestGravity CenterGravity EastGravity].include? g then
    offsetY += metrics[:ascent] / 2
  end
  draw.text offsetX, offsetY, g
  cursor += 1
}
dotes.draw(img)
draw.draw(img)

img.write('output.png')