Repository: GuardKenzie/chafa.py (language: python)

Issue:
Support for MacOS
```
❯ pip show chafa.py | grep Version
Version: 1.0.0.post2
❯ chafa --version
Chafa version 1.12.4

OS: macOS 13.1 22C65 arm64
```


```
❯ brew install imagemagick chafa
Warning: imagemagick 7.1.0-57 is already installed and up-to-date.
To reinstall 7.1.0-57, run:
  brew reinstall imagemagick
Warning: chafa 1.12.4 is already installed and up-to-date.
To reinstall 1.12.4, run:
  brew reinstall chafa
❯ pip3 install chafa.py
Requirement already satisfied: chafa.py in /Users/reagle/.pyenv/versions/3.11.0/lib/python3.11/site-packages (1.0.0.post2)
❯ ipy
Python 3.11.0 (main, Oct 27 2022, 13:28:08) [Clang 14.0.0 (clang-1400.0.29.102)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.5.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import chafa
---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
Cell In [1], line 1
----> 1 import chafa

File ~/.pyenv/versions/3.11.0/lib/python3.11/site-packages/chafa/__init__.py:1
----> 1 from .chafa import PixelMode
      2 from .chafa import DitherMode
      3 from .chafa import CanvasMode

File ~/.pyenv/versions/3.11.0/lib/python3.11/site-packages/chafa/chafa.py:9
      6 import array
      8 #  CHAFA LETS GOOOOOOO!!!
----> 9 _Chafa = ctypes.CDLL("libchafa.so")
     11 #
     12 # === PIXEL MODES ===
     13 #
     15 class PixelMode(IntEnum):

File ~/.pyenv/versions/3.11.0/lib/python3.11/ctypes/__init__.py:376, in CDLL.__init__(self, name, mode, handle, use_errno, use_last_error, winmode)
    373 self._FuncPtr = _FuncPtr
    375 if handle is None:
--> 376     self._handle = _dlopen(self._name, mode)
    377 else:
    378     self._handle = handle

OSError: dlopen(libchafa.so, 0x0006): tried: 'libchafa.so' (no such file), '/System/Volumes/Preboot/Cryptexes/OSlibchafa.so' (no such file), '/opt/homebrew/lib/libchafa.so' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/lib/libchafa.so' (no such file), '/opt/homebrew/lib/libchafa.so' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/lib/libchafa.so' (no such file), '/opt/homebrew/lib/libchafa.so' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/lib/libchafa.so' (no such file), '/opt/homebrew/lib/libchafa.so' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/lib/libchafa.so' (no such file), '/opt/homebrew/lib/libchafa.so' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/lib/libchafa.so' (no such file), '/opt/homebrew/lib/libchafa.so' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/opt/homebrew/lib/libchafa.so' (no such file), '/usr/lib/libchafa.so' (no such file, not in dyld cache), 'libchafa.so' (no such file), '/usr/local/lib/libchafa.so' (no such file), '/usr/lib/libchafa.so' (no such file, not in dyld cache)
```



Discussion / hints:
Hihi!

Currently only Linux is supported but Windows #4 and hopefully MacOS support will hopefully be added with v1.1.

I do not have access to an apple computer but could you provide me with the output of:

```
ls /usr/lib | grep -E 'chafa|glib-2|MagickWand'
ls /usr/local/lib | grep -E 'chafa|glib-2|MagickWand'
ls ~/lib | grep -E 'chafa|glib-2|MagickWand'
```

That should give me an idea of the names of the files I should look for.

Again, since I don't have an apple computer, I cannot test the implementation when I get to it. If you are interested in helping me with testing, could you please contact me via email or through Discord?


Hello, none of those paths will be relevant on a Mac. I install most packges via homebrew:

```
==> imagemagick: stable 7.1.0-57 (bottled), HEAD
Tools and libraries to manipulate images in many formats
https://imagemagick.org/index.php
/opt/homebrew/Cellar/imagemagick/7.1.0-57 (807 files, 31MB) *
  Poured from bottle on 2023-01-02 at 09:33:14
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/imagemagick.rb
License: ImageMagick
==> Dependencies
Build: pkg-config
Required: freetype, ghostscript, jpeg-turbo, libheif, liblqr, libpng, libraw, libtiff, libtool, little-cms2, openexr, openjpeg, webp, xz, libomp
==> Options
--HEAD
	Install HEAD version
==> Analytics
install: 155,027 (30 days), 454,807 (90 days), 1,988,156 (365 days)
install-on-request: 137,476 (30 days), 404,578 (90 days), 1,759,670 (365 days)
build-error: 7 (30 days)

==> chafa: stable 1.12.4 (bottled)
Versatile and fast Unicode/ASCII/ANSI graphics renderer
https://hpjansson.org/chafa/
/opt/homebrew/Cellar/chafa/1.12.4 (49 files, 1.5MB) *
  Poured from bottle on 2023-01-11 at 12:42:00
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/chafa.rb
License: LGPL-3.0-or-later
==> Dependencies
Build: pkg-config
Required: freetype, glib, jpeg-turbo, librsvg, libtiff, webp
==> Analytics
install: 225 (30 days), 904 (90 days), 4,347 (365 days)
install-on-request: 201 (30 days), 810 (90 days), 3,818 (365 days)
build-error: 0 (30 days)


```
Can you provide me with the output of the following Python script?

```python
from ctypes.util import find_library

listi = [
    "chafa", 
    "libchafa",
    "libchafa-0",
    "libchafa.dylib",
    "libchafa-0.dylib",
    "glib",
    "glib-2", 
    "glib-2.0.dylib"
]

for lib in listi:
    print(f"{lib:<18} {find_library(lib)}")
```

I'm hoping I can use the `find_library` function in `ctypes` instead of including the library in the python wheel until I figure out how to cross compile for macos (or get a proper VM up and running).
```
chafa              None
libchafa           None
libchafa-0         None
libchafa.dylib     None
libchafa-0.dylib   None
glib               None
glib-2             None
glib-2.0.dylib     None
```

Some of these are here:

```
/opt/homebrew/Cellar/chafa/1.12.4/lib
├── chafa
│   └── include
├── libchafa.0.dylib
├── libchafa.a
├── libchafa.dylib -> libchafa.0.dylib
└── pkgconfig
    └── chafa.pc
```

Ok so I have been doing some reading on using ctypes with homebrew and this is the conclusion:

### The mess

After apple introduced Apple silicon, homebrew moved the installation location of libraries from `/usr/local` to `/opt/homebrew` (See [this discussion](https://github.com/Homebrew/brew/issues/9177)). The Python `ctypes` library does not search for `.dylib` files in this path but homebrew seems to ship a patched version of python which does (See [this discussion](https://github.com/Homebrew/discussions/discussions/3424) and this [stack overflow post](https://stackoverflow.com/questions/31148387/which-paths-does-python-ctypes-module-search-for-libraries-on-mac-os))

I can see two ways of moving forwards:
1. Manually search for `libchafa` and `libglib-2.0` in `/opt/homebrew` (I'm leaning towards this solution)
2. Having part of the requirements for MacOS be using  a brew installed Python

### What I need from you
Are any of the libraries stored in `/opt/homebrew/lib`? I need the locations of `glib2` and `chafa`. 

If not, can you provide me with the directory in `/opt/homebrew` where `glib2` is installed and what the `.dylib` file is called?
Hi @GuardKenzie, I was going to use this for a task I've now completed. I don't know much about python and brew packaging. I don't see `libglib-2.0` in  `/opt/homebrew/lib` but I don't know if I'm missing an installed brew.
Sure thing. Putting a pin in this issue for now and if anyone is interested discussing this further, head over to discussion thread #7 ❤️  

Fix patch:
diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml
index c2cd202..8963246 100644
--- a/.github/workflows/build_wheels.yml
+++ b/.github/workflows/build_wheels.yml
@@ -8,7 +8,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     strategy:
       matrix:
-        os: [ubuntu-20.04, windows-2019]
+        os: [ubuntu-20.04, windows-2019, macos-11]
 
     steps:
       - uses: actions/checkout@v3
@@ -56,4 +56,4 @@ jobs:
     - uses: pypa/gh-action-pypi-publish@v1.6.4
       with:
         user: __token__
-        password: ${{ secrets.pypi_password }}
\ No newline at end of file
+        password: ${{ secrets.pypi_password }}
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index 74380a5..43c5604 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -1,14 +1,8 @@
 name: Docs
 on: [push, pull_request, workflow_dispatch]
 jobs:
-  docs:
+  build_docs:
     runs-on: ubuntu-latest
-    permissions:
-      pages: write
-      id-token: write
-    environment:
-      name: github-pages
-      url: ${{ steps.deployment.outputs.page_url }}
     steps:
       - uses: actions/checkout@v3
       - uses: actions/setup-python@v4
@@ -19,15 +13,26 @@ jobs:
         working-directory: docs
         run: |
           make clean html
-      - name: Setup Pages
-        uses: actions/configure-pages@v3
+      # - name: Setup Pages
+      #   uses: actions/configure-pages@v3
       - name: Upload artifact
         uses: actions/upload-pages-artifact@v1
         with:
-          # Upload entire repository
           path: './docs/_build/html'
+
+  upload_docs:
+    needs: [build_docs]
+    runs-on: ubuntu-latest
+    if: github.ref == 'refs/heads/main'
+    permissions:
+      pages: write
+      id-token: write
+    environment:
+      name: github-pages
+      url: ${{ steps.deployment.outputs.page_url }}
+    steps:
       - name: Deploy to GitHub Pages
-        id: deployment
+        id:   deployment
         uses: actions/deploy-pages@v1
         with:
           repo-token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/hatch_build.py b/hatch_build.py
index 1ffb2f8..503d509 100644
--- a/hatch_build.py
+++ b/hatch_build.py
@@ -46,4 +46,26 @@ def initialize(self, version, build_data) -> None:
 
             for file in not_chafa_glob:
                 build_data["force_include"][str(file)] = str(libs_folder / file.name)
+        
+        else:
+            chafa_glob = Path("libs/macos").glob("*chafa*.dylib")
+            chafa_glob = chafa_glob = [p for p in chafa_glob if not ".0" in p.name]
+            
+            print(chafa_glob)
+
+            if len(chafa_glob) > 1:
+                raise FileNotFoundError("Too many files matched the glob pattern 'libs/macos/*chafa*.dylib'")
+
+            elif len(chafa_glob) < 1:
+                raise FileNotFoundError("No file matched the glob pattern 'libs/macos/*chafa*.dylib'")
+
+            build_data["force_include"][str(chafa_glob[0])] = str(libs_folder / "libchafa.dylib")
+            
+            # Find everything else
+            not_chafa_glob = [p for p in Path("libs/macos").glob("*.dylib") if not "chafa" in p.name]
+
+            for file in not_chafa_glob:
+                build_data["force_include"][str(file)] = str(libs_folder / file.name)
+
+
 
diff --git a/img/logo.svg b/img/logo.svg
index 7690ccd..3ce998a 100644
--- a/img/logo.svg
+++ b/img/logo.svg
@@ -2,295 +2,119 @@
 <!-- Created with Inkscape (http://www.inkscape.org/) -->
 
 <svg
-   width="238.3896mm"
-   height="94.456245mm"
-   viewBox="0 0 238.3896 94.456245"
+   width="164.59734mm"
+   height="38.487022mm"
+   viewBox="0 0 164.59734 38.487022"
    version="1.1"
    id="svg5"
    xml:space="preserve"
-   inkscape:export-filename="bitmap.svg"
-   inkscape:export-xdpi="96"
-   inkscape:export-ydpi="96"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns="http://www.w3.org/2000/svg"
-   xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
-     id="namedview7"
-     pagecolor="#505050"
-     bordercolor="#ffffff"
-     borderopacity="1"
-     inkscape:showpageshadow="0"
-     inkscape:pageopacity="0"
-     inkscape:pagecheckerboard="1"
-     inkscape:deskcolor="#505050"
-     inkscape:document-units="mm"
-     showgrid="false"
-     showguides="true" /><defs
+   xmlns:svg="http://www.w3.org/2000/svg"><defs
      id="defs2" /><g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(15.042125,-72.20809)"><rect
-       style="fill:#eff1f5;fill-opacity:1;stroke:#4c4f69;stroke-width:0;stroke-linejoin:miter;stroke-dasharray:none"
-       id="rect300"
-       width="117.75383"
-       height="94.456253"
-       x="105.59364"
-       y="72.208092"
-       ry="0" /><g
-       aria-label="chafa.py"
-       id="text3194"
-       style="font-weight:bold;font-size:22.5778px;font-family:Eczar;-inkscape-font-specification:'Eczar Bold';fill:#4c4f69;stroke:#eff1f5;stroke-width:0"><path
-         d="m 131.90497,125.61125 q -1.30951,0.2032 -2.50614,-0.11289 -1.19662,-0.31609 -2.14489,-1.06116 -0.92569,-0.76765 -1.46755,-1.89654 -0.54187,-1.15146 -0.54187,-2.61902 0,-1.76107 0.74507,-3.07058 0.76764,-1.33209 2.05458,-2.07716 1.30951,-0.74507 2.91253,-0.74507 0.99343,0 1.91911,0.31609 0.92569,0.31609 1.60303,0.97085 0.67733,0.65475 0.97084,1.64818 l -3.09315,1.73849 q -0.47414,-0.92569 -1.03858,-1.58045 -0.54187,-0.67733 -1.2192,-1.03858 -0.63218,0.69992 -0.85796,1.60303 -0.22578,0.88053 -0.22578,1.64818 0,1.08373 0.33867,1.96427 0.36124,0.85795 1.06115,1.35466 0.72249,0.49671 1.76107,0.49671 0.58703,0 1.19663,-0.15804 0.6096,-0.18062 1.26435,-0.51929 l 0.54187,1.24178 z"
-         id="path3350" /><path
-         d="m 137.43652,125.31773 v -15.44321 l 2.68675,-1.19663 1.2192,1.12889 v 15.51095 z m 6.77334,0 v -6.43467 q 0,-1.03858 -0.4064,-1.58045 -0.40641,-0.54186 -1.15147,-0.51928 -0.49671,0.0226 -1.08374,0.29351 -0.58702,0.24835 -1.17404,0.63217 -0.58703,0.36125 -1.12889,0.76765 l -0.11289,-0.58702 q 0.92569,-0.94827 1.89653,-1.69334 0.97085,-0.76764 1.89654,-1.26435 0.94827,-0.51929 1.76107,-0.79023 0.45155,0 1.016,0.15805 0.58702,0.13546 1.15147,0.49671 0.56444,0.33867 0.94826,0.97084 0.11289,0.18063 0.15805,0.49672 0.0677,0.31608 0.0903,0.88053 0.0452,0.54187 0.0452,1.49013 v 6.68303 z m -8.46668,-14.67557 -0.11289,-1.12889 q 0.99342,-0.36124 2.14489,-0.56444 1.15147,-0.2032 2.34809,-0.27094 l -0.0226,1.60303 -1.71592,0.83538 z m 0.0452,14.67557 -0.0452,-0.79022 q 0.65476,-0.38382 1.39982,-0.65476 0.76765,-0.27093 1.39983,-0.42897 l -0.22578,1.87395 z m 3.47698,0 0.56444,-2.32551 q 0.69991,0.18062 1.4224,0.49671 0.72249,0.29351 1.35467,0.72249 l -0.0452,1.10631 z m 6.99912,0 0.56444,-2.32551 q 0.69991,0.18062 1.4224,0.49671 0.72249,0.29351 1.35467,0.72249 l -0.0677,1.10631 z"
-         id="path3352" /><path
-         d="m 159.13378,125.67898 q -0.45155,0 -0.92569,-0.24836 -0.45155,-0.22578 -0.85795,-0.65475 -0.38383,-0.45156 -0.65476,-1.03858 l -0.31609,-0.11289 v -5.48641 q 0,-1.06115 -0.31609,-1.55787 -0.31609,-0.49671 -0.72249,-0.72248 -0.33867,0.0226 -0.69991,0.11288 -0.33867,0.0677 -0.56445,0.15805 l -0.54186,2.48356 -2.2352,0.0452 q -0.24836,-0.76764 -0.36125,-1.67075 -0.11289,-0.90312 -0.0226,-1.7385 0.69991,-0.27093 1.53529,-0.49671 0.83538,-0.24835 1.64818,-0.4064 0.83538,-0.18062 1.53529,-0.27093 0.72249,-0.0903 1.17405,-0.0903 0.63218,0 1.2192,0.18062 0.58702,0.18062 1.08373,0.56445 0.51929,0.36124 0.90312,0.90311 0.18062,0.27093 0.22577,0.79022 0.0452,0.51929 0.0452,1.51271 v 4.62845 q 0,0.22578 0.13547,0.38382 0.15804,0.15805 0.4064,0.15805 0.27093,0 0.54186,-0.0226 0.27094,-0.0226 0.63218,-0.0452 l 0.13547,0.99342 z m -4.69618,-0.0903 q -1.33209,0.2032 -2.28036,-0.2032 -0.94827,-0.4064 -1.4224,-1.12889 -0.47413,-0.74507 -0.47413,-1.51272 0,-0.69991 0.42897,-1.4224 0.42898,-0.74506 1.39983,-1.24178 l 4.98969,-0.11289 -0.0226,1.42241 -0.63217,-0.0226 q -0.4064,0 -0.83538,0.0452 -0.4064,0.0452 -0.74507,0.15805 -0.33867,0.11289 -0.54187,0.33867 -0.2032,0.22577 -0.2032,0.58702 0,0.24835 0.0903,0.51929 0.11289,0.27093 0.31609,0.45155 0.42898,-0.0226 0.85796,-0.13546 0.45156,-0.11289 0.85796,-0.24836 0.4064,-0.13547 0.69991,-0.22578 l 0.29351,0.94827 z"
-         id="path3354" /><path
-         d="m 164.1912,125.31773 v -12.07912 q 0,-1.39982 0.6096,-2.50614 0.63218,-1.10631 1.67076,-1.73849 1.06116,-0.63217 2.32552,-0.63217 0.74506,0 1.6256,0.27093 0.90311,0.27093 1.73849,0.83538 l -2.05458,3.40925 q -0.72249,-0.72249 -1.58045,-1.21921 -0.85795,-0.51929 -1.80622,-0.8128 l 1.44498,3.9737 -0.0677,0.63217 v 9.8665 z m -1.46755,0 -0.0452,-0.79022 q 0.65476,-0.38382 1.39982,-0.65476 0.76765,-0.27093 1.39983,-0.42897 l -0.22578,1.87395 z m 4.10916,0 0.56444,-2.19004 q 0.69991,0.18062 1.4224,0.45155 0.72249,0.24836 1.33209,0.63218 l -0.0451,1.10631 z m -4.31236,-8.128 -0.0677,-1.24178 q 0.79023,-0.49672 1.55787,-0.90312 0.76765,-0.42897 1.51271,-0.8128 l 1.51272,1.35467 -0.29351,1.55787 z m 4.38009,0 v -2.5513 h 3.72534 l 0.0226,1.10632 -1.12889,1.44498 z"
-         id="path3356" /><path
-         d="m 179.70215,125.67898 q -0.45156,0 -0.92569,-0.24836 -0.45156,-0.22578 -0.85796,-0.65475 -0.38382,-0.45156 -0.65476,-1.03858 l -0.31609,-0.11289 v -5.48641 q 0,-1.06115 -0.31609,-1.55787 -0.31608,-0.49671 -0.72248,-0.72248 -0.33867,0.0226 -0.69992,0.11288 -0.33866,0.0677 -0.56444,0.15805 l -0.54187,2.48356 -2.2352,0.0452 q -0.24836,-0.76764 -0.36125,-1.67075 -0.11289,-0.90312 -0.0226,-1.7385 0.69991,-0.27093 1.53529,-0.49671 0.83538,-0.24835 1.64818,-0.4064 0.83537,-0.18062 1.53529,-0.27093 0.72249,-0.0903 1.17404,-0.0903 0.63218,0 1.2192,0.18062 0.58703,0.18062 1.08374,0.56445 0.51929,0.36124 0.90311,0.90311 0.18062,0.27093 0.22578,0.79022 0.0452,0.51929 0.0452,1.51271 v 4.62845 q 0,0.22578 0.13547,0.38382 0.15804,0.15805 0.4064,0.15805 0.27093,0 0.54187,-0.0226 0.27093,-0.0226 0.63218,-0.0452 l 0.13546,0.99342 z m -4.69619,-0.0903 q -1.33209,0.2032 -2.28035,-0.2032 -0.94827,-0.4064 -1.42241,-1.12889 -0.47413,-0.74507 -0.47413,-1.51272 0,-0.69991 0.42898,-1.4224 0.42898,-0.74506 1.39982,-1.24178 l 4.9897,-0.11289 -0.0226,1.42241 -0.63218,-0.0226 q -0.4064,0 -0.83538,0.0452 -0.4064,0.0452 -0.74507,0.15805 -0.33866,0.11289 -0.54186,0.33867 -0.2032,0.22577 -0.2032,0.58702 0,0.24835 0.0903,0.51929 0.11289,0.27093 0.31609,0.45155 0.42897,-0.0226 0.85795,-0.13546 0.45156,-0.11289 0.85796,-0.24836 0.4064,-0.13547 0.69991,-0.22578 l 0.29351,0.94827 z"
-         id="path3358" /><path
-         d="m 187.49148,126.266 q -0.38382,-0.15804 -0.85796,-0.47413 -0.47413,-0.31609 -0.92569,-0.69991 -0.42897,-0.38383 -0.69991,-0.74507 0.36125,-0.72249 0.90312,-1.4224 0.54186,-0.69991 1.10631,-1.016 0.42898,0.18062 0.88053,0.51929 0.47414,0.31608 0.85796,0.69991 0.4064,0.38382 0.63218,0.69991 -0.24836,0.65476 -0.79023,1.35467 -0.51929,0.67733 -1.10631,1.08373 z"
-         id="path3360" /><path
-         d="m 196.83871,125.43062 q -1.15146,0 -2.52871,-0.33866 -1.35467,-0.36125 -2.50614,-0.94827 l 1.55787,-1.71591 q 0.38382,0.31608 0.99342,0.6096 0.60961,0.27093 1.3321,0.42897 0.74506,0.13547 1.49013,0.0903 0.58702,-0.54187 0.92569,-1.49014 0.33867,-0.97084 0.33867,-1.98685 0,-0.8128 -0.24836,-1.53529 -0.22578,-0.74506 -0.69991,-1.19662 -0.47413,-0.45156 -1.17405,-0.45156 -0.51929,0 -1.12889,0.29352 -0.6096,0.27093 -1.26435,0.69991 l -0.2032,-0.79023 3.90596,-2.86738 q 1.17404,-0.2032 2.07715,0.15805 0.92569,0.33867 1.55787,1.10631 0.65476,0.74507 0.99343,1.76107 0.33866,1.016 0.33866,2.16747 0,1.17404 -0.38382,2.25778 -0.36125,1.06115 -1.08373,1.91911 -0.69992,0.85796 -1.78365,1.35467 -1.08374,0.47413 -2.50614,0.47413 z m -6.93138,4.44783 -0.0452,-0.8128 q 0.63218,-0.27093 1.37725,-0.54187 0.76764,-0.27093 1.39982,-0.51929 l -0.2032,1.87396 z m 4.15431,0 0.56445,-2.32551 q 0.69991,0.27093 1.4224,0.56444 0.72249,0.31609 1.35467,0.65476 l -0.0677,1.10631 z m -2.70933,0 v -14.63042 l 2.68676,-1.17404 1.2192,1.08373 v 14.72073 z m -1.67076,-13.88535 -0.11289,-1.08373 q 0.99342,-0.38382 2.14489,-0.58703 1.15147,-0.22577 2.34809,-0.24835 l 0.13547,0.94827 -1.87396,1.46755 z"
-         id="path3362" /><path
-         d="m 205.62146,130.51063 -2.032,-3.54472 q 1.33209,-0.4064 2.59644,-0.90311 1.26436,-0.47413 2.43841,-1.10631 -0.56445,-0.13547 -1.10632,-0.29351 -0.54186,-0.18062 -1.10631,-0.33867 l -3.34151,-9.18916 3.95111,-0.63218 1.55787,5.4864 0.18062,1.80623 h 0.38383 q 0.29351,-1.15147 0.56444,-2.37067 0.29351,-1.24178 0.54187,-2.48356 0.24835,-1.26436 0.42898,-2.4384 h 4.04142 q -0.38382,1.39982 -0.8128,2.93511 -0.42898,1.51271 -0.90311,3.048 -0.45156,1.53529 -0.99342,2.9577 -0.58703,1.46755 -1.42241,2.70933 -0.83537,1.26436 -2.032,2.32552 -1.19662,1.06115 -2.93511,2.032 z m 0.38382,-12.53068 -4.08658,-2.2352 0.0226,-1.24178 h 5.05742 z m 7.65388,-1.53529 -1.9417,-1.94169 h 3.58988 l 0.0451,1.10631 q -0.33867,0.24836 -0.79022,0.45156 -0.45156,0.2032 -0.90311,0.38382 z"
-         id="path3364" /></g><image
-       width="132.29167"
-       height="94.456253"
+     id="g18702"
+     transform="translate(-27.80428,-85.36057)"><g
+       id="g18822"><g
+         aria-label="-"
+         id="text8073"
+         style="font-weight:bold;font-size:22.5778px;font-family:Eczar;-inkscape-font-specification:'Eczar Bold';fill:#4c4f69;stroke:#eff1f5;stroke-width:0"
+         transform="matrix(9.1261894,0,0,8.9704849,-735.56656,-481.38493)"><path
+           d="m 90.970329,66.979522 -0.43231,-2.032002 0.474134,-1.278807 h 9.998077 l 0.67166,2.362542 -0.47413,0.948267 z"
+           style="fill:#eff1f5"
+           id="path8079" /></g><text
+         xml:space="preserve"
+         style="font-weight:bold;font-size:22.5778px;font-family:Eczar;-inkscape-font-specification:'Eczar Bold';fill:#232634;fill-opacity:1;stroke:#eff1f5;stroke-width:0"
+         x="95.381165"
+         y="110.48559"
+         id="text337"><tspan
+           id="tspan335"
+           style="fill:#232634;fill-opacity:1;stroke-width:0"
+           x="95.381165"
+           y="110.48559">chafa.py</tspan></text></g></g><g
+     id="g18694"
+     transform="translate(-30.407006,-85.018882)"><g
+       aria-label=".
+"
+       transform="matrix(1.1871339,-0.54655469,0.33137311,0.70099637,-0.91850948,-10.625671)"
+       id="text553"
+       style="font-weight:bold;font-size:272.295px;font-family:Eczar;-inkscape-font-specification:'Eczar Bold';fill:#eff1f5;fill-opacity:1;stroke:#eff1f5;stroke-width:0"><path
+         d="m 14.982733,201.68797 c -3.08601,-1.27071 -14.10196674,-9.65049 -17.9906194,-12.68914 -3.7177595,-2.90512 -7.1914086,-5.96356 -10.8220086,-9.04957 -3.44907,-3.08601 -5.327816,-4.18542 -7.506176,-7.0899 1.672658,-6.76422 3.143749,-13.87961 5.716702,-22.06466 2.567992,-8.16927 4.409101,-13.86793 8.0368196,-17.77563 3.5636505,-0.0338 16.8488846,10.57981 20.4203404,13.51315 3.720554,3.08236 7.26892,5.94458 10.35493,9.03059 2.784178,3.56741 1.875907,2.29097 3.691207,4.83239 -0.134012,4.42211 -2.175623,13.12873 -4.612393,21.40975 -2.429174,8.35428 -4.531277,13.74902 -7.288802,19.88302 z"
+         id="path557"
+         style="fill:#eff1f5;fill-opacity:1" /></g><g
+       aria-label=". "
+       transform="matrix(1.0912781,-0.50242282,0.30461622,0.64439403,3.8469652,-1.3489713)"
+       id="text553-52"
+       style="font-weight:bold;font-size:272.295px;font-family:Eczar;-inkscape-font-specification:'Eczar Bold';fill:#232634;fill-opacity:1;stroke:#eff1f5;stroke-width:0"><path
+         d="m 14.982733,201.68797 c -3.08601,-1.27071 -14.10196674,-9.65049 -17.9906194,-12.68914 -3.7177595,-2.90512 -7.1914086,-5.96356 -10.8220086,-9.04957 -3.44907,-3.08601 -5.327816,-4.18542 -7.506176,-7.0899 1.672658,-6.76422 3.143749,-13.87961 5.716702,-22.06466 2.567992,-8.16927 4.409101,-13.86793 8.0368196,-17.77563 3.5636505,-0.0338 16.8488846,10.57981 20.4203404,13.51315 3.720554,3.08236 7.26892,5.94458 10.35493,9.03059 2.784178,3.56741 1.875907,2.29097 3.691207,4.83239 -0.134012,4.42211 -2.175623,13.12873 -4.612393,21.40975 -2.429174,8.35428 -4.531277,13.74902 -7.288802,19.88302 z"
+         id="path557-0"
+         style="fill:#232634;fill-opacity:1" /></g><image
+       width="27.790932"
+       height="30.184408"
        preserveAspectRatio="none"
-       xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAAFlCAIAAACSjo07AAAEpWlUWHRYTUw6Y29tLmFkb2JlLnht
-cAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQi
-Pz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUg
-NS41LjAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIy
-LXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgeG1s
-bnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczpleGlmPSJo
-dHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyIKICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDov
-L25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIKICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFk
-b2JlLmNvbS94YXAvMS4wLyIKICAgIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hh
-cC8xLjAvbW0vIgogICAgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9z
-VHlwZS9SZXNvdXJjZUV2ZW50IyIKICAgdGlmZjpJbWFnZUxlbmd0aD0iMzU3IgogICB0aWZmOklt
-YWdlV2lkdGg9IjUwMCIKICAgdGlmZjpSZXNvbHV0aW9uVW5pdD0iMiIKICAgdGlmZjpYUmVzb2x1
-dGlvbj0iOTYvMSIKICAgdGlmZjpZUmVzb2x1dGlvbj0iOTYvMSIKICAgZXhpZjpQaXhlbFhEaW1l
-bnNpb249IjUwMCIKICAgZXhpZjpQaXhlbFlEaW1lbnNpb249IjM1NyIKICAgZXhpZjpDb2xvclNw
-YWNlPSIxIgogICBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIgogICBwaG90b3Nob3A6SUNDUHJvZmls
-ZT0ic1JHQiBJRUM2MTk2Ni0yLjEiCiAgIHhtcDpNb2RpZnlEYXRlPSIyMDIzLTAxLTA2VDA0OjA5
-OjIyWiIKICAgeG1wOk1ldGFkYXRhRGF0ZT0iMjAyMy0wMS0wNlQwNDowOToyMloiPgogICA8eG1w
-TU06SGlzdG9yeT4KICAgIDxyZGY6U2VxPgogICAgIDxyZGY6bGkKICAgICAgc3RFdnQ6YWN0aW9u
-PSJwcm9kdWNlZCIKICAgICAgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWZmaW5pdHkgUGhvdG8gMS4x
-MC41IgogICAgICBzdEV2dDp3aGVuPSIyMDIzLTAxLTA2VDA0OjA5OjIyWiIvPgogICAgPC9yZGY6
-U2VxPgogICA8L3htcE1NOkhpc3Rvcnk+CiAgPC9yZGY6RGVzY3JpcHRpb24+CiA8L3JkZjpSREY+
-CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+peMgQAAAAYFpQ0NQc1JHQiBJRUM2MTk2
-Ni0yLjEAACiRdZG7SwNBEIe/JGpEIwpaWFgEUQtJJCoEbSwSfIFaJBGM2iSXl5DHcZcgwVawDSiI
-Nr4K/Qu0FawFQVEEsdVa0UblnEuEiJhZdvbb384Mu7NgDaWVjF7ngUw2rwUmfc6F8KLT/oSFBmx4
-6I8oujobnAhR095vJVrs2m3Wqh33rzXH4roClkbhMUXV8sJTwjOredXkLeEOJRWJCZ8IuzS5oPCN
-qUcr/GxyssKfJmuhgB+sbcLO5C+O/mIlpWWE5eX0ZNIF5ec+5ksc8ex8UNZumV3oBJjEh5NpxvHj
-ZZBR8V7cDDEgO2rke8r5c+QkVxGvUkRjhSQp8rhELUj1uKwJ0eMy0hTN/v/tq54YHqpUd/ig/tEw
-XnvBvglfJcP4ODCMr0OwPcB5tpqf24eRN9FLVa1nD1rX4fSiqkW34WwDOu/ViBYpSzaZ1kQCXo6h
-JQztV9C0VOnZzzlHdxBak6+6hJ1d6JP41uVvcdJn61F1L0wAAAAJcEhZcwAADsQAAA7EAZUrDhsA
-ACAASURBVHic7d13lJxXmefxN1Xu6qRu5WRJlizL2BKWLCNbso2xDXiwCbtrs2b2LBNYmGHPDMws
-YcPAeGdgWc5wdjgDHNJZGOAQjw0O2GCcs4yQZeVk5dRS5+7qSm+9+8caU9WWvi1VdaXbv89fLj1+
-3/dWun3rvs99rv0fPvZB69xc14NoUChANBmJQLSrvR2is7u6IXrVyisgumjhYojGogmI2uEwRC3b
-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
-GOj/AU3WtmkN62aeAAAAAElFTkSuQmCC
+       style="image-rendering:optimizeSpeed"
+       xlink:href="data:image/png;base64,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
 "
-       id="image3489"
-       x="-15.042126"
-       y="72.208092" /></g></svg>
+       id="image18760"
+       x="42.616947"
+       y="88.641022" /><text
+       xml:space="preserve"
+       style="font-weight:bold;font-size:12.0046px;font-family:Eczar;-inkscape-font-specification:'Eczar Bold';fill:#eff1f5;fill-opacity:1;stroke:#eff1f5;stroke-width:0"
+       x="37.129749"
+       y="96.766037"
+       id="text690"><tspan
+         id="tspan688"
+         style="fill:#eff1f5;fill-opacity:1;stroke-width:0"
+         x="37.129749"
+         y="96.766037">&gt;</tspan></text></g></svg>
diff --git a/libs/macos/MACOS_DYLIBS_GO_HERE b/libs/macos/MACOS_DYLIBS_GO_HERE
new file mode 100644
index 0000000..e69de29
diff --git a/pyproject.toml b/pyproject.toml
index 9916a2b..bc5ceab 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -31,12 +31,19 @@ classifiers = [
 
 [tool.cibuildwheel]
 build = "cp3*-*"
-skip = ["*-manylinux_i686", "*-musllinux_*", "*-win32", "*macosx*"]
+skip  = ["*-manylinux_i686", "*-musllinux_*", "*-win32"]
+
 manylinux-x86_64-image = "manylinux2014"
 
+test-requires = ["pytest", "Pillow", "numpy"]
+test-command  = "pytest {package}/tests"
+
+
+
+
 [tool.cibuildwheel.linux]
 before-all = [
-    "yum install -y libtool",
+    "yum install -y libtool ImageMagick-devel",
     "cd libs",
     "git clone https://github.com/hpjansson/chafa libchafa_src",
     "cd libchafa_src",
@@ -45,12 +52,30 @@ before-all = [
     "./autogen.sh --without-tools",
     "make",
     "cd ../",
-    "cp libchafa_src/chafa/.libs/*chafa.so linux/",
-    "cd .."
+    "cp libchafa_src/chafa/.libs/*chafa.so linux/"
 ]
 
 repair-wheel-command = "auditwheel repair -w {dest_dir} {wheel}"
 
+[tool.cibuildwheel.macos]
+before-all = [
+    "NONINTERACTIVE=1 /bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"",
+    "brew install make libtool pkg-config glib automake imagemagick",
+    "ln -s $(which glibtoolize) /usr/local/bin/libtoolize",
+    "git clone https://github.com/hpjansson/chafa libchafa_src",
+    "cd libchafa_src",
+    "./autogen.sh --without-tools",
+    "make",
+    "cd ..",
+    "cp libchafa_src/chafa/.libs/*chafa*.dylib libs/macos"
+]
+
+test-command = "MAGICK_HOME=/usr/local/Cellar/imagemagick/ pytest {package}/tests"
+
+[tool.cibuildwheel.windows]
+
+test-command = "pytest {package}/tests/0_PIL_test.py"
+
 [tool.hatch.build]
 exclude = [
     ".github",
diff --git a/src/chafa/chafa.py b/src/chafa/chafa.py
index 066668b..06b43ae 100644
--- a/src/chafa/chafa.py
+++ b/src/chafa/chafa.py
@@ -3,23 +3,30 @@
 from enum import IntEnum
 from collections.abc import Iterable
 import array
-
+from pathlib import Path
 import os
-import sys
+import platform
 
 #  CHAFA LETS GOOOOOOO!!!
-_library_path = os.path.dirname(__file__) + os.path.sep + "libs"
+_root_dir = Path(os.path.dirname(__file__)) 
 
 # Figure out which libraries we need to import
-if sys.platform == "linux":
+if platform.system() == "Linux":
     _lib_glib = "libglib-2.0.so"
-    _lib = _library_path + os.path.sep + "libchafa.so"
+    _lib      = str(_root_dir / "libs" / "libchafa.so")
 
-elif sys.platform == "win32":
+elif platform.system() == "Windows":
     os.add_dll_directory(os.path.dirname(__file__))
 
-    _lib_glib = _library_path + os.path.sep + "libglib-2.0-0.dll"
-    _lib = _library_path + os.path.sep + "libchafa.dll"
+    _lib_glib = str(_root_dir / "libs" / "libglib-2.0-0.dll")
+    _lib      = str(_root_dir / "libs" / "libchafa.dll")
+
+elif platform.system() == "Darwin":
+    _lib_glib = str(_root_dir / ".dylibs" / "libglib-2.0.0.dylib")
+    _lib      = str(_root_dir / "libs"    / "libchafa.dylib")
+
+else:
+    raise ImportError("You appear to be running on an unsupported system.")
 
 _Chafa = ctypes.CDLL(_lib)
 
diff --git a/src/chafa/loader.py b/src/chafa/loader.py
index 5dfc1b0..da16cc5 100644
--- a/src/chafa/loader.py
+++ b/src/chafa/loader.py
@@ -2,7 +2,7 @@
 import ctypes
 from pathlib import Path
 from chafa import PixelType
-import sys
+import platform
 import os
 
 def _get_library_name():
@@ -12,7 +12,7 @@ def _get_library_name():
     """
     libwand = None
 
-    if sys.platform == "win32":
+    if platform.system() == "Windows":
         import winreg
 
         # Query registry for imageMagick and add it to our dll path
@@ -22,29 +22,45 @@ def _get_library_name():
 
             libwand = "CORE_RL_MagickWand_"
 
-    else:
-        versions = [
-            "",
-            "-7",
-            "-7.Q8",
-            "-7.Q16",
-            "-6",
-            "-Q16",
-            "-Q8",
-            "-6.Q16"
-        ]
+        return libwand
+
+    versions = [
+        "",
+        "-7",
+        "-7.Q8",
+        "-7.Q16",
+        "-6",
+        "-Q16",
+        "-Q8",
+        "-6.Q16"
+    ]
+
+    # Check if we have a MAGICK_HOME env set
+    magick_home = os.environ.get("MAGICK_HOME")
+
 
-        i = 0
-        while i < len(versions) and not libwand:
-            libwand = ctypes.util.find_library(f"MagickWand{versions[i]}")
-            i += 1
+    if magick_home:
+        file_type = ".so" if platform.system() == "Linux" else ".dylib"
+        libwand   = list(Path(magick_home).glob(f"**/*MagickWand*{file_type}"))
+
+        if len(libwand) > 0:
+            libwand = libwand[0]
+
+            return libwand
+
+    # Last resort is to iterate over versions
+    i = 0
+    while i < len(versions) and not libwand:
+        libwand = ctypes.util.find_library(f"MagickWand{versions[i]}")
+        i += 1
 
     return libwand
 
+
 # Try to find library and raise ImportError if it isn't found
 _lib = _get_library_name()
 
-if _lib is None:
+if not _lib:
     raise ImportError("MagickWand library not found.")
 
 _MagickWand = ctypes.CDLL(_lib)


Test patch:
diff --git a/tests/0_PIL_test.py b/tests/0_PIL_test.py
new file mode 100644
index 0000000..0f671a3
--- /dev/null
+++ b/tests/0_PIL_test.py
@@ -0,0 +1,38 @@
+from chafa import *
+from PIL import Image
+import numpy as np
+from pathlib import Path
+
+def test_PIL():
+    # Init canvas config
+    config = CanvasConfig()
+
+    # Set canvas height and width
+    config.height = 30
+    config.width  = 30
+
+    # Open image with PIL
+    image = Image.open(Path(__file__).parent / "snake.jpg")
+
+    width  = image.width
+    height = image.height
+    bands  = len(image.getbands())
+
+    # Put image into correct format
+    pixels = np.array(image)
+    pixels = np.reshape(pixels, pixels.size)
+
+    # Init the canvas
+    canvas = Canvas(config)
+
+    # Draw to canvas
+    canvas.draw_all_pixels(
+        PixelType.CHAFA_PIXEL_RGB8,
+        pixels,
+        height,
+        width,
+        width * bands
+    )
+
+    # Write picture
+    print(canvas.print().decode())
\ No newline at end of file
diff --git a/tests/1_aspect_test.py b/tests/1_aspect_test.py
new file mode 100644
index 0000000..d95c767
--- /dev/null
+++ b/tests/1_aspect_test.py
@@ -0,0 +1,46 @@
+from chafa import *
+from chafa.loader import Loader
+
+from pathlib import Path
+
+FONT_WIDTH  = 11
+FONT_HEIGHT = 24
+
+import platform
+
+def test_aspect():
+    # Init canvas config
+    config = CanvasConfig()
+
+    # Set canvas height, width and cell geometry
+    config.height = 30
+    config.width  = 30
+
+    # Set the canvas cell geometry
+    config.cell_height = FONT_HEIGHT
+    config.cell_width  = FONT_WIDTH
+
+    # Open image with the loader
+    image = Loader(Path(__file__).parent / "snake.jpg")
+
+    width      = image.width
+    height     = image.height
+    rowstride  = image.rowstride
+
+    # Calculate the appropriate geometry for the canvas
+    config.calc_canvas_geometry(width, height, FONT_WIDTH/FONT_HEIGHT)
+
+    # Init the canvas
+    canvas = Canvas(config)
+
+    # Draw to canvas
+    canvas.draw_all_pixels(
+        image.pixel_type,
+        image.get_pixels(),
+        width,
+        height,
+        rowstride
+    )
+
+    # Write picture
+    print(canvas.print().decode())
\ No newline at end of file
diff --git a/tests/snake.jpg b/tests/snake.jpg
new file mode 100644
index 0000000..fdbed71
Binary files /dev/null and b/tests/snake.jpg differ