Jump to content

angusj

Members
  • Content Count

    132
  • Joined

  • Last visited

  • Days Won

    8

Everything posted by angusj

  1. I found it. I thought opening the structures tab with a PE file loaded might show the structure automatically, but I realise now that I have to click on what's on my PC a very tiny toolbar icon that drops a menu to manually load the the structure definition. That's just fine with me (except for the tiny icon 😜). Anyhow, thanks again for sharing your work.
  2. My first impression is it looks very promising. Thanks for sharing! 1. Semi-urgent request: Either automatically or manually resize toolbar icons as they are currently unreadably small on high DPI displays. Suggest SVG icons as they resize very well. 2. Suggestion: I see support for viewing image files (which makes sense since they can be embedded as resources), but I would really like to see viewers for file structures (eg PE File format and zip file structures)
  3. angusj

    TBitmap32 to jpg (graphics32)

    It's not pretty, but on occasions it's a useful way around protected properties and methods.
  4. angusj

    TBitmap32 to jpg (graphics32)

    No. What I'm saying is if you just need this to solve a short term problem - ie convert 1000s of images as a one off, then a hidden bug is not likely to cause grief. But if this code is going to be used for a very long time, then I'd recommend digging a little deeper and trying to locate the root cause of your memory consumption. (And I really am trying to help, not gang up on you.)
  5. angusj

    TBitmap32 to jpg (graphics32)

    In fairness, I think David asks a valid question. While it's certainly possible this presumed leak is due to a bug in Delphi code, based on probabilities it's much more likely in your code. Even though it's now working (without TJpegImage or whatever), it's likely still there, just not currently causing problems. If a short term fix is all you need then that's great. But it you're counting on this to work in a presumably unattended server long term, it's usually better to invest the time to find out the definitive cause now than have things blow up later when it's far less convenient.
  6. angusj

    TBitmap32 to jpg (graphics32)

    Thanks, I'm very pleased to hear that. And I'm now curious as to how the performance compares with your converter? Also, I could fairly easily modify Delphi's JPEG unit to expose the functions in the JPEG OBJ files and bypass TBitmap entirely but I'm not sure it's worth the effort thought it could improve performance .
  7. angusj

    TBitmap32 to jpg (graphics32)

    Not necessarily. In my Image32 graphics library, I'm using Delphi's JPEG unit without touching TBitmap. Edit: Sorry, the JPEG unit does use TBitmap.
  8. angusj

    Delphi IDE Colors

    The attached file contains a utility I created some time ago to work around Delphi's IDE that was almost unusable on high DPI screens. (And I still use it in Delphi 10.4.) In it you'll see a file called IDEFontSizeFix.pas that does (or at least demonstrates) most of what you're asking. fancyshortcuts.zip
  9. angusj

    Rounded polygon

    I wasn't suggesting that you download Image32, just a couple of extra functions. And MakePath was only a shortcut to demonstrate path construction, which of course you'd generate in your own way. And even with FlattenCBezier, I was (I think quite reasonably) expecting that your graphics library could handle this since cubic bezier paths are a very common graphics data structure. Anyhow, I'm sorry I dissapointed you.
  10. angusj

    Rounded polygon

    Hi xstrider. I've actually modified this function again since posting the link above, but I didn't want to abuse this thread since it's not specifically about my routine. Anyhow, here's the link to the up to date documentation on this function that's been renamed SmoothToCubicBezier (which I think better describes what the function does). This can be found in the Img32.Extra unit that part of my Image32 Library on GitHub. Both MakePath and FlattenCBezier are found in Img32.Vector. I'm not sure what you're referring to here. The MakePath function parameter is array of double, and the entire Image32 library uses double coordinate values. It appears you're using GDIPlus and I'm not familiar with it. However, while GraphicsPath does accept cubic bezier input (and will flatten these), these beziers appear to be cubic bezier splines, which are very different to cubic bezier arrays. Nevertheless you could copy FlattenCBezier from my library and simply add the flattened path using GraphicsPath's AddPolygon method. I hope that helps. ps: Here's a link to a short video that demonstrates this smoothing (together with vectorizing monochrome raster images, and path simplification).
  11. angusj

    Community Edition expiring again, no new keys

    And I still think Idera has the math all wrong. If they sold Delphi Developer at 1/3 the current price, I believe they'd more than triple their sales. As a hobby developer I'd be prepared to spend that instead of using the CE, which I'm currently using. Edit: At the very least Idera should do some market research and ask CE users what they'd be prepared to spend for the Developer edition. Heaven forbid, they might even attract some new developers instead of just bleeding their current user base.
  12. angusj

    Community Edition expiring again, no new keys

    I'm also using the Community Edition and I'm now reluctant to close the IDE in case I also run into this "expired" issue. However I note that my license states its expiry date is unlimited.
  13. angusj

    Rounded polygon

    I've simplified this and uploaded it here: https://github.com/AngusJohnson/Image32/blob/0bb2e258f66c37f9eb263909480c473abf654f74/source/Img32.Extra.pas#L2044
  14. Indeed it is. Although the zip files are still there (DrawObjects and DrawObjectsDemo), I've removed the published links because this code is obsolete (and untouched for more than 10yrs) since Graphics32 has evolved and I've also moved on to other things 😁.
  15. angusj

    Rounded polygon

    Here's my GetSmoothPath() routine. It requires no specific graphics library to use, just a few extra functions (also included below). This function generates an array of control points that's very easily converted into a flattened cubic bezier path using just about any 2D graphics library. (nb: The code below has been written with simplicity as the focus rather than performance.) uses SysUtils, Math; type TPointD = record X, Y: double; end; TPathD = array of TPointD; TArrayOfDouble = array of double; function DistanceSqrd(const pt1, pt2: TPointD): double; begin result := Sqr(pt1.X - pt2.X) + Sqr(pt1.Y - pt2.Y); end; function Distance(const pt1, pt2: TPointD): double; begin Result := Sqrt(DistanceSqrd(pt1, pt2)); end; function OffsetPoint(const pt: TPointD; dx, dy: double): TPointD; begin result.x := pt.x + dx; result.y := pt.y + dy; end; function GetAvgUnitVector(const vec1, vec2: TPointD): TPointD; var inverseHypot: Double; begin Result.X := (vec1.X + vec2.X) * 0.5; Result.y := (vec1.Y + vec2.Y) * 0.5; inverseHypot := 1 / Hypot(Result.X, Result.Y); Result.X := Result.X * inverseHypot; Result.Y := Result.Y * inverseHypot; end; procedure MakeSymmetric(var val1, val2: double); begin val1 := (val1 + val2) * 0.5; val2 := val1; end; function GetUnitVector(const pt1, pt2: TPointD): TPointD; var dx, dy, inverseHypot: Double; begin if (pt1.x = pt2.x) and (pt1.y = pt2.y) then begin Result.X := 0; Result.Y := 0; Exit; end; dx := (pt2.X - pt1.X); dy := (pt2.Y - pt1.Y); inverseHypot := 1 / Hypot(dx, dy); dx := dx * inverseHypot; dy := dy * inverseHypot; Result.X := dx; Result.Y := dy; end; // GetSmoothPath - returns cubic bezier control points // parameters: 1. path for smoothing // 2. whether or not the smoothed path will closed // 3. percent smoothness (0..100) // 4. maximum dist control pts from path pts (0 = no limit) // 5. symmetric vs asymmmetric control pts function GetSmoothPath(const path: TPathD; pathIsClosed: Boolean; percentOffset, maxCtrlOffset: double; symmetric: Boolean): TPathD; var i, len, prev: integer; vec: TPointD; pl: TArrayOfDouble; unitVecs: TPathD; d, d1,d2: double; begin Result := nil; len := Length(path); if len < 3 then Exit; d := Max(0, Min(100, percentOffset))/200; if maxCtrlOffset <= 0 then maxCtrlOffset := MaxDouble; SetLength(Result, len *3 +1); prev := len-1; SetLength(pl, len); SetLength(unitVecs, len); for i := 0 to len -1 do begin pl[i] := Distance(path[prev], path[i]); unitVecs[i] := GetUnitVector(path[prev], path[i]); prev := i; end; Result[len*3] := path[0]; for i := 0 to len -1 do begin if i = len -1 then begin vec := GetAvgUnitVector(unitVecs[i], unitVecs[0]); d2 := pl[0]*d; end else begin vec := GetAvgUnitVector(unitVecs[i], unitVecs[i+1]); d2 := pl[i+1]*d; end; d1 := pl[i]*d; if symmetric then MakeSymmetric(d1, d2); if i = 0 then Result[len*3-1] := OffsetPoint(path[i], -vec.X * Min(maxCtrlOffset, d1), -vec.Y * Min(maxCtrlOffset, d1)) else Result[i*3-1] := OffsetPoint(path[i], -vec.X * Min(maxCtrlOffset, d1), -vec.Y * Min(maxCtrlOffset, d1)); Result[i*3] := path[i]; Result[i*3+1] := OffsetPoint(path[i], vec.X * Min(maxCtrlOffset, d2), vec.Y * Min(maxCtrlOffset, d2)); end; if not pathIsClosed then begin Result[1] := Result[0]; dec(len); Result[len*3-1] := Result[len*3]; SetLength(Result, Len*3 +1); end; end; And here's what it produces ... the path to smooth (black), the cubic bezier control path produced by GetSmoothPath() (blue) and the flattened cubic bezier path (2D graphics library of you choice required) (red). var TPathD path; begin path := MakePath([190,120, 260,270, 560,120, 190,490]); path := GetSmoothPath(path, true, 20, 0, false); path := ThirdParty2DGraphicsLibrary.FlattenCBezier(path); end; var TPathD path; begin path := MakePath([190,120, 260,270, 560,120, 190,490]); path := GetSmoothPath(path, true, 80, 0, false); path := ThirdParty2DGraphicsLibrary.FlattenCBezier(path); end; Edit: The best way to avoid intersections is to make sure you have enough data points before generating your curves.
  16. Thanks Dale. I have been doing that. I just find it somewhat tedious having to do that every time i visit DP. IMHO, having a "Mark site read" button at the bottom as in desktop view would be much more convenient. Cheers.
  17. See above. While I also missed downloading and reading Normann's book, it seems he wasn't encouraged by the initial feedback. I think there's a lessen in that. Normann had put considerable effort into writing this book and uploaded it as a free resource and, from what I can glean from this thread, it was mostly of high quality.
  18. angusj

    Detecting start of drag operations

    That seems likely be the solution to Dave Nottage's problem, though it isn't the answer to his question 😁.
  19. angusj

    Detecting start of drag operations

    Despite the lack of documentation on EVENT_OBJECT_DRAGSTART here: https://docs.microsoft.com/en-us/windows/win32/winauto/event-constants it seems likely that this event is only triggered by "UI Automation" Drag-and-Drop https://docs.microsoft.com/en-us/windows/win32/winauto/ui-automation-support-for-drag-and-drop
  20. angusj

    Detecting start of drag operations

    Is there a difference between OLE and "the standard windows drag and drop"? "The OLE DoDragDrop function calls this method (IDropSource::QueryContinueDrag) during a drag-and-drop operation." https://docs.microsoft.com/en-us/windows/win32/api/oleidl/nn-oleidl-idropsource Of course, this is very different to Delphi's custom drag drop stuff.
  21. angusj

    Detecting start of drag operations

    guessing ... startDragEvent := SetWinEventHook(EVENT_OBJECT_DRAGSTART, EVENT_OBJECT_DRAGSTART, 0, @DragStartEvent, 0, 0, WINEVENT_OUTOFCONTEXT); procedure DragStartEvent(hWinEventHook: THandle; event: DWORD; hwnd: HWND; idObject, idChild: Longint; idEventThread, dwmsEventTime: DWORD); stdcall; begin //do stuff end; Note: All OLE drag events are initiated by DoDragDrop https://docs.microsoft.com/en-us/windows/win32/api/ole2/nf-ole2-dodragdrop Since the drag souce (IDropSource, IDataObject) is initiated by another process so you'll certainly need a system event hook.
  22. angusj

    32bit bitmap

    I wholeheartedly agree with you Anders that TBitmap.AlphaFormat is broken and should be deprecated. Not only does it not behave in an intuitive manner, but Premultiplying and UnPremultiplying images is (mildly) destructive. But there's another potentially bigger problem - when writing an afDefined Bitmap to stream, UnPreMultiplyAlpha is called and hence the image will no longer be properly rendered. ps: Isn't it fun digging up old threads 😜.
  23. angusj

    tImagecollection, how to improve downscaling?

    Delete this line. It's only (sort of) useful for images without alpha transparency.
×