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

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

Problem Description:

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('image.png')
pix = im.load()
for i in range(100):
    for j in range(100):
        print(pix[i, j])

Using 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,%5dn", 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 < 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")
    }

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 < 100; x++ {
        for y := 0; y < 100; y++ {
            switch {
            case x < 50 && y < 50:
                img.SetColorIndex(x, y, 0) // Set the pixel at (x, y) to red
            case x >= 50 && y < 50:
                img.SetColorIndex(x, y, 1) // Set the pixel at (x, y) to green
            case x < 50 && y >= 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("image.png")
    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)
    }
}

Solution – 1

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)

Rate this post
We use cookies in order to give you the best possible experience on our website. By continuing to use this site, you agree to our use of cookies.
Accept
Reject