diff --git a/recipes/mimage/README.md b/recipes/mimage/README.md new file mode 100644 index 00000000..471d789d --- /dev/null +++ b/recipes/mimage/README.md @@ -0,0 +1,83 @@ +
+
+ + Logo + + +

Mimage

+ +

+ A library for reading images in pure* Mojo 🔥 + + ![Language Badge](https://img.shields.io/badge/language-mojo-orange) + ![CodeQL](https://github.com/fnands/mimage/workflows/CodeQL/badge.svg) +

+
+ +*Not pure Mojo yet, but hopefully soon. +## About The Project + +Mimage is a image manipulation library loosely based on Python's [Pillow](https://github.com/python-pillow/Pillow). The goal is to be able to read and write the most popular image formats directly from Mojo. + +## Quick Start + +Basic usage: + +```mojo +import mimage as mi + +def main(): + + tensor = mi.imread("my/png/image.png") + +``` + +Try out the tests yourself: + +```sh +mojo -I . tests/test_open_png.mojo +``` + +## Roadmap + +### v0.1.0 ✅ +- [x] Read simple 8-bit PNGs + +### Near term +- [ ] Read jpegs + +### Medium term +- [ ] Read more complex PNGs +- [ ] Write PNGs +- [ ] Write jpegs + +### Long term +- [ ] v1.0.0 will be achieved when Mimage can open all the same images as Pillow. + + +## Contributing + +Before creating a new issue, please: +* Check if the issue already exists. If an issue is already reported, you can contribute by commenting on the existing issue. +* If not, create a new issue and include all the necessary details to understand/recreate the problem or feature request. + +### Creating A Pull Request + +1. Fork the Project +2. Create your Feature Branch +3. Commit your Changes +4. Push to the Branch +5. Open a Pull Request +> Once your changes are pushed, navigate to your fork on GitHub. And create a pull request against the original fnands/mimage repository. +> - Before creating a PR make sure it doesn't break any of the unit-tests. (e.g. `mojo -I . tests/test_open_png.mojo`) +> - Introducing new big features requires a new test! +> - In the pull request, provide a detailed description of the changes and why they're needed. Link any relevant issues. +> - If there are any specific instructions for testing or validating your changes, include those as well. + +## License + +Distributed under the Apache 2.0 License with LLVM Exceptions. See [LICENSE](https://github.com/fnands/mimage/blob/main/LICENSE) and the LLVM [License](https://llvm.org/LICENSE.txt) for more information. + +## Acknowledgements + +* Built with [Mojo](https://github.com/modularml/mojo) created by [Modular](https://github.com/modularml) \ No newline at end of file diff --git a/recipes/mimage/image.jpeg b/recipes/mimage/image.jpeg new file mode 100644 index 00000000..d273c2c3 Binary files /dev/null and b/recipes/mimage/image.jpeg differ diff --git a/recipes/mimage/recipe.yaml b/recipes/mimage/recipe.yaml new file mode 100644 index 00000000..720765bc --- /dev/null +++ b/recipes/mimage/recipe.yaml @@ -0,0 +1,51 @@ +context: + version: "0.2.3" + +package: + name: "mimage" + version: ${{ version }} + +source: + - git: https://github.com/fnands/mimage.git + tag: "0.2.3" + +build: + number: 0 + script: + - mojo package mimage -o ${{ PREFIX }}/lib/mojo/mimage.mojopkg +requirements: + host: + - max=25.2 + run: + - ${{ pin_compatible('max') }} + +tests: + - script: + - if: unix + then: + - mojo run -I ${{ PREFIX }}/lib/mojo/mimage.mojopkg tests/test_open_png.mojo + + requirements: + run: + - max=25.2 + - pillow + - numpy + + files: + recipe: + - tests/test_open_png.mojo + - tests/testing_utils.mojo + - tests/__init__.mojo + - tests/images/hopper.png + +about: + homepage: https://github.com/fnands/mimage + license: Apache-2.0 + license_file: LICENSE + summary: mimage is a library for image processing in Mojo 🔥. + repository: https://github.com/fnands/mimage + +extra: + project_name: mimage + maintainers: + - fnands diff --git a/recipes/mimage/tests/__init__.mojo b/recipes/mimage/tests/__init__.mojo new file mode 100644 index 00000000..89754539 --- /dev/null +++ b/recipes/mimage/tests/__init__.mojo @@ -0,0 +1 @@ +from .testing_utils import * diff --git a/recipes/mimage/tests/images/hopper.png b/recipes/mimage/tests/images/hopper.png new file mode 100644 index 00000000..60ac671a Binary files /dev/null and b/recipes/mimage/tests/images/hopper.png differ diff --git a/recipes/mimage/tests/test_open_png.mojo b/recipes/mimage/tests/test_open_png.mojo new file mode 100644 index 00000000..0bad4c61 --- /dev/null +++ b/recipes/mimage/tests/test_open_png.mojo @@ -0,0 +1,11 @@ +import mimage as mi +from pathlib import Path +from tests import compare_to_numpy + + +def main(): + hop_tensor = mi.imread("tests/images/hopper.png") + hop_tensor = mi.imread(String("tests/images/hopper.png")) + hop_tensor = mi.imread(Path("tests/images/hopper.png")) + + compare_to_numpy(hop_tensor, "tests/images/hopper.png") diff --git a/recipes/mimage/tests/testing_utils.mojo b/recipes/mimage/tests/testing_utils.mojo new file mode 100644 index 00000000..bfd21f8d --- /dev/null +++ b/recipes/mimage/tests/testing_utils.mojo @@ -0,0 +1,17 @@ +from tensor import Tensor +from python import Python +from testing import assert_true + + +fn compare_to_numpy(mojo_tensor: Tensor, image_path: StringLiteral) raises: + var PillowImage = Python.import_module("PIL.Image") + var np = Python.import_module("numpy") + var py_array = np.array(PillowImage.open(image_path)) + + for rows in range(mojo_tensor.shape()[0]): + for columns in range(mojo_tensor.shape()[1]): + for channels in range(mojo_tensor.shape()[2]): + assert_true( + mojo_tensor[rows, columns, channels] == py_array[rows][columns][channels].__int__(), + "Pixel values do not match", + )