9

How can I convert an image to array of bytes using ImageSharp library?

Can ImageSharp library also suggest/provide RotateMode and FlipMode based on EXIF Orientation?

dudedev
  • 451
  • 1
  • 5
  • 19
  • 1
    Onto the second question: There's a transformation API function called `AutoOrient()`. Look it up ;) – John T May 02 '18 at 06:31

2 Answers2

16

If you are looking to convert the raw pixels into a byte[] you do the following.

var bytes = image.SavePixelData()

If you are looking to convert the encoded stream as a byte[] (which I suspect is what you are looking for). You do this.

using (var ms = new MemoryStream())
{
    image.Save(ms, imageFormat);
    return ms.ToArray();
}
James South
  • 10,147
  • 4
  • 59
  • 115
  • 1
    Yes, I used the latter way. Thanks. – dudedev Jun 05 '18 at 21:53
  • 3
    Great. Can you mark the answer then please to satisfy my OCD. – James South Jun 07 '18 at 04:53
  • 4
    For anyone coming along later: Note that the image.SavePixelData() function has been replaced with image.GetPixelSpan(), which returns a Span of the pixel type (which can then be turned into an array with .ToArray() if need be). – Jarak Sep 04 '18 at 23:35
  • 2
    `GetPixelSpan()` returns `Span`, so `ToArray()` will return `Rgba32[]`. To have `byte[]`, you can use `MemoryMarshal.AsBytes(image.GetPixelSpan()).ToArray()` – Majid Mar 19 '19 at 20:36
  • 3
    @Majid; and in order to gain access to `GetPixelSpan`, one should add `using SixLabors.ImageSharp.Advanced;` (took me a few minutes to figure out why VS couldn't find this method...) – odalet Oct 14 '19 at 14:18
  • man, u just give me the answer which i have been looking for 1 week ! – BerkGarip Jul 27 '21 at 09:20
  • https://docs.sixlabors.com/api/index.html Hopefully that will save you time in the future. – James South Jul 27 '21 at 15:18
  • 1
    `GetPixelSpan` is gone now. So? – zwcloud Jan 17 '22 at 15:10
  • Seems [`TryGetSinglePixelSpan` should be used instead](https://github.com/SixLabors/ImageSharp/discussions/1258) now. – zwcloud Jan 17 '22 at 15:17
  • According to the source code of the `MemoryStream` class you will not be able to store more than 2 GB. – Andrei Krasutski Aug 23 '22 at 09:10
3

For those who look after 2020:

SixLabors seems to like change in naming and adding abstraction layers, so... Now to get a raw byte data you do the following steps.

  1. Get MemoryGroup of an image using GetPixelMemoryGroup() method.
  2. Converting it into array (because GetPixelMemoryGroup() returns a interface) and taking first element (if somebody tells me why they did that, i'll appreciate).
  3. From System.Memory<TPixel> get a Span and then do stuff in old way. (i prefer solution from @Majid comment)

So the code looks something line this:

var _IMemoryGroup = image.GetPixelMemoryGroup();
var _MemoryGroup = _IMemoryGroup.ToArray()[0];
var PixelData = MemoryMarshal.AsBytes(_MemoryGroup.Span).ToArray();

ofc you don't have to split this into variables and you can do this in one line of code. I did it just for clarification purposes. This solution only viable as for 06 Sep 2020

ZecosMAX
  • 216
  • 1
  • 9
  • 1
    This is not a good answer and should be avoided. [`IMemoryGroup`](https://docs.sixlabors.com/api/ImageSharp/SixLabors.ImageSharp.Memory.IMemoryGroup-1.html) represents a collection of uniformly-sized discontiguous memory. The first element only represents the first item in that collection. – James South Jul 27 '21 at 15:25
  • @JamesSouth and what about trying to get pixel data in async functions? `Span`s aren't available there. – r2d2rigo Aug 04 '21 at 20:27
  • 1
    @JamesSouth Provide a solution that work at least – ZecosMAX Aug 07 '21 at 18:22
  • You need to copy each individual Memory in the memory group not just the first one. P.S "SixLabors seems to like change in naming and adding abstraction layers" is a really unhelpful comment. If you were using a beta that is your responsibility. – James South Aug 09 '21 at 02:39
  • @JamesSouth tho it's not beta – ZecosMAX Aug 10 '21 at 13:57
  • It was when the span APIs were last changed. Nothing has changed in that area since the first release candidate. – James South Aug 11 '21 at 00:25
  • @ZecosMAX when a library's author tells you you're doing it wrong, that you're using the wrong API, it's a good idea to listen. The library's author posted the accepted, working answer. – Panagiotis Kanavos Dec 17 '21 at 08:10
  • 1
    @Panagiotis Kanavos, not really, you're not considering time period. if you check answer's above comments you'll find this following text: "Note that the SavePixelData() function has been replaced with GetPixelSpan()" I was using release version of a library, not beta as James thinks it was, i've checked his answer, the method was not there, i've checked Jarak's and Majid's solution. The methods was not there. So i came up with my solution. This meant that author of library just really-really likes to swap functions around, and am i guilty if by today he returns the ~handy one-liner~ ? – ZecosMAX Dec 17 '21 at 12:24
  • 1
    @Panagiotis Kanavos, and, yeah... his answer is not accepted :) – ZecosMAX Dec 17 '21 at 12:25
  • @ZecosMAX Doesn't make you any less incorrect. I provided my answer in 2018. That was 2 years before your one. I described a workaround in the comments above per request rather than update my answer as to not break conversation flow for readers. As to why I thought you were using a beta... Things changed from beta to V1 RC1 but no breaking changes were from V1 RC1 until we introduced changes in V2. So perhaps as Panagiotis suggested, perhaps listening to the library author is wise. – James South Feb 09 '22 at 10:55
  • To get all the pixels as a single array use this instead of the first two lines: `image.GetPixelMemoryGroup().SelectMany(group => group.ToArray()).ToArray()` - though this will not work if combining the groups would exceed the maximum array size. – György Kőszeg Feb 22 '23 at 16:02