Jump to content

Anders Melander

Members
  • Content Count

    2297
  • Joined

  • Last visited

  • Days Won

    119

Everything posted by Anders Melander

  1. Anders Melander

    smooth scaling of bitmaps

    @wadepm Here's the branch with the optimized scroll: https://github.com/graphics32/graphics32/tree/TImgView32_optimized_scroll Note that the optimization only comes into play if you're not using the rmFull repaint mode (see TImgView.RepaintMode). Give it a spin!
  2. Anders Melander

    smooth scaling of bitmaps

    Well, I couldn't resist the challenge so I have a nicely working implementation now. I'll create a pull request with it tonight (it's 6 in the morning here in Denmark) when I wake up again .
  3. Anders Melander

    smooth scaling of bitmaps

    I think TLinearKernel (or just the TLinearResampler) will yield the best down-sample quality with good performance. The links I posted explains why. The update mechanism redraws the areas of the bitmap that changes. When you pan the bitmap doesn't change but the view of it does. Therefore the optimized update can't handle the pan so the whole viewport is repainted instead. I'm currently investigating if I can shoehorn a pan optimization into the existing framework with minimal changes. That's what I do when previewing large bitmaps (for PixelFormat=pf32bit) but I only do it do avoid out of memory: // Get RGBA from source ImageView.Bitmap.BeginUpdate; try // Limit preview image size const MaxPixels = 1024*1024; var Pixels := TBitmap(FImage).Width * TBitmap(FImage).Height; if (Pixels >= MaxPixels) then begin var Scale := Sqrt(MaxPixels / Pixels); // Proportionally scale bitmap so the result doesn't contain more than the desired number of pixels ImageView.Bitmap.SetSize(Round(TBitmap(FImage).Width * Scale), Round(TBitmap(FImage).Height * Scale)); // Stretch draw the source bitmap onto the scaled bitmap TBitmap(FImage).Canvas.Lock; try SetStretchBltMode(ImageView.Bitmap.Canvas.Handle, COLORONCOLOR); ImageView.Bitmap.Draw(ImageView.Bitmap.BoundsRect, TBitmap(FImage).Canvas.ClipRect, TBitmap(FImage).Canvas.Handle); finally TBitmap(FImage).Canvas.Unlock; end; end else begin ImageView.Bitmap.SetSize(TBitmap(FImage).Width, TBitmap(FImage).Height); for var Row := 0 to TBitmap(FImage).Height-1 do MoveLongword(TBitmap(FImage).ScanLine[Row]^, ImageView.Bitmap.ScanLine[Row]^, TBitmap(FImage).Width); end; finally ImageView.Bitmap.EndUpdate; end; ImageView.Bitmap.Changed;
  4. If the TStrings.Objects isn't used for anything then, instead of separating the strings and checked states into two list and then sort both simultaneously, you could just stuff the checked state into TStrings.Objects and then use the standard TStrings.Sort. Or you could sort a TList<integer> of indices, using TList<>.Sort and then reassemble the sorted string list based on the result.
  5. Anders Melander

    smooth scaling of bitmaps

    It's sampling every time it draws something. That doesn't mean that it necessarily resamples the whole bitmap though. It will only sample the parts that it needs in order to paint the visible part of the bitmap. Read this: https://graphics32.github.io/Docs/Additional Topics/Sampling and Rasterization.htm https://graphics32.github.io/Docs/Additional Topics/Repaint Optimization.htm Of course when scale < 1 then the whole bitmap will probably be visible and everything will be sampled. As far as I remember there's no repaint optimization with regard to panning - I guess that's something I could look into if I run out of other stuff to do Anyway, even if you did pan 1 pixel at a time (which I doubt you're doing) it should be fast enough that you shouldn't experience any stutter. Of course it depends on the type of sampler/kernel you're using, your hardware and the size of the bitmap but on my old system I can pan a zoomed (in or out) 4000x4000 multi layer bitmap without any noticeable stutter.
  6. Anders Melander

    grid with expandable area below each row?

    It's not the look that's the problem. It's the usability. The DevExpress grid has both a preview pane and an in-place edit form feature. I'm referring to the edit form, I suspect you're referring the the preview pane. In-place editor form: Preview: That sounds more sensible to me. Like a property inspector. The problem with putting stuff into the grid is that is interferes with the nice overview the grid layout provides. Regardless it would still be a good idea to create a mockup before investing too much time on this.
  7. Anders Melander

    smooth scaling of bitmaps

    I don't really know what type Source is but assuming it's a TBitmap32 then loading a PNG with LoadFromFile will internally use a TPicture to load the file and then assign the TPicture.Graphic (which will be a TPNGImage) to the TBitmap32 using a generic import routine that replaces the transparency with white. This matches what you're observing. As far as I can tell everything works "as designed". What did you expect this would do? If you want to display a 32-bit TBitmap with alpha using TImage then I suggest you create a 32-bit RGBA bmp file and experiment with getting TImage do display that. You have too many variable factors in your approach. Get one thing working first. Then move on to the next problem. The above has nothing to do with Graphics32.
  8. Anders Melander

    smooth scaling of bitmaps

    You didn't answer my question: Have you verified that the transparent PNG pixels are still transparent after conversion to TBitmap32? As far as I can tell, from the 4 lines of code you posted, you're not really using graphics32 to draw anything here. If you draw a TBitmap32 onto a Windows GDI device (Image.Canvas.Handle) then the GDI StretchDIBits function will be used to draw it - hence no transparency. The primary reason to use graphics32 is that it allows you to do the composition (blending, merging, layers, rendering, etc) really fast and then draw the final image onto the screen. If what you actually want is to draw something onto the screen with transparency then maybe you shouldn't be using graphics32 at all? If you really want to draw a TBitmap32 onto a GDI device with transparency then you should assign it to a TBitmap, set TBitmap.AlphaFormat=afDefined and then draw the TBitmap instead. TBitmap will use the AlphaBlend function in this case. var Bitmap := TBitmap.Create; try Bitmap.Assign(Bitmap32); Bitmap.AlphaFormat := afDefined; Bitmap.DrawTo(Image.Canvas.Handle, 0, 0); finally Bitmap.Free; end; Btw, are you really sure you want to draw onto the TImage.Canvas? That seems.... um... like a mistake...
  9. Anders Melander

    grid with expandable area below each row?

    Maybe you should make a proof of concept using a DevExpress trial first and have your users test it. We use DevExpress grids and have that feature enabled on a few of them and the users hate it. It looks like a good idea but the usability sucks. Maybe that's just the way DevExpress has implemented it though.
  10. Anders Melander

    smooth scaling of bitmaps

    I don't use LoadBitmap32FromPNG and it's not part of Graphics32. Have you verified that the transparent PNG pixels are still transparent after conversion to TBitmap32? Other than that the problem could be the blend and combine mode used when drawing but that should be the same regardless of the origin of the pixel data.
  11. Anders Melander

    smooth scaling of bitmaps

    Yes. That was just a brain fart on my behalf.
  12. Anders Melander

    smooth scaling of bitmaps

    Well that was easy. Luckily the bug was in my own code. Here's the code that works: procedure TFormMain.ImgViewMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer); begin if (Button = mbLeft) then begin FPanning := True; ImgView.Cursor := crSizeAll; FStartPos := Point(X, Y); end else if (Button = mbMiddle) then ImgView.Scale := 1; end; procedure TFormMain.ImgViewMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer; Layer: TCustomLayer); begin if (not FPanning) then Exit; var NewPos := Point(X, Y); var Delta := FStartPos - NewPos; FStartPos := NewPos; if (Delta.X <> 0) or (Delta.Y <> 0) then ImgView.Scroll(Delta.X, Delta.Y); end;
  13. Anders Melander

    smooth scaling of bitmaps

    Reproduced. I've actually encountered that problem in my own applications but I've never been able to pinpoint the circumstances that surfaced the problem. I'll investigate now.
  14. Anders Melander

    smooth scaling of bitmaps

    My guess is that you're using the wrong TImgView32.ScaleMode. Make sure TImgView32.ScaleMode=smScale. I've attached a small example that demonstrates how to pan and zoom with TImgView32. imgview32demo.zip
  15. Anders Melander

    Unfixed bug in Sydney

    Do you sell your software? Are there bugs in it? How do you sleep at night? I guess I don't understand what your point is.
  16. Anders Melander

    Application does not close

    Instead of terminating the application in the debugger you can pause it and then examine the call stack to see what the application was doing.
  17. Anders Melander

    Update of Actions in ActionList in a DataModule

    Nope. A rewrite of an old, large and complex system is not something that you just do. The history and literature is full of examples why. Remember Netscape, Lotus 123, etc.?
  18. Anders Melander

    Update of Actions in ActionList in a DataModule

    As you've probably discovered then only difference between having the TActionList on a form and having it on a datamodule is that the shortcuts isn't processed. You can see why in TCustomForm.IsShortCut. As far as I can see you can solve that by simply calling TActionList.IsShortCut from your forms OnShortCut event handler. Apart from that, as @PiedSoftware wrote, the TAction.OnUpdate event only gets called when the action isn't suspended and the associated control(s) becomes visible. For example if you have an action linked to a menu item then the action is only updated when the sub menu that contains the menu item is shown. If you have an action linked to multiple controls then the action is updated if just one of them is visible. A classic goof is to update the actions Visible property in the OnUpdate handler and then wondering why the action isn't updated anymore - it's because the associated control has been hidden and hidden control don't cause the action to update. Also if you use the TActionList.OnUpdate handler be aware that it's called once for each and every action in the list. If you just want an OnUpdate handler that called once for every "cycle" then you can create an action and assign it to the form and use that actions OnUpdate instead. You will have to control the form caption through the action though.
  19. Anders Melander

    smooth scaling of bitmaps

    Yes that seems to be it; TImgView32 adds scrollbars and methods to scroll and center the image.
  20. 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.
  21. 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
  22. 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?
  23. 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.
  24. 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!
×