- 移除固定的明暗阈值等级数组,改用动态分档机制 - 引入 neutralMargin 常量,当两分差幅小于 0.15 时视为中性图 - 修改 BrightnessName 函数,实现三分法分类:bright_N、dark_N、mid - 新增 brightnessTier 辅助函数,将占比分档到最接近的 10% - 完全透明的像素(alpha=0)不再参与明暗统计计算 - 更新错误提示信息,明暗分析失败时按中性 mid 归类 - 调整 README 文档描述,同步更新明暗分类规则说明
72 lines
1.7 KiB
Go
72 lines
1.7 KiB
Go
package probe
|
|
|
|
import (
|
|
"image"
|
|
"math"
|
|
"os"
|
|
|
|
_ "image/gif"
|
|
_ "image/jpeg"
|
|
_ "image/png"
|
|
|
|
_ "golang.org/x/image/bmp"
|
|
_ "golang.org/x/image/tiff"
|
|
_ "golang.org/x/image/webp"
|
|
)
|
|
|
|
// AnalyzeBrightness 打开并解码图片,分析明暗程度。
|
|
// darkScore: 暗色像素(亮度 < 80)占比;lightScore: 亮色像素(亮度 > 175)占比。
|
|
func AnalyzeBrightness(filePath string) (darkScore float64, lightScore float64, err error) {
|
|
f, err := os.Open(filePath)
|
|
if err != nil {
|
|
return 0, 0, err
|
|
}
|
|
defer f.Close()
|
|
img, _, err := image.Decode(f)
|
|
if err != nil {
|
|
return 0, 0, err
|
|
}
|
|
dark, light := analyzeBrightness(img)
|
|
return dark, light, nil
|
|
}
|
|
|
|
// analyzeBrightness 统计暗色/亮色像素占比(ITU-R BT.601 亮度公式),大图自动采样加速。
|
|
// 完全透明的像素(alpha=0)不计入统计。
|
|
func analyzeBrightness(img image.Image) (darkScore float64, lightScore float64) {
|
|
bounds := img.Bounds()
|
|
totalPixels := bounds.Dx() * bounds.Dy()
|
|
if totalPixels == 0 {
|
|
return 0, 0
|
|
}
|
|
|
|
darkCount, lightCount, sampleCount := 0, 0, 0
|
|
sampleStep := 1
|
|
if totalPixels > 1_000_000 {
|
|
sampleStep = int(math.Sqrt(float64(totalPixels) / 100_000))
|
|
}
|
|
|
|
for y := bounds.Min.Y; y < bounds.Max.Y; y += sampleStep {
|
|
for x := bounds.Min.X; x < bounds.Max.X; x += sampleStep {
|
|
r, g, b, a := img.At(x, y).RGBA()
|
|
if a == 0 {
|
|
continue
|
|
}
|
|
r8 := uint8(r >> 8)
|
|
g8 := uint8(g >> 8)
|
|
b8 := uint8(b >> 8)
|
|
brightness := 0.299*float64(r8) + 0.587*float64(g8) + 0.114*float64(b8)
|
|
if brightness < 80 {
|
|
darkCount++
|
|
} else if brightness > 175 {
|
|
lightCount++
|
|
}
|
|
sampleCount++
|
|
}
|
|
}
|
|
|
|
if sampleCount == 0 {
|
|
return 0, 0
|
|
}
|
|
return float64(darkCount) / float64(sampleCount), float64(lightCount) / float64(sampleCount)
|
|
}
|