asura Posted January 7, 2007 Share Posted January 7, 2007 (edited) Simple plugin, no options, just run it on an image or a selection. You might want to adjust contrast or levels before running this plugin for better results. The example above was dithered without any prior adjustments. Copy the dll into the effects folder to install it. Source: <no longer available - EER> Download Edited October 16, 2018 by toe_head2001 Restored image 1 Quote Link to comment Share on other sites More sharing options...
Rick Brewster Posted January 8, 2007 Share Posted January 8, 2007 From looking at the source code, you are calling Clone() on the input Surface every time Render() is called. Your memory usage is going to explode, causing Paint.NET to crash a lot on anything but small images. Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
asura Posted January 8, 2007 Author Share Posted January 8, 2007 :oops: I had some troubles getting my code to run properly in CodeLab. The problem was that the dithering needs to apply changes to the source surface, and in CodeLab it seemed to apply the effect twice. By cloning it I was able to get around that problem, but I forgot to dispose the copy afterwards. Or can I just apply the changes to the source surface without disturbing any code outside my plugin? Regards, Asura Quote Link to comment Share on other sites More sharing options...
BoltBait Posted January 8, 2007 Share Posted January 8, 2007 If you make changes to the source surface, you can not "undo" the changes--that is, you break the undo function. Quote Download: BoltBait's Plugin Pack | CodeLab | and a Free Computer Dominos Game Link to comment Share on other sites More sharing options...
asura Posted January 8, 2007 Author Share Posted January 8, 2007 I've uploaded the corrected code and dll. It's still cloning, but now it's cleaning up after itself as well. Asura Quote Link to comment Share on other sites More sharing options...
Aron Posted January 9, 2007 Share Posted January 9, 2007 whaha! this is a funny plugin! the only problem is that it doens't work good with darker pictures Quote My Deviant Link to comment Share on other sites More sharing options...
BoltBait Posted January 9, 2007 Share Posted January 9, 2007 the only problem is that it doens't work good with darker pictures Thus his comment... You might want to adjust contrast or levels before running this plugin for better results. Quote Download: BoltBait's Plugin Pack | CodeLab | and a Free Computer Dominos Game Link to comment Share on other sites More sharing options...
usedHONDA Posted January 9, 2007 Share Posted January 9, 2007 The example looks like the lizard woman from hell. Quote "The greatest thing about the Internet is that you can write anything you want and give it a false source." ~Ezra Pound twtr | dA | tmblr | yt | fb Link to comment Share on other sites More sharing options...
LimeLight Posted January 10, 2007 Share Posted January 10, 2007 The example looks like the lizard woman from hell. If that's what hell looks like... :wink: Quote Link to comment Share on other sites More sharing options...
Rick Brewster Posted January 10, 2007 Share Posted January 10, 2007 I've uploaded the corrected code and dll. It's still cloning, but now it's cleaning up after itself as well. So on my quad-core CPU, it's still going to require 4x the memory as the original image to run your effect (one active rendering thread per logical CPU, with a minimum of 2 threads) For a 7 megapixel image that means it'd require an additional 112 MB of memory ........ are you sure this requires writing to the source? I have this same algorithm implemented for saving GIF images and it just requires two passes of analysis, but doesn't require anything like this. Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
asura Posted January 10, 2007 Author Share Posted January 10, 2007 I don't have any experience with more than one core at a time. I always assumed that the cores would work together by sharing at least some the memory. Oh well, learning moment... Anyway, I've kicked pretty much everything out and started again. It's now only using its source and destination surface, assisted by a much smaller buffer, just as big as the width of the image. Memory impact will be much lower. I've tested this with a 4000x5400 image: Loading the image increased memory usage by 176MB. Starting the effect made it increase by another 92MB (which it does with any effect, not just this one). During processing memory usage grew with about 5 or 6MB and it dropped back when it was done. I found that my original code was rather slow on larger images, so I also made the processing loop more efficient using pointers instead of the surface indexers. On the test image it took about 11 seconds. The previous version would've taken a few minutes probably... And since I was busy anyway, I also documented the code The dll and source are available at the original locations. Quote Link to comment Share on other sites More sharing options...
Rick Brewster Posted January 10, 2007 Share Posted January 10, 2007 Ahh yes, this code looks much better now. The memory you are allocating will be insignificant. If you want to optimize performance further, I of course have tons of ideas. But I think you're probably already at the break-even point where any further optimization will be a lot of work and the gains will be proportionally much smaller than what you just gained. (well maybe you could gain, say, another 50% ... but 50% of 11 seconds isn't worth as much as the 80% [or whatever] of "a few minutes" you already got) Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
asura Posted January 10, 2007 Author Share Posted January 10, 2007 Thanks for your constructive input I was already happy that it was faster than the 'Edge Detect' filter, which I think is a technically similar effect. Where do you think I could gain a bit, 50% still sounds like a lot. I know it isn't, but you've got my curiosity triggered. Pointers for navigating through the cache as well, or something like that? Or throwing in some threads for the rois that need to be rendered? Quote Link to comment Share on other sites More sharing options...
Rick Brewster Posted January 11, 2007 Share Posted January 11, 2007 Well you're allocating at the start of every call to Render(). From a performance perspective it's better to have a static [ThreadStatic] variable for your cache variable, load it once into a method variable at the start of the Render() method (retrieving a static [ThreadStatic] var is expensive), make it bigger if necessary (if rect.Width > cache.Width { cache = new Cache(rect.Width) }). That will keep the cache in the CPU cache better, and reduce a lot of pressure on the GC (garbage collector). Quote The Paint.NET Blog: https://blog.getpaint.net/ Donations are always appreciated! https://www.getpaint.net/donate.html Link to comment Share on other sites More sharing options...
asura Posted January 12, 2007 Author Share Posted January 12, 2007 Hmm, I've tried the static cache, but then it isn't 'clean' when the Render method is called. The image still renders in a recognizable way, but it gets polluted with noise from previous renderings. Cleaning the cache by resetting all its elements at the start of the Render method pretty much cancels out the static cache gain. However, when I change the ColorError class to a struct it gets much faster even when I'm creating new caches every time the Render method is called. The structs are created much faster than classes, and they're instantiated automatically when I create an array. Since the default value happens to be exactly what I need, I don't need to loop through the array afterwards. According to my profiler the Floyd-Steinberg calculations are also twice as fast. I did some performance tests with arrays of structs and arrays of classes , and the structs turned out to be much faster then the classes, with half the number of GC collections as well. An array with just one struct isn't much faster than an array with one class, but it gets better with bigger arrays. With 10000 elements it's 4 times faster, with 500000 elements it's 80x faster. So, that sounds like a gain. I'll upload a new version later today. Quote Link to comment Share on other sites More sharing options...
asura Posted January 12, 2007 Author Share Posted January 12, 2007 That's weird. The performance tests I did on the separate parts promised some gain, but when I put the whole thing together it actually works a little slower with my test image. Memory usage is lower, but the number of GC collections stays the same. I guess there are some other forces at work... Since it doesn't improve at all I've kept the code as it was. So no new upload, sorry. Quote Link to comment Share on other sites More sharing options...
zerodown002 Posted May 22, 2014 Share Posted May 22, 2014 (edited) Download link is broken here is a link to download it: <snip!> Edited May 22, 2014 by david.atwell Nope. Quote Link to comment Share on other sites More sharing options...
mottoman Posted May 22, 2014 Share Posted May 22, 2014 (edited) Download link is broken here is a link to download it: Read This Post Only download plugins from this forum. If the link is broken don't link to outside sources. Edited May 22, 2014 by mottoman Quote Link to comment Share on other sites More sharing options...
Ego Eram Reputo Posted May 23, 2014 Share Posted May 23, 2014 I don't have a copy of this DLL to attach. If anyone can provide a copy - please PM me. Quote ebook: Mastering Paint.NET | resources: Plugin Index | Stereogram Tut | proud supporter of Codelab plugins: EER's Plugin Pack | Planetoid | StickMan | WhichSymbol+ | Dr Scott's Markup Renderer | CSV Filetype | dwarf horde plugins: Plugin Browser | ShapeMaker Link to comment Share on other sites More sharing options...
david.atwell Posted May 23, 2014 Share Posted May 23, 2014 I don't have a copy of this DLL to attach. If anyone can provide a copy - please PM me. Not one from Megalo, of course. Quote The Doctor: There was a goblin, or a trickster, or a warrior... A nameless, terrible thing, soaked in the blood of a billion galaxies. The most feared being in all the cosmos. And nothing could stop it, or hold it, or reason with it. One day it would just drop out of the sky and tear down your world.Amy: But how did it end up in there?The Doctor: You know fairy tales. A good wizard tricked it.River Song: I hate good wizards in fairy tales; they always turn out to be him. Link to comment Share on other sites More sharing options...
Ego Eram Reputo Posted January 9, 2016 Share Posted January 9, 2016 DLL attached to the first post. Alternatively - there is this implementation by @BoltBait Floyd-Steinberg Dithering Quote ebook: Mastering Paint.NET | resources: Plugin Index | Stereogram Tut | proud supporter of Codelab plugins: EER's Plugin Pack | Planetoid | StickMan | WhichSymbol+ | Dr Scott's Markup Renderer | CSV Filetype | dwarf horde plugins: Plugin Browser | ShapeMaker Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.