使用 image/jpeg 编码导致图像饱和/错误像素

我遇到这个问题已经有一段时间了:我正在创建一个模块来处理图像,我的功能之一是遍历图像的每个像素并反转颜色。该函数在编码 .png 图像时返回预期结果,但它“饱和”了 .jpeg/jpg 图像。

处理 .png 图像时的示例(正确):https ://i.imgur.com/DG35RsR.png

处理 .jpeg 图像时的示例(错误):https ://i.imgur.com/DZQmxJ2.png

我正在研究并发现最接近我的问题,虽然这不是答案,但这个问题来自 Go 存储库:https ://github.com/golang/go/issues/23936

// InvertColors function


func InvertColors(img image.Image) image.Image {

    bounds := img.Bounds()

    width := bounds.Max.X

    height := bounds.Max.Y

    inverted := image.NewRGBA(bounds)


    for y := bounds.Min.Y; y < height; y++ {

        for x := bounds.Min.X; x < width; x++ {

            r, g, b, a := img.At(x, y).RGBA()

            c := color.RGBA{uint8(255 - r), uint8(255 - g), uint8(255 - b), uint8(a)}


            inverted.SetRGBA(x, y, c)

        }

    }


    return inverted

}


// main example

func main() {

    link := "https://i.imgur.com/n5hsdl4.jpg"

    img, err := GetImageFromURL(link)

    if err != nil {

        panic(err)

    }


    buf := new(bytes.Buffer)

    Encode(buf, img, "jpg")

    ioutil.WriteFile("temp.jpg", buf.Bytes(), 0666)


    invImg := InvertColors(img)

    buf = new(bytes.Buffer)

    Encode(buf, invImg, "jpg")

    ioutil.WriteFile("temp2.jpg", buf.Bytes(), 0666)

}


// GetImageFromURL 

func GetImageFromURL(link string) (image.Image, error) {

    _, format, err := ParseURL(link)

    if err != nil {

        return nil, err

    }


    req, err := http.NewRequest("GET", link, nil)

    if err != nil {

        return nil, err

    }


    // Required to make a request.

    req.Close = true

    req.Header.Set("Content-Type", "image/"+format)


    res, err := http.DefaultClient.Do(req)

    if err != nil {

        return nil, err

    }

    defer res.Body.Close()


    b, err := ioutil.ReadAll(res.Body)

    if err != nil {

        return nil, err

    }


    img, err := Decode(bytes.NewReader(b), format)

    if err != nil {

        return nil, err

    }


    return img, nil

}

HUX布斯
浏览 225回答 1
1回答

九州编程

您的代码中有两个与颜色处理相关的错误(第二个可能不相关)。首先,该RGBA()方法返回 16 位 R、G、B、A,但您将它们视为 8 位值。其次,值是 alpha 预乘的,因此) 而不是color.RGBA的倒数。这可能不相关,因为看起来您的图片没有任何重要的 alpha。(R, G, B, A)(A-R, A-G, A-B, A(MAX-R, MAX-G, MAX-B, A)修复代码的一种方法是替换它:r,&nbsp;g,&nbsp;b,&nbsp;a&nbsp;:=&nbsp;img.At(x,&nbsp;y).RGBA() c&nbsp;:=&nbsp;color.RGBA{uint8(255&nbsp;-&nbsp;r),&nbsp;uint8(255&nbsp;-&nbsp;g),&nbsp;uint8(255&nbsp;-&nbsp;b),&nbsp;uint8(a)}有了这个:r,&nbsp;g,&nbsp;b,&nbsp;a&nbsp;:=&nbsp;img.At(x,&nbsp;y).RGBA() c&nbsp;:=&nbsp;color.RGBA{uint8((a&nbsp;-&nbsp;r)>>8),&nbsp;uint8((a&nbsp;-&nbsp;g)>>8),&nbsp;uint8((a&nbsp;-&nbsp;b)>>8),&nbsp;uint8(a>>8)}(请注意,您可能会发现,首先将图像转换为image.NRGBA(如果尚未转换)然后迭代存储图像的(非 alpha 预乘)RGBA 通道的底层字节切片比使用更抽象的接口要快得多image和color包提供。)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go