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

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

Recolour Icon like Google Earth

问题

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

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <kml xmlns="http://earth.google.com/kml/2.0">
  3. <Placemark>
  4. <name>Pin</name>
  5. <Point>
  6. <coordinates>0, 0</coordinates>
  7. </Point>
  8. <Style>
  9. <IconStyle>
  10. <color>ff8c4800</color>
  11. <scale>10</scale>
  12. <Icon>
  13. <href>http://maps.google.com/mapfiles/kml/pushpin/wht-pushpin.png</href>
  14. </Icon>
  15. </IconStyle>
  16. </Style>
  17. </Placemark>
  18. </kml>

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

  1. // blendColors使用Porter-Duff over方法
  2. // 用于合并具有alpha通道的两种颜色
  3. func blendColors(c1 color.Color, c2 color.Color) color.Color {
  4. r1, g1, b1, a1 := extractComponents(c1)
  5. r2, g2, b2, a2 := extractComponents(c2)
  6. var (
  7. a = a1 + a2*(1.0-a1)
  8. r = (r1*a1 + r2*a2*(1.0-a1)) / a
  9. g = (g1*a1 + g2*a2*(1.0-a1)) / a
  10. b = (b1*a1 + b2*a2*(1.0-a1)) / a
  11. )
  12. return color.RGBA{
  13. R: clampColorValue(int(r)),
  14. G: clampColorValue(int(g)),
  15. B: clampColorValue(int(b)),
  16. A: clampColorValue(int(a * 255)),
  17. }
  18. }

完整代码请参见此处

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

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

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

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

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

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

英文:

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

  1. &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
  2. &lt;kml xmlns=&quot;http://earth.google.com/kml/2.0&quot;&gt;
  3. &lt;Placemark&gt;
  4. &lt;name&gt;Pin&lt;/name&gt;
  5. &lt;Point&gt;
  6. &lt;coordinates&gt;0, 0&lt;/coordinates&gt;
  7. &lt;/Point&gt;
  8. &lt;Style&gt;
  9. &lt;IconStyle&gt;
  10. &lt;color&gt;ff8c4800&lt;/color&gt;
  11. &lt;scale&gt;10&lt;/scale&gt;
  12. &lt;Icon&gt;
  13. &lt;href&gt;http://maps.google.com/mapfiles/kml/pushpin/wht-pushpin.png&lt;/href&gt;
  14. &lt;/Icon&gt;
  15. &lt;/IconStyle&gt;
  16. &lt;/Style&gt;
  17. &lt;/Placemark&gt;
  18. &lt;/kml&gt;

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

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

  1. // blendColors uses the Porter-Duff over method
  2. // for combing two colors with alpha channels
  3. func blendColors(c1 color.Color, c2 color.Color) color.Color {
  4. r1, g1, b1, a1 := extractComponents(c1)
  5. r2, g2, b2, a2 := extractComponents(c2)
  6. var (
  7. a = a1 + a2*(1.0-a1)
  8. r = (r1*a1 + r2*a2*(1.0-a1)) / a
  9. g = (g1*a1 + g2*a2*(1.0-a1)) / a
  10. b = (b1*a1 + b2*a2*(1.0-a1)) / a
  11. )
  12. return color.RGBA{
  13. R: clampColorValue(int(r)),
  14. G: clampColorValue(int(g)),
  15. B: clampColorValue(int(b)),
  16. A: clampColorValue(int(a * 255)),
  17. }
  18. }

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. 使用原始像素颜色的灰度来确定混合颜色的透明度。

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

  1. // blendColors使用Porter-Duff over方法
  2. // 用于组合具有alpha通道的两种颜色
  3. func blendColors(c1 color.Color, original color.Color) color.Color {
  4. r1, g1, b1, _ := extractComponents(c1)
  5. r2, g2, b2, a2 := extractComponents(original)
  6. // 使用原始颜色的灰度值来计算
  7. // 使用新颜色的程度
  8. a1 := float64(color.GrayModel.Convert(original).(color.Gray).Y) / 255
  9. // 如果原始像素的alpha不是100%,则不进行任何混合
  10. if int(a2) == 0 {
  11. return original
  12. }
  13. var (
  14. a = a1 + a2*(1.0-a1)
  15. r = (r1*a1 + r2*a2*(1.0-a1)) / a
  16. g = (g1*a1 + g2*a2*(1.0-a1)) / a
  17. b = (b1*a1 + b2*a2*(1.0-a1)) / a
  18. )
  19. return color.RGBA{
  20. R: clampColorValue(int(r)),
  21. G: clampColorValue(int(g)),
  22. B: clampColorValue(int(b)),
  23. A: clampColorValue(int(a * 255)),
  24. }
  25. }

编辑:要求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.

  1. // blendColors uses the Porter-Duff over method
  2. // for combing two colors with alpha channels
  3. func blendColors(c1 color.Color, original color.Color) color.Color {
  4. r1, g1, b1, _ := extractComponents(c1)
  5. r2, g2, b2, a2 := extractComponents(original)
  6. // use the origial color&#39;s greyscale value to calculate
  7. // how much of the new color to use
  8. a1 := float64(color.GrayModel.Convert(original).(color.Gray).Y) / 255
  9. // don&#39;t do any blending if the original pixels
  10. // alpha isn&#39;t 100%
  11. if int(a2) == 0 {
  12. return original
  13. }
  14. var (
  15. a = a1 + a2*(1.0-a1)
  16. r = (r1*a1 + r2*a2*(1.0-a1)) / a
  17. g = (g1*a1 + g2*a2*(1.0-a1)) / a
  18. b = (b1*a1 + b2*a2*(1.0-a1)) / a
  19. )
  20. return color.RGBA{
  21. R: clampColorValue(int(r)),
  22. G: clampColorValue(int(g)),
  23. B: clampColorValue(int(b)),
  24. A: clampColorValue(int(a * 255)),
  25. }
  26. }

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

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:

确定