text: from ctypes import *
  import os.path
  import logging
  import filetype
  import logging
  
  so_name = "libimgsmlr.so"
  so_path_name = os.path.dirname(os.path.abspath(__file__)) + os.path.sep + so_name
  try:
      libimgsmlr = cdll.LoadLibrary(so_path_name)
  except OSError as ex:
      logging.error("ctypes.cdll.LoadLibrary(%s) failed! ex: %s", so_path_name, ex)
      raise ex
  
  """
  typedef struct
  {
      float values[PATTERN_SIZE][PATTERN_SIZE];
  } Pattern;
  
  typedef float Signature[SIGNATURE_SIZE];
  int shuffle_pattern(Pattern* patternDst, Pattern* patternSrc);
  int pattern2signature(Pattern* pattern, Signature signature);
  Pattern* jpeg2pattern(void* img, int size, Pattern* pattern);
  Pattern* png2pattern(void* img, int size, Pattern* pattern);
  Pattern* gif2pattern(void* img, int size, Pattern* pattern);
  Pattern* webp2pattern(void* img, int size, Pattern* pattern);
  """
  
  PATTERN_SIZE = 64
  SIGNATURE_SIZE = 16
  
  class Pattern(Structure):
      _fields_ = [("values", c_float * PATTERN_SIZE * PATTERN_SIZE)]
      def as_array(self):
          arr = []
          for i in range(PATTERN_SIZE):
              arr2 = []
              for j in range(PATTERN_SIZE):
                  arr2.append(round(self.values[i][j], 8))
              arr.append(arr2)
          return arr
  
  Pattern_p = POINTER(Pattern)
  Signature = c_float * SIGNATURE_SIZE
  
  def initImg2PatternFunc(func):
      func.argtypes = (c_void_p, c_int, Pattern_p)
      func.restype = Pattern_p
      return func
  
  def initJpeg2patternFunc():
      return initImg2PatternFunc(libimgsmlr.jpeg2pattern)
  
  def initPng2patternFunc():
      return initImg2PatternFunc(libimgsmlr.png2pattern)
  
  def initGif2patternFunc():
      return initImg2PatternFunc(libimgsmlr.gif2pattern)
  
  def initWebp2patternFunc():
      return initImg2PatternFunc(libimgsmlr.webp2pattern)
  
  def initPattern2signatureFunc():
      pattern2signature = libimgsmlr.pattern2signature
      pattern2signature.argtypes = (Pattern_p, Signature)
      pattern2signature.restype = c_int
      return pattern2signature
  
  def initShufflePatternFunc():
      shuffle_pattern = libimgsmlr.shuffle_pattern
      shuffle_pattern.argtypes = (Pattern_p, Pattern_p)
      shuffle_pattern.restype = c_int
      return shuffle_pattern
  
  c_jpeg2pattern = initJpeg2patternFunc()
  c_png2pattern = initPng2patternFunc()
  c_gif2pattern = initGif2patternFunc()
  c_webp2pattern = initWebp2patternFunc()
  c_pattern2signature = initPattern2signatureFunc()
  c_shuffle_pattern = initShufflePatternFunc()
  
  def jpeg2pattern(img: bytes):
      patternBuf = Pattern()
      pattern = c_jpeg2pattern(img, len(img), patternBuf)
      if pattern:
          return True, patternBuf
      return False, "not a valid jpeg file"
  
  def png2pattern(img: bytes):
      patternBuf = Pattern()
      pattern = c_png2pattern(img, len(img), patternBuf)
      if pattern:
          return True, patternBuf
      return False, "not a valid png file"
  
  def gif2pattern(img: bytes):
      patternBuf = Pattern()
      pattern = c_gif2pattern(img, len(img), patternBuf)
      if pattern:
          return True, patternBuf
      return False, "not a valid gif file"
  
  def webp2pattern(img: bytes):
      patternBuf = Pattern()
      pattern = c_webp2pattern(img, len(img), patternBuf)
      if pattern:
          return True, patternBuf
      return False, "not a valid webp file"
  
  
  def img2pattern(img: bytes):
      if type(img) != bytes:
          raise ValueError("Need a bytes")
  
      kind = filetype.guess(img)
      if not kind:
          raise ValueError("not a valid image file")
  
      pattern = None
      if kind.mime == "image/jpeg":
          ok, pattern = jpeg2pattern(img)
      elif kind.mime == "image/png":
          ok, pattern = png2pattern(img)
      elif kind.mime == "image/gif":
          ok, pattern = gif2pattern(img)
      # elif kind.mime == "image/webp":
      #     ok, pattern = webp2pattern(img)
      else:
          raise ValueError("'%s' not supported" % kind.mime)
      if not ok:
          raise ValueError(pattern)
  
      return pattern
  
  def pattern2signature(pattern):
      if not pattern:
          raise ValueError("pattern cannot be None")
  
      c_signature = Signature()
      c_pattern2signature(pattern, c_signature)
      signature = []
      for sign in c_signature:
          signature.append(round(sign, 6))
      return signature
  
  def shuffle_pattern(pattern):
      if not pattern:
          raise ValueError("pattern cannot be None")
      patternOut = Pattern()
      c_shuffle_pattern(patternOut, pattern)
      return patternOut
  