Efficiently convert RBGA image to RGB byte array

WBOY
Release: 2024-02-05 22:51:12
forward
1094 people have browsed it

Efficiently convert RBGA image to RGB byte array

Question content

I have a c library and function that requires a pointer to a byte array containing a 24-bit bitmap in rgb format. The alpha channel is not important and can be truncated. I've tried something like this:

func load(filePath string) *image.RGBA {
    imgFile, err := os.Open(filePath)
    if err != nil {
        fmt.Printf("Cannot read file %v\n", err)
    }
    defer imgFile.Close()

    img, _, err := image.Decode(imgFile)
    if err != nil {
        fmt.Printf("Cannot decode file %v\n", err)
    }
    return img.(*image.RGBA)
}

    img := load("myimg.png")

    bounds := img.Bounds()
    width, height := bounds.Max.X, bounds.Max.Y

    // Convert to RGB? Probably not...
    newImg := image.NewNRGBA(image.Rect(0, 0, width, height))
    draw.Draw(newImg, newImg.Bounds(), img, bounds.Min, draw.Src)
    // Pass image pointer to C function.
    C.PaintOnImage(unsafe.Pointer(&newImg.Pix[0]), C.int(newImg.Bounds().Dy()), C.int(newImg.Bounds().Dx())
Copy after login

However, nrgba also seems to be built on 4 bytes per pixel. I could solve this problem by using gocv, but this seems like overkill for such a simple task. Is there a way to do this in go in a simple and efficient way?


Correct answer


There is no rgb image type in the standard library, but you can assemble an rgb array very easily:

bounds := img.bounds()
rgb := make([]byte, bounds.dx()*bounds.dy()*3)
idx := 0
for y := bounds.min.y; y < bounds.max.y; y++ {
    for x := bounds.min.x; x < bounds.max.x; x++ {
        offs := img.pixoffset(x, y)
        copy(rgb[idx:], img.pix[offs:offs+3])
        idx += 3
    }
}
Copy after login

img.pix Data holds 4-byte rgba value. The above code just copies the first 3 bytes rgb value of all pixels.

Since the rows in the pix array are contiguous, the above code can be improved by calling pixoffset only once per row, and advancing each pixel by 4 bytes. Also, manually copying 3 bytes may be faster than calling copy() (baseline if that matters to you):

bounds := img.Bounds()
rgb := make([]byte, bounds.Dx()*bounds.Dy()*3)
idx := 0

for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
    offs := img.PixOffset(bounds.Min.X, y)
    for x := bounds.Min.X; x < bounds.Max.X; x++ {
        rgb[idx+0] = img.Pix[offs+0]
        rgb[idx+1] = img.Pix[offs+1]
        rgb[idx+2] = img.Pix[offs+2]
        idx += 3
        offs += 4
    }
}
Copy after login

The above is the detailed content of Efficiently convert RBGA image to RGB byte array. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template