eXoCooLd / Waveshare.EPaperDisplay

.Net Core Library to show images on Waveshare E-Paper Displays
MIT License
30 stars 13 forks source link

Please check if the develop branch is working for your display #12

Closed eXoCooLd closed 2 years ago

eXoCooLd commented 3 years ago

Hello @thecaptncode and @Quotic can you please check, if there are any issues on the develop branch, with your displays?

It is using a library for dithering, moved the imageing outside the devices and fixed a bug in the ByteMerge method. (Dithering is now optional on the DisplayImage method)

Thank you.

Quotic commented 3 years ago

Example works fine on my Display 👍🏻 Thanks for your work.

thecaptncode commented 3 years ago

Cheers @eXoCooLd . I am currently traveling but I will test this next Sunday.

Best regards, Greg

eXoCooLd commented 3 years ago

Hey @thecaptncode no Problem, have a nice trip. :-)

thecaptncode commented 3 years ago

@eXoCooLd , I am still traveling but I have had an opportunity to look over the changes a little bit.

I am glad to see that we have a new device and contributor. Also, you have done a lot of refactoring work. That is very nice.

Would it be more flexible if DisplayImage received a stream type instead of a generic type? The current System.Drawing bitmap method would have to be set to deprecated but a new method could be created with stream that used SKBitmap.Decode to read it.

Just a thought to run by you two. Thanks for everyone's help.

Something that might interest you. I had an opportunity to show off my project that uses this driver in an episode of a streaming show. In case you wanted to see the recording, here is the link: https://www.youtube.com/watch?v=t-rFj54BsDI

Regards, Greg

eXoCooLd commented 3 years ago

A generic RGB Byte array or a a stream could be a option but makes the use of a dithering library more complicate. Stream / array needs to be decoded to a image than dithered with the plalet and than we can use the array to write it on the display. As option to write directly on the display without dithering it would be a option (or if someone wants tu build a working dithering method for all supported colors on the byte array).

With the new Implementation we could split the library for Hardware and Imaging with different NuGet Packages. So we have the hardware Nuget Package and different Imaging Nugets, maybe that would be a good option to support System.Drawing.Common and SkiaSharp.

thecaptncode commented 3 years ago

I have been able to test your develop branch on my display. It runs a little slower but it looks good.

I wasn't thinking about a stream with a a RGB Byte array. I know SKBitmap has a decode method that will decode the image itself. For example, you could create a filestream of a JPG on disk and pass it to SKBitmap.Decode. ImageSharp had a Load method to do the same.

If we used a stream to receive the image instead of a generic type, then read it into what ever is used internally (System.Drawing, SkiaSharp, ImageSharp), that breaks any external dependency on a graphics library and we are free to use what ever makes sense to use within this package.

Regarding Dithering, I know SkiaSharp has a dithering option as well as ImageSharp. ImageSharp may be easier to use there. I can also look into updating my dithering routine to use a custom pallet instead of just black and white. I did start work on refactoring my dithering routine but stopped it when you started your recent work.

What are your thoughts?

Regards, Greg

thecaptncode commented 3 years ago

@eXoCooLd I have figured out how to dither with a custom pallet instead of just black and white. It is not a huge change and I can write this if you'd like. Basically you have to determine if the pallet is monochrome. If it is not, you dither each R, G, B channel separately. If it is monochrome, then you need convert to the pixel to grayscale first and dither that as one channel. Then you match the result with the closest color from the custom pallet using a Euclidean distance method.

None if this is too difficult to do and it can be done in the same pass as reading the image to prevent the performance loss of multiple passes over the image.

eXoCooLd commented 3 years ago

Ok that sound awesome and would reduce the external dependency to the dithering lib. Please continue the work on the dithering method with pallet support.

The stream option is a nice option too, but if we already created a image in the ram we would always convert it to a new object (image -> stream -> image) insted of converting the image to the RGB Array for the display. I need to do some tests how that performes with SkiaSharp.

I watched the YT video, very nice Project and nice to see realword UseCase of the E-Paper Library.

thecaptncode commented 3 years ago

Glad you liked the project.

If you already have the image in ram, then it will be in a specific type (System.Drawing.Bitmap, SKBitmap, etc) and that requires a dependency for this project on that library. By using an image stream, we do not have that limitation.

I see what you are saying about performance. I wouldn't expect it to be much of an issue and probably will be offset by us needing to do less passes internally but it should be tested.

Greg

Quotic commented 3 years ago

@thecaptncode Very interesting video, thanks for that.

thecaptncode commented 3 years ago

@Quotic I have some questions about your Epd7in5b V2 E-Paper device.

I was making a change to the develop fork and I'm having problems getting the image test to pass on that device. Looking at the code, something doesn't seem right with the color determination and I thought you may have information that could help.

I believe your display uses 100 bytes for a single display line of black/white, another 100 bytes for a single display line of red/white and they are transmitted separately. There are 8 pixels packed into one byte for each. Therefor a single pixel is represented as one bit in each transmissions of black and red.

If you would, please help me understand what the following value combinations of a specific bit in the two transmissions would look like. I suspect there would be one combination that shouldn't be used. Below are my assumptions.

0 and 0 = black 0 and 1 = red 1 and 0 = white 1 and 1 = unused

Am I correct or have I misunderstood something?

Thank you in advance for your help. Greg

Quotic commented 3 years ago

Hi Greg,

yes this display is using 1 bit for every pixel, first data transmission is black/white 0 = black 1 = white second is red/lets call it transparent 0 = transparent 1 = red

so your combinations are correct, but to be honest I didn't found anything about 1 & 1 combination in specification and have not tested it on my display yet.

Unfortunately, I don't have time to work on this project at the moment.

Regards Bastian

thecaptncode commented 3 years ago

@Quotic that was exactly what I needed. Thanks!

thecaptncode commented 3 years ago

@eXoCooLd ,

Would you check our my develop branch when you get a chance? It is performing very well for me and I expect writing to the Epd7in5b_V2 device will use a lot less resources. I commented out the pre-dithering process and added in a full color dithering routine to EPaperDisplayBase that should work for all devices, if desired. Here are the list of changes: Updates to disposing Fixed issues with Ebd7in5b_V2 Tests Commented out loading with dithering Added a struct for colors (red, green and blue) Added a color to device byte mapping method that finds the closest color. This works for all devices. Added color dithering while writing. Added a DisplayWriter to simplify and standardize image writing Added a Epd7in5b_V2Writer which extends the DisplayWriter to handle the writing of two separate images, one for Black/White and one for Red. This may be reusable for other split image displays with little or no change.

I left much of the existing code in just in case you wanted to go in a different direction. I also did not add the ability to read a stream bitmap, but I can if you wish. I apologize for how many places I had to touch. Hopefully the end result will be simpler process.

Hope you are well.

Best regards, Greg

eXoCooLd commented 3 years ago

Thank you for your hard work!

I will test and review your changes over the weekend.

Best regards Andre

thecaptncode commented 3 years ago

I'm glad to help. I will do the best I can creating tests for these changes if this is the direction you want to go.

Normally, in the spirit of collaboration, I would have discussed some of these changes beforehand. Once I started working on the dithering, the other changes just made sense to me and I thought it easier to show a working version instead.

eXoCooLd commented 3 years ago

Hey @thecaptncode i reviewed your changes and they are amazing! With the dithering and the DisplayWriter this should be a very good base for future developpment and new displays. Please create a Pull Request for it. :-)

Best regards Andre

thecaptncode commented 3 years ago

@eXoCooLd ,

I'm really glad you liked it. Thank you :-)

There is one thing I noticed and I am not sure if it is the way you want it to behave.

BitmapRawImage disposing is happening more real time and less dependent on the garbage collector. That means the bitmap itself is disposed as soon as ePaperDisplay.DisplayImage finishes. This is fine if it is desired but any bitmap passed to ePaperDisplay.DisplayImage will be unusable afterwards.

If you don't want that behavior, removing the Bitmap?.Dispose() and Bitmap = null from BitmapRawImage.Dispose should resolve it.

Best regards, Greg

eXoCooLd commented 2 years ago

All supported Displays should work with current branch. Removed the Dispose() for the input Bitmap.