July 10, 2015
On Friday, 10 July 2015 at 04:35:51 UTC, rikki cattermole wrote:
> write("output.png", image
> .flipHorizontalRange
> .flipVerticalRange
> .rotate90Range
> .copyInto(new TheImage!RGB8(2, 2))
>
> .asPNG().toBytes);

Why the "Range" suffix for functions? Aren't most functions going to be lazy, and thus have a "Range" suffix?

Does copyInto do resizing / colorspace conversion? Such operations should be explicit. If it doesn't, then most of that sub-expression is redundant...

Have you looked at ae.utils.graphics.image.copy? If a second argument is not provided, an appropriate image is allocated automatically (on the heap though).

> I have an idea similar to copyInto except:
> .copyIntoTemporary!TheImage(allocator) // return SwappableImage!(ImageColor!TheImage)(allocator.make!TheImage, allocator); // auto ref return type

It took me a while to understand what SwappableImage does. The documentation could be improved.

I think you should not be adding runtime polymorphism implicitly anywhere. There are virtual range interfaces in Phobos, yes, but wrapping is only done explicitly, as it should be here.

> Basically SwappableImage can already deallocate the original storage instance when it's destructor gets called. If provided with the allocator. Same with RangeOf.

I suggest to avoid conflating Phobos range terminology with 2D image views. The current naming scheme makes me think that it returns a range of rows, or some other range which is directly pluggable into std.algorith. What's wrong with "View"?

I'd also like to ask why you decided to write a library from scratch instead of reusing existing ones. I've spent days solving certain design issues of ae.utils.graphics, it seems wasteful to me to discard that and duplicate the effort. If the license is the issue, I'd be happy to relicence it.
July 10, 2015
On Thursday, 9 July 2015 at 23:35:02 UTC, Vladimir Panteleev wrote:
> On Tuesday, 7 July 2015 at 03:39:00 UTC, Rikki Cattermole wrote:
>> I've been sold on the unsigned vs signed type issue for and only for the x and y coordinates.
>
> The first version of ae.utils.graphics had unsigned coordinates. As I found out, this was a mistake.
>
> A rule of thumb I discovered is that any numbers you may want to subtract, you should use signed types. Otherwise, operations such as drawing an arc with its center point off-canvas (with negative coordinates) becomes unreasonably complicated.

Canvas API != image library.
I'm quite happy for the canvas API to use signed integers. While the image library does not. After all the canvas API would just wrap how its being stored.
You lose the ability to have such large images as the CPU architecture can support but meh. Not my problem.

The canvas API being built on top should sanitise coordinates as need be. This is not unreasonable.

Little unknown fact is Devisualization.Util features a type called LineGraph which basically gets points based upon primitives such as lines and arcs. With support for deltas.
https://github.com/Devisualization/util/blob/master/source/core/devisualization/util/core/linegraph.d
Of course it was buggy but, I ran into the same issue you did. My view is definitely canvas should be signed. Just the underlying image storage type doesn't need to use it.
July 10, 2015
On Friday, 10 July 2015 at 04:56:53 UTC, rikki cattermole wrote:
> On Thursday, 9 July 2015 at 23:35:02 UTC, Vladimir Panteleev wrote:
>> On Tuesday, 7 July 2015 at 03:39:00 UTC, Rikki Cattermole wrote:
>>> I've been sold on the unsigned vs signed type issue for and only for the x and y coordinates.
>>
>> The first version of ae.utils.graphics had unsigned coordinates. As I found out, this was a mistake.
>>
>> A rule of thumb I discovered is that any numbers you may want to subtract, you should use signed types. Otherwise, operations such as drawing an arc with its center point off-canvas (with negative coordinates) becomes unreasonably complicated.
>
> Canvas API != image library.
> I'm quite happy for the canvas API to use signed integers. While the image library does not. After all the canvas API would just wrap how its being stored.

Why must there be a distinction between canvas and image? Seems like a pointless abstraction layer.

> You lose the ability to have such large images as the CPU architecture can support but meh. Not my problem.

No, that's wrong. The limit (for 32 bits) is 2 billion pixels for signed coordinates ON ONE AXIS. So the only situation in which an unsigned width/height will be advantageous is a 1-pixel-wide/tall image with a 1-byte-per-pixel-or-less color type.

> The canvas API being built on top should sanitise coordinates as need be. This is not unreasonable.

I think it is. If you want to draw something 10 pixels away from the right border, the expression img.width-10 will be unsigned.

July 10, 2015
On Friday, 10 July 2015 at 04:52:54 UTC, Vladimir Panteleev wrote:
> On Friday, 10 July 2015 at 04:35:51 UTC, rikki cattermole wrote:
>> write("output.png", image
>> .flipHorizontalRange
>> .flipVerticalRange
>> .rotate90Range
>> .copyInto(new TheImage!RGB8(2, 2))
>>
>> .asPNG().toBytes);
>
> Why the "Range" suffix for functions? Aren't most functions going to be lazy, and thus have a "Range" suffix?

There are three kinds of mutation functions per functionality.

1) Modifies an image in place and returns it
2) image.rangeOf.function
3) Takes in a PixelPoint input range

Range suffix seemed like a good way to separate out which return a range and which don't.

> Does copyInto do resizing / colorspace conversion? Such operations should be explicit. If it doesn't, then most of that sub-expression is redundant...

Nope. It just copies a PixelPoint input range into an image storage type.

> Have you looked at ae.utils.graphics.image.copy? If a second argument is not provided, an appropriate image is allocated automatically (on the heap though).
>
>> I have an idea similar to copyInto except:
>> .copyIntoTemporary!TheImage(allocator) // return SwappableImage!(ImageColor!TheImage)(allocator.make!TheImage, allocator); // auto ref return type
>
> It took me a while to understand what SwappableImage does. The documentation could be improved.
>
> I think you should not be adding runtime polymorphism implicitly anywhere. There are virtual range interfaces in Phobos, yes, but wrapping is only done explicitly, as it should be here.

In this case the only reason SwappableImage would be used is to use its lifetime management facilities. But hey you can manage it yourself if you want too...

>> Basically SwappableImage can already deallocate the original storage instance when it's destructor gets called. If provided with the allocator. Same with RangeOf.
>
> I suggest to avoid conflating Phobos range terminology with 2D image views. The current naming scheme makes me think that it returns a range of rows, or some other range which is directly pluggable into std.algorith. What's wrong with "View"?

As far as I am aware the range capabilities could be used with std.algorithm. There is nothing stopping you. It just uses PixelPoint!Color to represent a single pixel instead an instance of the color.
http://cattermole.co.nz/phobosImage/docs/html/std_experimental_image_interfaces.html#.PixelPoint

> I'd also like to ask why you decided to write a library from scratch instead of reusing existing ones. I've spent days solving certain design issues of ae.utils.graphics, it seems wasteful to me to discard that and duplicate the effort. If the license is the issue, I'd be happy to relicence it.

Licensing isn't an issue. I choose to write a new one to take advantage of std.experimental.color. It originally was meant to just test it. In fact I've been taking a lot of queues from ae.utils.graphics for this very reason. It is a very good piece of code and it already has solved may of the issues already.
Although now it is also pretty much testing e.g. std.experimental.allocators too.

I chose against reusing ae.utils.graphics as a base (same as e.g. dlib's and Devisualization.Image) because it would take a lot of work to get working with the newer Phobos to be modules. Almost as much as a new library would take.

You were the only person I was really interested in opinion wise. Manu's is great, but you have already done this. You know what works and doesn't.
July 10, 2015
On Friday, 10 July 2015 at 05:01:57 UTC, Vladimir Panteleev wrote:
> On Friday, 10 July 2015 at 04:56:53 UTC, rikki cattermole wrote:
>> On Thursday, 9 July 2015 at 23:35:02 UTC, Vladimir Panteleev wrote:
>>> On Tuesday, 7 July 2015 at 03:39:00 UTC, Rikki Cattermole wrote:
>>>> I've been sold on the unsigned vs signed type issue for and only for the x and y coordinates.
>>>
>>> The first version of ae.utils.graphics had unsigned coordinates. As I found out, this was a mistake.
>>>
>>> A rule of thumb I discovered is that any numbers you may want to subtract, you should use signed types. Otherwise, operations such as drawing an arc with its center point off-canvas (with negative coordinates) becomes unreasonably complicated.
>>
>> Canvas API != image library.
>> I'm quite happy for the canvas API to use signed integers. While the image library does not. After all the canvas API would just wrap how its being stored.
>
> Why must there be a distinction between canvas and image? Seems like a pointless abstraction layer.

A canvas API may only be in name only.
In other words, instead of it taking size_t it would take ptrdiff_t in e.g. free-functions.

>> You lose the ability to have such large images as the CPU architecture can support but meh. Not my problem.
>
> No, that's wrong. The limit (for 32 bits) is 2 billion pixels for signed coordinates ON ONE AXIS. So the only situation in which an unsigned width/height will be advantageous is a 1-pixel-wide/tall image with a 1-byte-per-pixel-or-less color type.

Okay okay, I'm getting picky I know its silly.

>> The canvas API being built on top should sanitise coordinates as need be. This is not unreasonable.
>
> I think it is. If you want to draw something 10 pixels away from the right border, the expression img.width-10 will be unsigned.

Okay you have a point here with img.width.

Humm, complicated problem here. To the average developer having to wrap up an image type with e.g. CanvasImage before using it, even if it was a struct would just seem useless. Just to change index types to be signed.

What we need is a unsigned integer type of word size that can have an out of bounds value aka negative. While also supporting calculations that is both signed and unsigned.
So basically a unsigned integer behaving like a signed one.
Now wouldn't that solve the problem we have?
July 10, 2015
On Friday, 10 July 2015 at 05:27:21 UTC, rikki cattermole wrote:
> What we need is a unsigned integer type of word size that can have an out of bounds value aka negative. While also supporting calculations that is both signed and unsigned.
> So basically a unsigned integer behaving like a signed one.
> Now wouldn't that solve the problem we have?

Yeah we have those, they are called signed integers...

But for real, you are way over complicating the problem, just use an int.
July 10, 2015
On Thu, 09 Jul 2015 23:35:00 +0000, Vladimir Panteleev wrote:

> On Tuesday, 7 July 2015 at 03:39:00 UTC, Rikki Cattermole wrote:
>> I've been sold on the unsigned vs signed type issue for and only for the x and y coordinates.
> 
> The first version of ae.utils.graphics had unsigned coordinates. As I found out, this was a mistake.
> 
> A rule of thumb I discovered is that any numbers you may want to subtract, you should use signed types. Otherwise, operations such as drawing an arc with its center point off-canvas (with negative coordinates) becomes unreasonably complicated.

giving that `int` and `uint` are freely interchangeable... `uint` is better, as it allows only one bound check in `if`, and without casts. ;-)

July 10, 2015
On Fri, 10 Jul 2015 03:59:29 +0000, Tofu Ninja wrote:

> On Friday, 10 July 2015 at 03:00:57 UTC, Rikki Cattermole wrote:
>>> getPixel/putPixel or a variation of such? This is the most common name for such functions.
>>
>> Fine by me.
> 
> This is honestly just nitpicking, but I see setPixel more than putPixel I think.

i'm using `setPixel` to change pixel unconditionally (think of it as "set rgb"), and `putPixel` to blend pixel (think of it as "do rgba color mix").

July 11, 2015
On Friday, 10 July 2015 at 23:23:32 UTC, ketmar wrote:
> On Fri, 10 Jul 2015 03:59:29 +0000, Tofu Ninja wrote:
>
>> On Friday, 10 July 2015 at 03:00:57 UTC, Rikki Cattermole wrote:
>>>> getPixel/putPixel or a variation of such? This is the most common name for such functions.
>>>
>>> Fine by me.
>> 
>> This is honestly just nitpicking, but I see setPixel more than putPixel I think.
>
> i'm using `setPixel` to change pixel unconditionally (think of it as "set rgb"), and `putPixel` to blend pixel (think of it as "do rgba color mix").

Wouldn't that better be called blendPixel?
July 11, 2015
On Saturday, 11 July 2015 at 00:49:27 UTC, Meta wrote:
> Wouldn't that better be called blendPixel?

Also wouldn't a blendPixel need to know the blending scheme, alpha, premultiplied, additive, ect...