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?
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!