Jump to content

cltom

Members
  • Content Count

    16
  • Joined

  • Last visited

Posts posted by cltom


  1. Hej,

    since some other projects took over, there is quite some delay now. However, I still should make some progress on this, so I put it on github as promised:

     

    tomonsight/PMDraw: Symbolic Drawing App (github.com)

     

    Needless to say this is not a ready application and it surely reflects all sorts of incompetencies ...

     

    Anyway, some issues that I am facing:

    - the constraint to the grid is "jumpy"

    - I cannot select text

    - the functionality to select multiple objects is missing

     

    But still, the idea is probably visible of what I am trying to do.

     

    Thanks for attention/help, maybe you can spot some easy fixes.

     

     


  2. Hej Anders, 

     

    thank you again for the dedicated help!

     

    As I had some to do some clean-up in another project, this one received a little less attention. But some progress is there:

     

    - the save I could just use from the Layers-example 😉

    - the OnConstraint works (I was using OldLocation instead of new - along the lines of NewLocation := OldLocation div x etc.

     

    So I have quite a bit of work left to do but the project is alive! 😄 

    • Like 1

  3. Despite the help even in the form of source code that I could just paste, I am struggling with some fundamentals:

     

    On 3/21/2023 at 6:42 PM, Anders Melander said:

    If you are using the TRubberbandLayer then there's a OnConstrain event where you can examine and modify the move/resize. 

    How to do that? Do I just write a new OnConstrain event that I assign to the TRubberband-Layer?

     

    On 3/21/2023 at 6:42 PM, Anders Melander said:

    type TObjectLayer = class; TObjectLayerNotification = ( olnDestroy, // Subscribers should remove reference to layer olnPosition // Layer has moved ); ....

    Here, I guess I am lacking the fundamentals on how this should work. I can't get this to run. 

     

    On 3/21/2023 at 6:42 PM, Anders Melander said:

    property ObjectID: TSomeType read FObjectID write FObjectID;

    on this one, field definition not allowed after methods or properties, no matter where I put it.

    On 3/21/2023 at 6:42 PM, Anders Melander said:

    Notify(olnDestroy);

    Here it says incompatible types IObjectLayerNotification and TObjectLayernotification.

     

    On 3/21/2023 at 6:42 PM, Anders Melander said:

    procedure TSelectionLayer.Paint(Buffer: TBitmap32); begin try // Update local copy of selection polygon UpdateCache; if (BitmapEditor.HasSelection) then begin Buffer.SetStipple(SelectionStipple); Buffer.StippleCounter := FSelectionStippleCounter; Buffer.StippleStep := 1; PolylineXSP(Buffer, FCachedSelection, not SelectionInProgress); end; except // Prevent AV flood due to repaint Visible := False; raise; end; end;

    should this be a separate class of its own? TSelectionLayer?

     

    And another one: in order to save all objects including the background, do I need to flatten all layers? Essentially I guess I have to make a copy of the bitmap and all layers flatten the copies and continue to work with the original one?

     

    I was thinking about sharing the project as I think this generic functionality could be a useful template, at this point I it is still rather a fragment though.


  4. On 3/23/2023 at 12:24 AM, Anders Melander said:

    This should of course not have been an abstract class.

    I have just committed an implementation of the class to the main branch: https://github.com/graphics32/graphics32/commit/aec3713e187d1300b111f0315380a38b50033fef

    Would this ObjectLayer class also be the right place to add a TAffineTransformation for rotating or flipping an element? Should then the transformation take place in the Paint event?


  5. 18 hours ago, Anders Melander said:

    I would just store a reference to your object and the object owner in the layer and then notify the owner when the layer is moved.

    Something like this:

    The object ID is stored in the ObjectID property (change the type to whatever type you use an an ID). The owner must implement the IObjectLayerNotification interface and call Subscribe on the layer to get notifications. This is a pretty standard observer pattern.

     

    If you are using the TRubberbandLayer then there's a OnConstrain event where you can examine and modify the move/resize. If you are doing move/resize with some other method then I'll need some information about that.

     

    I usually implement rubber-band selection via the TImgView32 mouse events (i.e. I'm not using a layer).

    So I manage the selection-in-progress state (usually just the mouse-down position) and any current selection on the form. In the mouse-up handler, I create a rectangle polygon from the mouse-down pos and the mouse-up pos and then either replace the current selection with the new one or merge the two (union), depending on the keyboard shift state. The selection is stored as a polygon. You can also use a polypolygon depending on your needs.

    The selection is drawn by a custom layer (visible only when there actually is a selection). The layer has a copy of the polygon and draws a marching ants (btw, try googling "marching ants") animated line using a stipple pattern and a timer.

    Here's the Paint method of the layer:

    and the setup and control of the stipple pattern:

     

    A massive thank you for your support and work! I will dive into it and try to get it implemented! As a quick reaction, again: thank you!!


  6. On 3/18/2023 at 3:06 PM, Anders Melander said:

    The code was copied from TCustomBitmapLayer in GR32_Layers, so you can find it there:

    
    type
      TImage32Access = class(TCustomImage32);

    Stretchtransfer is declared in GR32_Resamplers.

     

    I'm considering making TIndirectBitmapLayer the base class for TCustomBitmapLayer.

    Again, a huge thank you! As an update: I got this to run with the TIndirectBitmapLayer class which - both to my shame but also to my joy - works well with very little code. Also, I had some inspirational from the ImgView_Layers-Demo.

     

    In general: I have now a main class which handles the Objectlist for all elements (which is then used to save the drawing, etc.) and another class that does the drawing. Consequently, some conceptual questions:

     

    - When using the TLayerCollection, the whole movement/scaling of objects is handled (great!). What is a good method of getting information on the movement of the layer back to my main class where I need to keep track of the objects and their coordinates? I could access the TLayerCollection and the position of the layers. I can only rely though on an ID in either structure to get the same object. Alternatively I could follow track the selected object and the mouse move in the main class.

     

    - also, when trying to restrict the movement of layers, how can I access the coordinates of a layer while moving it to mimic a SnapToGrid function?

     

    - coming back to the rubberband-question: how to implement this? Should I create a TRubberband layer via the MouseDown/MouseMove events?

     


  7. 13 hours ago, Anders Melander said:

    SrcRect := MakeRect(0, 0, FBitmap.Width, FBitmap.Height); if Cropped and (LayerCollection.Owner is TCustomImage32) and (not TImage32Access(LayerCollection.Owner).PaintToMode) then begin if (DstRect.Width < 0.5) or (DstRect.Height < 0.5) then Exit; ImageRect := TCustomImage32(LayerCollection.Owner).GetBitmapRect; GR32.IntersectRect(ClipRect, ClipRect, ImageRect); end; StretchTransfer(Buffer, DstRect, ClipRect, FBitmap, SrcRect, FBitmap.Resampler, FBitmap.DrawMode, FBitmap.OnPixelCombine); end;

    Sorry, the TImage32Access and Stretchtransfer come from which unit?


  8. 13 hours ago, Anders Melander said:

    No, definitely not.

    Each layer draws itself onto the back buffer on demand (i.e. when the TImage32 requests it). To force a layer to redraw itself you call the layer Changed method. To force a full redraw call TImage32.Changed

    You can either use a standard TPositionedLayer (and draw in its OnPaint event handler) or a simple custom layer class that can draw itself:

    I think you should start by getting the bitmap layers working and then we can talk about how to handle the selection UI later.

    Hej Anders, 

    as a quick reaction: thank you for the support! I will dive into the layer concept a little more as (until now) the only way I did was to draw everyting onto one bitmap. Thanks for the patience! 😉

    best regards

    thomas


  9. 2 hours ago, angusj said:

    I was a contributor to Graphics32 for many years, but eventually Graphics32 had become too unweildy for me, and no longer useful over the longer term. My initial inclination was to do a major Graphics32 rewrite/update .. things like pruning 20!! various Line and Lineto methods from TBitmap32. These kind of made sense historically, but made absolutely no sense now. But when I started pruning these methods, I realised I was unravelling a Gordian's knot (ie an almost impossible task). So many of these methods had been interwoven inside other methods that I realised I'd be better off starting from scratch, which is what I did with Image32.

     

    Edit: Not that I'm including myself in "all the brilliant people", just a long term programming hack 😜.

    Edit2: And an expert is just someone who knows an awful lot about very little.

    Thank you for the insight! I guess with every growing project you can come to a point where the continuous addition of complexity and the widening of the scope over the years results in the feeling that the only way forward is to start all over with better structures to begin with (at least in this aspect I think I know what I am talking about ;-)). I clearly cannot comment on the specifics of GR32, I just used it in some applications.

     

    However, after browsing graphics libraries for some time now and finding a myriad of them in all sorts of flavours, degrees of completion, target auditorium, documentation quality, accessibility, future proofness and of course commercial approaches I had the impression that many of the projects seem to rely on the effort of individuals. As impressive as it is, this left me with the question, if the "market" for components/libraries in the Delphi space is big enough for so many solutions and if a common effort would lead to a more sustainable, more accessible, better documented, better supported solution. Also this is more a question than a statement.

     

    Personally, my biggest struggle is to get into these components. There are often demos, which is an excellent showcase, an ad if you will. However, to me it sometimes feels like advertising a set of workshop tools with an art nouveau dresser. It is impressive that such a piece of furniture was built with those tools. If you want to build a table of your own, it is however, still a long journey.

     

    By no means I am not complaining about the availability of components (many of them even free of charge) where individuals have spent months of their time to create something that enables others to build something. I am deeply impressed and grateful for these components. Also, of course, I am nowhere close to judge about how many libraries are the "right amount" let alone "which is the best". Again, I was just asking, given the fact that there are only so many of those experts/hacks/experts 😉 and the target auditorium is not exactly a million of JS developers, if the balance is right between the number of packages vs. the broad acceptance/documentation/future proofness/... of them.


  10. 4 hours ago, Edwin Yip said:

    Graphics32 + Angus's GR32_lines and GR32_text can be firm foundation for graphical apps.

     

    And no one mentioned https://github.com/fatihtsp/Blen2d4Delphi ?

    thank you!

     

    Just as a sidenote, seeing another package, I guess if all the brilliant people that have created these libraries aligned their efforts and focuses on fewer but more consistently supported libraries, it would be a huge leap.

     


  11. 5 hours ago, Anders Melander said:

    I haven't seen you ask for help anywhere. You could have tried that.

    I can probably tell you how to solve your problems with Graphics32, should you choose to continue that way, but you need to ask the questions first 🙂

     

    I believe Image32 does layers too and it might be more accessible than Graphics32. When @angusj comes online he can chime in on that.

     

     

    If you're using the TImage32 or TImgView32 controls then the double buffering is already built in and handled automatically. Each layer just needs to draw itself into a bitmap and the control will take care of the rest.
     

    Use a TRubberbandLayer. The layer is drawn on demand onto a bitmap like all other layers but that is already done by TRubberbandLayer so you don't need to do anything special.

     

    It depends on your needs. One possible solution is to have each vector object be represented by its own layer. Another is to draw all objects onto a single layer. Or you could do a combination.

    For simplicity, I would probably choose to draw all objects onto a single layer.

    Regardless TImage32 takes care of producing the final combined image.

    Hello Anders, thanks a lot for your input and the offer to help ;-) Having used GR32 for some projects, I have a bias to continue to use it. Also the more successfull applications and prototypes and are based on GR32.

     

    Two of the main conceptual topics are already answered (single image vs. multiple layers and doublebuffering). Regarding single image vs. layers: does the number of layers make a difference in the choice? I expect around 50-300 elements. Simplicity is a strong argument though ;-) Drawing the elements that way already works pretty straightforward. I have all the images in a Bitmap32List and copy them over to the main Image32. By the way: is there a recommendation difference for this task between GR32.Image32 and ImageView32?

     

    Regarding DoubleBuffering: so it should work to have the procedure that draws everyting in the MouseMove event of the Image32? Something like:

     

    procedure Tfrm_Draw.img_MainMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer; Layer: TCustomLayer);
    begin
      case SelectedTool of
        pmSelect : if ssLeft in Shift then Drawing.ObjectMove(X, Y);
      end;
      Drawing.Draw(Library);
    end;

    and

     

    
    procedure TDrawing.Draw(ElementLibrary: TLibrary);
    begin
      Destination.SetupBitmap(true, Config.BackGroundColor);
      Destination.BeginUpdate;
    
      if Config.BackGroundImageShow then
        DrawBackgroundImage;
    
      if Config.GridShow then
        DrawGrid;
    
      DrawAllElements(ElementLibrary);
    
      Destination.EndUpdate;
    end;

    Destination being a TImage32.

     

    I guess with larger images this might give performance issues? Or does this approach still allow to only repaint a section?

     

    In case of drawing all elements onto a single GR32.Image32 the idea is then to use the TRubberBand for the visual representation of the frame but do the selection of the elements within that range manually? Finding the objects is not difficult given their coordinates and dimensions.

     

    Thank you!!

     


  12. 2 hours ago, FPiette said:

    Reading your post, I think you are looking for a library which does exactly what your application has to do. That would be marvelous but forget it!

    You actually need a library (or even none since you can use Delphi built-in function) capable of doing primitive graphic manipulation and display.

    Speaking about the main image - as you name it - your application should have a model of what is expected on screen and a rendering engine. The model is a list of operation applied to images. The list is ordered. By manipulation, I mean and image, and an operation such as position at X/Y coordinate, rotate of a given angle, scale with a given factor, crop this way, mask like that, and so on.

    The user interaction solely work on the list. When the user want to move an image, you use mouse event and the list to find which (sub)image if on the top and the user want - for example - drag. At each user interaction, you do the rendering.

    At the end, instead of rendering on screen, you render to a standard bitmap that you write as JPG or other image file format.

    Got the idea?

    Thank you for your input. Probably yes, I am trying to compensate my skill level by searching for components that do most of what I want to achieve. When I started, I found the layers-example in the GR32 demos and with the functionality there (importing images), selecting them, scaling them, etc. it seemed this is already very close. But then again that's the downside, if a solution covers 50% of what you need, the remaining 50% can be a long way if you did not do the first half yourself.

     

    To the process: I think the idea is clear. In my prototypes I already had built a simple XML-syntax to describe the objects, so I would essentially just edit text and for the graphical representation interpret it.

     

    Where I was struggling the most I guess is conceptual decisions:

     

    - do I draw on an offline bitmap and copy that bitmap to screen when needed - with GDI+ I do it like that. Should I be doing it like that with GR32?

    - how to implement the marching an/rubberband controls to select multiple objects - see above: do I draw the rubberband offline? I guess this has all been solved a million times

    - the library: do I draw all elements of the library onto one single image and arrange the single images on the big parent image? or do I rather create a series of Images (TImage or TImage32) and arrange those?

     

    I went as far as reading through some OpenSource vector drawing programs to understand concepts. But then again, how much do you understand (with a certain skill level) from such projects ...


  13. Hello,

    this is a topic over which I have been turning in circles sinces years. Which graphics library to choose for which task. What functionality is there, how hard is it to accomplish the given task. This may sound generic but I feel with graphics libraries it is the desperately hard. For my applications I often have some drawing functionality. For some applications I found reasonable approaches: for some GDI+, for other cases GR32. 

     

    For one specific project/idea I am stuck however, meanwhile to a pretty extensive degree. I guess the fundamental problem is that all libraries would do the trick it is just my lack of skill (despite the years of trying) prevents progress. So I have been looking into all sorts of libraries, packages, demos, examples, recommendations and threads which of course does not accomplish the actual goal.

     

    What the application should do: from a library of images the user should be able to drag and drop elements to the main image. Those elements can then be moved, deleted, rotated, single or in groups. 

     

    I was pretty far with that approach with Graphics32, not quite there yet, though. The functionality to mark multiple elements was missing. More accuarely, the functionality to find/mark objects was rubbish too. Later I found the TRubberband which could help but there I guess for my skill-level graphics32 might not be the right tool. I was lucky enough that some approaches worked but the documentation, the examples, I spend hours and hours trying to understand it with little success. Other than that I found the learning curve of GR32 brutally steep given that the documentation and demos are not easy to understand and there are pretty much no introduction like tutorials. One of the examples that was actually really helpful was the "Reflect it baby" application that was posted on the german DP site.

     

    Purely drawing-based tasks I have tackled with a GDI+ component with decent results, I do not quite see it being ideal in this case.

     

    I gave it another go with an SVG component (because ideally the graphics library would come from svg-files). However, I dropped that SVG goal again since dissecting the svg elements would create another level of complexity. Even though the approach to have the library elements editable would stil be amazing.

     

    I looked briefly into Skia, also there I feel the demos are impressive (just as the graphics32 demos) but I'd need to spend way more time and again, I barely understand the demos. Again, my own limitations.

     

    So, there I am, somewhere between desperately wanting to get this done and losing endless amounts of time with very little progress. 

     

    Finally, the question then is: which library to display, arrange, select images (png or svg) would you recommend? Either because the built-in functionality is there or the documentation allows enough progress. 

×