• Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by MJW

  1. If it isn't already, make black the Primary Color. Select the blue color with the Magic Wand, as Ego Eram Reputo explained above. Invert the section with Ctrl+I (or use the Edit menu). Fill the selection with Backspace (or use the Edit menu).
  2. From what I can see with a quick look at your code (my excuse if I missed something), you should compute the gradient in PreRender(), where it's only done once each time a control is changed. You could still do the compare-to-previous-value test, though I doubt it's worth the effort.
  3. Would you expand of this. Do you just mean the write has no effect, so the effort is wasted, or does it waste resources in some other way? If it just wastes the effort to compute the unused pixels, is that behavior that's intended to remain that way, so that it can be relied on? There are probably lots of cases where it would be convenient to clip at most to the selection's bounding rectangle, and not worry that there will be some wasted computations if the user happens to have an elliptical selection. Also, does is writing outside the ROI in Render() allowed, in the sense that it will properly write into pixels if they're selected? To paraphrase Ghostbusters, are the ROI bounds more guidelines than rules?
  4. After looking through the code more carefully, I notice: dst[fx,y] = src[x,y]; That's a sure sign the call to Render() may write outside its ROI, which shouldn't be done. Either the algorithm needs to be redone (unlikely), or you need to use an aux surface. Usually, the Render() code when using an aux surface is trivial. Inside the render loops is simply: dst[x, y] = aux[x, y]. In some cases, it's possible to save some of the computations for Render() to do. It's good to do as much in Render as possible, since it's done in parallel, where PreRender() is not. Also Render() properly updates the progress bar. Also, aux doesn't have to be an actual surface. In many cases a two-dimensional array of ColorBgras works just as well, and doesn't need to be carefully disposed of. Sometimes a 2D array of floats or ints is better, leaving it to Render() to compute the color from the value in the array. For this algorithm, it could be an array of 2D indexes that tell where in the source buffer the proper color is located. (That's just an example, not a recommendation.)
  5. Not really start over. It would mostly be a matter of moving code from one routine to another. I wish I understood better what the code is doing; but I have great difficulty reading poorly-formatted code. (In fact, I have difficulty reading code not formatted in by preferred indentation style.)
  6. I didn't know that. Or if I knew it at one time, I'd forgotten it. In the plugin under discussion, I doubt writing to dst in PreRender() makes sense, anyhow. If the algorithm itself can be done in Render(), so can the clears. I doubt the clears in PreRender() even make sense. I bet they're just a band aid that reduces what ever problem Reptillian is seeing.
  7. Assuming dst can't be written in PreRender() (as I believe it can't), you've got to figure out a way to do it in Render(). It that's impossible, you need to use an auxiliary surface, do the rendering to it in PreRender(), and copy the results to dst in Render(). That's not ideal, but it's necessary for algorithms that only go in the source-to-destination direction; that is, algorithms where you can't take the destination coordinates, and figure out what color should be there.
  8. Also, for (int x = 0; x < w; x++) { int nonZeroAlphaCount = 0; for (int y = 0; y < h; y++) { if (src[x,y].A >= alpha_threshold) {nonZeroAlphaCount++;} columnNonZeroAlphas[x] = nonZeroAlphaCount; //dst[x,y]=ColorBgra.FromBgra(0,0,0,0); } } Would be better as: for (int x = 0; x < w; x++) { int nonZeroAlphaCount = 0; for (int y = 0; y < h; y++) { if (src[x,y].A >= alpha_threshold) {nonZeroAlphaCount++;} //dst[x,y]=ColorBgra.FromBgra(0,0,0,0); } columnNonZeroAlphas[x] = nonZeroAlphaCount; } The point of using a local variable to accumulate the count is to avoid an array index. It's probably not worth the effort, and could be the simpler: for (int x = 0; x < w; x++) { int nonZeroAlphaCount = 0; for (int y = 0; y < h; y++) { if (src[x,y].A >= alpha_threshold) columnNonZeroAlphas[x]++; //dst[x,y]=ColorBgra.FromBgra(0,0,0,0); } }
  9. One thing I noticed is that in PreRender you have: dst[x,y]=ColorBgra.FromBgra(0,0,0,0); I don't think that's kosher. As far as I know, you can only write to the destination buffer in Render, and then only within the Rectangle-Of-Interest.
  10. Excellent penmanship by @welshblue, @Pixey and @yellowman! Nice jobs also by @$5footslong and @Vagabondi. I regret that I didn't have an entry.
  11. If you need the info for both the rows and columns, the simplest way is probably: for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (src[x, y].Alpha != 0) { columnNonZeroAlphas[x]++; rowNonZeroAlphas[y]++; } } } There are probably slightly more efficient ways, but since it only runs once, and doesn't do anything too complex, it's probably plenty efficient enough. (You don't need to first zero the arrays, since C# zeroes numeric arrays when they're allocated.)
  12. It probably makes no significant difference whether a while or a for loop is used, especially when the optimizer is on for the Release version. And if it does make a difference, about the only way to know is to look at the compiled code, or run a profiler. In any case, it will be so quick it will almost certainly not matter. (I'd use a for loop.) As to the flag: OnSetRenderInfo() runs each time a control is changed, as does PreRender() (which is called from OnSetRenderInfo()). That's good, because it allows global things to be updated to take into account the new control values. However, the number of pixels in a row with non-zero alphas depends only on the state of the image at the time you run the plugin, so the count only needs to be done once. The usual way to accomplish this is to use a "first time" flag to say whether it's already been done. Since you probably need to store the results in an array, the pointer to the array is a very convenient flag. Something like this: int[] rowNonZeroAlphas = null; void PreRender(Surface dst, Surface src) { int width = src.Width, height = src.Height; if (rowNonZeroAlphas == null) { rowNonZeroAlphas = new int[height]; for (int y = 0; y < height; y++) { int nonZeroAlphaCount = 0; for (int x = 0; x < width; x++) { if (src[x, y].Alpha != 0) nonZeroAlphaCount++; } rowNonZeroAlphas[y] = nonZeroAlphaCount } } } (Please forgive any mistakes) The first time it runs, the array address will be null, so it will allocate the array and compute the results. On all subsequent times it's run, the address will be non-null, so it will skip over the computations.
  13. If I correctly understand the question (which I may not), you would just count and save the number of pixels with non-zero alphas in each row or column in the pre-processing step, which is PreRender() in Codelab and OnSetRenderInfo() in Visual Studio. Since it doesn't change, a flag (likely just the non-null pointer to the array where the results are saved) should be used to prevent re-doing it each time a control is changed.
  14. You might try Perspective Transformation. It's not exactly what you're asking for, but is similar. If you want to perspective-map an image onto another image, put the image you want to map in the top layer, and the other image in the lower layer. Sometimes it helps to temporarily make the top layer partially transparent.
  15. Another way, which works better, but is more complex: Put the City layer in the lowest layer. Put a the Text layer in the next layer. Put the Stripe layer in the next layer. Put a copy of the Text layer in the top layer, and invert the color to make the text black. Copy the Stripe layer to clipboard. Run BoltBait's Paste Alpha plugin on the top (inverted Text) using the Minimum of current alpha mode, and the Alpha source being Alpha channel on clipboard.
  16. One way, probably not the best. Put the City layer in the lowest layer. Put a copy of the Text layer in the next layer, and invert to color, to make it black. Put the Stripe layer in the next layer. Put the Text layer in the top layer, with a Blend Mode of XOR. This works pretty well, except the text has a thin dark edge for the semi-transparent edge pixels.
  17. That was done by using the infamous beta-released Texture View Skewer, followed by the beta-released, but less infamous, Perspective Transformation, then lots of shape adjustments with pyrochild's Liquify. (The Texture View Skewer is infamous to me, because it's on the verge of being something really useful, but I can't quite figure out how to make it work as I'd like it to.)
  18. Sweet work by @welshblue and @Pixey! In fact, all the entries were nicely done. My favorite, though, was welshblue's 3rd place entry. Something about the coloration and texture really said "cookie"! I was also impressed by the handling of the off-angle views of the surfaces on several entries, and in particular the fluted edges of the Oreos.
  19. Looks like there's about a one pixel shift. I'll look into it.
  20. I'm not sure what you mean by " plugins with drawing area." If you mean would it be possible to make a tool-type plugin that lets you draw on a canvas it creates (the way Brush Factory does), then yes it would. That's not how I interpreted your original request. I thought you wanted to add a pixel-perfect mode to the existing freehand tools.
  21. Rick Brewster is the only one who has any control over what the freehand tools do.
  22. Truly, on the Paint.Net website, April first will henceforth be known as the cruelest day of the cruelest month!
  23. It would help if you could show some examples of what you're trying to achieve. (Sort of guessing what you might want to do) If you can select the region where you want the hatching, you can paste a stripe pattern into it. Or you can erase the region where you want the hatching, put the hatch pattern in a lower layer, then merge the layers.
  24. Congratulations, @welshblue and @lynxster4! Beautiful butterflies, beautifully done! Thanks to @Pixey for hosting, and to @toe_head2001 and @Ego Eram Reputo for choosing the excellent theme!