

A.M. Hoornweg
-
Content Count
494 -
Joined
-
Last visited
-
Days Won
9
Posts posted by A.M. Hoornweg
-
-
I have a workaround that works:
procedure SaveAsWebP(aBitmap: tbitmap; aOutputfilename: string; Compressionfactor: integer; out MimeContentType: string); var lStream: tMemorystream; skimage: iSkImage; begin lStream := tMemorystream.Create; try aBitmap.SaveToStream(lStream); lStream.Position := 0; skimage := tskimage.MakeFromEncodedStream(lStream); skimage.encodetofile(aOutputfilename, tskEncodedImageFormat.WebP, Compressionfactor); MimeContentType := 'image/webp'; finally lStream.Free; end; end;
So it appears that it is really the following code that is broken:
var skimage:=aBitmap.ToSKImage;
-
Hello all,
I have a 32-bit Windows application (it is an Intraweb based ISAPI dll) and I try to write images in losslessly compressed webp format.
The bitmap that I want to convert to webp is a 32-bit tBitmap containing some 2-D graphics.
My problem:
The generated output image is totally broken when I use Delphi 12's SKIA routines for the conversion. Graphics programs render it only partially, then give up.
This is the code that I wrote; The compression factor that I pass is 100.
Did I do anything wrong?
... uses system.skia, vcl.skia; procedure SaveAsWebP(aBitmap: tbitmap; aOutputfilename: string; Compressionfactor: integer;Out MimeContentType:String); begin var skimage:=aBitmap.ToSKImage; skimage.encodetofile(aOutputfilename, tskEncodedImageFormat.WebP, compressionfactor); MimeContentType:='image/webp'; end ;
-
Smart Setup is a unified tool for installing and building Delphi packages, whether they come from TMS or elsewhere.
See: https://www.tmssoftware.com/site/blog.asp?post=1360
-
3
-
2
-
-
If you want to store either integers or objects into your grid, just declare a simple class that contains an integer. That way you can consistently store objects in the grid and treat everything alike.
And you can simply test if the object is an integer or something else: "(if Obj IS tInteger then ...)"
Type tInteger=Class protected fValue:Integer; public Constructor Create(const aValue:Integer); Property Value: Integer read fValue write fValue; end; Constructor tInteger.Value (const aValue:integer); begin fValue:=aValue; end;
-
If the problem is just that the cdecl function needs to be in an external module, maybe it's possible to work around that. It may sound counter-intuitive, but it's perfectly possible to export a function contained in an *.exe project and then call it from a DLL loaded by the executable. I see no reason why the executable shouldn't be allowed to import a function that it exports itself.
Program test; uses windows; function somefunction:integer; cdecl; export; begin result:=1; outputdebugstring(pchar('Hello World')); end; Exports somefunction; end;
-
19 minutes ago, Lars Fosdal said:@A.M. Hoornweg Passing the exception type and callstack info from the server would be useful for making an educated handling in the client, but I don't see why raising an exception in the client would be helpful. The callstack from the server side exception won't be the same as the callstack from an exception raised in the client,. It all depends on the client-side context, of course, so sometimes an exception may be acceptable, but frankly; I prefer to not raise an exception if I can handle a problem flow in a better way.
One advantage is that it's way less work server-side. If anything goes wrong, you need not worry too much about how to inform the client because that information is already contained in the exception that was thrown by whatever action failed. The stack is unrolled automatically just like in regular Delphi apps and the exception information is automatically propagated to the client.
Client-side, a remote procedure call is used like any other Delphi call. In the case of an error, you use structured exception handling and use the exception type as a criterium for how the client should proceed.
try server.executequery(query) except on e:exception do begin if e is eCommsError then //did the internet connection fail? If so, client should try again later. ... else if e is eDatabaseError then showmessage(format('The server really didn''t like this query, this is wrong with it: (%s) "%s"',[e.classname, e.message])) else ... end; end;
-
21 minutes ago, Lars Fosdal said:It isn't worse than your response having result codes that indicate success + data, or failure + type of failure, and your client responding to these the way you want it to.
F.x
Client -> Server, send me all the details on <some reference><- Server: dude, that was a bad reference - I almost crashed!
Client: Well, server didn't like that, so I better tell the user that the server couldn't find his shit and that the request upset the server.
The disadvantage of that is that it doesn't tell you in detail what went wrong on the server. It is also tedious, the server needs to CATCH exceptions and convert them into something meaningful (an error code?) to pass back to the client, hopefully yielding sufficient information.
If the framework itself is designed in such a way that it can pass exceptions back from server to client, the client will re-raise the same exception type (eOverflow, eConvertError, eInOutError, eListError...) with (hopefully) the server's error address in the error message so you can easily find the root cause. It also simplifies server-side development enormously; if something goes wrong on the server, it can simply raise an exception and it will be passed back to the client.
-
I use Remobjects Remoting SDK as a middleware and that is perfectly capable of passing an exception that happens in a remote procedure call back to the client without hanging. The exception is then raised in the client.
-
Thank you very much!
-
I use MMX code explorer but I can't find the option to do this, can you point me to it? Thanks in advance!
-
Hello World,
does anyone know of an IDE plugin or other tool that will analyze the interface section of a unit and expand the unit names with their full namespaces, such as "rtl, vcl, db" etc ?
Thanks in advance!
-
Please try to disable "code inlining control" in the compiler settings and see if the problem disappears.
-
FOUND!
The L902 linker error disappears if I set the compiler switch "code inlining control" to OFF! I can reproduce this in several 32-bit programs that had this problem. Kudos to my colleague Ralf Claussen who discovered this by chance.
-
I want "F2084 Internal Error L902" gone !!!
-
1
-
-
Hello all,
I have ported a large project (32-bit, 1.4 million LOC) from Delphi 11 to Delphi 12 (enterprise).
Performing a "full build" works fine, but a "make" produces linker error L902 every time; now just imagine you're debugging something and have to do a full build all the time. It's simply no fun.
I have never had this problem in Delphi 11. Is there any way I can circumvent this problem ?
-
16 hours ago, Brandon Staggs said:Then fix the deployment process instead. Compressing the EXE instead of using a compressed data package for deployment is at best lazy. Even a basic apache web server can be configured to compress your binaries for downloading of the client and you wouldn't have to do anything special to support it.
What are you talking about??? I'm not compressing any EXEs. I'm just preventing that 30-40% of unused stuff gets linked into them (it would be nice if Delphi's linker had such an option). And of course I use highly compressed setups.
-
5 minutes ago, Anders Melander said:So use an installer or zip the files.
I have *always* used installers.
Nowadays executable size is not much of an issue anymore, thanks to better networks. But in a not so distant past I had to regularly push software updates to locations that were using T&T Inmarsat Mini-M satellite terminals. Imagine the slowest and most expensive connection imaginable, 2400 bps, costing like 5 euros per minute. I'm glad those days are over.
-
38 minutes ago, David Heffernan said:I still don't understand what actual problem people who want to make their executables a few mb smaller are trying to solve.
It adds up in some projects consisting of dozens of dlls and executables. I had to cope with deployment over slow connections paid by data volume until quite recently.
-
The problem with using UPX is the following.
Normally Windows would open an executable file using a "memory mapped file" mechanism instead of bluntly allocating memory and loading the contents. This allows the Windows virtual memory manager to efficiently "page in" sections of the executable as needed (on demand paging), improving performance and minimizing memory use.
If the file is compressed using UPX, execution starts in the UPX loader stub which immediately allocates a big block of memory and extracts the executable into that before proceeding with the "real" execution. This simply wastes precious resources.
-
2
-
-
I have made an application that copies the Delphi RTL/VCL source files into a temporary folder, inserts the text '{$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}' in the right places and re-builds the whole lot. The compiled *.dcu files contain a lot less RTTI than before.
By linking against this compacted RTL I achieve a size reduction in a 64-bit VCL application from 14 MB to 10.3 MB using Delphi 12.
For just a single executable that isn't worthwhile, but I use this in some multi-module projects that consist of a few dozen ActiveX EXE's and DLL'S. There the cumulative size reduction is substantial. Proper testing is hugely important, one has to be sure that the missing RTTI doesn't cause the program to malfunction.
-
1
-
-
9 hours ago, StephenM said:I've discovered the issue and can easily replicate it in a sample project. And it's bizarre.
A quick recap. The simple D12 project loading the DLL works. It's composed of a main form and a unit with the DLL function declarations. No issue calling the DLL methods.
I drop a second VCL form into the project. To this form I add a TDBChart from the 'TeeChart Std' components. Compile, run, and after a while the access violations in my DLL are reported.
If I remove the form with the TDBChart from the project, the simple app works once again.
Any ideas?
In that case it may have to do with the changed FPU flags behavior in Delphi 12.
Try doing this right before calling your DLL, does it make a difference?
SetFPUMask([exdenormalized, exunderflow, exprecision]);This setting makes the FPU behave like in previous Delphi versions. In other words, a FP division by 0 will generate an exception instead of continuing the code path with a NAN result.
-
16 minutes ago, StephenM said:@A.M. Hoornweg, thanks. All three projects, D5, D12 simple, D12 complex, all have the same field alignment.
Please verify if "sizeof (tViewerParams)" gives the same result in all compilers.
Also, is the calling convention to the dll function declared identically and clearly in all projects (e.g. "stdcall") ?
-
The thing that may bite you here is field alignment. The compiler that created the DLL and the compiler that created the *.exe must use identical settings for field alignment so they expect the members of the record at identical offsets.
see https://docwiki.embarcadero.com/RADStudio/Athens/en/Align_fields_(Delphi)
-
@StephenM:
You write "It ingests a data structure that identifies a report".
Please be aware that there are strict limitations about what data types you can safely pass between the exe <--> dll boundary.
Can you describe what this data structure looks like?
Creating webp files with Skia fails
in RTL and Delphi Object Pascal
Posted
The bitmap is created like this, the 32-bits is just for alignment (speed) reasons:
ResultBitmap := tbitmap.Create; ResultBitmap.pixelformat := pf32bit; ResultBitmap.Alphaformat := TAlphaFormat.afIgnored;
and function TSkBitmapHelper.ToSkImage (found in Unit vcl.skia) explicitly handles that 32bit/afIgnored case, so there's probably a bug there somewhere:
if PixelFormat = TPixelFormat.pf32bit then begin case AlphaFormat of TAlphaFormat.afIgnored: LAlphaType := TSkAlphaType.Opaque; TAlphaFormat.afDefined: LAlphaType := TSkAlphaType.Unpremul; TAlphaFormat.afPremultiplied: LAlphaType := TSkAlphaType.Premul; else LAlphaType := TSkAlphaType.Unknown; end; ......
Saving the tBitmap to a stream and then creating the tSkImage from that stream works, but this still seems a bug to me.