我正在尝试将高斯模糊应用于具有透明度的 PIL.Image,但模糊似乎不适用于 alpha 通道。
这是我的代码:
import wx
from PIL import Image, ImageFilter
import io
class HaloButton(wx.Button):
def __init__(self, parent, image, id=wx.ID_ANY, label='', pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, validator=wx.DefaultValidator, name=wx.ButtonNameStr):
super().__init__(parent, id, label, pos, size, style, validator, name)
self._image = image.copy()
self.Bind(wx.EVT_PAINT, self._OnPaint)
def _OnPaint(self, event):
dc = wx.PaintDC(self)
dc.Clear()
pil_image = self._image.copy()
blurred_image = pil_image.filter(ImageFilter.GaussianBlur(radius=15))
bitmap = wx.Bitmap.FromBufferRGBA(blurred_image.size[0], blurred_image.size[1], blurred_image.tobytes())
dc.DrawBitmap(bitmap, 0, 0)
if __name__ == '__main__':
app = wx.App()
frame = wx.Frame(parent=None, title='Halo Button Example', size=(400, 400), style=wx.DEFAULT_FRAME_STYLE)
frame.SetBackgroundColour((255, 192, 203)) # Rose
panel = wx.Panel(frame, size=(400, 400), style=wx.SUNKEN_BORDER)
pil_image = Image.open("image.png")
button = HaloButton(panel, pil_image, size=(100, 100))
button.SetPosition((150, 150))
frame.Show()
app.MainLoop()
我看到两个问题。显然,即使原始图像具有透明背景,图像的背景颜色也与框架不同。第二个是,在模糊的地方,它似乎没有融合圆圈中的黄色,也没有与窗户的粉红色或图像的白色背景融合。相反,存在某种黑暗成分。
我做错了什么?
模糊:
import wx
from PIL import Image, ImageFilter
import io
class HaloButton(wx.Button):
def __init__(self, parent, image, id=wx.ID_ANY, label='', pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, validator=wx.DefaultValidator, name=wx.ButtonNameStr):
super().__init__(parent, id, label, pos, size, style, validator, name)
self._image = image.copy()
self.Bind(wx.EVT_PAINT, self.OnPaint)
def OnPaint(self, event):
dc = wx.PaintDC(self)
#dc.Clear()
pil_image = self._image.copy()
blurred_image = pil_image.filter(ImageFilter.GaussianBlur(radius=15))
bitmap = wx.Bitmap.FromBufferRGBA(blurred_image.size[0], blurred_image.size[1], blurred_image.tobytes())
dc.DrawBitmap(bitmap, 0, 0)
class Frame(wx.Frame):
def __init__(self, parent, id, title):
super().__init__(parent, -1, title, size=(400, 400), style=wx.DEFAULT_FRAME_STYLE | wx.FULL_REPAINT_ON_RESIZE)
self.SetBackgroundColour((255, 192, 203)) # Rose
self.panel = wx.Panel(self, size=(400, 400), style=wx.SUNKEN_BORDER| wx.TRANSPARENT_WINDOW)
self.Bind(wx.EVT_BUTTON, self.OnClick)
self.panel.Bind(wx.EVT_ENTER_WINDOW, self.OnEnter)
pil_image = Image.open("image.png").convert('RGBA')
button = HaloButton(self.panel, pil_image, size=(100, 100))
button.SetPosition((150, 150))
def OnEnter(self, event): # setHover
print("Refresh")
self.Refresh()
def OnClick(self, event):
print("Click! (%d)\n" % event.GetId())
self.Refresh()
class App(wx.App):
def OnInit(self):
frame = Frame(None, -1, "Halo Button Example")
self.SetTopWindow(frame)
frame.Centre()
frame.Show(True)
return True
def main():
app = App(False)
app.MainLoop()
if __name__ == "__main__" :
main()
并且没有模糊:
import wx
from PIL import Image, ImageFilter
import io
class HaloButton(wx.Button):
def __init__(self, parent, image, id=wx.ID_ANY, label='', pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, validator=wx.DefaultValidator, name=wx.ButtonNameStr):
super().__init__(parent, id, label, pos, size, style, validator, name)
self._image = image.copy()
self.Bind(wx.EVT_PAINT, self.OnPaint)
def OnPaint(self, event):
dc = wx.PaintDC(self)
#dc.Clear()
pil_image = self._image.copy()
blurred_image = pil_image.filter(ImageFilter.GaussianBlur(radius=15))
blurred_image.putalpha(pil_image.getchannel('A')) # Preserve transparency
bitmap = wx.Bitmap.FromBufferRGBA(blurred_image.size[0], blurred_image.size[1], blurred_image.tobytes())
dc.DrawBitmap(bitmap, 0, 0)
class Frame(wx.Frame):
def __init__(self, parent, id, title):
super().__init__(parent, -1, title, size=(400, 400), style=wx.DEFAULT_FRAME_STYLE | wx.FULL_REPAINT_ON_RESIZE)
self.SetBackgroundColour((255, 192, 203)) # Rose
self.panel = wx.Panel(self, size=(400, 400), style=wx.SUNKEN_BORDER| wx.TRANSPARENT_WINDOW)
self.Bind(wx.EVT_BUTTON, self.OnClick)
self.panel.Bind(wx.EVT_ENTER_WINDOW, self.OnEnter)
pil_image = Image.open("image.png").convert('RGBA')
button = HaloButton(self.panel, pil_image, size=(100, 100))
button.SetPosition((150, 150))
def OnEnter(self, event): # setHover
print("Refresh")
self.Refresh()
def OnClick(self, event):
print("Click! (%d)\n" % event.GetId())
self.Refresh()
class App(wx.App):
def OnInit(self):
frame = Frame(None, -1, "Halo Button Example")
self.SetTopWindow(frame)
frame.Centre()
frame.Show(True)
return True
def main():
app = App(False)
app.MainLoop()
if __name__ == "__main__" :
main()