2022-04-24 19:20:08 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"image"
|
|
|
|
"image/color"
|
|
|
|
"image/jpeg"
|
2022-05-01 09:07:46 +02:00
|
|
|
"log"
|
2022-04-24 19:20:08 +02:00
|
|
|
"math"
|
|
|
|
"os"
|
2022-05-04 10:22:02 +02:00
|
|
|
"path"
|
2022-04-24 19:20:08 +02:00
|
|
|
)
|
|
|
|
|
2022-05-01 17:49:51 +02:00
|
|
|
// convert RGBA pixel to grayscale. BT.709 luminosity formula
|
2022-04-24 19:20:08 +02:00
|
|
|
func grayscale(pixel color.Color) color.Color {
|
|
|
|
c := color.RGBAModel.Convert(pixel).(color.RGBA)
|
2022-05-01 17:49:51 +02:00
|
|
|
gray := uint8(0.2126*float64(c.R) + 0.7152*float64(c.G) + 0.0722*float64(c.B))
|
2022-04-24 19:20:08 +02:00
|
|
|
return color.RGBA{
|
|
|
|
R: gray,
|
|
|
|
G: gray,
|
|
|
|
B: gray,
|
|
|
|
A: c.A,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-01 22:20:25 +02:00
|
|
|
// sepia toning filter
|
|
|
|
func sepia(pixel color.Color) color.Color {
|
|
|
|
c := color.RGBAModel.Convert(pixel).(color.RGBA)
|
|
|
|
|
|
|
|
var npr uint8
|
|
|
|
var npg uint8
|
|
|
|
var npb uint8
|
|
|
|
|
|
|
|
tr := float64(c.R)*0.393 + float64(c.G)*0.769 + float64(c.B)*0.189
|
|
|
|
tg := float64(c.R)*0.349 + float64(c.G)*0.686 + float64(c.B)*0.168
|
|
|
|
tb := float64(c.R)*0.272 + float64(c.G)*0.534 + float64(c.B)*0.131
|
|
|
|
|
|
|
|
npr = uint8(math.Min(255, tr))
|
|
|
|
npg = uint8(math.Min(255, tg))
|
|
|
|
npb = uint8(math.Min(255, tb))
|
|
|
|
|
|
|
|
return color.RGBA{
|
|
|
|
R: npr,
|
|
|
|
G: npg,
|
|
|
|
B: npb,
|
|
|
|
A: c.A,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if a filter is specified, apply it to the pixel, if not returns it unchanged
|
|
|
|
func filter(pixel color.Color) color.Color {
|
|
|
|
if ConfigRegister.Grayscale {
|
|
|
|
return grayscale(pixel)
|
|
|
|
}
|
|
|
|
|
|
|
|
if ConfigRegister.Sepia {
|
|
|
|
return sepia(pixel)
|
|
|
|
}
|
|
|
|
return pixel
|
|
|
|
}
|
|
|
|
|
2022-05-02 13:25:50 +02:00
|
|
|
func average(fc uint8, bc uint8, fa uint8) float64 {
|
|
|
|
return (float64(fc)/2 + float64(bc)/2)
|
|
|
|
}
|
|
|
|
|
2022-04-26 13:51:49 +02:00
|
|
|
func darken(fc uint8, bc uint8, fa uint8) float64 {
|
2022-04-24 19:20:08 +02:00
|
|
|
return math.Min(float64(fc), float64(bc))
|
2022-04-26 13:51:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func lighten(fc uint8, bc uint8, fa uint8) float64 {
|
|
|
|
return math.Max(float64(fc), float64(bc))
|
|
|
|
}
|
2022-04-24 19:20:08 +02:00
|
|
|
|
2022-05-02 21:35:21 +02:00
|
|
|
func multiply(fc uint8, bc uint8, fa uint8) float64 {
|
|
|
|
return float64(fc) * float64(bc) / 255
|
|
|
|
}
|
|
|
|
|
2022-04-26 13:51:49 +02:00
|
|
|
// produce absolute garbage
|
|
|
|
func fuckyfun(fc uint8, bc uint8, fa uint8) float64 {
|
|
|
|
return float64((fc * fa) + (bc * (fa * 2)))
|
|
|
|
}
|
|
|
|
|
|
|
|
// get the blending method from the config register
|
|
|
|
func blend(fc uint8, bc uint8, fa uint8, ba uint8) float64 {
|
|
|
|
var newValue float64
|
|
|
|
switch ConfigRegister.Method {
|
|
|
|
case "darken":
|
|
|
|
newValue = darken(fc, bc, fa)
|
2022-05-02 13:25:50 +02:00
|
|
|
case "average":
|
|
|
|
newValue = average(fc, bc, fa)
|
2022-05-02 21:35:21 +02:00
|
|
|
case "lighten":
|
2022-04-26 13:51:49 +02:00
|
|
|
newValue = lighten(fc, bc, fa)
|
2022-05-02 21:35:21 +02:00
|
|
|
case "multiply":
|
|
|
|
newValue = multiply(fc, bc, fa)
|
2022-04-26 13:51:49 +02:00
|
|
|
case "fuckyfun":
|
|
|
|
newValue = fuckyfun(fc, bc, fa)
|
|
|
|
default:
|
|
|
|
newValue = darken(fc, bc, fa)
|
|
|
|
}
|
|
|
|
return newValue
|
2022-04-24 19:20:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// blend two RGBA colors/pixels and returns a new one
|
|
|
|
func blendColor(color1 color.Color, color2 color.Color) color.Color {
|
|
|
|
oc1 := color.RGBAModel.Convert(color1).(color.RGBA)
|
|
|
|
oc2 := color.RGBAModel.Convert(color2).(color.RGBA)
|
|
|
|
r := uint8(blend(oc1.R, oc2.R, oc1.A, oc2.A))
|
|
|
|
g := uint8(blend(oc1.G, oc2.G, oc1.A, oc2.A))
|
|
|
|
b := uint8(blend(oc1.B, oc2.B, oc1.A, oc2.A))
|
|
|
|
a := oc1.A + (1-oc1.A)*oc2.A
|
2022-05-01 17:49:51 +02:00
|
|
|
new := color.RGBA{
|
2022-04-24 19:20:08 +02:00
|
|
|
R: r, G: g, B: b, A: a,
|
|
|
|
}
|
2022-05-01 22:20:25 +02:00
|
|
|
return filter(new)
|
2022-04-24 19:20:08 +02:00
|
|
|
}
|
|
|
|
|
2022-05-04 09:31:21 +02:00
|
|
|
// encode the image
|
|
|
|
func encodeImage(imgData *image.RGBA) {
|
2022-05-04 10:22:02 +02:00
|
|
|
outputFile := fmt.Sprintf("%s/%s", path.Clean(ConfigRegister.OutputDir), "output.jpg")
|
2022-05-04 09:31:21 +02:00
|
|
|
out, _ := os.Create(outputFile)
|
|
|
|
defer out.Close()
|
|
|
|
log.Println("Encoding the new image...")
|
|
|
|
jpeg.Encode(out, imgData, nil)
|
|
|
|
log.Println("Done.")
|
2022-05-01 15:33:55 +02:00
|
|
|
}
|