重新着色图标,就像谷歌地球一样。

huangapple go评论92阅读模式
英文:

Recolour Icon like Google Earth

问题

KML允许您为图标指定一个<color>

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.0">
  <Placemark>
    <name>Pin</name>
    <Point>
      <coordinates>0, 0</coordinates>
    </Point>
    <Style>
      <IconStyle>
        <color>ff8c4800</color>
        <scale>10</scale>
        <Icon>
          <href>http://maps.google.com/mapfiles/kml/pushpin/wht-pushpin.png</href>
        </Icon>
      </IconStyle>
    </Style>
  </Placemark>
</kml>

我正在尝试使用Porter-Duff颜色混合方法在Go语言中实现相同的效果。

// blendColors使用Porter-Duff over方法
// 用于合并具有alpha通道的两种颜色
func blendColors(c1 color.Color, c2 color.Color) color.Color {
    r1, g1, b1, a1 := extractComponents(c1)
    r2, g2, b2, a2 := extractComponents(c2)
    var (
        a = a1 + a2*(1.0-a1)
        r = (r1*a1 + r2*a2*(1.0-a1)) / a
        g = (g1*a1 + g2*a2*(1.0-a1)) / a
        b = (b1*a1 + b2*a2*(1.0-a1)) / a
    )
    return color.RGBA{
        R: clampColorValue(int(r)),
        G: clampColorValue(int(g)),
        B: clampColorValue(int(b)),
        A: clampColorValue(int(a * 255)),
    }
}

完整代码请参见此处

以下是使用不同不透明度级别(从0到255)的输出示例。

  • 0 重新着色图标,就像谷歌地球一样。

  • 100 重新着色图标,就像谷歌地球一样。

  • 200 重新着色图标,就像谷歌地球一样。

  • 255 重新着色图标,就像谷歌地球一样。

这些结果不够理想(由于锯齿状边缘和褪色的黑色边框),我想知道应该采取什么方法才能获得更接近Google Earth效果的结果。

英文:

KML allows you to specify a &lt;color&gt; for an icon.

&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;kml xmlns=&quot;http://earth.google.com/kml/2.0&quot;&gt;
  &lt;Placemark&gt;
    &lt;name&gt;Pin&lt;/name&gt;
    &lt;Point&gt;
      &lt;coordinates&gt;0, 0&lt;/coordinates&gt;
    &lt;/Point&gt;
    &lt;Style&gt;
      &lt;IconStyle&gt;
        &lt;color&gt;ff8c4800&lt;/color&gt;
        &lt;scale&gt;10&lt;/scale&gt;
        &lt;Icon&gt;
          &lt;href&gt;http://maps.google.com/mapfiles/kml/pushpin/wht-pushpin.png&lt;/href&gt;
        &lt;/Icon&gt;
      &lt;/IconStyle&gt;
    &lt;/Style&gt;
  &lt;/Placemark&gt;
&lt;/kml&gt;

重新着色图标,就像谷歌地球一样。

I'm trying to do the same thing in Go using the Porter-Duff colour blending method.

	// blendColors uses the Porter-Duff over method
	// for combing two colors with alpha channels
	func blendColors(c1 color.Color, c2 color.Color) color.Color {
		r1, g1, b1, a1 := extractComponents(c1)
		r2, g2, b2, a2 := extractComponents(c2)
		var (
			a = a1 + a2*(1.0-a1)
			r = (r1*a1 + r2*a2*(1.0-a1)) / a
			g = (g1*a1 + g2*a2*(1.0-a1)) / a
			b = (b1*a1 + b2*a2*(1.0-a1)) / a
		)
		return color.RGBA{
			R: clampColorValue(int(r)),
			G: clampColorValue(int(g)),
			B: clampColorValue(int(b)),
			A: clampColorValue(int(a * 255)),
		}
	}

See full code here

Here are some output examples with different opacity levels (from 0 - 255).

  • 0 重新着色图标,就像谷歌地球一样。

  • 100 重新着色图标,就像谷歌地球一样。

  • 200 重新着色图标,就像谷歌地球一样。

  • 255 重新着色图标,就像谷歌地球一样。

These are not satisfactory (due to the jagged edges and faded black border) and I want to know what approach I should take to get results more akin to what Google Earth does.

答案1

得分: 1

我成功地通过两个技巧修复了输出。

  1. 如果原始像素没有100%的透明度,则不要触摸它。这样可以修复锯齿边缘。如果我不想这样做,我认为我需要实现某种类型的反锯齿。

  2. 使用原始像素颜色的灰度来确定混合颜色的透明度。

以下是我修改后的混合代码。

// blendColors使用Porter-Duff over方法
// 用于组合具有alpha通道的两种颜色
func blendColors(c1 color.Color, original color.Color) color.Color {
    r1, g1, b1, _ := extractComponents(c1)
    r2, g2, b2, a2 := extractComponents(original)

    // 使用原始颜色的灰度值来计算
    // 使用新颜色的程度
    a1 := float64(color.GrayModel.Convert(original).(color.Gray).Y) / 255

    // 如果原始像素的alpha不是100%,则不进行任何混合
    if int(a2) == 0 {
        return original
    }

    var (
        a = a1 + a2*(1.0-a1)
        r = (r1*a1 + r2*a2*(1.0-a1)) / a
        g = (g1*a1 + g2*a2*(1.0-a1)) / a
        b = (b1*a1 + b2*a2*(1.0-a1)) / a
    )
    return color.RGBA{
        R: clampColorValue(int(r)),
        G: clampColorValue(int(g)),
        B: clampColorValue(int(b)),
        A: clampColorValue(int(a * 255)),
    }
}

编辑:要求alpha为100%并不总是有效。我最终使用了alpha < 0.3的阈值。

重新着色图标,就像谷歌地球一样。

英文:

I managed to fix the output using two tricks.

  1. If the original pixel doesn't have 100% alpha, don't touch it. This fixes the jagged edges. If I didn't want to do this, I think I'd have to implement some type of anti-aliasing.

  2. Use the grayscale of the original pixel color to determine the alpha of the color that's being blended in.

Here's my revised blending code.

	// blendColors uses the Porter-Duff over method
	// for combing two colors with alpha channels
	func blendColors(c1 color.Color, original color.Color) color.Color {
		r1, g1, b1, _ := extractComponents(c1)
		r2, g2, b2, a2 := extractComponents(original)

		// use the origial color&#39;s greyscale value to calculate
		// how much of the new color to use
		a1 := float64(color.GrayModel.Convert(original).(color.Gray).Y) / 255

		// don&#39;t do any blending if the original pixels
		// alpha isn&#39;t 100%
		if int(a2) == 0 {
			return original
		}

		var (
			a = a1 + a2*(1.0-a1)
			r = (r1*a1 + r2*a2*(1.0-a1)) / a
			g = (g1*a1 + g2*a2*(1.0-a1)) / a
			b = (b1*a1 + b2*a2*(1.0-a1)) / a
		)
		return color.RGBA{
			R: clampColorValue(int(r)),
			G: clampColorValue(int(g)),
			B: clampColorValue(int(b)),
			A: clampColorValue(int(a * 255)),
		}
	}

重新着色图标,就像谷歌地球一样。

edit: Requiring alpha to be 100% doesn't work well all the time. I ended up using a alpha &lt; 0.3 threshold.

huangapple
  • 本文由 发表于 2016年2月12日 05:45:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/35350677.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定