Skip to content

Colors expected from wx versus skia's with CPU or raster backend #323

@prashant-saxena

Description

@prashant-saxena

Describe the bug
Colors are flipped. RGB -> BGR
You should suppose to see a blue color square not red.
This issue has been discussed earlier #191 but no clear explanation of the behavior.

To Reproduce
Steps to reproduce the behavior:

# python imports
import ctypes
# pip imports
import numpy as np
import wx
import skia


"""Enable high-res displays."""
try:
    ctypes.windll.shcore.SetProcessDpiAwareness(1)
    ctypes.windll.shcore.SetProcessDpiAwareness(2)
except Exception:
    pass  # fail on non-windows


class SkiaCPUCanvas(wx.Panel):
    """A cpu based skia canvas"""

    def __init__(self, parent, size):
        super().__init__(parent, size=size)
        # or else we'll have a flicker
        self.SetBackgroundStyle(wx.BG_STYLE_PAINT)

        self.Bind(wx.EVT_SIZE, self.on_size)
        self.Bind(wx.EVT_PAINT, self.on_paint)
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.on_timer, self.timer)
        self.timer.Start(32)  # 1000/32 = 31.25 FPS

    def bgra_to_rgba(self, pixels: bytes, width: int, height: int) -> bytes:
        arr = np.frombuffer(pixels, dtype=np.uint8).reshape((height, width, 4))
        arr = arr[:, :, [2, 1, 0, 3]]  # Swap BGR -> RGB, keep Alpha
        return arr.tobytes()

    def on_paint(self, event):
        w, h = self.GetSize()
        if w == 0 or h == 0:
            return

        self.draw(w, h)

        image = self.surface.makeImageSnapshot()
        # image = image.toarray(colorType=skia.ColorType.kRGBA_8888_ColorType).tobytes()
        # pixels_rgba = self.bgra_to_rgba(image.tobytes(), w, h)
        bitmap = wx.Bitmap.FromBufferRGBA(w, h, image.tobytes())

        dc = wx.PaintDC(self)
        dc.DrawBitmap(bitmap, 0, 0)

    def draw(self, w, h):
        self.canvas.clear(skia.ColorBLACK)  # Clear the canvas with white background
        self.canvas.save()
        self.canvas.translate(w / 2, h / 2)

        paint = skia.Paint(AntiAlias=True, Color=skia.Color(0, 0, 255)) # BLUE COLOR
        self.canvas.drawRect(skia.Rect(0, 0, 100, 100), paint)
        self.canvas.restore()

    def on_size(self, event):
        wx.CallAfter(self.set_size)
        event.Skip()

    def set_size(self):
        # Actual drawing area (without borders) is GetClientSize
        size = self.GetClientSize()
        # On HiDPI screens, this could be 1.25, 1.5, 2.0, etc.
        scale = self.GetContentScaleFactor()
        width = int(size.width * scale)
        height = int(size.height * scale)
        self.size = wx.Size(width, height)

        self.surface = skia.Surface(width, height)
        self.canvas = self.surface.getCanvas()

        self.Refresh()

    def on_timer(self, event):
        self.Refresh()


class MainFrame(wx.Frame):
    def __init__(self):
        super().__init__(None, title="Skia CPU Canvas", size=(800, 600))
        panel = wx.Panel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.canvas = SkiaCPUCanvas(panel, (800, 600))
        sizer.Add(self.canvas, 1, wx.EXPAND)
        panel.SetSizer(sizer)
        self.Show()


if __name__ == "__main__":
    app = wx.App(False)
    frame = MainFrame()
    frame.Show()
    app.MainLoop()

Expected behavior
skia.Color() should create RGB color not BGR.

Desktop (please complete the following information):

  • OS: Windows 10
  • Python: 3.10.0
  • skia-python version: 87.8
  • wxpython: 4.2.3

Additional context
This behavior is only on CPU based canvas. On OpenGL based canvas there are no issues.

image = image.toarray(colorType=skia.ColorType.kRGBA_8888_ColorType).tobytes()
pixels_rgba = self.bgra_to_rgba(image.tobytes(), w, h)

I can use either of these to solve the problem but the performance is really going down when working with large resolution 1920x1000 and implementing operations such as pan or zoom.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions