Jump to content

Anders Melander

Members
  • Content Count

    2297
  • Joined

  • Last visited

  • Days Won

    119

Posts posted by Anders Melander


  1. 4 hours ago, Clément said:

    Since I'm explicitly posting a message to a private window that is designed to handle it in a specific way and is not a subclass of a Windows control, it should be safe to use it. Isn't it?

    You missed the point: The +$0001 is not necessary. The first available custom message ID is WM_USER, not WM_USER+1.

    • Like 1

  2. One of my current clients has been using ChilKat for FTP & SFTP for years and it seems to work fine.

    The first thing I did in order to work with it was write a set of wrapper classes that hide the ugly DLL API and abstract the FTP and SFTP differences away.

     

    I'd have preferred something with source code though, but AFAIK there's nothing for Delphi and the choice had already been made.

    • Like 1
    • Thanks 1

  3. 35 minutes ago, Renate Schaaf said:

    Here is a first result for radius 10.

    Pretty nice validation result.

     

    Extrapolating from your benchmark result, I'm guessing your CPU is about twice as fast as mine and that my blur would process something like 20,000,000 pix/sec on your system. Can that be right?

     

    45 minutes ago, Renate Schaaf said:

    Need to give that a closer look.

    There's no guarantee that my validation algorithm is correct (I cooked it up myself). You might want to verify that before you start mangling your code.


  4. 9 minutes ago, Eric Grange said:

    the JCL's JDBG format allows that (in addition to being useful for debug stacks)
    https://stackoverflow.com/questions/6019698/access-jcl-debug-information-contained-in-executable

    The last time I looked, the JCL JDBG functions didn't directly surface the debug data; You can ask the functions to resolve addresses and so on, but you can't get a list of all units, symbols, line numbers, etc.

    Isn't it correct that you had to modify the JCL source in order to get the JDBG data you needed out of it for your profiler?


  5. On 10/11/2023 at 11:33 AM, Renate Schaaf said:

    They do handle the alpha-channel, though. I would have liked to see the alpha-blended result, but I couldn't get the ImageView to show it.

    You really do need to handle the alpha channel if you are going to operate on 32-bit bitmaps. Basically, it's the same as what you did for the resampler: Premultiply, blur, unpremultiply.

    Enable the checkerboard pattern in TImgView32.Background and you should be able to see it.

     

    On 10/11/2023 at 11:33 AM, Renate Schaaf said:

    Seeing as my (unthreaded) routine is truly Gaussian, and that it outperforms GR32.GaussianBlur by a factor of roughly 2-3, would it make sense for me to suggest it as a replacement in GR32?

    Sure, that would be nice; Go ahead. Just make a version that has the same API as the existing ones:

    procedure Blur(Bitmap32: TBitmap32; Radius: TFloat); overload;

    and optionally:

    procedure Blur(Bitmap32: TBitmap32; Radius: TFloat; const Bounds: TRect); overload;
    procedure Blur(Bitmap32: TBitmap32; Radius: TFloat; const BlurRegion: TArrayOfFloatPoint); overload;

    If you start by posting to your own repository I can do the work required to get it integrated into Graphics32.

     

    On 10/11/2023 at 11:33 AM, Renate Schaaf said:

    How can I better test the quality?

    My test bench validates the following:

    • Edge handling
      Does the "outside" of the bitmap bleed into the blurred bitmap. Basically, I just blur a white bitmap and verify that all pixels are still white.
    • Alpha bleed
      Does the color of fully transparent pixels bleed into semi-tranparent pixels.
    • Color overflow
      No R, G, or B values should increase. A minor decrease, when blurring a solid color bitmap, is allowed.
    • Loss/gain due to premultiplication
      I test the average color loss of blur of a solid color bitmap, with varying alpha. This mostly tests the precision of the premultiplication.
    • Average RGB error and lightness change
      I blur a gradient and compare the average RGB-, and lightness change.
    • Horizontal and vertical symmetry
      I blur some horizon and vertical lines and verify that they have been blurred symmetrically.
    • Gaussian error
      I blur a line and verify that the blurred result corresponds to the Gaussian curve. RMS error and signal loss are validated.
    • Vertical error
      I blur a vertical line and verify that all rows contain the same color value.
    • Horizontal error
      I blur a horizontal line and verify that all columns contain the same color value.
    • Uniform RGB
      I blur a sequence of solid color bitmaps, with increasing R=G=B and verify that the result doesn't contain noise. This usually catches simple over/underflows.

    The result looks like this:

    FastBlur (box), Angus Johnson [1024 x 1024, 10]
      PASS: Edge handling
      PASS: 100% alpha bleed:   0.00% bleed, 0 errors
      PASS: Overflows: 0, max swell: 0.00%, 0 bleeds
      PASS: Alpha:  31, Average loss, RGB:   0.92 %, A:   0.00%
      PASS: Alpha:  63, Average loss, RGB:   0.52 %, A:   0.00%
      PASS: Alpha:  95, Average loss, RGB:   0.26 %, A:   0.00%
      PASS: Alpha: 127, Average loss, RGB:   0.26 %, A:   0.00%
      PASS: Alpha: 159, Average loss, RGB:   0.13 %, A:   0.00%
      PASS: Alpha: 191, Average loss, RGB:   0.00 %, A:   0.00%
      PASS: Alpha: 223, Average loss, RGB:   0.00 %, A:   0.00%
      PASS: Alpha: 255, Average loss, RGB:   0.00 %, A:   0.00%
      PASS: Average RGB error:   0.48 %
          : Lightness change:  -0.50 %
      PASS: Horizontal symmetry error:   0.00
      PASS: Vertical symmetry error:   0.00
      PASS: Gaussian RMS error:   7.94
      FAIL: Gaussian signal loss:   6.67 %
      PASS: Vertical errors:      0
      PASS: Horizontal errors:      0
      PASS: Uniform RGB[ 31] errors:      0 (  0.00 %), noise:      0
      PASS: Uniform RGB[ 63] errors:      0 (  0.00 %), noise:      0
      PASS: Uniform RGB[ 95] errors:      0 (  0.00 %), noise:      0
      PASS: Uniform RGB[127] errors:      0 (  0.00 %), noise:      0
      PASS: Uniform RGB[159] errors:      0 (  0.00 %), noise:      0
      PASS: Uniform RGB[191] errors:      0 (  0.00 %), noise:      0
      PASS: Uniform RGB[223] errors:      0 (  0.00 %), noise:      0
      PASS: Uniform RGB[255] errors:      0 (  0.00 %), noise:      0

     

    On 10/11/2023 at 11:33 AM, Renate Schaaf said:

    Where can I find your routine then?

    In your mailbox in a few days, if you're lucky :classic_cool:

    I'll include the test bench too.

     

    By the way, I can really recommend that you profile your implementation with VTune. This is an area that usually benefits greatly from that.

    • Thanks 1

  6. 22 minutes ago, David Heffernan said:

    What's especially awesome about the VCL code is that it writes the for loop in a really weird way as 

    
    for var I: Integer := 0 to -1 + Items.Count do

    with the -1 before the count, and that seems to have taken from Setting the drop down width of a Combobox in Delphi – twm's blog (dummzeuch.de) which in turn is taken from Sizing the ComboBox Drop Down Width (thoughtco.com)

    THeY fouND tHe cOdE On ThE InTeRwebS. It muST be ThE beSTESt!

    • Haha 4

  7. 10 minutes ago, Renate Schaaf said:

    Performance: Unthreaded routine: For radii up to 8 Unsharp is on par with FastGaussian, after that FastGaussian is the clear winner.

    By "FastGaussian" I guess you mean the FastBlur routine?

    FastBlur is actually a box blur and not a true Gaussian blur. This is just fine for some setups, but not so great for others.

     

    Also, performance is, as you've discovered, not the only important metric when comparing blurs. Fidelity can also be important. It completely depends on what the blur is used for. Some algorithms are fast but suffer from signal loss or produce artifacts. Some are precise but slow. And then there are some that do it all well 🙂

     

    The parameters below are [Width, Height, Radius]:

    image.png.b32a26003d5ca0aef95412a671ac0dcd.png

    image.png.5673519d0e33a7f94c76ef0d92d66c0c.png

    image.png.812a0c070745c3517cfc7c836547ab9d.png

    image.png.68f41d9bef013a399599363f33280f5a.png

    Case in point, BoxBlur32 above is consistently the fastest but also has the worst quality and doesn't handle Alpha at all.

     

    45 minutes ago, Renate Schaaf said:

    But if anybody has an idea for how to implement it better, I'm all ears.

    Use floats and implement it with SSE. That's what I did 🙂


  8. 54 minutes ago, Fr0sT.Brutal said:

    dynamically generated code to bypass AV signature detection.

    You are talking about self-modifying code or simply the ability of a process to alter its own page-level protection. While that is an OS feature that is used to implement embedded DLLs it isn't specific to it. Lots of other application techniques use that feature.

     

    I thought you meant that embedded DLLs posed a risk to the applications using them. It seems you mean that an application using embedded DLLs potentially poses a risk to the system as a whole.
    By extension of that argument, you could just as well argue that compiled code is unsafe and that all applications must be distributed as source and compiled by the user. But since you are not going to argue, let's not go there 🙂


  9. 7 hours ago, Fr0sT.Brutal said:

    it could be used by malicious software

    I fail to see how. Can you give an example?

     

    Using an embedded DLL, the application executes code that it itself has supplied and linked. If anything, this should be safer than loading an external DLL from disk and executing code in that.

     

    7 hours ago, Fr0sT.Brutal said:

    Look at Android which gets more and more restrictions of getting into the system with every new release.

    This is not "getting into the system". Everything happens in user mode within the application.


  10. 2 hours ago, Fr0sT.Brutal said:

    One more concern: with the global trend to tighten security of user-level OS-es (I mean, all that are not severe Linux), I suspect this kind of lib loading could be likely removed or at least require admin rights.

    I can't see how they could prevent it without breaking a lot of applications that are doing similar (but not necessarily the same) things. It's basically just juggling page protection and modifying memory. All done in USER-level.

    Also, why should it pose a security threat?


  11. Just now, Dave Craggs said:

    Really don't know why I should need one

    Because the manifest controls the runtime environment where Windows execute your application. If your application doesn't have a manifest (internal or external), then Windows assumes that your application is completely clueless about the environment and gives you one where you can party like it's 1999.

     

    Apart from that, you seldom need to use a custom manifest; The one generated by Delphi should be good enough for most uses. Try examining the manifest setting in your project again.


  12. 29 minutes ago, Dave Craggs said:

    Bit confused about manifest. Delphi suggests it shod auto generate, but I can't find any.

    It's included in the .res file generated by Delphi so you can examine it with a resource editor.

    image.thumb.png.50279b8a5be924c090f52c0b5f1614e1.png

     


  13. 51 minutes ago, Fr0sT.Brutal said:

    However,

    Quote

    Used by more Delphi developers than any other single version, Delphi 7 is one of the most successful IDEs created by Borland. Its stability, speed, and low hardware requirements led to active use through 2020.

     

    That's one interpretation but just because the Wikipedia page states it (unsourced, incidentally) doesn't make it so.

    Another is that it's the most pirated version (the last version without license activation). Yet another is the self-goal of Delphi 8.

    It's impossible to know.

     

    Funnily, if you follow the edits on the wiki, the section you quoted at one point stated:

    Quote

    Delphi 7 is one of the most appreciated IDEs created by Borland because its stability, speed and low hardware requirements. However, as in all Delphi versions there are a huge number of known bugs that Borland never fixed. The task of fixing those bugs was left to Delphi community (see projects as Kylix Unofficial Patch and the Reviving Delphi project).

     


  14. 55 minutes ago, Fr0sT.Brutal said:

    Ah, yes. Forgot about that one. It's too bad your changes from Martin Offenwanger's version predate the Git repo. That makes it pretty impossible to identify the changes.

    It does look like they have been updated independently since the fork though. FWIW, I can see you have a fix similar to mine in your version.

     

    1 hour ago, Fr0sT.Brutal said:

    Alas, the process of loading from memory involves too much of black voodoo magic

    I do think it's fairly well-documented but I will agree that it's pretty complex and not for the faint of heart (The implementation of it, that is. The use is trivial).

    I think my attitude toward it would be: If it works right away use it, otherwise don't bother with it. As I wrote, I've been using it for years without any problems.


  15. 17 hours ago, Angus Robertson said:

    I'm looking at adding the OpenSSL DLLs as resources to ICS projects, to simplify distribution to one file.

    But currently it seems a DLL can only be loaded using the LoadLibrary API from a disk file, so the resource has to be written to disk first then LoadLibrary used. 

    I've been loading DLLs from resources for years using Martin Offenwanger's BTMemoryModule: https://github.com/DSPlayer/memorymodule

    It's a Pascal port of Joachim Bauch's solution: https://www.joachim-bauch.de/tutorials/loading-a-dll-from-memory/

     

    I have a small patch that I have never gotten around to committing to the BTMemoryModule repo. If you elect to go the BTMemoryModule route let me know and I will push a pull request to the repo.

×