www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - daffodil, a D image processing library

reply Benjamin Schaaf <ben.schaaf gmail.com> writes:
daffodil is a image processing library inspired by python's 
Pillow (https://pillow.readthedocs.org/). It is an attempt at 
designing a clean, extensible and transparent API.

https://github.com/BenjaminSchaaf/daffodil
https://benjaminschaaf.github.io/daffodil/

The library makes full use out of D's templates and 
metaprogramming. The internal storage mechanism is entirely 
configurable from almost every endpoint. File headers are 
directly loaded into structs defining them, removing most of the 
difficulties in reading them according to spec. The image type 
and loading API is entirely extensible, making extra image 
formats entirely self-contained.

Currently only loading and saving of simple BMP images is 
supported, with convolution and Gaussian Blur filters and flip 
transformations. Its still early in development, but I'd love to 
get some feedback on it.

Example:
---
import daffodil;
import daffodil.filter;
import daffodil.transform;

void main() {
     auto image = load!32("daffodil.bmp");

     image.gaussianBlurred(1.4).save("blurry_daffodil.bmp");

     image.flipped!"y".save("upside_down_daffodil.bmp");
}
---

The license is MIT, so feel free to do whatever you want with the 
code. Issues and pull requests are of course welcome ;)

Alongside I've also written (an admittedly hacky) sphinx 
(http://www.sphinx-doc.org/en/stable/) extension that provides a 
domain and autodocumenter for D, using libdparse and pyd.
Jun 30 2016
next sibling parent reply rikki cattermole <rikki cattermole.co.nz> writes:
On 01/07/2016 9:35 AM, Benjamin Schaaf wrote:
 daffodil is a image processing library inspired by python's Pillow
 (https://pillow.readthedocs.org/). It is an attempt at designing a
 clean, extensible and transparent API.

 https://github.com/BenjaminSchaaf/daffodil
 https://benjaminschaaf.github.io/daffodil/

 The library makes full use out of D's templates and metaprogramming. The
 internal storage mechanism is entirely configurable from almost every
 endpoint. File headers are directly loaded into structs defining them,
 removing most of the difficulties in reading them according to spec. The
 image type and loading API is entirely extensible, making extra image
 formats entirely self-contained.

 Currently only loading and saving of simple BMP images is supported,
 with convolution and Gaussian Blur filters and flip transformations. Its
 still early in development, but I'd love to get some feedback on it.

 Example:
 ---
 import daffodil;
 import daffodil.filter;
 import daffodil.transform;

 void main() {
     auto image = load!32("daffodil.bmp");

     image.gaussianBlurred(1.4).save("blurry_daffodil.bmp");

     image.flipped!"y".save("upside_down_daffodil.bmp");
 }
 ---

 The license is MIT, so feel free to do whatever you want with the code.
 Issues and pull requests are of course welcome ;)

 Alongside I've also written (an admittedly hacky) sphinx
 (http://www.sphinx-doc.org/en/stable/) extension that provides a domain
 and autodocumenter for D, using libdparse and pyd.
Doesn't use allocators or Manu's color work, yup yup not interested.
Jun 30 2016
next sibling parent reply Jack Stouffer <jack jackstouffer.com> writes:
On Friday, 1 July 2016 at 01:24:55 UTC, rikki cattermole wrote:
 Doesn't use allocators or Manu's color work, yup yup not 
 interested.
Way to be a dismissive asshole. Let me rewrite that sentence for you: "Hey, nice work, we really need something like this. I'm a bit concerned about the GC usage though, have you checked out std.allocators or the proposed std.color? I think these will help make your library much faster."
Jun 30 2016
next sibling parent rikki cattermole <rikki cattermole.co.nz> writes:
On 01/07/2016 1:47 PM, Jack Stouffer wrote:
 On Friday, 1 July 2016 at 01:24:55 UTC, rikki cattermole wrote:
 Doesn't use allocators or Manu's color work, yup yup not interested.
Way to be a dismissive asshole. Let me rewrite that sentence for you: "Hey, nice work, we really need something like this. I'm a bit concerned about the GC usage though, have you checked out std.allocators or the proposed std.color? I think these will help make your library much faster."
I thought I was being quite lighthearted really given how many different implementations there are these days. If the author would like me to apologize I will.
Jun 30 2016
prev sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
On Friday, 1 July 2016 at 01:47:44 UTC, Jack Stouffer wrote:
 Way to be a dismissive asshole.
why so serious? it is clearly a joke.
Jun 30 2016
prev sibling next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
On Friday, 1 July 2016 at 01:24:55 UTC, rikki cattermole wrote:
 Doesn't use allocators
great library! definitely worth a closer look.
Jun 30 2016
prev sibling parent reply Benjamin Schaaf <ben.schaaf gmail.com> writes:
On Friday, 1 July 2016 at 01:24:55 UTC, rikki cattermole wrote:
 On 01/07/2016 9:35 AM, Benjamin Schaaf wrote:
 daffodil is a image processing library inspired by python's 
 Pillow
 (https://pillow.readthedocs.org/). It is an attempt at 
 designing a
 clean, extensible and transparent API.

 https://github.com/BenjaminSchaaf/daffodil
 https://benjaminschaaf.github.io/daffodil/

 The library makes full use out of D's templates and 
 metaprogramming. The
 internal storage mechanism is entirely configurable from 
 almost every
 endpoint. File headers are directly loaded into structs 
 defining them,
 removing most of the difficulties in reading them according to 
 spec. The
 image type and loading API is entirely extensible, making 
 extra image
 formats entirely self-contained.

 Currently only loading and saving of simple BMP images is 
 supported,
 with convolution and Gaussian Blur filters and flip 
 transformations. Its
 still early in development, but I'd love to get some feedback 
 on it.

 Example:
 ---
 import daffodil;
 import daffodil.filter;
 import daffodil.transform;

 void main() {
     auto image = load!32("daffodil.bmp");

     image.gaussianBlurred(1.4).save("blurry_daffodil.bmp");

     image.flipped!"y".save("upside_down_daffodil.bmp");
 }
 ---

 The license is MIT, so feel free to do whatever you want with 
 the code.
 Issues and pull requests are of course welcome ;)

 Alongside I've also written (an admittedly hacky) sphinx
 (http://www.sphinx-doc.org/en/stable/) extension that provides 
 a domain
 and autodocumenter for D, using libdparse and pyd.
Doesn't use allocators or Manu's color work, yup yup not interested.
In terms of std.experimental.color, one of the things I focused on was extensibility. What if someone came along and had their own color space they needed to implement? With std.experimental.color, the only option you currently have is editing the library. If it gets included into phobos, then suddenly your "I want to implement my own color space" has turned into editing the standard library. Albeit currently rough around the edges, all you have to do to implement your own color space in daffodil, is to implement the ColorSpace interface. I haven't looked into using allocators yet, but I've put it on the horizon.
Jul 01 2016
next sibling parent reply Edwin van Leeuwen <edder tkwsping.nl> writes:
On Friday, 1 July 2016 at 08:11:37 UTC, Benjamin Schaaf wrote:
 On Friday, 1 July 2016 at 01:24:55 UTC, rikki cattermole wrote:
 On 01/07/2016 9:35 AM, Benjamin Schaaf wrote:

 Doesn't use allocators or Manu's color work, yup yup not 
 interested.
In terms of std.experimental.color, one of the things I focused on was extensibility.
Also, the only way currently to use Manu's color work is to install his phobos branch. The dub package will throw unittest errors and loads of deprecation warnings.
Jul 01 2016
parent reply Manu via Digitalmars-d-announce <digitalmars-d-announce puremagic.com> writes:
On 1 July 2016 at 18:19, Edwin van Leeuwen via Digitalmars-d-announce
<digitalmars-d-announce puremagic.com> wrote:
 On Friday, 1 July 2016 at 08:11:37 UTC, Benjamin Schaaf wrote:
 On Friday, 1 July 2016 at 01:24:55 UTC, rikki cattermole wrote:
 On 01/07/2016 9:35 AM, Benjamin Schaaf wrote:

 Doesn't use allocators or Manu's color work, yup yup not interested.
In terms of std.experimental.color, one of the things I focused on was extensibility.
Also, the only way currently to use Manu's color work is to install his phobos branch. The dub package will throw unittest errors and loads of deprecation warnings.
Really? Nobody ever mentioned that before. I don't use dub, so I didn't notice... but I thought the code there was up to date...?
Jul 04 2016
parent Edwin van Leeuwen <edder tkwsping.nl> writes:
On Monday, 4 July 2016 at 15:10:30 UTC, Manu wrote:
 On 1 July 2016 at 18:19, Edwin van Leeuwen via 
 Digitalmars-d-announce <digitalmars-d-announce puremagic.com> 
 wrote:
 On Friday, 1 July 2016 at 08:11:37 UTC, Benjamin Schaaf wrote:
 On Friday, 1 July 2016 at 01:24:55 UTC, rikki cattermole 
 wrote:
 On 01/07/2016 9:35 AM, Benjamin Schaaf wrote:

 Doesn't use allocators or Manu's color work, yup yup not 
 interested.
In terms of std.experimental.color, one of the things I focused on was extensibility.
Also, the only way currently to use Manu's color work is to install his phobos branch. The dub package will throw unittest errors and loads of deprecation warnings.
Really? Nobody ever mentioned that before. I don't use dub, so I didn't notice... but I thought the code there was up to date...?
Maybe I am confused. I am talking about the code/package here: https://github.com/TurkeyMan/color which hasn't seen an update since november. Relevant issue: https://github.com/TurkeyMan/color/issues/5 I had a look at the unittest, but couldn't immediately figure out why it wasn't working, so didn't look further into it.
Jul 04 2016
prev sibling parent Rory McGuire via Digitalmars-d-announce writes:
On Fri, Jul 1, 2016 at 10:11 AM, Benjamin Schaaf via Digitalmars-d-announce
<digitalmars-d-announce puremagic.com> wrote:

 On Friday, 1 July 2016 at 01:24:55 UTC, rikki cattermole wrote:

 On 01/07/2016 9:35 AM, Benjamin Schaaf wrote:

 daffodil is a image processing library inspired by python's Pillow
 (https://pillow.readthedocs.org/). It is an attempt at designing a
 clean, extensible and transparent API.

 https://github.com/BenjaminSchaaf/daffodil
 https://benjaminschaaf.github.io/daffodil/

 The library makes full use out of D's templates and metaprogramming. The
 internal storage mechanism is entirely configurable from almost every
 endpoint. File headers are directly loaded into structs defining them,
 removing most of the difficulties in reading them according to spec. The
 image type and loading API is entirely extensible, making extra image
 formats entirely self-contained.

 Currently only loading and saving of simple BMP images is supported,
 with convolution and Gaussian Blur filters and flip transformations. Its
 still early in development, but I'd love to get some feedback on it.

 Example:
 ---
 import daffodil;
 import daffodil.filter;
 import daffodil.transform;

 void main() {
     auto image = load!32("daffodil.bmp");

     image.gaussianBlurred(1.4).save("blurry_daffodil.bmp");

     image.flipped!"y".save("upside_down_daffodil.bmp");
 }
 ---

 The license is MIT, so feel free to do whatever you want with the code.
 Issues and pull requests are of course welcome ;)

 Alongside I've also written (an admittedly hacky) sphinx
 (http://www.sphinx-doc.org/en/stable/) extension that provides a domain
 and autodocumenter for D, using libdparse and pyd.
Doesn't use allocators or Manu's color work, yup yup not interested.
In terms of std.experimental.color, one of the things I focused on was extensibility. What if someone came along and had their own color space they needed to implement? With std.experimental.color, the only option you currently have is editing the library. If it gets included into phobos, then suddenly your "I want to implement my own color space" has turned into editing the standard library. Albeit currently rough around the edges, all you have to do to implement your own color space in daffodil, is to implement the ColorSpace interface. I haven't looked into using allocators yet, but I've put it on the horizon.
Yeah, good choice. I lean more towards the standard library defining a set if inspection templates (to avoid forcing use of classes/interfaces) and a default implementation rather than tying us so close to the standard library, D is better than that.
Jul 01 2016
prev sibling next sibling parent reply Relja Ljubobratovic <ljubobratovic.relja gmail.com> writes:
On Thursday, 30 June 2016 at 21:35:37 UTC, Benjamin Schaaf wrote:
 daffodil is a image processing library inspired by python's 
 Pillow (https://pillow.readthedocs.org/). It is an attempt at 
 designing a clean, extensible and transparent API.

 https://github.com/BenjaminSchaaf/daffodil
 https://benjaminschaaf.github.io/daffodil/

 The library makes full use out of D's templates and 
 metaprogramming. The internal storage mechanism is entirely 
 configurable from almost every endpoint. File headers are 
 directly loaded into structs defining them, removing most of 
 the difficulties in reading them according to spec. The image 
 type and loading API is entirely extensible, making extra image 
 formats entirely self-contained.

 Currently only loading and saving of simple BMP images is 
 supported, with convolution and Gaussian Blur filters and flip 
 transformations. Its still early in development, but I'd love 
 to get some feedback on it.

 Example:
 ---
 import daffodil;
 import daffodil.filter;
 import daffodil.transform;

 void main() {
     auto image = load!32("daffodil.bmp");

     image.gaussianBlurred(1.4).save("blurry_daffodil.bmp");

     image.flipped!"y".save("upside_down_daffodil.bmp");
 }
 ---

 The license is MIT, so feel free to do whatever you want with 
 the code. Issues and pull requests are of course welcome ;)

 Alongside I've also written (an admittedly hacky) sphinx 
 (http://www.sphinx-doc.org/en/stable/) extension that provides 
 a domain and autodocumenter for D, using libdparse and pyd.
Hi there. Took a quick look at the source and it seems really nice! I like your idea of extensibility for color conversion. Also, image I/O seems to be set up quite nicely for a starting point. Although I have to comment that bit depth shouldn't be a template argument, in my opinion. When loading images, bit depth should be determined in the runtime, depending on the image you'd be loading at the moment. Or am I wrong? - do you have some other way of handing this case? Also wanted to let you know I've been working on a similar library for some time now [1]. Hope we could merge some modules and learn from each other, and not have multiple different implementations of the same stuff. Please let me know if your interested. [1] https://github.com/ljubobratovicrelja/dcv
Jul 01 2016
next sibling parent reply Benjamin Schaaf <ben.schaaf gmail.com> writes:
On Friday, 1 July 2016 at 11:09:49 UTC, Relja Ljubobratovic wrote:
 On Thursday, 30 June 2016 at 21:35:37 UTC, Benjamin Schaaf 
 wrote:
 daffodil is a image processing library inspired by python's 
 Pillow (https://pillow.readthedocs.org/). It is an attempt at 
 designing a clean, extensible and transparent API.

 https://github.com/BenjaminSchaaf/daffodil
 https://benjaminschaaf.github.io/daffodil/

 The library makes full use out of D's templates and 
 metaprogramming. The internal storage mechanism is entirely 
 configurable from almost every endpoint. File headers are 
 directly loaded into structs defining them, removing most of 
 the difficulties in reading them according to spec. The image 
 type and loading API is entirely extensible, making extra 
 image formats entirely self-contained.

 Currently only loading and saving of simple BMP images is 
 supported, with convolution and Gaussian Blur filters and flip 
 transformations. Its still early in development, but I'd love 
 to get some feedback on it.

 Example:
 ---
 import daffodil;
 import daffodil.filter;
 import daffodil.transform;

 void main() {
     auto image = load!32("daffodil.bmp");

     image.gaussianBlurred(1.4).save("blurry_daffodil.bmp");

     image.flipped!"y".save("upside_down_daffodil.bmp");
 }
 ---

 The license is MIT, so feel free to do whatever you want with 
 the code. Issues and pull requests are of course welcome ;)

 Alongside I've also written (an admittedly hacky) sphinx 
 (http://www.sphinx-doc.org/en/stable/) extension that provides 
 a domain and autodocumenter for D, using libdparse and pyd.
Hi there. Took a quick look at the source and it seems really nice! I like your idea of extensibility for color conversion. Also, image I/O seems to be set up quite nicely for a starting point. Although I have to comment that bit depth shouldn't be a template argument, in my opinion. When loading images, bit depth should be determined in the runtime, depending on the image you'd be loading at the moment. Or am I wrong? - do you have some other way of handing this case? Also wanted to let you know I've been working on a similar library for some time now [1]. Hope we could merge some modules and learn from each other, and not have multiple different implementations of the same stuff. Please let me know if your interested. [1] https://github.com/ljubobratovicrelja/dcv
The problem with not knowing bit depth at compile time, is that you're now forced to store the image internally as plain bytes. So if you wanted to add two colors, you end up with ubyte[4] + ubyte[4] instead of int + int. At some point you're going to have to use a proper numerical representation (ie. long), or be faced with slow calculations (ie. bigint). Other libraries (eg. ImageMagick) get around this by just using longs as the internal representation. Daffodil allows you to control this. So if you know you will never use more than 4 bytes per color, you don't have to pay for anything more. If you don't know, you can just use 8 and essentially have the same behaviour as ImageMagick.
Jul 01 2016
parent Relja Ljubobratovic <ljubobratovic.relja gmail.com> writes:
On Friday, 1 July 2016 at 14:30:17 UTC, Benjamin Schaaf wrote:
 The problem with not knowing bit depth at compile time, is that 
 you're now forced to store the image internally as plain bytes. 
 So if you wanted to add two colors, you end up with ubyte[4] + 
 ubyte[4] instead of int + int. At some point you're going to 
 have to use a proper numerical representation (ie. long), or be 
 faced with slow calculations (ie. bigint).

 Other libraries (eg. ImageMagick) get around this by just using 
 longs as the internal representation. Daffodil allows you to 
 control this. So if you know you will never use more than 4 
 bytes per color, you don't have to pay for anything more. If 
 you don't know, you can just use 8 and essentially have the 
 same behaviour as ImageMagick.
Yes, I'm aware of that problem. But if you store the type information in the image (as enum field), later on you can do the casting to correct types and perform arithmetics the right way. This is how opencv's cv::Mat works under the hood, also I believe numpy.ndarray's c implementation performs the same way. Don't get me wrong, I'm not saying your way is not correct. :) Just explaining my viewpoint. I believe your way is a lot easier - if you could show that it works well in production environment, I'd be glad to adopt it! Cheers, Relja
Jul 01 2016
prev sibling next sibling parent Michael <michael toohuman.io> writes:
On Friday, 1 July 2016 at 11:09:49 UTC, Relja Ljubobratovic wrote:
 On Thursday, 30 June 2016 at 21:35:37 UTC, Benjamin Schaaf 
 wrote:
 [...]
Hi there. Took a quick look at the source and it seems really nice! I like your idea of extensibility for color conversion. Also, image I/O seems to be set up quite nicely for a starting point. Although I have to comment that bit depth shouldn't be a template argument, in my opinion. When loading images, bit depth should be determined in the runtime, depending on the image you'd be loading at the moment. Or am I wrong? - do you have some other way of handing this case? Also wanted to let you know I've been working on a similar library for some time now [1]. Hope we could merge some modules and learn from each other, and not have multiple different implementations of the same stuff. Please let me know if your interested. [1] https://github.com/ljubobratovicrelja/dcv
This is how responses should be, so thanks for adding to the conversation, unlike the initial commenter. I do think, as there has been multiple proposed libraries for audio/CV/UI models, that some collaboration and merging of the more similar modules would benefit greatly from the combined effort and increased output, as getting these kinds of libraries off the ground seems to be quite slow at first. I'd love to start using some CV libraries in D for video processing.
Jul 01 2016
prev sibling parent reply Vladimir Panteleev <thecybershadow.lists gmail.com> writes:
On Friday, 1 July 2016 at 11:09:49 UTC, Relja Ljubobratovic wrote:
 When loading images, bit depth should be determined in the 
 runtime, depending on the image you'd be loading at the moment. 
 Or am I wrong?
Generally most use cases for using an image library can be divided into: 1. You have full control over the images being loaded. This is the case when you're loading graphical assets for your application which otherwise doesn't concern itself for graphical work. 2. You're writing an image editor, or some other program that processes images out of your control, i.e. supplied by the user. Generally the first case is by far the most common one (think GUI applications, video games...). In this case, since you already know or have control over the format of your images, there is no reason to burden your application with performance-killing abstraction layers - you should load and work in the format that your images already are. Additionally, if necessary, it is easy to build such a runtime abstraction layer over a templated library by creating an algebraic type from only the set of formats that you want to support. Doing the inverse is impossible. In case anyone from this thread haven't seen it, I have my own image library, which I wrote about here: https://blog.thecybershadow.net/2014/03/21/functional-image-processing-in-d/
Jul 01 2016
next sibling parent Relja Ljubobratovic <ljubobratovic.relja gmail.com> writes:
On Friday, 1 July 2016 at 21:18:28 UTC, Vladimir Panteleev wrote:
 Generally most use cases for using an image library can be 
 divided into:

 1. You have full control over the images being loaded. This is 
 the case when you're loading graphical assets for your 
 application which otherwise doesn't concern itself for 
 graphical work.

 2. You're writing an image editor, or some other program that 
 processes images out of your control, i.e. supplied by the user.

 Generally the first case is by far the most common one (think 
 GUI applications, video games...). In this case, since you 
 already know or have control over the format of your images, 
 there is no reason to burden your application with 
 performance-killing abstraction layers - you should load and 
 work in the format that your images already are.

 Additionally, if necessary, it is easy to build such a runtime 
 abstraction layer over a templated library by creating an 
 algebraic type from only the set of formats that you want to 
 support. Doing the inverse is impossible.

 In case anyone from this thread haven't seen it, I have my own 
 image library, which I wrote about here: 
 https://blog.thecybershadow.net/2014/03/21/functional-image-processing-in-d/
Hi Vladimir, thanks for your response and explanation. Also wanted to take the opportunity to say that the blog post about your library was one of the biggest motivations for me to pursue D for computer vision. Thanks a tone for your effort! :) Cheers, Relja
Jul 01 2016
prev sibling parent Martin Nowak <code dawg.eu> writes:
On Friday, 1 July 2016 at 21:18:28 UTC, Vladimir Panteleev wrote:
 In case anyone from this thread haven't seen it, I have my own 
 image library, which I wrote about here: 
 https://blog.thecybershadow.net/2014/03/21/functional-image-processing-in-d/
There is also a very nice and somewhat popular image loader/writer out there, http://code.dlang.org/packages/imageformats.
Jul 06 2016
prev sibling next sibling parent Guillaume Piolat <first.last gmail.com> writes:
On Thursday, 30 June 2016 at 21:35:37 UTC, Benjamin Schaaf wrote:
 daffodil is a image processing library inspired by python's 
 Pillow (https://pillow.readthedocs.org/). It is an attempt at 
 designing a clean, extensible and transparent API.
Nice. Minor nitpick, please make the width and height of an image an int instead of s size_t. We've had numerous discussions about this: https://forum.dlang.org/post/ifjiebtudbyrnaxgmzbp forum.dlang.org https://github.com/lgvz/imageformats/issues/24
Jul 01 2016
prev sibling parent reply Leandro Lucarella <llucax gmail.com> writes:
On Thursday, 30 June 2016 at 21:35:37 UTC, Benjamin Schaaf wrote:
 Alongside I've also written (an admittedly hacky) sphinx 
 (http://www.sphinx-doc.org/en/stable/) extension that provides 
 a domain and autodocumenter for D, using libdparse and pyd.
Where can I get the Sphinx extension? :-D
Jul 01 2016
parent Benjamin Schaaf <ben.schaaf gmail.com> writes:
On Friday, 1 July 2016 at 23:37:59 UTC, Leandro Lucarella wrote:
 On Thursday, 30 June 2016 at 21:35:37 UTC, Benjamin Schaaf 
 wrote:
 Alongside I've also written (an admittedly hacky) sphinx 
 (http://www.sphinx-doc.org/en/stable/) extension that provides 
 a domain and autodocumenter for D, using libdparse and pyd.
Where can I get the Sphinx extension? :-D
https://github.com/BenjaminSchaaf/sphinxddoc It has a sphinx language domain for D and an autodocumenter. I've written a python extension using pyd and libdparse to parse D source into a consumable json format. I then use that output to autodocument the code. Its a bit of a hack, but I find having proper control of the output and being able to use sphinx themes is worth it compared to the alternative.
Jul 01 2016