Grayscale Table

msensoy's Avatar

msensoy

31 May, 2020 02:33 PM

Hello, I'm new to Nodebox 3, trying to learn from zero,
I've found pi_2 setup in the forum and try to implement it for grayscale table chart creation.
Actually maybe it can be done much easier using basic nodes.
My final goal to create grayscale table charts with optional column&row numbers. Top left should always be black while bottom right is pure white, in between grid boxes should gradually increase depending on column x row numbers.
Thank you for your help.

  1. 1 Posted by msensoy on 31 May, 2020 02:43 PM

    msensoy's Avatar

    By the way,
    I still have the same crashing issues as two years ago. I was trying to learn at that time and I was also very excited about it but no matter what it kept on crashing. I've checked the forum and one guy suggested installing Version 3.0.50 and then Version 3.0.51. I uninstalled and installed like this. I'm really willing to learn Node box but it's annoying that in the middle of your work it crashes. For example as my question above, after writing I decided to make an empty project, using very simple nodes like grids and etc.
    I'd be really glad if you can help me in solving this issue.
    Regards.

    Here is my error code;
    java.lang.NullPointerException
    at nodebox.client.NetworkView.paintCurrentConnection(NetworkView.java:352)
    at nodebox.client.NetworkView.paintComponent(NetworkView.java:301)
    at javax.swing.JComponent.paint(JComponent.java:1056)
    at javax.swing.JComponent.paintChildren(JComponent.java:889)
    at javax.swing.JComponent.paint(JComponent.java:1065)
    at javax.swing.JComponent.paintChildren(JComponent.java:889)
    at javax.swing.JSplitPane.paintChildren(JSplitPane.java:1047)
    at javax.swing.JComponent.paint(JComponent.java:1065)
    at javax.swing.JComponent.paintChildren(JComponent.java:889)
    at javax.swing.JSplitPane.paintChildren(JSplitPane.java:1047)
    at javax.swing.JComponent.paint(JComponent.java:1065)
    at javax.swing.JComponent.paintChildren(JComponent.java:889)
    at javax.swing.JComponent.paint(JComponent.java:1065)
    at javax.swing.JComponent.paintChildren(JComponent.java:889)
    at javax.swing.JComponent.paint(JComponent.java:1065)
    at javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
    at javax.swing.JComponent.paintChildren(JComponent.java:889)
    at javax.swing.JComponent.paint(JComponent.java:1065)
    at javax.swing.JComponent.paintToOffscreen(JComponent.java:5210)
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1579)
    at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1502)
    at javax.swing.RepaintManager.paint(RepaintManager.java:1272)
    at javax.swing.JComponent._paintImmediately(JComponent.java:5158)
    at javax.swing.JComponent.paintImmediately(JComponent.java:4969)
    at javax.swing.RepaintManager$4.run(RepaintManager.java:831)
    at javax.swing.RepaintManager$4.run(RepaintManager.java:814)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:814)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:789)
    at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:738)
    at javax.swing.RepaintManager.access$1200(RepaintManager.java:64)
    at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1732)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:109)
    at java.awt.WaitDispatchSupport$2.run(WaitDispatchSupport.java:190)
    at java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:235)
    at java.awt.WaitDispatchSupport$4.run(WaitDispatchSupport.java:233)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.awt.WaitDispatchSupport.enter(WaitDispatchSupport.java:233)
    at java.awt.Dialog.show(Dialog.java:1084)
    at java.awt.Component.show(Component.java:1671)
    at java.awt.Component.setVisible(Component.java:1623)
    at java.awt.Window.setVisible(Window.java:1014)
    at java.awt.Dialog.setVisible(Dialog.java:1005)
    at nodebox.client.Application$2$1.run(Application.java:159)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:756)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:726)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

  2. Support Staff 2 Posted by john on 31 May, 2020 07:15 PM

    john's Avatar

    Dear Msensoy,

    Sorry you are having so much trouble. NodeBox rarely crashes for me (though it does have trouble launching every now and then). But first to the problem you posed...

    Making a grayscale chart in NodeBox is easy. You do not need the pi custom node.

    I have attached an example (grayscale.zip) which also does row and column numbers (see screenshot).

    You could use the standard grid control, but it requires a little extra math to calculate the overall width and height. So instead I used my handy grid_plus node (which lets you base the grid on cell size).

    You will notice that the size of each cell is controlled by a point_size number, as it was in your first attempt. The numbers do not scale with point_size, though this would be easy to add if need be. Actually, an easier way to handle that is to construct the whole table at an arbitrary size and then use the scale node to shrink or expand the whole thing, numbers and all.

    Please let me know if this does what you need and makes sense to you.

    As for the crashing, it wasn't clear to me if reinstalling fixed the problem or not. If not, perhaps you could give us more information - Mac or PC, OS version, Java version (from about box), etc. Does it crash on launch or in the middle of your work and if the latter, what did you do just before?

    I am not able to debug the error code you supplied, but perhaps it will make sense to Frederick if he is listening (adding him to discussion).

    John

  3. 3 Posted by msensoy on 31 May, 2020 09:09 PM

    msensoy's Avatar

    Hello John,
    Thank you very much for your answer,
    I guess I've started to understand some basic stuff, I tried to make it with optional row & column amounts. Still, If you have time I'd like you to check with the eye of an expert. (By the way, I'd like to thank you personally as you're sharing so useful examples with clean instructions. So helpful.)

    For crashing issues, I have two pcs with both Windows 10 installed. I didn't install any external Java application. Both of them are X64.
    Sorry for too many questions but meanwhile I'd also like to ask if it is possible to add your nodes as default nodes. For example, is there a way to make them seen when adding new node. I was able to add custom examples with previews but for example for scripts like your make_curve.py and etc. I thinking putting them all under the Scripts folder doesn't work? Lastly is there a way to get document width/height? I tried it with custom node, try to change its function value to canvas/documentWidth or canvas/width.
    Thank you once again.

  4. Support Staff 4 Posted by john on 31 May, 2020 10:45 PM

    john's Avatar

    Hello msensoy,

    Your modification to allow adjustment of total rows and columns is perfect.

    The only change I would make is to tidy it up: rearrange the nodes to tighten everything up, group related sections together, and minimize crossed links. I did this to your network and have attached before and after screenshots.

    This may seem like a waste of time. It doesn't effect the operation of the network. But over the years I've found it surprisingly useful to tidy up as I go. It makes everything much easier to scan - especially when you leave a project and come back a few days later. Reducing the sprawl means less scrolling as you tinker. And in the process of tidying you often notice unneeded or disconnected nodes or see ways to improve your code. I also find it restful - like flower arrangement. While the front of my mind relaxes, the back of my mind is free to churn away on unsolved problems.

    I really wish there was a way to add the nodes from my node library as default nodes. This has been on the NodeBox wishlist for many years. Frederik allows something like this in NodeBox Live, but never got around to adding it to NodeBox 3. It would be near the top of my personal wishlist.

    What I do instead is leave my node library handy. I have an alias on the desktop that I can launch, or I "Open Recent" while working on another network and open it in a second window. I can then copy-paste the nodes I need. Cumbersome but with practice I can do it fairly quickly. Adding custom nodes is more of a pain.

    I have also long wished for a way to get document width/height. I don't think you can do it with a custom node. But I did come up with a workaround (docsize.zip attached).

    This node returns a rect the same size as the document size. The catch is that you have to point it to your .ndbx file. It then opens that file as a text file and extracts the width and height. This is easy to do since a ndbx file is just an XML text file and the doc size info is always stored at the top of the file.

    I wish there was a way to automatically find the file path of the currently open network, but if there is I've never figured it out. So if you use this node you'll have to manually locate the current file the first time you use it. After that it seems to work even if you move the file into a folder, but it will break if you change the file name. If you modify the document size you will need to save the file then refresh.

    Not perfect, but maybe better than nothing. Please let me know if you find it useful; if you do, I'll add it to the next update of my node library.

    It was nice of you to say you wanted to thank me personally - I think you just did that. I really appreciate it; often I help people out and get no response at all. If you want to chat further, my personal email is [email blocked].

    Happy NodeBoxing!

    John

  5. 5 Posted by msensoy on 01 Jun, 2020 01:18 AM

    msensoy's Avatar

    Thank you once again for your great explanation.

    What I do instead is leave my node library handy. I have an alias on the desktop that I can launch, or I "Open Recent" while working on another network and open it in a second window. I can then copy-paste the nodes I need. Cumbersome but with practice, I can do it fairly quickly. Adding custom nodes is more of a pain.

    I was opening files by double-clicking on them but after your suggestion, I tried to open both files (your library file and my file) from NodeBox file-open then copy/paste worked. I thought there was no feature, I'm writing it might be useful for beginners like me.

    I totally agree with you for tidying things up and try to keep it in mind.

    From this article I guess I've found another way to get document width/height. (Of course, it's already there but for me, I do discover :) ) and added return width, height line only.
    Then from metadata, I've changed the value to list. (At this point I might have added unnecessary nodes because I'm still very new to nodes.)
    I tried to do it like this because I couldn't really understand your way. But still thank you, in only one day I have learnt a lot from you and for sure that I would like to keep in touch. email

    Image

    def cook(context):
        library = context.nodeLibrary
        width = float(library.getProperty("canvasWidth"))
        height = float(library.getProperty("canvasHeight")) 
        return width,height
    
  6. Support Staff 6 Posted by john on 01 Jun, 2020 07:44 AM

    john's Avatar

    Msensoy,

    Wow! Nice find! The forum is a goldmine for things like this.

    I modified your code snippet to create a custom node called doc_size that requires a python file called docsize.py. It returns the width and height as a point. That way you can retrieve the width and height using ordinary lookup nodes (lookup x and lookup y) - no need to do all the string munging.

    Modified node and screenshot attached.

    I will probably include that node in my next library update. Thanks again for finding it!

    The file-based node I made earlier might still be of use in the unlikely case you need to look up document sizes for a list of Nodebox projects (which you could retrieve using my list_files node). But in most situations this new node is a better solution.

    It's been an educational day for both of us!

    John

  7. 7 Posted by msensoy on 01 Jun, 2020 08:45 PM

    msensoy's Avatar

    Hi John,
    Thank you for your reply and solution as well, as I said I am a newbie:) still trying to understand nodes but I am glad that you liked it and found it useful. By the way, I've downloaded your node and yes It works perfectly, so you should definitely add it to your library update. Actually my initial goal was to arrange the external gridded image (say 10x10) due to their luminosity values, then re-arrange them from top-left to bottom-right gradually again from their luminosity values. But after all, what I am trying to achieve is to create a photo mosaic.
    The user will give one single image; for example, a 10x10 grid single image (with various different average luminosities randomly), and the software will re-arrange them with the same grid amount due to their luminosity amount and may relocate them according to their luminosity values again.
    In another software (filter forge), with the help of a user (emme) it was possible to separate units from one single image due to their luminosity values. Yes, it's working but I'd still love to know if it would be possible in node box too.(Imagine 10x10 collage image (with random lightness) is given, it re-locates these units according to original images values)

  8. Support Staff 8 Posted by john on 02 Jun, 2020 09:02 PM

    john's Avatar

    Hi Msensoy,

    Sorting objects based on a property like luminosity is easy in NodeBox. Just make a table with two columns: index and luminosity. Index is simply a range of numbers from 0 to n and luminosity is the value for each item. Then sort the table by luminosity and lookup the index. You will get a list of index numbers which you can then feed into a slice node to pull out your objects in the new order.

    Dealing with images, though, is a problem. NodeBox is a pure vector app - it doesn't even have an image object. So I'm not clear on how you were going to sort images with NodeBox.

    You can, however, do something similar. Years ago another user posted a custom node that can scan a JPEG image at a given granularity (e.g. one out of every ten pixels) and return RGB values. If you use these values to color cells (rectangles of size g x g where g is granularity) you can produce a mosaic which forms a pixelated version of the JPEG. If you set granularity to 1 you would get a perfect reproduction, but depending on the size of the image you might wind up with millions of pixel-sized rectangles which would slow NodeBox to a crawl.

    By using this method, you can produce a mosaic of sorts which you can then sort by luminance or whatever using the method described above. Actually, I wasn't sure what you meant by "luminance", so I tried it with all three HSB properties (hue, saturation, brightness) plus something called a "luma" based on a formula I found online.

    I am attaching a demo (with the necessary files included in the zip) and a screenshot. The magic is done by a subnetwork called sort_cells. You can choose any of the four properties to sort by, and can also make the luminance or whatever flow east (left to right), north (bottom to top), etc. Have a peek inside and see how it works.

    I included several small JPEGs to play with. I find the results rather interesting. This is probably not exactly what you are trying to do, but you should find it instructive.

    Happy NodeBoxing!

    John

  9. 9 Posted by msensoy on 06 Jun, 2020 10:05 AM

    msensoy's Avatar

    Hi John,
    Sorry for the late reply,
    That's great, actually, it opens up many possibilities. Thank you very much.
    I wonder is there a multi-switch node in node box? Why I am asking is let's say we have 10 or more (pictograms or icons for example) SVG vectors. They can also be generated directly inside the node box (for example with some pictogram fonts.).
    And according to the external image's luminosity values, these vectors can be populated. I guess this way it gives the possibilities to create typographic illustrations, optic art illustrations, vector engraving, or even vector seamless patterns.
    By the way, I have seen this post and very excited;
    Dissasemble Grid I wonder would it be possible to convert this project into something as I've attached.
    Or Piet Mondrian's Circle kind artworks.
    (Meanwhile after downloading this project I noticed that it gives many tiny squares with the same color, I think it was needed at that time. But do you think it would be possible to merge all with the same color? This way with the help of some illustrator or photoshop scripting these colors can be separated into layers.) Lastly, maybe you know it there is a circle fill script for illustrator. But after making some experiments with it I've noticed that it doesn't always fit accurately. I know these are all different questions or ideas but I'd really like to use Node Box as an important vector tool for my work furthermore. I hope Frederik would also keep Node Box 3 alive in the future as well.
    Once again Thank you John.

  10. Support Staff 10 Posted by john on 07 Jun, 2020 04:08 AM

    john's Avatar

    Hi Msensoy,

    So many questions! I'm glad to see you are excited by the possibilities.

    The short answer to all your questions is: yes. Where there's a will there's a way. Things like sorting and filtering and grouping are fairly easy in Nodebox. As described in my previous note, the basic trick is to make a table using the original order of the objects as ID numbers. You can add as many properties as you want, then sort them, filter them, cull them, etc., then do a lookup on the index column to recover the subset of object IDs you want, and feed those index numbers into a slice node to pull up the actual objects.

    Consolidating same-colored blocks into larger blocks is possible but could be tricky. It's easy to filter for all the blocks of a given color, but analyzing them spatially to see which ones form larger blocks takes some thought. Things that are instantly intuitive to the human brain often require math and algorithms for a computer to figure out. And those algorithms often tend to be recursive (e.g. small blocks forming bigger blocks, bigger blocks forming even bigger blocks, etc.) and NodeBox doesn't do recursion. At that point you would probably need a custom node and some Python code.

    The second image you attached should be fairly easy. You can take the Mondrian patterns I created in that Disassemble Grid demo and use a compound node to cut out or mask a circle.

    The third image is harder. Circular treemaps and circle packing and Voronoi diagrams involve some complex mathematics and more of those pesky recursive algorithms. There are packages and libraries out there that can do them for you, but it would be very difficult to do them directly in NodeBox without making custom nodes. I have long wanted to make some kind of custom packing node, but have yet to summon the patience and energy to tackle such a project.

    My advice to you is to go forth and play! Imagine something fun that you want to make and try to make it. Start small if you can, but not so small that you become bored. Learning happens when your reach exceeds your grasp.

    John

Reply to this discussion

Internal reply

Formatting help / Preview (switch to plain text) No formatting (switch to Markdown)

Attaching KB article:

»

Already uploaded files

  • pi_2.zip 648 KB

Attached Files

You can attach files up to 10MB

If you don't have an account yet, we need to confirm you're human and not a machine trying to post spam.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac

Recent Discussions

04 Jul, 2020 08:13 AM
07 Jun, 2020 04:08 AM
04 Jun, 2020 11:48 PM
25 May, 2020 09:13 PM
24 May, 2020 09:33 PM