package main import ( "fmt" "image" "image/color" "image/jpeg" "log" "math" "os" "path" ) // convert RGBA pixel to grayscale. BT.709 luminosity formula func grayscale(pixel color.Color) color.Color { c := color.RGBAModel.Convert(pixel).(color.RGBA) gray := uint8(0.2126*float64(c.R) + 0.7152*float64(c.G) + 0.0722*float64(c.B)) return color.RGBA{ R: gray, G: gray, B: gray, A: c.A, } } // 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 } func average(fc uint8, bc uint8, fa uint8) float64 { return (float64(fc)/2 + float64(bc)/2) } func darken(fc uint8, bc uint8, fa uint8) float64 { return math.Min(float64(fc), float64(bc)) } func lighten(fc uint8, bc uint8, fa uint8) float64 { return math.Max(float64(fc), float64(bc)) } func multiply(fc uint8, bc uint8, fa uint8) float64 { return float64(fc) * float64(bc) / 255 } // 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) case "average": newValue = average(fc, bc, fa) case "lighten": newValue = lighten(fc, bc, fa) case "multiply": newValue = multiply(fc, bc, fa) case "fuckyfun": newValue = fuckyfun(fc, bc, fa) default: newValue = darken(fc, bc, fa) } return newValue } // 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 new := color.RGBA{ R: r, G: g, B: b, A: a, } return filter(new) } // encode the image func encodeImage(imgData *image.RGBA) { outputFile := fmt.Sprintf("%s/%s", path.Clean(ConfigRegister.OutputDir), "output.jpg") out, _ := os.Create(outputFile) defer out.Close() log.Println("Encoding the new image...") jpeg.Encode(out, imgData, nil) log.Println("Done.") }