Jump to content

Anders Melander

Members
  • Content Count

    2563
  • Joined

  • Last visited

  • Days Won

    133

Everything posted by Anders Melander

  1. Anders Melander

    smooth scaling of bitmaps

    Yeah, I figured that question would be coming To be honest I simply can't remember and the documentation doesn't provide any clues. I'll see if I can figure it out tomorrow unless someone else comes up with the answer.
  2. Anders Melander

    smooth scaling of bitmaps

    First of all you have to use a scale mode that doesn't control the position of the drawn image. Then it's pretty simple. Save the start cursor position in MouseDown, calculate the delta in MouseMove and scroll the image and end the drag in MouseUp. Here's some code: type TBitmapEditorPreview = class(TWinControl) private FImage: TImgView32; FStartPos: TPoint; FPanning: boolean; procedure ImageMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer); procedure ImageMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer); procedure ImageMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer); public constructor Create(AOwner: TComponent); override; end; constructor TBitmapEditorPreview.Create(AOwner: TComponent); begin inherited Create(AOwner); FImage := TImgView32.Create(Self); FImage.Parent := Self; FImage.Align := alClient; FImage.Height := 200; FImage.SizeGrip := sgNone; FImage.OverSize := 16; FImage.ScaleMode := smScale; FImage.Centered := True; FImage.Bitmap.Delete; FImage.Bitmap.DrawMode := dmBlend; FImage.Bitmap.CombineMode := cmMerge; FImage.OnMouseDown := ImageMouseDown; FImage.OnMouseMove := ImageMouseMove; FImage.OnMouseUp := ImageMouseUp; end; procedure TBitmapEditorPreview.ImageMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer); begin if (ssLeft in Shift) then begin FStartPos := FImage.ControlToBitmap(Point(X, Y)); FImage.Cursor := crSizeAll; FPanning := True; end; end; procedure TBitmapEditorPreview.ImageMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer); var NewPos: TPoint; dX, dY: integer; begin if (FPanning) then begin NewPos := FImage.ControlToBitmap(Point(X, Y)); dX := FStartPos.X - NewPos.X; dY := FStartPos.Y - NewPos.Y; if (dX <> 0) or (dY <> 0) then begin FImage.Scroll(dX, dY); FImage.Update; end; Changed; end; end; procedure TBitmapEditorPreview.ImageMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer); begin if (FPanning) then begin FPanning := False; FImage.Cursor := crDefault; end; end; I've attached the unit I copied the above from. It's part of a larger framework so you will not be able to use it as-is. Here's what it looks like in action (it's the lower pane displaying your avatar): amBitmapEditorPreview.pas
  3. Anders Melander

    adding graphics32 component

    The documentation used to be pretty good but much of the newer stuff hasn't been documented (did I mention cowboys ) and many of the examples are more focused on showcasing how awesome graphics32 is instead of explaining how to get stuff done. I even think the current online help is somewhat broken in places. Is there anything I can help with?
  4. Anders Melander

    smooth scaling of bitmaps

    What's the problem? No but you can assign a TBitmap32 to a TBitmap so this works: var Bitmap: TBitmap32; var Image: TImage; ... Image.Picture.Bitmap.Assign(Bitmap); Note though that if your TBitmap32 uses alpha (i.e. transparency) then you'll need to handle that somehow.
  5. Anders Melander

    adding graphics32 component

    I wouldn't bother. It's easy enough for people to open and adjust one of the existing packages. What's lacking is documentation on how to do it. Nobody has all the supported versions of Delphi installed anyway, so we don't really know if all the existing packages are valid. I just did a fast compare of them and I can see that they differ in what they contain and what compiler settings they use so we've already passed the point of maintainability. As I see it, for graphics32, the killing blow was when the team stopped using the newsgroups for communication and moved everything to Github. It fragmented both the developers and the users. Without the newsgroups there is no community and no team. There's no place for the users to ask questions and no place for the team to air ideas or visions and get feedback. Any task that is too big or complex for a single individual is simply not done. On top of that we have a lot of poorly documented code that was contributed by cowboys [*] which are apparently no longer interested in fixing their bugs. This doesn't make it any easier for the remaining devs to keep the project going. *) Cowboy Developer: Rides into town, shooting right and left and then rides out of town leading a mess behind. Yeeeehaw!
  6. Anders Melander

    smooth scaling of bitmaps

    Remove the "{$define OPTIMIZED}" to disable the assembler. That probably won't work with the 64-bit compiler anyway. The pointers are unavoidable. But like I said, I would use Graphics32 instead. It has a high learning curve but the results are better and the library is maintained. Something like this: procedure Test; var Source: TBitmap32; Target: TBitmap32; Resampler: TKernelResampler; begin Target := TBitmap32.Create; try Source := TBitmap32.Create; try Source.LoadFromFile('foobar.bmp'); // Make new bitmap twice the size. You can also make it smaller. Target.SetSize(Source.Width*2, Source.Height*2); Resampler := TKernelResampler.Create(Source); // Resampler is now owned by TBitmap32 Resampler.Kernel := TLanczosKernel.Create; // Kernel is now owned by resampler // Stretch using kernel resampler Target.Draw(Target.BoundsRect, Source.BoundsRect, Source); finally Source.Free; end; // Do something with target bitmap... finally Target.Free; end; end;
  7. Anders Melander

    adding graphics32 component

    I've just merged it and as far as I can see that's your first PR to the graphics32 repository, so I guess you meant that you got ignored at some other repository? It seems graphics32 is de facto without a project lead and I appear to be the only one of the old core team doing anything with it these days so there's not much progress or direction anymore. The fabled 2.0 release was planned almost 10 years ago but these days no one seems interested in making it happen and moving forward.
  8. Anders Melander

    PlasticSCM, Delphi, Semantic merge

    I use Plastic's regular 3-way merge tool with Git but I've never used Plastic SCM itself. You can get your hands on the merge tool by installing a trial of the Plastic SCM client. I don't think Semantic Merge has working support for Delphi syntax. There are some external parsers but AFAIK they don't support the newer versions of neither the Delphi language nor Semantic Merge. Here's one: https://github.com/andremussche/SemanticMergeDelphi
  9. Anders Melander

    smooth scaling of bitmaps

    I've attached an old library (from 1999) that can do it for you. I believe it's been incorporated in several other libraries over the years. I haven't used it since D5 so you might need to tweak it a bit for newer versions. Apart from that I would probably use Graphics32. resample.pas
  10. Anders Melander

    Can an app beat a spreadsheet?

    I worked as the lead developer for seven years at a company that pretty much made it their business to move people from Excel to "something better". https://sigmaestimates.com/
  11. Anders Melander

    Example of wasteful, innefficient string manipulation

    You test is a synthetic benchmark of metrics you don't understand yeilding results you don't know how to interpret. As usual this is completely pointless. I see you've highlighted the peak working set size but do you even know and understand what a working set is? If you really want to learn about how different memory management challenges can affect you then start by learning about what those problems are. Make an effort. One of the reason why your benchmark isn't doing as bad as you'd expect is probable the lack of randomness in the test. You're repeating the same pattern 100 times. If your allocation were random this would fragment the heap badly but since you're allocating, freeing and then later reallocating the same block sizes again and again, there's good likelihood that the blocks can be reused.
  12. Anders Melander

    Images in High DPI, how?

    Yes but the topic isn't "stuff that scale nicely".
  13. Anders Melander

    Images in High DPI, how?

    Not really relevant to the topic.
  14. Anders Melander

    ways to organize related code in a form?

    A psychoanalyst would have an opinion or two about that statement. I'd say you've integrated your weirdness nicely That's a pretty unnuanced statement. I'd say it has a more narrow meaning than what most people think, The rest of your post made little sense to me. Regarding IQ and "intelligence" I would recommend this book: https://www.amazon.com/Intelligence-Reframed-Howard-Gardner/dp/0465026117 or any of his other books on Multiple Intelligences.
  15. Googling "delphi natural sort" would have gotten you the answer.
  16. Anders Melander

    RichEdit Popup question

    I don't have any knowledge about your exact problem but: You have the source so you should be able to see how and why assigning a popup menu to the control affects the standard menu. Use a TActionList instead of wiring the menu items directly.
  17. Anders Melander

    Images in High DPI, how?

    If it works for you then that's great. Why should I try to convince you otherwise.
  18. Anders Melander

    A library path manager...

    Yes, exactly like that. Now you just need to convince Embarcadero to integrate it with the IDE. I haven't tried it yet as I wasn't too happy about adding one problem (an external dependency) to fix another one. I'll give it a try now anyway. I guess that should be fixed by the authors. Did you try to make that happen?
  19. Anders Melander

    A library path manager...

    Indeed. All paths relative and everything it source control. This also makes it trivial to build the project on a build server. At my current client the main product used to have dependencies on 5-6 different Git repositories and a bunch of 3rd party libraries that wasn't under source control. One person was responsible for figuring out what revision to checkout from the different repositories and what version of the 3rd party libraries to install and then build a version that could be sent to QA or deployed to the customers. And of course there were no relative paths. It was a nightmare. I moved everything into Git, made the dependent repositories submodules of the project repository, adding the source of the 3rd party libraries (also as submodules) and made all the paths relative. It took a few days to set up and now we have a fresh build after each commit. Wouldn't it be great if the project package configuration actually worked like most people expect it to (i.e. only load the packages specified in the project settings) and we could specify a (relative) path to the packages? I wouldn't even mind if I had to restart Delphi to switch from one project to the next. It would be better than the current situation.
  20. Yes but by doing it explicitly, at the point of your choice, you control exactly when it happens. The autocreate form/datamodule code, using TApplication.CreateForm, is managed by the IDE and it has been known to mess that up once you start editing the dpr file.
  21. Anders Melander

    Images in High DPI, how?

    That was pretty much the point of what I wrote; You can't just rescale an image (vector or raster) at run time and expect good results.
  22. Anders Melander

    Images in High DPI, how?

    The problem is the same as the one you have when you resample bitmaps. For small bitmaps you want to leave out a lot of details but keep the important parts and take advantage of the fact that the brain uses pattern recognition to reassemble the details. For larger bitmaps you can add details but leave of parts that were necessary in the smaller bitmaps for pattern recognition. This is why one can't just start with a large bitmap and downsample it to whatever size needed. The result usually looks awful. Same with SVG: For small SVG you don't necessarily want all the vectors to be rasterized. For larger ones maybe you do. An example of this is TrueType font hinting; Rasterizations of a font to a small point size uses different metrics and rules than the rasterization of the same font to a larger point size. One reason is that even with antialiasing we still need to take the pixel grid into account to get a good result.
  23. Anders Melander

    Images in High DPI, how?

    You believe it may? If you want vectorized images that sometimes, maybe, almost, resembles the original bitmaps, then yes I'm sure you could train an engine to do that. But it would be faster and cheaper to just have a professional design a new set of vector images.
  24. Anders Melander

    Images in High DPI, how?

    You don't convert your PNGs to SVG. You have to replace the PNGs with new SVG images. Since SVG is a vector format (hence the "V" in SVG) the visual expression will probably be very different from what you have now and it might not be what you want. There are probably someone that will suggest using vectorization to convert from PNG to SVG but I wouldn't bother. Vectorization only works well with large bitmaps. If you stay with raster images then you have to provide the individual bitmaps in different sizes and use something like TVirtualImageList. You typically don't need that many different sizes; 16, 24 and 32 should do but that of course depends on what amount of scaling you're willing to accept. Make sure that your bitmaps use alpha for best result - i.e. PNG or 32 bit bitmaps.
  25. Compile and press F7 and you'd know. I would recommend that you change the autocreate datamodules so they're created on-demand instead. That way you'll defer the overhead until the datamodule is actually needed. Something like: type TMyBigDataModule = class(TDataModule) ... end; function MyBigDataModule: TMyBigDataModule; implementation var FMyBigDataModule: TMyBigDataModule; function MyBigDataModule: TMyBigDataModule; begin if (FMyBigDataModule = nil) then FMyBigDataModule := TMyBigDataModule.Create(Application); Result := FMyBigDataModule; end; Yeah. All those features and versatility definitely comes at a price. Since they switched to a subscription only model they have become become lazy with regard to avoiding dependencies and so the applications become pretty bloated. Put a simple grid on a form and you get much of the spreadsheet stuff linked in as well.
×