Home  >  Article  >  Backend Development  >  Efficiently convert RBGA image to RGB byte array

Efficiently convert RBGA image to RGB byte array

WBOY
WBOYforward
2024-02-05 22:51:121093browse

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())

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
    }
}

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
    }
}

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!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete