69 lines
2.2 KiB
Go
69 lines
2.2 KiB
Go
|
package painter
|
|||
|
|
|||
|
import (
|
|||
|
"image"
|
|||
|
_ "image/jpeg" // avoid users having to import when using image widget
|
|||
|
_ "image/png" // avoid the same for PNG images
|
|||
|
|
|||
|
"golang.org/x/image/draw"
|
|||
|
|
|||
|
"fyne.io/fyne/v2"
|
|||
|
"fyne.io/fyne/v2/canvas"
|
|||
|
)
|
|||
|
|
|||
|
// PaintImage renders a given fyne Image to a Go standard image
|
|||
|
// If a fyne.Canvas is given and the image’s fill mode is “fill original” the image’s min size has
|
|||
|
// to fit its original size. If it doesn’t, PaintImage does not paint the image but adjusts its min size.
|
|||
|
// The image will then be painted on the next frame because of the min size change.
|
|||
|
func PaintImage(img *canvas.Image, c fyne.Canvas, width, height int) image.Image {
|
|||
|
if img.Size().IsZero() && c == nil { // an image without size or canvas won't get rendered unless we setup
|
|||
|
img.Resize(fyne.NewSize(float32(width), float32(height)))
|
|||
|
}
|
|||
|
dst, err := paintImage(img, width, height)
|
|||
|
if err != nil {
|
|||
|
fyne.LogError("failed to paint image", err)
|
|||
|
}
|
|||
|
|
|||
|
return dst
|
|||
|
}
|
|||
|
|
|||
|
func paintImage(img *canvas.Image, width, height int) (dst image.Image, err error) {
|
|||
|
if width <= 0 || height <= 0 {
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
dst = img.Image
|
|||
|
if dst == nil {
|
|||
|
dst = image.NewNRGBA(image.Rect(0, 0, width, height))
|
|||
|
}
|
|||
|
|
|||
|
size := dst.Bounds().Size()
|
|||
|
if width != size.X || height != size.Y {
|
|||
|
dst = scaleImage(dst, width, height, img.ScaleMode)
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
func scaleImage(pixels image.Image, scaledW, scaledH int, scale canvas.ImageScale) image.Image {
|
|||
|
if scale == canvas.ImageScaleFastest || scale == canvas.ImageScalePixels {
|
|||
|
// do not perform software scaling
|
|||
|
return pixels
|
|||
|
}
|
|||
|
|
|||
|
bounds := pixels.Bounds()
|
|||
|
pixW := int(fyne.Min(float32(scaledW), float32(bounds.Dx()))) // don't push more pixels than we have to
|
|||
|
pixH := int(fyne.Min(float32(scaledH), float32(bounds.Dy()))) // the GL calls will scale this up on GPU.
|
|||
|
scaledBounds := image.Rect(0, 0, pixW, pixH)
|
|||
|
tex := image.NewNRGBA(scaledBounds)
|
|||
|
switch scale {
|
|||
|
case canvas.ImageScalePixels:
|
|||
|
draw.NearestNeighbor.Scale(tex, scaledBounds, pixels, bounds, draw.Over, nil)
|
|||
|
default:
|
|||
|
if scale != canvas.ImageScaleSmooth {
|
|||
|
fyne.LogError("Invalid canvas.ImageScale value, using canvas.ImageScaleSmooth", nil)
|
|||
|
}
|
|||
|
draw.CatmullRom.Scale(tex, scaledBounds, pixels, bounds, draw.Over, nil)
|
|||
|
}
|
|||
|
return tex
|
|||
|
}
|