-
Content Count
2771 -
Joined
-
Last visited
-
Days Won
147
Everything posted by Anders Melander
-
system.zlib.pas(2958): E2065 Unsatisfied forward or external declaration: '@zcalloc'
Anders Melander replied to alogrep's topic in VCL
That would be too easy. -
Parnassus Bookmarks for Delphi 11 Alexandria?
Anders Melander replied to PeterPanettone's topic in Delphi IDE and APIs
I've heard that it's a special integration operation and that everything is going according to plan. Nothing to see here. Move along. -
Replace this: if fChooseResult.showModal=mrOK then did:=dm.qStockNum.fieldbyname('design_id').asstring; with: if fChooseResult.Execute then did := dm.qStockNum.FieldByName('design_id').AsString; and then modify the TfChooseResult form like this: const MSG_AFTERSHOW = WM_USER; type TfChooseResult = class(TForm) ... protected procedure MsgAfterShow(var Msg: TMessage); message MSG_AFTERSHOW; public function Execute: boolean; end; implementation {$R *.dfm} procedure TfChooseResult.MsgAfterShow(var Msg: TMessage); begin BitBtn1.SetFocus; end; function TfChooseResult.Execute: boolean; begin PostMessage(Handle, MSG_AFTERSHOW, 0, 0); Result := (ShowModal = mrOK); end; Edit: Maybe I should explain what's going on. The PostMessage puts a custom message into the form's message queue. When ShowModal is called the form is displayed and the modal loop pumps the message queue [*]. The message pump grabs the custom message from the queue and calls the form's message handler (the MsgAfterShow method). MsgAfterShow focuses the button. [*] Pumping the message queue means that the code loops, reading one message at a time from the message queue and dispatching these messages to the "message handlers". It's "a bit" more complicated than that but hopefully you get the overall picture.
-
Yes You can use Search->Find in files (Ctrl+Shift+F) to locate the place. Search for " fChooseResult .Show". No problem. Happy to help.
-
@Pat Foley That example was really confusing - and contains so many bad practices.
-
By the way, do yourself a favor and stop using TBitBtn. They were cute in the nineties. Not anymore.
-
Nope. He's not calling the event handler. He's calling the Click method on the button - which emulates a click on the button.
-
Assuming that you're showing this form modally from somewhere else I would do it like this: type TfChooseResult = class(TForm) wwDBGrid1: TwwDBGrid; Panel1: TPanel; dsResult: TDataSource; BitBtn1: TBitBtn; BitBtn2: TBitBtn; procedure wwDBGrid1DblClick(Sender: TObject); private public function Execute: boolean; end; var fChooseResult: TfChooseResult; implementation {$R *.dfm} procedure TfChooseResult.wwDBGrid1DblClick(Sender: TObject); begin BitBtn1.click; end; function TfChooseResult.Execute: boolean; begin BitBtn1.SetFocus; Result := (ShowModal = mrOK); end; and then display the form like this: begin ...do other stuff here... if (fChooseResult.Execute) then begin // User pressed OK end else begin // User closed dialog some other way end; end; And like Peter suggested, set the ModalResult property of the OK button to mrOK and the Default property of the same to True. If you add a Cancel button, set its ModalResult property to mrCancel and the Cancel property to True. If you're not displaying the form modally, then you'll need to call SetFocus in the forms OnShow event handler instead. This of course assumes that the form isn't visible all the time.
-
Set it in code: ButtonOK.SetFocus; The ActiveControl property is a property of the form but that is only applied when the form is first created and it sounds like you are only doing that once.
-
FireDAC, New OLE DB Driver, and SQL Server
Anders Melander replied to BruceTTTT's topic in Databases
Um... you aren't using ODBC data sources via FireDAC, are you? ODBC is just the API FireDAC uses to talk to the driver. From your perspective there's nothing ODBC about it - the API could be anything. Maybe they did 🙂 We've just completed replacing MSSQL via ADO with FireDAC and for us it works fine. We had to update the client library to a newer version on a couple of clients but apart from that it's faster, better. I think the oldest SQL server version we connect to is 2014/v12. -
What you're dealing with is an unavavoidable rounding problem and a misunderstanding of what's going on mathematically. The two versions are equally bad. They just distribute the rounding error differently. You want the first palette entry to have a grey-level value of 0 and the last one to have a value of 255 - not 256. Level = 255 * (Index / (Levels-1)) or Grey := i * 255 div (_NumColors-1)
-
https://letmegooglethat.com/?q=delphi+webp Seems Bing has hijacked that service so here's a link without the sarcasm: https://www.google.com/search?q=delphi+webp
-
Parallel Resampling of (VCL-) Bitmaps
Anders Melander replied to Renate Schaaf's topic in I made this
I had to reread the source 3 times before I spotted the place it occurs. "with" strikes again: ClusterWeight := ClusterX[X].Weight; with HorzBuffer[ClusterX[X].Pos - MapXLoPos] do begin Inc(Cb, B * ClusterWeight); // Note: Fixed precision multiplication done here Inc(Cg, G * ClusterWeight); Inc(Cr, R * ClusterWeight); Inc(Ca, A * ClusterWeight); end; As you can see I have now added a comment to make it obvious 🙂 Anyway, your changes has now been committed. Please verify that the comments I've added in the source are correct. I will continue working on correcting the alpha handling (i.e. do premultiplication). -
Parallel Resampling of (VCL-) Bitmaps
Anders Melander replied to Renate Schaaf's topic in I made this
Yes, you're right. I understand the midpoint rule but I just can't make your code fit it. Let me have a look again... Ah, now I get it. It was your comments that confused me. For example: // old weight: Filter(x0*Oldscale)*Oldscale If I just read the code and ignore the comments it makes much more sense. That's a new one 🙂 I mean that when you operate on 32-bit integer values which has been multiplied by $800 (= 1 shl 11) it means that the upper 21 bits will contain the integer part and the lower 11 bits the fractional part. In other words [21:11] fixed precision. When applying the weight values you do a shr 22 (= $800*$800) to convert from [10:22] fixed precision back to integer. The [10:22] must mean that you have multiplied two [21:11] values at some point but I can't really spot where that happens. FWIW much of Graphics32 supports the TFixed [16:16] fixed precision type. For example many methods allow you to specify coordinates in either integer, TFixed or floating point format. I don't understand what this refers to. -
Parallel Resampling of (VCL-) Bitmaps
Anders Melander replied to Renate Schaaf's topic in I made this
Duh! Yes of course. I've just checked and the value was correct in my original resampler source so it appears to be a copy/paste bug introduced when the code was integrated in GR32. As far as I can tell the bug has been there from the start 😕 Regarding this: x0 := J - Center; // old weight: Filter(x0*Oldscale)*Oldscale x1 := max(x0 - 0.5, -FilterWidth); x2 := min(x0 + 0.5, FilterWidth); // intersect symmetric interval of length 1 about x0 with support of scaled filter x3 := 0.5 * (x2 + x1); // new center Weight := Round(Prec * Filter(x3 * OldScale) * OldScale * (x2 - x1)); // intersection with support entered into the weight You say that you're "computing the integral for the convolution with the filter using the midpoint-rule" so I would have expected to see the averaging of two filter values in order to find the midpoint but I can't really match that with the above. Can you explain what's going on, please? Once I understand it I'll comment the code so it's maintainable. Also, am I correct in assuming that you're doing calculation in [21:11] fixed precision and storing the weights in [10:22] instead of the old [24:8] and [16:16]? -
Parallel Resampling of (VCL-) Bitmaps
Anders Melander replied to Renate Schaaf's topic in I made this
Very, very nice. The performance has suffered a bit but the result is much better. It actually seems that the quality of the Graphics32 resampler now surpasses your original algorithm for most kernels (there's still artifacts with the GR32 box filter). I've integrated your changes locally and will commit once I've done a bit more testing. One thing that almost gave me brain cancer was the abysmal ASM generated by this code (not your fault): C.B := min((max(Cb, 0) + $1FFFFF) shr 22, 255) It goes something like this cmp dword ptr [Cb],$00 jle A mov eax,[Cb] jmp B A: xor eax,eax B: lea edx,[eax+$001fffff] shr edx,$16 cmp edx,$000000ff jnl C add eax,$001fffff shr eax,$16 jmp D C: mov eax,$000000ff D: mov [C.B],al Luckily the path with that code isn't taken in your example. -
Parallel Resampling of (VCL-) Bitmaps
Anders Melander replied to Renate Schaaf's topic in I made this
Take a bath. Always works for me 🙂 -
Parallel Resampling of (VCL-) Bitmaps
Anders Melander replied to Renate Schaaf's topic in I made this
I was surprised that this was necessary at all as I really thought that the compiler already made this optimization. Anyway, basically a "for" loop like this (the loop value isn't used inside the loop): for i := LowValue to HighValue do begin ..stuff here end; is compiled to this pseudo code: var i := LowValue; var test := HighValue - i; if (test = 0) then goto end_loop; :start_loop ..stuff here Inc(i); var test := HighValue - i; if (test <> 0) then goto start_loop; :end_loop while this equivalent while loop: i := HighValue - LowValue; while (i >= 0) do begin ..stuff here Dec(i); end; is compiled to: var i := HighValue - LowValue; if (test = 0) then goto end_loop; :start_loop ..stuff here Dec(i); if (test <> 0) then goto start_loop; :end_loop Exact same code if iterating from zero in case you wondered. Similarly a for loop where the loop variable is used inside the loop is also slightly faster when implemented as a while loop. -
Parallel Resampling of (VCL-) Bitmaps
Anders Melander replied to Renate Schaaf's topic in I made this
I've now merged your changes into the main Graphics32 branch. In addition I also included the following (very minor) optimizations of the Resample() function: Replaced for loops with while loops where possible. The channels are processed in their physical order: B, G, R, A instead of R, G, B, A. I've replaced the RGB bit-twiddling with regular record field access (32-bit compiler only). For example instead of: with BufferEntry^ do begin B := Integer(SourceColor.ARGB and $000000FF) * ClusterWeight; G := Integer(SourceColor.ARGB and $0000FF00) shr 8 * ClusterWeight; R := Integer(SourceColor.ARGB and $00FF0000) shr 16 * ClusterWeight; A := Integer(SourceColor.ARGB shr 24) * ClusterWeight; end; I now do this: BufferEntry.B := SourceColor.B * ClusterWeight; BufferEntry.G := SourceColor.G * ClusterWeight; BufferEntry.R := SourceColor.R * ClusterWeight; BufferEntry.A := SourceColor.A * ClusterWeight; I'm pretty sure the old method used to be faster but apparently not anymore. Maybe the compiler has gotten better or maybe it's the hardware (I have a pretty old CPU so I doubt it's that). I have only profiled the changes with optimization enabled so it's possible that I've made the unoptimized code slower. With optimization enabled, the performance of Resample() now matches, and in some cases even exceed, your algorithm. However since yours is also alpha-aware I still consider yours faster. There are a few additional things that could be done to make the code faster but I'm not really inclined to go there as it would also make it pretty unreadable. The performance of Resample() with the 64-bit compiler is horrible. For some reason your code is much faster there. I've not done anything to improve that. -
Parallel Resampling of (VCL-) Bitmaps
Anders Melander replied to Renate Schaaf's topic in I made this
That's excellent. I'm a bit surprised about the presence of the XY iteration order problem as that's a bit of a rookie mistake. It probably wasn't caught because the outer loop does iterate Y (and then iterates XY in the inner). Anyway, good catch. Would you mind either creating a pull request or posting a patched version of GR32_Resamplers.pas (without the reformat as that makes it hard to spot the actual changes - not that I disagree about the need to reformat). Your algorithm seems to be consistently 5-15% faster than GR32 on my system (tested with your latest changes). The quality is almost identical. For some kernels yours is marginally better, for some GR32 is marginally better. For the box filter GR32 wins in quality of details, but loses on fidelity (artifacts). WIC wins on both quality and speed. I think these results are as expected; GR32 is paying the price of the overhead a generalized framework. The quality could probably be improved to match WIC but the question is if it's worth the trouble or if the current quality is "good enough"...? I haven't had time to investigate why the Resample function doesn't use the alpha-aware methods. I'm knee deep in a quantization/dithering extension for GR32. P.S. "const StopWatch: TStopWatch" really should be "var StopWatch: TStopWatch". The only reason it works with const is Delphi doesn't know/care that the methods are modifying the TStopWatch record. -
Can undefined function result point to valid/used data in memory?
Anders Melander replied to Mike Torrettinni's topic in RTL and Delphi Object Pascal
No. It's empty. I don't know who "we" are but there's nothing unsafe about the code you posted. It's just fundamental string handling. -
Parallel Resampling of (VCL-) Bitmaps
Anders Melander replied to Renate Schaaf's topic in I made this
Apparently the GetSampleX methods are only used when sampling via a rasterizer or a transformation (e.g. rotate/skev/etc). -
Parallel Resampling of (VCL-) Bitmaps
Anders Melander replied to Renate Schaaf's topic in I made this
That's correct. A fully transparent pixel has no color. I'm not sure what it is you're showing here. I contributed code to handle that in 2011. See TKernelResampler.GetSampleFloat. That said there does seem to be a problem because when I resample in my own bitmap editor the alpha isn't handled correctly. I'll look into it. -
Parallel Resampling of (VCL-) Bitmaps
Anders Melander replied to Renate Schaaf's topic in I made this
Of course it's wanted. Improvements are always welcome and you seem to have a really good understanding of the subject. You might opt to have two versions instead: One for 32-bit opaque RGB and one for 32-bit RGBA. The premultiply/unpremultiply really messes with the quality since you're operating on 8-bit values. One way to avoid this is to premultiply to floating or fixed point, resample the floating/fixed point values and then unpremultiply back to 8-bit. As you can imagine this doesn't exactly improve the performance or memory usage. The memory usage can be lessened by processing one channel at a time. -
Parallel Resampling of (VCL-) Bitmaps
Anders Melander replied to Renate Schaaf's topic in I made this
Very nice. As a Graphics32 contributor I would have preferred though that you'd spent the (probably considerable) effort improving Graphics32 🙂 A few suggestions: Use TStopWatch to measure elapsed time and add the stopwatch as a parameters to TScaleProcedure. This way the procedure can pause the stopwatch when it's doing something which shouldn't be included in the benchmarking. For example assigning back and forth between TBitmap/TBitmap32. Use TTask instead of TThread. This solves your problem of how to manage the threads and avoids the overhead of creating the threads. I understood that you had problems with TTask, but IMO the solution to that is to locate and fix those problems rather than avoiding TTask. For Graphics32, using the memory backend instead of the GDI backend is better when you don't need to use GDI features. See below. In this case it doesn't make much of a difference though. Your code seems to handle RGBA but as far as I can tell you're doing it wrong. You cannot process each RGBA channel independently. Instead you need to operate on premultiplied RGBA values. For example you wouldn't want an RGBA value of $00FFFFFF to have any influence on neighboring pixels. So: 1) Premultiply, 2) Resample, 3) Unpremultiply. Unfortunately this will probably have a very negative impact on both performance and quality. Have cake/Eat cake - Choose one. FWIW, Graphics32 does have a multi-threaded rasterizer but since it uses TThread it doesn't make sense to use it in your benchmark since the overhead of thread setup/teardown for just a single call would kill performance. procedure LanczosGR32(const Source, Target: TBitmap; parallel: boolean); var Source32, Target32: TBitmap32; Resampler: TKernelResampler; begin Source32 := TBitmap32.Create(TMemoryBackend); Target32 := TBitmap32.Create(TMemoryBackend); try Source32.Assign(Source); Target32.SetSize(Target.Width, Target.Height); Resampler := TKernelResampler.Create; try Resampler.KernelClassName := 'TLanczosKernel'; Resampler.Resample(Target32, Target32.BoundsRect, Target32.BoundsRect, Source32, Source32.BoundsRect, dmOpaque, nil); finally Resampler.Free; end; Target.Assign(Target32); finally Source32.Free; Target32.Free; end; end;