Disabled image quality patch

This commit is contained in:
Eduard Urbach 2018-04-26 20:20:41 +02:00
parent 1f0adabde2
commit 4f6078943c

View File

@ -1,287 +1,289 @@
package main
import (
"bytes"
"fmt"
"image"
"image/color"
_ "image/jpeg"
"image/png"
"io/ioutil"
"os"
)
func main() {}
func main() {
data, err := ioutil.ReadFile("input.jpg")
// import (
// "bytes"
// "fmt"
// "image"
// "image/color"
// _ "image/jpeg"
// "image/png"
// "io/ioutil"
// "os"
// )
if err != nil {
panic(err)
}
// func main() {
// data, err := ioutil.ReadFile("input.jpg")
img, _, err := image.Decode(bytes.NewReader(data))
// if err != nil {
// panic(err)
// }
if err != nil {
panic(err)
}
// img, _, err := image.Decode(bytes.NewReader(data))
improved := ImproveQuality(img)
f, err := os.Create("output.png")
// if err != nil {
// panic(err)
// }
if err != nil {
panic(err)
}
// improved := ImproveQuality(img)
// f, err := os.Create("output.png")
defer f.Close()
png.Encode(f, improved)
}
// if err != nil {
// panic(err)
// }
// Pixel ...
type Pixel struct {
X int
Y int
}
// defer f.Close()
// png.Encode(f, improved)
// }
// Area ...
type Area struct {
Pixels []Pixel
totalR uint64
totalG uint64
totalB uint64
totalA uint64
}
// // Pixel ...
// type Pixel struct {
// X int
// Y int
// }
// Add ...
func (area *Area) Add(x, y int, r, g, b, a uint32) {
area.Pixels = append(area.Pixels, Pixel{
X: x,
Y: y,
})
// // Area ...
// type Area struct {
// Pixels []Pixel
// totalR uint64
// totalG uint64
// totalB uint64
// totalA uint64
// }
area.totalR += uint64(r)
area.totalG += uint64(g)
area.totalB += uint64(b)
area.totalA += uint64(a)
}
// // Add ...
// func (area *Area) Add(x, y int, r, g, b, a uint32) {
// area.Pixels = append(area.Pixels, Pixel{
// X: x,
// Y: y,
// })
// AverageColor ...
func (area *Area) AverageColor() color.Color {
if len(area.Pixels) == 0 {
return color.Transparent
}
// area.totalR += uint64(r)
// area.totalG += uint64(g)
// area.totalB += uint64(b)
// area.totalA += uint64(a)
// }
return color.RGBA64{
R: uint16(area.totalR / uint64(len(area.Pixels))),
G: uint16(area.totalG / uint64(len(area.Pixels))),
B: uint16(area.totalB / uint64(len(area.Pixels))),
A: uint16(area.totalA / uint64(len(area.Pixels))),
}
}
// // AverageColor ...
// func (area *Area) AverageColor() color.Color {
// if len(area.Pixels) == 0 {
// return color.Transparent
// }
const (
tolerance = uint32(3000)
)
// return color.RGBA64{
// R: uint16(area.totalR / uint64(len(area.Pixels))),
// G: uint16(area.totalG / uint64(len(area.Pixels))),
// B: uint16(area.totalB / uint64(len(area.Pixels))),
// A: uint16(area.totalA / uint64(len(area.Pixels))),
// }
// }
func diffAbs(a uint32, b uint32) uint32 {
if a > b {
return a - b
}
// const (
// tolerance = uint32(3000)
// )
return b - a
}
// func diffAbs(a uint32, b uint32) uint32 {
// if a > b {
// return a - b
// }
// ImproveQuality returns the average color of an image in HSL format.
func ImproveQuality(img image.Image) *image.NRGBA {
width := img.Bounds().Dx()
height := img.Bounds().Dy()
clone := image.NewNRGBA(image.Rect(0, 0, width, height))
areas := []*Area{}
areaIndexMap := make([]int, width*height)
// return b - a
// }
for x := 0; x < width; x++ {
for y := 0; y < height; y++ {
color := img.At(x, y)
r, g, b, a := color.RGBA()
areaIndex := -1
// // ImproveQuality returns the average color of an image in HSL format.
// func ImproveQuality(img image.Image) *image.NRGBA {
// width := img.Bounds().Dx()
// height := img.Bounds().Dy()
// clone := image.NewNRGBA(image.Rect(0, 0, width, height))
// areas := []*Area{}
// areaIndexMap := make([]int, width*height)
// Find similar area
for i := 0; i < len(areas); i++ {
area := areas[i]
avgR, avgG, avgB, _ := area.AverageColor().RGBA()
// for x := 0; x < width; x++ {
// for y := 0; y < height; y++ {
// color := img.At(x, y)
// r, g, b, a := color.RGBA()
// areaIndex := -1
// Is the color similar?
if diffAbs(r, avgR) <= tolerance && diffAbs(g, avgG) <= tolerance && diffAbs(b, avgB) <= tolerance {
areaIndex = i
break
}
}
// // Find similar area
// for i := 0; i < len(areas); i++ {
// area := areas[i]
// avgR, avgG, avgB, _ := area.AverageColor().RGBA()
// Insert new area
if areaIndex == -1 {
areaIndex = len(areas)
areas = append(areas, &Area{})
}
// // Is the color similar?
// if diffAbs(r, avgR) <= tolerance && diffAbs(g, avgG) <= tolerance && diffAbs(b, avgB) <= tolerance {
// areaIndex = i
// break
// }
// }
areaIndexMap[y*width+x] = areaIndex
areas[areaIndex].Add(x, y, r, g, b, a)
}
}
// // Insert new area
// if areaIndex == -1 {
// areaIndex = len(areas)
// areas = append(areas, &Area{})
// }
fmt.Println(len(areas), "areas")
// areaIndexMap[y*width+x] = areaIndex
// areas[areaIndex].Add(x, y, r, g, b, a)
// }
// }
// Reduce noise
noiseCount := 0
// fmt.Println(len(areas), "areas")
for areaIndex, area := range areas {
noisePixelIndices := []int{}
areaSurroundedBy := map[int]int{}
// // Reduce noise
// noiseCount := 0
for i := 0; i < len(area.Pixels); i++ {
// If pixel is surrounded by 4 different areas, remove it
pixel := area.Pixels[i]
x := pixel.X
y := pixel.Y
left := areaIndex
right := areaIndex
top := areaIndex
bottom := areaIndex
// for areaIndex, area := range areas {
// noisePixelIndices := []int{}
// areaSurroundedBy := map[int]int{}
if x > 0 {
left = areaIndexMap[y*width+(x-1)]
}
// for i := 0; i < len(area.Pixels); i++ {
// // If pixel is surrounded by 4 different areas, remove it
// pixel := area.Pixels[i]
// x := pixel.X
// y := pixel.Y
// left := areaIndex
// right := areaIndex
// top := areaIndex
// bottom := areaIndex
if x < width-1 {
right = areaIndexMap[y*width+(x+1)]
}
// if x > 0 {
// left = areaIndexMap[y*width+(x-1)]
// }
if y > 0 {
top = areaIndexMap[(y-1)*width+x]
}
// if x < width-1 {
// right = areaIndexMap[y*width+(x+1)]
// }
if y < height-1 {
bottom = areaIndexMap[(y+1)*width+x]
}
// if y > 0 {
// top = areaIndexMap[(y-1)*width+x]
// }
differentNeighbors := 0
// if y < height-1 {
// bottom = areaIndexMap[(y+1)*width+x]
// }
if left != areaIndex {
differentNeighbors++
}
// differentNeighbors := 0
if right != areaIndex {
differentNeighbors++
}
// if left != areaIndex {
// differentNeighbors++
// }
if top != areaIndex {
differentNeighbors++
}
// if right != areaIndex {
// differentNeighbors++
// }
if bottom != areaIndex {
differentNeighbors++
}
// if top != areaIndex {
// differentNeighbors++
// }
// Determine surrounding area
areaIndexScore := map[int]int{}
// if bottom != areaIndex {
// differentNeighbors++
// }
areaIndexScore[left]++
areaIndexScore[right]++
areaIndexScore[top]++
areaIndexScore[bottom]++
// // Determine surrounding area
// areaIndexScore := map[int]int{}
areaSurroundedBy[left]++
areaSurroundedBy[right]++
areaSurroundedBy[top]++
areaSurroundedBy[bottom]++
// areaIndexScore[left]++
// areaIndexScore[right]++
// areaIndexScore[top]++
// areaIndexScore[bottom]++
newAreaIndex := -1
bestScore := 0
// areaSurroundedBy[left]++
// areaSurroundedBy[right]++
// areaSurroundedBy[top]++
// areaSurroundedBy[bottom]++
for checkIndex, score := range areaIndexScore {
if score > bestScore {
bestScore = score
newAreaIndex = checkIndex
}
}
// newAreaIndex := -1
// bestScore := 0
if differentNeighbors >= 3 && bestScore >= 3 {
noiseCount++
noisePixelIndices = append(noisePixelIndices, i)
// for checkIndex, score := range areaIndexScore {
// if score > bestScore {
// bestScore = score
// newAreaIndex = checkIndex
// }
// }
// Add to surrounding area
r, g, b, a := img.At(x, y).RGBA()
areas[newAreaIndex].Add(x, y, r, g, b, a)
// if differentNeighbors >= 3 && bestScore >= 3 {
// noiseCount++
// noisePixelIndices = append(noisePixelIndices, i)
area.totalR -= uint64(r)
area.totalG -= uint64(g)
area.totalB -= uint64(b)
area.totalA -= uint64(a)
}
}
// // Add to surrounding area
// r, g, b, a := img.At(x, y).RGBA()
// areas[newAreaIndex].Add(x, y, r, g, b, a)
// Remove noise pixels
offset := 0
// area.totalR -= uint64(r)
// area.totalG -= uint64(g)
// area.totalB -= uint64(b)
// area.totalA -= uint64(a)
// }
// }
for _, removal := range noisePixelIndices {
index := removal - offset
area.Pixels = append(area.Pixels[:index], area.Pixels[index+1:]...)
offset++
}
// // Remove noise pixels
// offset := 0
// // Determine surrounding area
// surroundingAreaIndex := -1
// bestScore := 0
// for _, removal := range noisePixelIndices {
// index := removal - offset
// area.Pixels = append(area.Pixels[:index], area.Pixels[index+1:]...)
// offset++
// }
// for checkIndex, score := range areaSurroundedBy {
// if score > bestScore && checkIndex != areaIndex {
// bestScore = score
// surroundingAreaIndex = checkIndex
// }
// }
// // // Determine surrounding area
// // surroundingAreaIndex := -1
// // bestScore := 0
// surroundingArea := areas[surroundingAreaIndex]
// // for checkIndex, score := range areaSurroundedBy {
// // if score > bestScore && checkIndex != areaIndex {
// // bestScore = score
// // surroundingAreaIndex = checkIndex
// // }
// // }
// if areaIndex != surroundingAreaIndex && len(surroundingArea.Pixels) > len(area.Pixels)*2 {
// // const surroundTolerance = 5000
// // surroundingArea := areas[surroundingAreaIndex]
// // r1, g1, b1, a1 := area.AverageColor().RGBA()
// // r2, g2, b2, a2 := surroundingArea.AverageColor().RGBA()
// // if areaIndex != surroundingAreaIndex && len(surroundingArea.Pixels) > len(area.Pixels)*2 {
// // // const surroundTolerance = 5000
// // if diffAbs(r1, r2) < surroundTolerance && diffAbs(g1, g2) < surroundTolerance && diffAbs(b1, b2) < surroundTolerance && diffAbs(a1, a2) < surroundTolerance {
// // // fmt.Println(areaIndex, "surrounded by", surroundingAreaIndex, "|", len(area.Pixels), len(surroundingArea.Pixels))
// // // r1, g1, b1, a1 := area.AverageColor().RGBA()
// // // r2, g2, b2, a2 := surroundingArea.AverageColor().RGBA()
// // // Add pixels to surrounding area
// // for _, pixel := range area.Pixels {
// // r, g, b, a := img.At(pixel.X, pixel.Y).RGBA()
// // surroundingArea.Add(pixel.X, pixel.Y, r, g, b, a)
// // }
// // // if diffAbs(r1, r2) < surroundTolerance && diffAbs(g1, g2) < surroundTolerance && diffAbs(b1, b2) < surroundTolerance && diffAbs(a1, a2) < surroundTolerance {
// // // // fmt.Println(areaIndex, "surrounded by", surroundingAreaIndex, "|", len(area.Pixels), len(surroundingArea.Pixels))
// // // Remove this area
// // area.Pixels = nil
// // area.totalR = 0
// // area.totalG = 0
// // area.totalB = 0
// // area.totalA = 0
// // }
// }
}
// // // // Add pixels to surrounding area
// // // for _, pixel := range area.Pixels {
// // // r, g, b, a := img.At(pixel.X, pixel.Y).RGBA()
// // // surroundingArea.Add(pixel.X, pixel.Y, r, g, b, a)
// // // }
fmt.Println(noiseCount, "noise pixels")
// // // // Remove this area
// // // area.Pixels = nil
// // // area.totalR = 0
// // // area.totalG = 0
// // // area.totalB = 0
// // // area.totalA = 0
// // // }
// // }
// }
pixelCount := 0
// fmt.Println(noiseCount, "noise pixels")
for _, area := range areas {
pixelCount += len(area.Pixels)
}
// pixelCount := 0
fmt.Println(pixelCount, "pixels", width*height)
// for _, area := range areas {
// pixelCount += len(area.Pixels)
// }
// Build image from areas
for _, area := range areas {
avgColor := area.AverageColor()
// fmt.Println(pixelCount, "pixels", width*height)
for _, pixel := range area.Pixels {
clone.Set(pixel.X, pixel.Y, avgColor)
}
}
// // Build image from areas
// for _, area := range areas {
// avgColor := area.AverageColor()
return clone
}
// for _, pixel := range area.Pixels {
// clone.Set(pixel.X, pixel.Y, avgColor)
// }
// }
// return clone
// }