{"id":17965160,"url":"https://github.com/tokenrove/imago","last_synced_at":"2025-04-03T19:43:50.523Z","repository":{"id":28218826,"uuid":"31723026","full_name":"tokenrove/imago","owner":"tokenrove","description":"image manipulation library for Common Lisp","archived":false,"fork":false,"pushed_at":"2025-01-23T09:57:58.000Z","size":2962,"stargazers_count":54,"open_issues_count":2,"forks_count":10,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-23T07:19:42.660Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://common-lisp.net/project/imago","language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tokenrove.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-03-05T16:17:12.000Z","updated_at":"2025-02-16T17:41:50.000Z","dependencies_parsed_at":"2023-01-14T08:22:35.525Z","dependency_job_id":"abb0c381-886f-4c06-a59a-281052e4eed8","html_url":"https://github.com/tokenrove/imago","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tokenrove%2Fimago","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tokenrove%2Fimago/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tokenrove%2Fimago/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tokenrove%2Fimago/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tokenrove","download_url":"https://codeload.github.com/tokenrove/imago/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247070779,"owners_count":20878581,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-29T12:10:19.778Z","updated_at":"2025-04-03T19:43:50.479Z","avatar_url":"https://github.com/tokenrove.png","language":"Common Lisp","readme":"# Imago\n![CI](https://github.com/tokenrove/imago/workflows/CI/badge.svg)\n\nImago is an image manipulation library for Common Lisp. It supports images in\npng, pcx, portable bitmap (.pnm), Truevision TGA (.tga) and jpeg formats. You\ncan read an image with `imago:read-image` and write an image with\n`imago:write-format` where `format` is one of `png`, `pcx`, `pnm`, `tga` or\n`jpg`.\n\n## Reading from and writing to jpeg files with libjpeg-turbo\n\nYou can use more advanced [libjpeg-turbo](https://libjpeg-turbo.org/) library to\ndeal with jpeg files by loading `imago/jpeg-turbo` system. Make sure that\n`libjpeg-turbo` is installed on your system. Use\n`imago-jpeg-turbo:read-jpg-turbo` and `imago-jpeg-turbo:write-jpg-turbo`\nfunctions (or just `imago:read-image` and `imago:write-image`) to use this\nfunctionality.\n\n## Alternative png I/O with imago/pngio\n\nYou can use more advanced and faster\n[pngload](https://github.com/bufferswap/pngload) library to read png files by\nloading `imago/pngio` system. Use `imago-pngio:read-png` (or just\n`imago:read-image`) to use this functionality. **NB:** `pngload` automatically\nconverts indexed color images to RGB (or ARGB) images. If you want to work with\nindexed images, use old png loader instead. Also\n[zpng](https://github.com/xach/zpng) (via `imago-pngio:write-png`) library will\nbe used for saving png images.\n\n## Creating an image\n\nTo create an image look at the documentation for image classes (like\n`imago:rgb-image` or `imago:grayscale-image`). You need to make an instance of\none of those classes by passing `:w`, `:h` and optionally `:initial-color`\nkeyword arguments to `make-instance`. Alternatively, you can use\n`make-XXX-image` and `make-XXX-image-from-pixels` functions:\n\n~~~~{.lisp}\n;; Create 100x100 px black grayscale image\n(imago:make-grayscale-image 100 100)\n\n;; Create 400x100 px red RGB image\n(imago:make-rgb-image 400 100 (imago:make-color 255 0 0))\n\n;; Create 400x100 px half-transparent red RGB image\n(imago:make-rgb-image 400 100 (imago:make-color 255 0 0 127))\n\n;; Create an image from an array of pixels\n(imago:make-rgb-image-from-pixels\n (make-array '(100 100)\n             :element-type 'imago:rgb-pixel\n             :initial-element (imago:make-color 0 255 255)))\n~~~~\n\n## Usage examples\n\nMost of the examples are taken from\n[here](http://matthieu.villeneuve.free.fr/dev/imago/examples.html).\n\n### Resizing an image\n\n`(resize *image* 400 150)`\n\n| Original | Processed |\n| -------- | --------- |\n| ![Original](docs/country.png) | ![Resized](docs/country-resize.png) |\n\n### Rotating an image\n\n`(rotate *image* 45)`\n\n| Original | Processed |\n| -------- | --------- |\n| ![Original](docs/lena.png) | ![Resized](docs/lena-rot.png) |\n\n\n### Applying an emboss effect\n\n`(emboss *image* :angle (* pi 0.75) :depth 1.0)`\n\n| Original | Processed |\n| -------- | --------- |\n| ![Original](docs/horse.png) | ![Processed](docs/horse-emboss.png) |\n\n### Using a custom convolution kernel\n\n~~~~{.lisp}\n(let ((kernel #2A((0  0  0  0  0)\n                  (0  0  1  0  0)\n                  (0  1 -4  1  0)\n                  (0  0  1  0  0)\n                  (0  0  0  0  0))))\n  (convolve *image* kernel 1 0))\n~~~~\n\n| Original | Processed |\n| -------- | --------- |\n| ![Original](docs/car.png) | ![Processed](docs/car-edge-detect.png) |\n\n### Inverting a rectangular region\n\n~~~~\n(do-region-pixels (*image* color x y 70 65 140 125)\n  (setf color (invert-color color)))\n~~~~\n\n| Original | Processed |\n| -------- | --------- |\n| ![Original](docs/oranges.png) | ![Processed](docs/oranges-region-invert.png) |\n\n### Adjusting contrast of a grayscale image\n\n~~~~\n(enhance-contrast *grayscale-image*)\n~~~~\n\n| Original | Processed |\n| -------- | --------- |\n| ![Original](docs/house.jpg) | ![Processed](docs/house-enchanced-contrast.jpg) |\n\n### Manipulating color components\n\n~~~~{.lisp}\n(do-image-pixels (*image* color x y)\n  (multiple-value-bind (r g b) (color-rgb color)\n    (setf color (make-color b\n                            (floor (* g 0.8))\n                            r))))\n~~~~\n\n| Original | Processed |\n| -------- | --------- |\n| ![Original](docs/flowers.png) | ![Processed](docs/flowers-color-change.png) |\n\n### Composing pictures\n\n~~~~{.lisp}\n(let ((operator (default-compose-operator *image1*)))\n  (compose nil *image1* *image2* 20 20 operator))\n~~~~\n\n| Original 1 | Original 2 | Processed |\n| ---------- | ---------- | --------- |\n| ![City](docs/city.png) | ![Text](docs/text.png) | ![Composed](docs/city-text.png) |\n\n### Drawing simple primitives\n\n~~~~{.lisp}\n(let ((points '(83 45 73 150 73 150 198 106 198 106 83 45)))\n  (draw-polygon *image* points +white+ :closed t))\n(draw-circle *image* 83 45 15 +white+)\n(draw-circle *image* 73 150 15 +white+)\n(draw-circle *image* 198 106 15 +white+)\n(draw-bezier-curve *image* 10 80 150 60 100 170 200 170 +red+)\n(draw-line *image* 0 5 254 5 +yellow+)\n(draw-line *image* 0 10 254 10 +yellow+ :dash-length 1 :dash-interval 1)\n(draw-line *image* 0 15 254 15 +yellow+ :dash-length 4 :dash-interval 2)\n~~~~\n\n| Original | Processed |\n| -------- | --------- |\n| ![Original](docs/fish.png) | ![Processed](docs/fish-drawing.png) |\n\n### A more complex example\n\n~~~~{.lisp}\n(defun sea-view (image)\n  (let ((image2 (flip nil image :horizontal)))\n    (do-image-pixels (image2 color x y)\n      (multiple-value-bind (r g b)\n          (color-rgb color)\n        (setf color (make-color (floor r 3) (floor g 3) (floor b 2)))))\n    (let* ((width (image-width image))\n           (height (image-height image))\n           (result (make-instance (class-of image)\n                                  :width width :height (* height 2))))\n      (copy result image)\n      (copy result image2 :dest-y height)\n      result)))\n~~~~\n\n| Original | Processed |\n| -------- | --------- |\n| ![Original](docs/citynight.png) | ![Processed](docs/citynight-sea.png) |\n\n### Connected components labeling\n\nThis example requires snakes and array-operations systems (available in\nquicklisp).\n\n~~~~{.lisp}\n(defpackage components-example\n  (:use #:cl\n        #:snakes\n        #:imago)\n  (:export #:convert-to-image))\n(in-package :components-example)\n\n(defgenerator generate-colors ()\n  (loop while t do\n    (yield (make-color (random 256)\n                       (random 256)\n                       (random 256)))))\n\n(defgenerator black ()\n  (yield (make-color 0 0 0)))\n\n(defun convert-to-image (components)\n  (declare (type (simple-array fixnum (* *)) components))\n  (let ((colors (take (1+ (reduce #'max (aops:flatten components)))\n                      (chain (black)\n                             (generate-colors))))\n        (image (make-array (array-dimensions components)\n                           :element-type 'rgb-pixel)))\n    (array-operations/utilities:nested-loop (i j)\n        (array-dimensions components)\n      (setf (aref image i j)\n            (nth (aref components i j) colors)))\n    (make-instance 'rgb-image :pixels image)))\n\n(in-package :cl-user)\n(let* ((image (imago:read-image \"~/.quicklisp/local-projects/imago/tests/spheres.png\"))\n       (components (imago:label-components (imago:convert-to-binary image 1))))\n  (components-example:convert-to-image components))\n~~~~\n\n| Original | Processed |\n| -------- | --------- |\n| ![Original](tests/spheres.png) | ![Processed](docs/spheres-colored.png) |\n\n\n### Distance transform\n\nCalculating squared Euclidean distance transform (also Manhattan distance\ntransform is available). This example requires `array-operations`.\n\n~~~~{.lisp}\n(defun edt-image (image)\n  (declare (type imago:binary-image image))\n  (let* ((dt (imago:distance-transform image :type :edt))\n         (max (reduce #'max (aops:flatten dt)))\n         (pixels (make-array (array-dimensions dt) :element-type 'imago:grayscale-pixel)))\n    (map-into (aops:flatten pixels)\n              (lambda (x) (imago:make-gray (floor (* 255 x) max)))\n              (aops:flatten dt))\n    (make-instance 'imago:grayscale-image :pixels pixels)))\n\n(edt-image original-image)\n~~~~\n\n| Original | Processed |\n| -------- | --------- |\n| ![Original](docs/edt-orig.png) | ![Processed](docs/edt.png) |\n\n## Intergation with common-lisp-jupyter\n\nYou can view imago images in Jupyter by installing `imago/jupyter`\nsystem. Then call `imago-jupyter:show-image` function to show an image.\n\n![Jupyter example](docs/jupyter.png)\n","funding_links":[],"categories":["Miscellaneous ##"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftokenrove%2Fimago","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftokenrove%2Fimago","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftokenrove%2Fimago/lists"}