英文:
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 <color>
for an icon.
<?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>
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
我成功地通过两个技巧修复了输出。
-
如果原始像素没有100%的透明度,则不要触摸它。这样可以修复锯齿边缘。如果我不想这样做,我认为我需要实现某种类型的反锯齿。
-
使用原始像素颜色的灰度来确定混合颜色的透明度。
以下是我修改后的混合代码。
// 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.
-
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.
-
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's greyscale value to calculate
// how much of the new color to use
a1 := float64(color.GrayModel.Convert(original).(color.Gray).Y) / 255
// don't do any blending if the original pixels
// alpha isn'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 < 0.3
threshold.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论