【问题标题】:How to set border color to the edge pixel in ImageMagick如何在 ImageMagick 中为边缘像素设置边框颜色
【发布时间】:2015-11-24 03:03:20
【问题描述】:

为了防止在我选择的图形引擎中缩放精灵或在不完整的像素上显示它们时出现伪影,我需要检查所有精灵并为每个精灵添加边缘。边缘需要是相邻像素的颜色,就像这样:

左图为原图,右图为预期结果。

在ImageMagick中可以实现这个效果吗?也就是说,你能不能把图片在四个方向都扩大一个像素,把边缘像素复制到新添加的边框里?

【问题讨论】:

    标签: imagemagick


    【解决方案1】:

    首先,您应该了解以下基本图像操作,它们将作为完整命令的构建块:

    1. image.ext[NxM+x+y] 将从 image.ext 中切出一个NxM 像素大小的区域,该区域向右偏移+x 像素,向底部偏移+y 像素,从左上角计算角落。
    2. +append 附加两个(或更多)图像水平
    3. -append 附加两个(或更多)图像垂直
    4. image.ext[1x+0+0] 切断图像中最左侧的像素列。
    5. -flop 将从左到右镜像图像。
    6. -flip 将从上到下镜像图像。
    7. image.ext[x1+0+0] 截取图像中最顶部的一行像素。
    8. image.ext[1x+0+0] 截取图像中最左侧的像素列。
    9. -crop NxM+x+y1. 的作用相同。
    10. mpr:ABC 将使用标签 ABC 将图像写入 Magick Persistent Registry。从位于特殊内存位置的 MPR 中,ImageMagick 只需调用标签名称即可检索图像的副本。
    11. -delete 0 将从当前图像序列中删除索引为 0 的图像。
    12. +write 将在给定的名称下写入图像序列。
    13. +repage 再次规范化图像画布。

    现在您可以将5.8. 组合起来以切掉最右侧的像素行:

    -flop image.ext[1x+0+0]
    

    您还可以将6.7. 组合起来以切掉最底部的像素列:

    -flip image.ext[x1+0+0]
    

    现在将这些效果与 括号 语法 \( ... \) 结合起来,以对完整命令的图像进行侧面处理:

    convert image.png                     \
      -respect-parentheses                \
      +write mpr:ABC                      \
      -delete 0                           \
        \( mpr:ABC[1x+0+0] \)             \
        \( mpr:ABC \)                     \
        \( mpr:ABC -flop -crop 1x+0+0 \)  \
      +append +repage                     \
      +write mpr:XYZ                      \
      -delete 0                           \
        \( mpr:XYZ[x1+0+0] \)             \
        \( mpr:XYZ \)                     \
        \( mpr:XYZ -flip -crop x1+0+0 \)  \
      -append +repage                     \
      extended-edges.png
    

    将此应用于内置的rose: 图像:

    convert rose:                         \
      -respect-parentheses                \
      +write mpr:ABC                      \
      -delete 0                           \
        \( mpr:ABC[1x+0+0] \)             \
        \( mpr:ABC \)                     \
        \( mpr:ABC -flop -crop 1x+0+0 \)  \
      +append +repage                     \
      +write mpr:XYZ                      \
      -delete 0                           \
        \( mpr:XYZ[x1+0+0] \)             \
        \( mpr:XYZ \)                     \
        \( mpr:XYZ -flip -crop x1+0+0 \)  \
      -append +repage                     \
      extend.png
    

    快速检查新图片的大小

    identify rose: extend.png 
     rose:=>ROSE   PPM 70x46 70x46+0+0 8-bit sRGB 9.67KB 0.000u 0:00.000
     extend.png[1] PNG 72x48 72x48+0+0 8-bit sRGB 7.11KB 0.000u 0:00.000
    

    检查前两行像素是否相同

    最顶行:

    convert extend.png[x1+0+0] txt:- | md5sum
     12b639cd1606559633ee23a062ae42a6  -
    

    倒数第二行:

    convert extend.png[x1+0+1] txt:- | md5sum
     12b639cd1606559633ee23a062ae42a6  -
    

    倒数第三行:

    convert extend.png[x1+0+2] txt:- | md5sum
     88fc6f9bac3f8ab4cbf2374fbef6fcf0  -
    

    检查最左边的两列是否相同

    最左列:

    convert extend.png[1x+0+0] txt:- | md5sum
     4d2223b74901f9ce1fb4456dacb4315c  -
    

    左起第二列:

    convert extend.png[1x+1+0] txt:- | md5sum
     4d2223b74901f9ce1fb4456dacb4315c  -
    

    左起第三列:

    convert extend.png[1x+2+0] txt:- | md5sum
     07794b4423f5b6515142d15a5c652743  -
    

    我没有展示如何检查两个最底部的行和两个最右边的列是否也相同...


    还有一种方法可以通过-virtual-pixel edge操作达到同样的效果,但是比较难理解……

    【讨论】:

    • 哇...这太棒了!我会试着在一分钟内试一试。由于我只需要将边缘增加一个像素,我想通过先在四个角上绘制原始图像,然后在四个边缘的中心,最后在中心,但我只能做最多基本的 imagemagick 操作。
    • @MaurycyZarzycki:然后呢?你试过了吗?
    • 警告:[1x+0+0]-thing(代码中第 5 行使用的第 4 点)总是为我生成 1x3px 的图像。通过使用 -crop 1x+0+0 来解决问题,因为它可以按预期工作。 [x1+0+0] 似乎工作正常。我正在运行 ImageMagick 6.9.7-4。
    【解决方案2】:

    我认为解决此问题的最简单方法是将原始图像的大小调整为比原始图像高 2 个像素和宽 2 个像素,然后为避免内部像素失真,将未更改的原始图像重新合成到中心。

    所以,要获得输出图像的尺寸,通过将宽度和高度加 2,

    geom=$(identify -format "%[fx:w+2]x%[fx:h+2]" sprite.png)
    

    给出类似的东西

    34x34
    

    如果原始图像是 32x32。

    然后我将图像调整为这个新大小以填充边框像素并将未更改的原始图像重新合成到顶部

    convert sprite.png -resize $geom -gravity center sprite.png -composite out.png
    

    【讨论】:

    • 我不太确定这个算法是否能够可靠地产生想要的结果。在大多数情况下,它很可能“足够好”,并且人眼不容易发现偏差,但是......
    • @KurtPfeifle 嗨,库尔特。你能解释一下你的恐惧吗?我假设您承认内部像素将与我的方法完美,因为它们是原始图像的直接副本,因此您担心的只是 1 像素边缘。我考虑调整一个非常可靠操作的大小,所以你能详细说明你的想法吗?谢谢。
    • @MarkSetchell 我可以看到一个真正的问题和一个潜力。真正的问题是,如果您试图使边缘超过 1 瓦宽(在大多数情况下,不需要这样做)。并且潜在地,如果缩放使用平滑,相邻的瓦片可能会影响目标边缘的颜色,并且可能会产生一些不同的颜色。但只需禁用平滑即可使其正常工作。
    • 我在问题中没有看到任何关于任何相邻图块的信息,也没有看到扩展超过一个像素的可能性......但我希望该方法能很好地满足您的需求.祝你好运!
    • @MarkSetchell:当然,内部像素将与您的方法完美结合。我只是怀疑边框像素是否会被“克隆”为 1:1 副本。 -resize 运算符隐式应用 -filter lanczos(如果未另外设置),它将在计算附加像素的颜色值时应用一些数学。 ——我仍然需要找时间提出一个明显偏差的例子。但我当然承认,无论如何,您的方法都将是一个非常好的近似值。黑色边框像素不会突然变白:-)
    【解决方案3】:

    使用虚拟像素:

    convert -resize "%[fx:w+4]x%[fx:h+4]" "./input.png" -set option:distort:viewport "%[fx:w+4]x%[fx:h+4]"-2-2 -virtual-pixel Edge -distort SRT 0 +repage ./output.png
    

    input.png 是输入图像。 output.png 将使用原始边缘的颜色将其边框扩展 2 个像素。通过添加两倍的扩展宽度来调整图像的大小。视口偏移设置为扩展宽度。

    更多信息请参见this page

    【讨论】:

      猜你喜欢
      • 2013-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-13
      • 2013-06-03
      • 2011-02-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多