Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image translucency causes blurriness on small icons #5476

Open
2 tasks done
hkparker opened this issue Jan 28, 2025 · 0 comments
Open
2 tasks done

Image translucency causes blurriness on small icons #5476

hkparker opened this issue Jan 28, 2025 · 0 comments
Labels
unverified A bug that has been reported but not verified

Comments

@hkparker
Copy link
Contributor

Checklist

  • I have searched the issue tracker for open issues that relate to the same problem, before opening a new one.
  • This issue only relates to a single bug. I will open new issues for any other problems.

Describe the bug

With small icons (png or svg), when the Translucency field is set on a canvas.Image, the image gets blurry, particularly when it has transparency already. This washes out some of the finer details of an icon.

How to reproduce

Run the example code and play with the checkboxes to see the icons in different theme variants and with and without translucency.

Interestingly, the white-on-dark icons look mostly fine, but the black-on-light ones look bad.

Screenshots

Without translucency:
Image

With translucency:
Image

Example code

package main

import (
	"image/color"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/canvas"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/theme"
	"fyne.io/fyne/v2/widget"
)

var iconSize = float32(12)

type forcedVariant struct {
	fyne.Theme

	variant fyne.ThemeVariant
}

func (f *forcedVariant) Color(name fyne.ThemeColorName, _ fyne.ThemeVariant) color.Color {
	return f.Theme.Color(name, f.variant)
}

func main() {
	demo := app.New()
	window := demo.NewWindow("Demo")
	window.SetMaster()
	window.Resize(fyne.Size{Height: 400, Width: 400})
	window.Show()

	whitePngSmooth := canvas.NewImageFromFile("read_white.png")
	whitePngSmooth.ScaleMode = canvas.ImageScaleSmooth
	whitePngSmooth.FillMode = canvas.ImageFillContain
	whitePngSmooth.SetMinSize(fyne.Size{iconSize, iconSize})

	whitePngPixel := canvas.NewImageFromFile("read_white.png")
	whitePngPixel.ScaleMode = canvas.ImageScalePixels
	whitePngPixel.FillMode = canvas.ImageFillContain
	whitePngPixel.SetMinSize(fyne.Size{iconSize, iconSize})

	whiteSvgSmooth := canvas.NewImageFromFile("read_white.svg")
	whiteSvgSmooth.ScaleMode = canvas.ImageScaleSmooth
	whiteSvgSmooth.FillMode = canvas.ImageFillContain
	whiteSvgSmooth.SetMinSize(fyne.Size{iconSize, iconSize})

	whiteSvgPixel := canvas.NewImageFromFile("read_white.svg")
	whiteSvgPixel.ScaleMode = canvas.ImageScalePixels
	whiteSvgPixel.FillMode = canvas.ImageFillContain
	whiteSvgPixel.SetMinSize(fyne.Size{iconSize, iconSize})

	blackPngSmooth := canvas.NewImageFromFile("read_black.png")
	blackPngSmooth.ScaleMode = canvas.ImageScaleSmooth
	blackPngSmooth.FillMode = canvas.ImageFillContain
	blackPngSmooth.SetMinSize(fyne.Size{iconSize, iconSize})

	blackPngPixel := canvas.NewImageFromFile("read_black.png")
	blackPngPixel.ScaleMode = canvas.ImageScalePixels
	blackPngPixel.FillMode = canvas.ImageFillContain
	blackPngPixel.SetMinSize(fyne.Size{iconSize, iconSize})

	blackSvgSmooth := canvas.NewImageFromFile("read_black.svg")
	blackSvgSmooth.ScaleMode = canvas.ImageScaleSmooth
	blackSvgSmooth.FillMode = canvas.ImageFillContain
	blackSvgSmooth.SetMinSize(fyne.Size{iconSize, iconSize})

	blackSvgPixel := canvas.NewImageFromFile("read_black.svg")
	blackSvgPixel.ScaleMode = canvas.ImageScalePixels
	blackSvgPixel.FillMode = canvas.ImageFillContain
	blackSvgPixel.SetMinSize(fyne.Size{iconSize, iconSize})

	darkSelection := widget.NewCheck("Dark Mode", func(checked bool) {
		if checked {
			demo.Settings().SetTheme(&forcedVariant{Theme: theme.DefaultTheme(), variant: theme.VariantDark})
		} else {
			demo.Settings().SetTheme(&forcedVariant{Theme: theme.DefaultTheme(), variant: theme.VariantLight})
		}
	})
	darkSelection.SetChecked(true)

	translucencySelection := widget.NewCheck("Translucency", func(checked bool) {
		if checked {
			whitePngSmooth.Translucency = 0.3
			whitePngPixel.Translucency = 0.3
			whiteSvgSmooth.Translucency = 0.3
			whiteSvgPixel.Translucency = 0.3
			blackPngSmooth.Translucency = 0.3
			blackPngPixel.Translucency = 0.3
			blackSvgSmooth.Translucency = 0.3
			blackSvgPixel.Translucency = 0.3
			whitePngSmooth.Refresh()
			whitePngPixel.Refresh()
			whiteSvgSmooth.Refresh()
			whiteSvgPixel.Refresh()
			blackPngSmooth.Refresh()
			blackPngPixel.Refresh()
			blackSvgSmooth.Refresh()
			blackSvgPixel.Refresh()
		} else {
			whitePngSmooth.Translucency = 0
			whitePngPixel.Translucency = 0
			whiteSvgSmooth.Translucency = 0
			whiteSvgPixel.Translucency = 0
			blackPngSmooth.Translucency = 0
			blackPngPixel.Translucency = 0
			blackSvgSmooth.Translucency = 0
			blackSvgPixel.Translucency = 0
			whitePngSmooth.Refresh()
			whitePngPixel.Refresh()
			whiteSvgSmooth.Refresh()
			whiteSvgPixel.Refresh()
			blackPngSmooth.Refresh()
			blackPngPixel.Refresh()
			blackSvgSmooth.Refresh()
			blackSvgPixel.Refresh()
		}
	})
	translucencySelection.SetChecked(true)

	window.SetContent(container.NewVBox(
		darkSelection,
		translucencySelection,
		container.NewHBox(
			widget.NewLabel("White PNG, ScaleSmooth"),
			whitePngSmooth,
		),
		container.NewHBox(
			widget.NewLabel("White PNG, ScalePixels"),
			whitePngPixel,
		),
		container.NewHBox(
			widget.NewLabel("White SVG, ScaleSmooth"),
			whiteSvgSmooth,
		),
		container.NewHBox(
			widget.NewLabel("White SVG, ScalePixels"),
			whiteSvgPixel,
		),
		container.NewHBox(
			widget.NewLabel("Black PNG, ScaleSmooth"),
			blackPngSmooth,
		),
		container.NewHBox(
			widget.NewLabel("Black PNG, ScalePixels"),
			blackPngPixel,
		),
		container.NewHBox(
			widget.NewLabel("Black SVG, ScaleSmooth"),
			blackSvgSmooth,
		),
		container.NewHBox(
			widget.NewLabel("Black SVG, ScalePixels"),
			blackSvgPixel,
		),
	))

	demo.Run()
}

Fyne version

2.5.3

Go compiler version

go1.23.4 linux/amd64

Operating system and version

Arch Linux

Additional Information

Required files to run the example
@hkparker hkparker added the unverified A bug that has been reported but not verified label Jan 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
unverified A bug that has been reported but not verified
Projects
None yet
Development

No branches or pull requests

1 participant