Jump to content

BoltBait

Administrator
  • Posts

    15,728
  • Joined

  • Last visited

  • Days Won

    405

Everything posted by BoltBait

  1. Be happy about it. That "unblocking" mechanic is one way that Windows uses to keep you from getting viruses.
  2. Nope. Sorry. Here's the best we currently have to offer: http://forums.getpaint.net/index.php?/topic/10056-
  3. Try like this: #region UICode int Amount1 = 0; // [0,255] Start int Amount2 = 255; // [0,255] Range byte Amount3 = 0; // Alpha value depends on...|Brightness|Darkness bool Amount4 = false; // Convert to grayscale before alpha filting #endregion public byte Pick(double Vxx) { if (Amount1 > Vxx) return 0; else if (Vxx <= Amount1 + Amount2) return (byte)Math.Ceiling((float) (Vxx-Amount1)*255/Amount2); else return 255; } public double Grscl(byte VxR, byte VxG, byte VxB) { return (double)Math.Ceiling(VxR*0.2988-0.4516-0.4999+VxG*0.5863-0.3252-0.4999+VxB*0.1137-0.4669-0.4999); } void Render(Surface dst, Surface src, Rectangle rect) { ColorBgra CurrentPixel; for (int y = rect.Top; y < rect.Bottom; y++) { if (IsCancelRequested) return; for (int x = rect.Left; x < rect.Right; x++) { CurrentPixel = src[x,y]; if (Amount4 == false) { if (Amount3 == 0) { CurrentPixel.A = Pick(HsvColor.FromColor(CurrentPixel.ToColor()).Value*2.55); } else { CurrentPixel.A = Pick(255-HsvColor.FromColor(CurrentPixel.ToColor()).Value*2.55); } } else { if (Amount3 == 0) { CurrentPixel.A = Pick(Grscl(CurrentPixel.R, CurrentPixel.G, CurrentPixel.); } else { CurrentPixel.A = Pick(255-Grscl(CurrentPixel.R, CurrentPixel.G, CurrentPixel.); } } dst[x,y] = CurrentPixel; } } } Basically, you changed the loops are are iterating over the entire selection instead of only the rectangle passed to you by Paint.NET. You should probably review the tutorials starting here: http://boltbait.com/pdn/CodeLab/help/overview.php There are other ways to speed this up even further, but I don't think you'll need to go any further. BTW, I have a very similar plugin in my pack called Effects > Object > Switch Gray to Alpha. It's just not adjustable. Try it on a black-to-white gradient to see what it does.
  4. After you're happy with what is selected, use Effects or do other actions just as you did before.
  5. CodeLab 2.3 Released This is only for Paint.NET 4.0! Changes: ▪ Fixed the bug described by AnthonyScoffler above that could crash Paint.NET Grab the CodeLab DLL here: http://www.boltbait.com/pdn/CodeLab/
  6. Don't be so modest, Ed. Your worst plugin is better than my best plugin.
  7. Paint.NET is not shipped with any additional software (malware or otherwise). I can only guess that you didn't download it from the official web site. There are many unscrupulous people out there bundling malware with Paint.NET. Be careful where you download it from.
  8. IF this was to become an option, I'd like to see it work this way: When autofinish is on, drawing something adds 2 entries to the history so that if you really didn't want to finish the thing you just drew you could press Ctrl-Z to "unfinish" it and make adjustments before finishing it. How cool would that be?
  9. Thanks for the report. I can reproduce the problem. Exception details: System.NullReferenceException: Object reference not set to an instance of an object. at PaintDotNet.Effects.CodeLabConfigDialog.Build(Boolean toDll, String submenuname, String menuname, String iconpath, String Author, Int32 MajorVersion, Int32 MinorVersion, String SupportURL, String WindowTitleStr, Boolean isAdjustment, Boolean ShowSource, String Description, String KeyWords, Boolean ForceAliasSelection, Boolean ForceSingleThreaded) at PaintDotNet.Effects.CodeLabConfigDialog.tmrCompile_Tick(Object sender, EventArgs e) at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) I'll check out the code later tonight and see if I can code a fix.EDIT: Would have been nice if the error message had included a line number. That's a huge functions and it took me a long time to find the issue.
  10. You know, in order to move a selection, your mouse doesn't actually need to be inside of that selection.
  11. I think you're not selecting all pixels of each letter. Due to the tolerance percentage, you're leaving a few of the pixels from each letter. It would be better to adjust the tolerance or simply select using the square selection tool.
  12. Well, I see that you have a really old version of my plugin pack. Follow the link in my sig to download an update. Follow the install directions very carefully and report back the results.
  13. Right-click on one of the DLL files and look at the properties. Is there an "unlock" button?
  14. The color replacer has a new option. Be sure you select how you want it to work.
  15. I think what Rick is saying is that rather than fix the issue with a button the user needs to press, he'd rather fix the issue by making it completely automatic and transparent to the user. Now that 4.0 is out... and the imidiate bug fixes are done, he's going to focus on other areas of the program... ... like a more robust plugin system ... printing ... etc. Just be patient. I'm sure more cool stuff is coming.
  16. Just testing out a new plugin: Yes, that's me. (Ladies, try to contain yourselves! )
  17. I was playing around with the Steganography plugin in order to improve the quality of the hidden images. I ended up adding in Floyd-Steinberg dithering to the hidden image which greatly improved the quality of the hidden image. Dithering reduces the number of colors of an image by choosing the closest color in the palette for a pixel, then taking the difference between that chosen color and the original color and spreads that difference out to the nearby pixels that haven't been processed yet. More info on dithering here: http://en.wikipedia.org/wiki/Error_diffusion Normally, paint.net breaks up your effect into multiple threads to complete the job faster. But, because of the way dithering works, the entire process needs to be done in a single thread. CodeLab could not handle making effects work this way. So, I modified CodeLab to add the option to the build screen. Then, I got to thinking, this might make a good example of the new CodeLab option for forcing the effect to run in a single thread. So, here ya go... Download here (Paint.NET 4.0+): https://forums.getpaint.net/index.php?/topic/32048-v Once installed, you can find it in your Effects > Stylize menu. Floyd-Steinberg Dithering Examples: Dithering Matrix (2 Options) Floyd-Steinberg uses the following dithering matrix:    - # 7 where #=pixel being processed, -=previously processed pixel 3 5 1 and pixel difference is distributed to neighbor pixels Note: 7+3+5+1 = 16    Custom uses the following dithering matrix:    - # 8 4 where #=pixel being processed, -=previously processed pixel 4 8 4 1 and pixel difference is distributed to neighbor pixels 0 2 1 0 by the weights shown. Note: 8+4+4+8+4+1+2+1 = 32    The Floyd-Steinberg matrix is not the only dithering matrix out there. The Jarvis, Judice, and Ninke matrix uses a total of 48. I designed the custom matrix because I wanted to only use factors of 2 in the math. By using only factors of 2, the math is simplified to bit shifts... so it runs really fast. I was actually surprised that no one had defined such a matrix. (Or, if they have, I could not find a reference to it on the Internet.) Palettes (6 Options) Several palettes are available including: Black & White 4 shades of gray 8 shades of gray 4 Colors CMYK This is surprisingly good. 16 Color Original Windows Palette 16 Color custom palette that I designed myself I designed my own 16 color palette because I felt that the 16 color Window's palette didn't do a very good job dithering people. That palette lacks any brown colors. I also didn't like the blues that were chosen. So, I adjusted the blues and removed one blue and one green color to add in some browns. Of course, there are pictures where the Windows palette will render a better picture than my custom palette. But, for most pictures, I've found that my palette does a better job.    Programmer's Section CodeLab Options CodeLab contains an option on the "save as dll" screen to force the effect to run as a single thread. Normally this is not a good idea because it slows down your effect. But, you can see here that it is necessary to process each row in order because values are being added to future pixels. This option can be added to your CodeLab script by using the following comment: // Force Single Threaded    If you want to see this "comment" in action, here is the complete example...       Complete Source Code Here is the complete CodeLab script for the dithering effect you can download above. // Title: BoltBait's Floyd-Steinberg Dithering Effect v1.0 // Author: BoltBait // Name: Floyd-Steinberg Dithering // Submenu: Stylize // Force Single Threaded // Keywords: Floyd|Steinberg|Dithering|Dither|Error|Diffusion // Desc: Dither selected pixels // URL: http://www.BoltBait.com/pdn #region UICode byte Amount1 = 0; // Palette type|Black & White|4 shades of gray|8 shades of gray|4 Colors CMYK|16 Color Original Windows Palette|16 Color Custom Palette byte Amount2 = 0; // Dithering method|Floyd-Steinberg (1/16)|Custom (1/32) #endregion byte PlusTruncate(byte a, int b) { int c = a + b; if (c < 0) return 0; if (c > 255) return 255; return (byte)c; } Color FindNearestColor(Color color, Color[] palette) { int minDistanceSquared = 255 * 255 + 255 * 255 + 255 * 255 + 1; byte bestIndex = 0; for (byte i = 0; i < palette.Length; i++) { int Rdiff = color.R - palette[i].R; int Gdiff = color.G - palette[i].G; int Bdiff = color.B - palette[i].B; int distanceSquared = Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff; if (distanceSquared < minDistanceSquared) { minDistanceSquared = distanceSquared; bestIndex = i; if (minDistanceSquared < 1) break; } } return palette[bestIndex]; } // Setup for using pixel op private UnaryPixelOps.Desaturate desaturateOp = new UnaryPixelOps.Desaturate(); // Here is the main render loop function void Render(Surface dst, Surface src, Rectangle rect) { // Call the copy function dst.CopySurface(src,rect.Location,rect); Color[] DitheringPalette = new Color[] { Color.Black, Color.White }; switch(Amount1) { case 0: // black and white DitheringPalette = new Color[] { Color.Black, Color.White }; break; case 1: // 4 shades of gray DitheringPalette = new Color[] { Color.White, Color.Silver, Color.Gray, Color.Black }; break; case 2: // 8 shades of gray DitheringPalette = new Color[] { Color.FromArgb(0,0,0), Color.FromArgb(36,36,36), Color.FromArgb(72,72,72), Color.FromArgb(108,108,108), Color.FromArgb(144,144,144), Color.FromArgb(180,180,180), Color.FromArgb(216,216,216), Color.FromArgb(255,255,255) }; break; case 3: // 4 color: CMYK DitheringPalette = new Color[] { Color.White, Color.Cyan, Color.Yellow, Color.Magenta, Color.Black }; break; case 4: // The original 16 color Windows palette DitheringPalette = new Color[] { Color.White, Color.Silver, Color.Gray, Color.Black, Color.Red, Color.Maroon, Color.Yellow, Color.Olive, Color.Lime, Color.Green, Color.Aqua, Color.Teal, Color.Blue, Color.Navy, Color.Fuchsia, Color.Purple }; break; case 5: // Custom 16 color palette DitheringPalette = new Color[] { Color.White, Color.LightGray, Color.FromArgb(77,77,77), Color.Black, // grays Color.Red, Color.Maroon, Color.Yellow, Color.Chocolate, Color.Brown, Color.LimeGreen, Color.DarkGreen, // red brown green Color.LightSkyBlue, Color.Blue, Color.FromArgb(79,79,249), Color.FromArgb(255,192,255), Color.Purple }; // blue purple break; } Color BestColor; ColorBgra BestColora; // Now in the main render loop, the dst canvas has a copy of the src canvas for (int y = rect.Top; y < rect.Bottom; y++) { if (IsCancelRequested) return; for (int x = rect.Left; x < rect.Right; x++) { if (Amount2==0) // Floyd-Steinberg Dithering { ColorBgra CurrentPixel = dst[x,y]; byte A = CurrentPixel.A; if (Amount1 < 3) CurrentPixel = desaturateOp.Apply(CurrentPixel); Color currentPixel = CurrentPixel.ToColor(); BestColor = FindNearestColor(currentPixel, DitheringPalette); BestColora = ColorBgra.FromColor(BestColor); BestColora.A = A; // Floyd-Steinberg Dithering int errorR = currentPixel.R - BestColor.R; int errorG = currentPixel.G - BestColor.G; int errorB = currentPixel.B - BestColor.B; // - * 7 where *=pixel being processed, -=previously processed pixel // 3 5 1 and pixel difference is distributed to neighbor pixels // Note: 7+3+5+1=16 so we divide by 16 (>>4) before adding. if (x + 1 < rect.Right) { dst[x + 1, y + 0] = ColorBgra.FromBgra( PlusTruncate(dst[x + 1, y + 0].B, (errorB * 7) >> 4), PlusTruncate(dst[x + 1, y + 0].G, (errorG * 7) >> 4), PlusTruncate(dst[x + 1, y + 0].R, (errorR * 7) >> 4), dst[x+1,y].A ); } if (y + 1 < rect.Bottom) { if (x - 1 > rect.Left) { dst[x - 1, y + 1] = ColorBgra.FromBgra( PlusTruncate(dst[x - 1, y + 1].B, (errorB * 3) >> 4), PlusTruncate(dst[x - 1, y + 1].G, (errorG * 3) >> 4), PlusTruncate(dst[x - 1, y + 1].R, (errorR * 3) >> 4), dst[x-1,y+1].A ); } dst[x - 0, y + 1] = ColorBgra.FromBgra( PlusTruncate(dst[x - 0, y + 1].B, (errorB * 5) >> 4), PlusTruncate(dst[x - 0, y + 1].G, (errorG * 5) >> 4), PlusTruncate(dst[x - 0, y + 1].R, (errorR * 5) >> 4), dst[x-0,y+1].A ); if (x + 1 < rect.Right) { dst[x + 1, y + 1] = ColorBgra.FromBgra( PlusTruncate(dst[x + 1, y + 1].B, (errorB * 1) >> 4), PlusTruncate(dst[x + 1, y + 1].G, (errorG * 1) >> 4), PlusTruncate(dst[x + 1, y + 1].R, (errorR * 1) >> 4), dst[x+1,y+1].A ); } } } else // Custom Dithering { ColorBgra CurrentPixel = dst[x,y]; byte A = CurrentPixel.A; if (Amount1 < 3) CurrentPixel = desaturateOp.Apply(CurrentPixel); Color currentPixel = CurrentPixel.ToColor(); BestColor = FindNearestColor(currentPixel, DitheringPalette); BestColora = ColorBgra.FromColor(BestColor); BestColora.A = A; // Custom 1/32 Dithering int errorR = currentPixel.R - BestColor.R; int errorG = currentPixel.G - BestColor.G; int errorB = currentPixel.B - BestColor.B; // - - # 8 4 where *=pixel being processed, -=previously processed pixel // 0 4 8 4 1 and pixel difference is distributed to neighbor pixels // 0 0 2 1 0 if (x + 1 < rect.Right) { dst[x + 1, y + 0] = ColorBgra.FromBgra( PlusTruncate(dst[x + 1, y + 0].B, errorB >> 2), PlusTruncate(dst[x + 1, y + 0].G, errorG >> 2), PlusTruncate(dst[x + 1, y + 0].R, errorR >> 2), dst[x+1,y].A ); } if (x + 2 < rect.Right) { dst[x + 2, y + 0] = ColorBgra.FromBgra( PlusTruncate(dst[x + 2, y + 0].B, errorB >> 3), PlusTruncate(dst[x + 2, y + 0].G, errorG >> 3), PlusTruncate(dst[x + 2, y + 0].R, errorR >> 3), dst[x+2,y].A ); } if (y + 1 < rect.Bottom) { if (x - 1 > rect.Left) { dst[x - 1, y + 1] = ColorBgra.FromBgra( PlusTruncate(dst[x - 1, y + 1].B, errorB >> 3), PlusTruncate(dst[x - 1, y + 1].G, errorG >> 3), PlusTruncate(dst[x - 1, y + 1].R, errorR >> 3), dst[x-1,y+1].A ); } dst[x, y + 1] = ColorBgra.FromBgra( PlusTruncate(dst[x, y + 1].B, errorB >> 2), PlusTruncate(dst[x, y + 1].G, errorG >> 2), PlusTruncate(dst[x, y + 1].R, errorR >> 2), dst[x,y+1].A ); if (x + 1 < rect.Right) { dst[x + 1, y + 1] = ColorBgra.FromBgra( PlusTruncate(dst[x + 1, y + 1].B, errorB >> 3), PlusTruncate(dst[x + 1, y + 1].G, errorG >> 3), PlusTruncate(dst[x + 1, y + 1].R, errorR >> 3), dst[x+1,y+1].A ); } if (x + 2 < rect.Right) { dst[x + 2, y + 1] = ColorBgra.FromBgra( PlusTruncate(dst[x + 2, y + 1].B, errorB >> 5), PlusTruncate(dst[x + 2, y + 1].G, errorG >> 5), PlusTruncate(dst[x + 2, y + 1].R, errorR >> 5), dst[x+2,y+1].A ); } } if (y + 2 < rect.Bottom) { dst[x, y + 2] = ColorBgra.FromBgra( PlusTruncate(dst[x, y + 2].B, errorB >> 4), PlusTruncate(dst[x, y + 2].G, errorG >> 4), PlusTruncate(dst[x, y + 2].R, errorR >> 4), dst[x,y+2].A ); if (x + 1 < rect.Right) { dst[x + 1, y + 2] = ColorBgra.FromBgra( PlusTruncate(dst[x + 1, y + 2].B, errorB >> 5), PlusTruncate(dst[x + 1, y + 2].G, errorG >> 5), PlusTruncate(dst[x + 1, y + 2].R, errorR >> 5), dst[x+1,y+2].A ); } } } dst[x,y] = BestColora; } } } Here is the palette file used for dithering: Enjoy! __________________________
  18. Did you install 4.0 to a different directory than 3.5?
  19. If you just want to make an animated gif, you can use our very own agif plugin: http://forums.getpaint.net/index.php?/topic/13454- Or, you can make the individual frames and use UnFREEz to put them together. BTW, programs like Sketchup or Blender are much more suited for advanced animation projects.
  20. Yes. When the Dwarf Horde approached me about plugin browser, I just did a quick look around and decided to use AssemblyConfiguration for the list of keywords. I knew that it wasn't the intended purpose for the field. But, I also knew that CodeLab always produces Release builds. AND, it was the option that caused me to write the least amount of code. We can always change it. I'm not opposed to that. In fact, I'd like to change it to something that is more flexible than AssemblyConfiguration. As we're doing it now, every effect in the same dll must have the same set of keywords and description. Only the display name can be changed. I'd like to fix that.
×
×
  • Create New...