Imagesharp: Looking for methods to Plot Single Pixel

Created on 7 Feb 2018  路  10Comments  路  Source: SixLabors/ImageSharp

Prerequisites

  • [X] I have written a descriptive issue title
  • [X] I have verified that I am running the latest version of ImageSharp
  • [X] I have verified if the problem exist in both DEBUG and RELEASE mode
  • [X] I have searched open and closed issues to ensure it has not already been reported

Description

I found DrawLines and DrawBeziers, but I don't see a simple function to draw a single pixel. I am using DrawLines from x,y -> x,y but it is really slow (plotting 120,000 points takes ~30 seconds).

Steps to Reproduce

        using (var bm = new Image<Rgba32>(1280, 960))
        {
            for (var sample = 0; sample < total;sample++) 
                bm.Mutate(
                    ctx => ctx
                        .DrawLines(Rgba32.Red, 1, new PointF[] { new Vector2(p1.x, p1.y), new Vector2(p1.x, p1.y) })
                        .DrawLines(Rgba32.Green, 1, new PointF[] { new Vector2(p2.x, p2.y), new Vector2(p2.x, p2.y) })
                        .DrawLines(Rgba32.Blue, 1, new PointF[] { new Vector2(p3.x, p3.y), new Vector2(p3.x, p3.y) })
                        .DrawLines(Rgba32.Black, 1, new PointF[] { new Vector2(p4.x, p4.y), new Vector2(p4.x, p4.y) })
                );
        }

System Configuration

i7-6500, 16GB memory, Windows 10, .Net Core 2, Visual Studio 2017

question

Most helpful comment

In my opinion, no one should use individual pixel getters/setters working on (x,y) coordinate pairs. It's slow by design, because the y coordinate is unnecessarily multiplied by width on every pixel access.

Use span-based row-by-row processing instead!

All 10 comments

Hi @mphipps1

Normally we would use our Gitter channel for questions such as this. It helps us stay on top of issues.

Setting individual pixels is performed via the indexer on Image<TPixel>

bm[x,y] = Rgba32.Red;

Hope that helps,

James

@mphipps1 a little note about manipulating individual pixels:

our image[x,y] indexer is way faster than the same feature in System.Drawing, but it's still not the most efficient way, if want to touch 120k pixels. We will provide lower level API-s for this through Memory<T> as soon as the newest version of the System.Memory module becomes official on NuGet.

Using the indexer took my code from 25 seconds to < 100ms. That's OUTSTANDING!
From an API design point of view, it's a little unusual to have Draw* commands and then use a different mechanism for points; maybe a good note for the documentation? Or maybe DrawPoint that is a wrapper around [x,y]?

Thanks!

I've wondered before whether we should create GetPixel SetPixel methods to act as syntactic sugar but I've never managed to convince myself that they're worth it. We're basically dealing with a 2D array so the indexer semantically works well.

The Draw- commands are specialist functions that require additional computation so I wouldn't classify them as the same API-wise.

Either way, we'll have API docs soon so discoverability will be much improved.

Manipulating individual pixels should be really considered as a primitive operation. Attempts to handle it as a high-level drawing operation will most likely end up introducing significant overhead in any image processing library :)

I've wondered before whether we should create GetPixel SetPixel methods

One benefit: it would help with discoverability (via intellisense); I had to google to find this issue and discover out how to get/set pixels.

In my opinion, no one should use individual pixel getters/setters working on (x,y) coordinate pairs. It's slow by design, because the y coordinate is unnecessarily multiplied by width on every pixel access.

Use span-based row-by-row processing instead!

That is a different issue from API discoverability, but I like the API you refer to, because I would have typed image.Pixel and found it if it was in the version I'm using (doesn't seem to be yet). I was initially looking for this kind of memory-access oriented API.

Good point - I could have looked more into the documentation :) - I'm too lazy and use intellisense to 'learn' APIs (indexers do show up in intellisense, but not after typing a '.' obviously).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

marcpabst picture marcpabst  路  3Comments

antonfirsov picture antonfirsov  路  3Comments

Inumedia picture Inumedia  路  3Comments

vad3x picture vad3x  路  4Comments

agoretsky picture agoretsky  路  4Comments