dongzuan4917 2017-07-14 03:49
浏览 135

如何通过计算每个像素内几个点的颜色值并取平均值来减少像素化的影响?

This is an exercise from The Go Programming Language by Donovan & Kernighan:

Exercise 3.6: Supersampling is a technique to reduce the effect of pixelation by computing the color value at several points within each pixel and taking the average. The simplest method is to divide each pixel into four "subpixels". Implement it.

Here is my solution:

// Mandelbrot emits a PNG image of the Mandelbrot fractal.
package main

import (
    //"fmt"
    "image"
    "image/color"
    "image/png"
    "math/cmplx"
    "os"
)

func main() {
    const (
        xmin, ymin, xmax, ymax = -2, -2, +2, +2
        width, height = 1024, 1024
        swidth, sheight = width * 2, height * 2
    )

    var superColors [swidth][sheight]color.Color


    for py := 0; py < sheight; py++ {
        y := float64(py) / sheight * (ymax - ymin) + ymin
        for px := 0; px < swidth; px++ {
            x := float64(px) / swidth * (xmax - xmin) + xmin
            z := complex(x, y)

            superColors[px][py] = mandelbrot(z)
        }
    }

    img := image.NewRGBA(image.Rect(0, 0, width, height))
    for j := 0; j < height; j++ {
        for i := 0; i < width; i++ {
            si, sj := 2*i, 2*j

            r1, g1, b1, a1 := superColors[si][sj].RGBA()
            r2, g2, b2, a2 := superColors[si+1][sj].RGBA()
            r3, g3, b3, a3 := superColors[si+1][sj+1].RGBA()
            r4, g4, b4, a4 := superColors[si][sj+1].RGBA()

            avgColor := color.RGBA{
                uint8((r1 + r2 + r3 + r4) / 4),
                uint8((g1 + g2 + g3 + g4) / 4),
                uint8((b1 + b2 + b3 + b4) / 4),
                uint8((a1 + a2 + a3 + a4) / 4)}

            img.Set(i, j, avgColor)
        }
    }

    png.Encode(os.Stdout, img)
}

func mandelbrot(z complex128) color.Color {
    const iterations = 200
    const contrast = 15

    var v complex128

    for n := uint8(0); n < iterations; n++ {
        v = v*v + z
        if cmplx.Abs(v) > 2 {
            return color.Gray{255 - contrast*n}
        }
    }

    return color.Black
}

However, the result of my solution seems that it doesn't reduce the effect of pixelation:

enter image description here

Is my solution wrong?

  • 写回答

3条回答 默认 最新

  • douxian9010 2017-07-14 06:02
    关注

    In go, when you obtained the RGBA values through Color.RGBA(), each color component (R, G, B, A) is represented by 16-bit unsigned, thus the range is between 0-0xffff (0-65535). However, when you save the image to PNG, each component is between 0-0xff (0-255). You need to correctly scale down each color component using the following formula:

    //e.g. red component
    r := ((r1+r2+r3+r4)/4)*(255/65535) => (r1+r2+r3+r4)/1028
    

    In your case, the correct formula is:

    avgColor := color.RGBA{
        uint8((r1 + r2 + r3 + r4) / 1028),
        uint8((g1 + g2 + g3 + g4) / 1028),
        uint8((b1 + b2 + b3 + b4) / 1028),
        uint8((a1 + a2 + a3 + a4) / 1028)}
    

    UPDATE:
    Output image looks like
    Supersampled Madlebrot image

    评论

报告相同问题?