Go语言是否有打开2位色深调色板PNG图像的库?

huangapple go评论81阅读模式
英文:

Does Go have library which opens paletted png of 2 bit color-depth?

问题

如何使用Go读取基于调色板的PNG图像?

对于Python中的图像,我可以简单地执行以下操作:

from PIL import Image

im = Image.open('image.png')
pix = im.load()
for i in range(100):
    for j in range(100):
        print(pix[i, j])

在Go中可以这样做:

f, err := os.Open("image.png")
if err != nil {
    log.Fatal(err)
}
defer f.Close()

pal, ok := cfg.ColorModel.(color.Palette) // ok is true
if ok {
    for i := range pal {
        cr, cg, cb, ca := pal[i].RGBA()
        fmt.Printf("pal[%3d] = %5d,%5d,%5d,%5d\n", i, cr, cg, cb, ca)
    }
}

img, err := png.Decode(f)
if err != nil {
    log.Fatal(err) // 在这里失败!
}

for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
    for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
        log.Println("img.At(x, y):", img.At(x, y))
    }
    fmt.Print("\n")
}

在解码时会抛出"png: invalid format: not a PNG file"的错误。

如果我在Mac终端上使用file命令,它会显示:

image.png: PNG image data, 100 x 100, 2-bit colormap, non-interlaced

而VsCode可以正常显示该图像。

我尝试了从Adobe Illustrator创建的图像和从下面的代码生成的图像。两者都遇到了相同的错误:

func createPNG() {
    // 创建具有所需尺寸的新图像
    img := image.NewPaletted(image.Rect(0, 0, 100, 100), color.Palette{
        color.RGBA{255, 0, 0, 255},   // 红色
        color.RGBA{0, 255, 0, 255},   // 绿色
        color.RGBA{0, 0, 255, 255},   // 蓝色
    })

    // 在图像中设置像素颜色
    for x := 0; x < 100; x++ {
        for y := 0; y < 100; y++ {
            switch {
            case x < 50 && y < 50:
                img.SetColorIndex(x, y, 0) // 将像素(x, y)设置为红色
            case x >= 50 && y < 50:
                img.SetColorIndex(x, y, 1) // 将像素(x, y)设置为绿色
            case x < 50 && y >= 50:
                img.SetColorIndex(x, y, 2) // 将像素(x, y)设置为蓝色
            default:
                img.SetColorIndex(x, y, 3) // 将像素(x, y)设置为透明
            }
        }
    }

    // 创建一个新文件来保存PNG图像
    file, err := os.Create("image.png")
    if err != nil {
        panic(err)
    }
    defer file.Close()

    // 将图像编码为PNG并保存到文件中
    err = png.Encode(file, img)
    if err != nil {
        panic(err)
    }
}
英文:

How do you read a palette-based PNG image with Go?

For an image in Python I can simply do:

from PIL import Image

im = Image.open(&#39;image.png&#39;)
pix = im.load()
for i in range(100):
    for j in range(100):
        print(pix[i, j])

Using Go:

	f, err := os.Open(&quot;image.png&quot;)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	pal, ok := cfg.ColorModel.(color.Palette) // ok is true
	if ok {
		for i := range pal {
			cr, cg, cb, ca := pal[i].RGBA()
			fmt.Printf(&quot;pal[%3d] = %5d,%5d,%5d,%5d\n&quot;, i, cr, cg, cb, ca)
		}
	}

	img, err := png.Decode(f)
	if err != nil {
		log.Fatal(err) // Fails here!!
	}

	for y := img.Bounds().Min.Y; y &lt; img.Bounds().Max.Y; y++ {
		for x := img.Bounds().Min.X; x &lt; img.Bounds().Max.X; x++ {
			log.Println(&quot;img.At(x, y):&quot;, img.At(x, y))
		}
		fmt.Print(&quot;\n&quot;)
	}

It'll go to throws "png: invalid format: not a PNG file" when decoding.

If I use the file command on Mac shell it says:

image.png: PNG image data, 100 x 100, 2-bit colormap, non-interlaced

And VsCode render the image just fine.

I tried it both on an image created from Adobe Illustrator and one generated from the below code. Both run into the same error:

func createPNG() {
	// Create a new image with the desired dimensions
	img := image.NewPaletted(image.Rect(0, 0, 100, 100), color.Palette{
		color.RGBA{255, 0, 0, 255}, // Red
		color.RGBA{0, 255, 0, 255}, // Green
		color.RGBA{0, 0, 255, 255}, // Blue
	})

	// Set the pixel colors in the image
	for x := 0; x &lt; 100; x++ {
		for y := 0; y &lt; 100; y++ {
			switch {
			case x &lt; 50 &amp;&amp; y &lt; 50:
				img.SetColorIndex(x, y, 0) // Set the pixel at (x, y) to red
			case x &gt;= 50 &amp;&amp; y &lt; 50:
				img.SetColorIndex(x, y, 1) // Set the pixel at (x, y) to green
			case x &lt; 50 &amp;&amp; y &gt;= 50:
				img.SetColorIndex(x, y, 2) // Set the pixel at (x, y) to blue
			default:
				img.SetColorIndex(x, y, 3) // Set the pixel at (x, y) to transparent
			}
		}
	}

	// Create a new file to save the PNG image
	file, err := os.Create(&quot;image.png&quot;)
	if err != nil {
		panic(err)
	}
	defer file.Close()

	// Encode the image as a PNG and save it to the file
	err = png.Encode(file, img)
	if err != nil {
		panic(err)
	}
}

答案1

得分: 1

在你的情况下,问题似乎不是图像的格式,而是你使用图像文件的方式。

我假设你首先将其传递给image.DecodeConfig()(代码中没有显示,但cfg必须已经初始化),然后传递给image.Decode()

问题在于,在第一次调用后,你的文件具有偏移量,但第二次调用假设它从文件的开头开始读取。

你可以通过在读取配置后将文件倒回来解决这个问题:

file.Seek(0, io.SeekStart)

英文:

The problem in your case seems to be not the format of the image, but rather the way you use the image file.

I assume you first pass it to image.DecodeConfig() (the code doesn't show it but cfg must have been initialized) and later to image.Decode().

The problem is that after the first call your file has an offset but the second call assumes that it is reading from the beginning of the file.

You can solve this by rewinding the file after reading the configuration:

> file.Seek(0, io.SeekStart)

huangapple
  • 本文由 发表于 2022年12月6日 13:45:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/74697783.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定