sinus.pyx
import cython
from libc cimport math as cmath
from libc.string cimport memcpy as c_memcpy
from libc.string cimport memset as c_memset
from libc.stdlib cimport malloc, free
import numpy as np
 
#################################################################################################################
def createImgSlow(img,imageHeight,imageWidth,phasePixel,orientation):
  cdef unsigned char [:, :] img_view = img
  cdef int u = 0
  cdef int v = 0
  cdef unsigned char val;
  for u in range(imageWidth):
    for v in range(imageHeight):
      val=<unsigned char> (127*(1+cmath.sin(((u+phasePixel)/10.))))
      img_view[v][u] = val
#################################################################################################################
def createImgFast(img,int imageHeight,int imageWidth,float frequencyPixel,float phasePixel,int orientation,int drawSquare):
  cdef unsigned char [:, :] img_view = img
  cdef int u = 0
  cdef int v = 0
  cdef unsigned char *singleLine
  cdef unsigned int squaresize=20
#generate one line of sinusoidal signal
  cdef int maxdim=imageWidth
  if maxdim<imageHeight:
    maxdim=imageHeight
  singleLine=<unsigned char *>malloc(maxdim)
  for u in range(maxdim):
    singleLine[u] = <unsigned char> (127*(1+cmath.sin(((u+phasePixel)*2*cmath.pi*frequencyPixel/<float>imageWidth))))
#vertical lines
  if orientation==0:
    for v in range(0,imageHeight,1):
      c_memcpy(&(img_view[v][0]),&(singleLine[0]),imageWidth)
#horizontal lines
  else: 
    if orientation==1:
      for v in range(0,imageHeight,1):
        c_memset(&(img_view[v][0]),singleLine[v],imageWidth)
#may be draw a black or white square in the corner
  if drawSquare!=0:
      for v in range(imageHeight-squaresize,imageHeight,1):
        c_memset(&(img_view[v][imageWidth-squaresize]),(drawSquare-1)*255,squaresize)
  free(singleLine)
#################################################################################################################
def testsinus():
  imageWidth=1920
  imageHeight=1080
  # Memoryview on a NumPy array
  img = np.empty((imageHeight,imageWidth), dtype=np.dtype("uint8"))
  # help (np.empty)
  print("-------------------------------------------------------")
  createImgSlow(img,imageHeight,imageWidth,0,0)
  createImgFast(img,imageHeight,imageWidth,1,0,0,1)
  print("-------------------------------------------------------")
#################################################################################################################
qt45sinus.py
#!/usr/bin/python3
# -*- coding: utf-8 -*
#Bertrand Vandeportaele 2017
#can use python2 or python3
#can use QT4 or QT5, qtVersionMajor is et accordingly to 4 or 5
 
 
fullScreen=False
#default size for windowed application
imageWidth=1920
imageHeight=1080
 
 
import os
import sys
#compile the library to .so with the corresponding version of python
if sys.version_info < (3, 0):
  os.system('python2 setup.py build_ext --inplace')
else:
  os.system('python3 setup.py build_ext --inplace')
import time
import sinus
import math
import sip
#https://pythonspot.com/qt4-pixmaps-images/
#import desired Qt library version
 
#https://stackoverflow.com/questions/1051254/check-if-python-package-is-installed
from imp import find_module
def checkPythonmod(mod):
    try:
        op = find_module(mod)
        return True
    except ImportError:
        return False
 
if checkPythonmod('PyQt5'): 
  from PyQt5.QtGui import *
  from PyQt5 import *
  from PyQt5 import QtCore, QtGui, QtWidgets
  from PyQt5.QtWidgets import *
  qtVersionMajor=5
  print('QT5 is used')
else: 
  if checkPythonmod('PyQt4'): 
    from PyQt4.QtGui import *
    from PyQt4 import *
    qtVersionMajor=4
    print('QT4 is used') 
  else: 
    print('Only QT4 and QT5 are supported. Quitting')
    exit(-1) 
 
from PIL import Image
import numpy
###############################"
COLORTABLE=[]
for i in range(256): COLORTABLE.append(QtGui.qRgb(i,i,i))
###############################"
 
def update():
  global label
  global imageWidth
  global imageHeight
  global img
  update.cpt=(update.cpt+1) #%255;
  t = time.time()
  #sinus.createImgSlow(img,imageHeight,imageWidth,update.cpt)
  sinus.createImgFast(img,imageHeight,imageWidth,(update.cpt//40),(update.cpt%40)*2.*math.pi/40.,(update.cpt/20)%2,(update.cpt%2)+1)
  #sinus.createImgFast(img,imageHeight,imageWidth,10,update.cpt,0,(update.cpt%2)+1)
  #sinus.createImgFast(img,imageHeight,imageWidth,(update.cpt//40),(update.cpt%40)*imageWidth/(update.cpt/40),(update.cpt/20)%2,(update.cpt%2)+1)
  elapsed = time.time() - t
  print(str(elapsed))
  QI=QtGui.QImage(img.data, imageWidth, imageHeight, QtGui.QImage.Format_Indexed8)    
  QI.setColorTable(COLORTABLE)
  label.setPixmap(QtGui.QPixmap.fromImage(QI))    
  if fullScreen==True:
    #always reset this windows as the active one.... only for linux
    command='wmctrl -a \''+windowsName+'\''
    os.system(command)
###############################"
#equivalent to the initialization of a static variable
update.cpt=40
 
# Create window
#app = QApplication(sys.argv)
if qtVersionMajor==4:
  app = QtGui.QApplication(sys.argv)
  if fullScreen==True:
    w = QWidget(None,QtCore.Qt.FramelessWindowHint)
  else:
    w = QWidget(None)
  windowsName="PyQT4 Sinus"  
else: 
  if qtVersionMajor==5:
    app = QtWidgets.QApplication(sys.argv)
    if fullScreen==True:
      w = QtWidgets.QWidget(None,QtCore.Qt.FramelessWindowHint)
    else:
      w = QtWidgets.QWidget(None)
    windowsName="PyQT5 Sinus"  
if fullScreen==True:
  V = app.desktop().screenGeometry()
  screenHeight = V.height()
  screenWidth = V.width()
  print("The screen resolution (width X height) is the following:")
  print(str(screenWidth) + "X" + str(screenHeight))
  imageWidth=screenWidth
  imageHeight=screenHeight
 
#for fullscreen: https://stackoverflow.com/questions/1732935/pyqt-display-fullscreen-image
w.setWindowTitle(windowsName) 
# Create widget
label = QLabel(w)
 
 
# Memoryview on a NumPy array,   # help (numpy.empty)
img = numpy.empty((imageHeight,imageWidth), dtype=numpy.dtype("uint8"))
 
update()
 
IM = QtGui.QImage(imageWidth, imageHeight, QtGui.QImage.Format_Indexed8)
label.setGeometry(QtCore.QRect(0,0,imageWidth,imageHeight))
 
#timer adpated from example 1 of https://www.programcreek.com/python/example/52106/PyQt4.QtCore.QTimer
timer = QtCore.QTimer()
if qtVersionMajor==4:
  app.connect(timer,  QtCore.SIGNAL('timeout()'), update)
else: 
  if qtVersionMajor==5:
    timer.timeout.connect(update)
timer.start(1 * 10) # 1 seconds
# Draw window
w.show()
if fullScreen==True:
  w.showFullScreen()
#set the focus to this windows so ALT+F4 close it.. no it is the qt focus only...
w.setFocus()
 
sys.exit(app.exec_())
setup.py
from distutils.core import setup
from Cython.Build import cythonize
setup(
  name = 'sinus lib',
  ext_modules = cythonize("​sinus.pyx"),)

Installation

sudo apt-get install build-essential python3-dev libqt4-dev
sudo apt-get install python3-pyqt4
sudo apt-get install python3-numpy python3-pip
pip3 install --upgrade pip
pip3 install Cython
sudo apt-get  install cython
pip3 install sip

Pour compiler la librairie sinus:

python3 setup.py build_ext --inplace

Pour analyser le code C généré et détecter les surcouts liés à python (en jaune)

cython  -3 -a sinus.pyx
firefox sinus.html