Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] Create Draw Shape from Image/Mask, or from Transparent sections of Image on Map Layer #641

Closed
PalasX opened this issue Jan 21, 2021 · 17 comments · Fixed by #675
Closed
Labels
enhancement New feature or request Vision

Comments

@PalasX
Copy link

PalasX commented Jan 21, 2021

Is your feature request related to a problem? Please describe.
The drawing tools to create shapes that block lights and movement, like walls and doors, are great, but can be time consuming and tedious for very large maps. Anything that takes a human a long time to do, and has to be done repeatedly, is prime territory for automation.

Describe the solution you'd like
After dragging an asset to the MAP layer, and resizing according to grid size using the MAP TOOL, provide a means to automatically generate a single solid shape from the transparent parts of the image. Alternatively, let the user upload an image containing transparency to be used as a mask to create a shape.

Describe alternatives you've considered
Import a standard library for edge detection on a map asset image to try and create a single or series of shapes for walls? It seems more complicated this way.

Additional context
Example Map:
image

Example resulting shape (white being transparent), or secondary mask image asset to be used as a "everything that isnt transparent will block light/vision as per user settings":
image

I realize this could be a huge undertaking, but hoped that since there was so much python to deal with images already, that sorting out which pixels were and werent transparent would at least be near-trivial. I assume translating a 1bit (black/transparent) image into a shape would be the hard part. It could save DMs a significant amount of time and effort when using randomly generation maps, and people that create their own map art assets could export a "pathing" layer of their image maybe?

Thanks again for all the amazing work you do!

@Kruptein
Copy link
Owner

Hey, this is indeed something that would immensely help DMs all around.

The complexity lies in how the lighting/vision actually is calculated. It's based on an algorithm that uses line segments to construct a triangulation that can be quickly queried.

So for all existing shapes when toggling the 'blocks vision' option, it adds all the lines of the shape to the triangulation and the lines are known because they are either simple shapes or hand-drawn polygons.

I'm sure that I should be able to get the lines from a more complex shape such as your mask, so I'm sure it's feasible, it will just as you mentioned maybe take some more time.

Might look into this in the near future! There are some other things that I would like to tackle first, but this one would be nice to have.

Also nice that you provided an example with a mask ;)

@Kruptein Kruptein added enhancement New feature or request Vision labels Jan 21, 2021
@PalasX
Copy link
Author

PalasX commented Jan 21, 2021

Continuing with the donjon exaple, would it be easier to directly import a .TSV file for a map, step through the TabSeperatedValue format, and build vector line segments from scratch? There is a python project donjon-painter on github that takes TSV and outputs PNG by building a tile based raster, but it might be a good start to grab the parsing for the TSV format?

Alternatively, what about building vector lines from an SVG? User could pre-convert their raster image to SVG with a tool like ImageMagick or AutoTrace or other. Obviously more complex raster images would result in an SVG thats just too big to the point of unusability, but might be doable on a 1bit image.

And yeah, i realize this is a "wouldn't it be nice" feature for down the road, and would be a large undertaking. Slow and steady, im sure none of us wants to subject you to burnout :)

@Kruptein
Copy link
Owner

the SVG approach is something a friend of mine has also suggested in the past and should be rather easy to get the lines from indeed.

Also just as a small clarification, most of the heavy lifting is done in javascript in the browser. The python backend is primarily a dumb server that handles authentication, authorization, persistence and message passing. Although nothing prevents me to implement some heavier things there if the ecosystem is better which might be the case for image processing.

@Kruptein
Copy link
Owner

Got some good news here, a friend of mine did some experiments way back in may related to svg stuff. I've looked at it and played around with some things and it's actually pretty promising.

I uploaded your example mask above to vectorizer to convert it to a svg and used some debug draw tools I have together with my friend's code and got this:

image

Ignore that one line in the bottom left, that's my draw tool connecting the last and first point, which is unnecessary here.

Next up is figuring out some scaling things, because we'll want to scale the fow lines along with the shape itself.

@Kruptein
Copy link
Owner

Expecting to actually have some working prototype tomorrow

@Kruptein Kruptein linked a pull request Feb 14, 2021 that will close this issue
Kruptein added a commit that referenced this issue Feb 14, 2021
Merge pull request #675 from Kruptein/feature/GH-641-svg-masks
@PalasX
Copy link
Author

PalasX commented Feb 15, 2021

That is SO WICKED COOL! Thanks to you and your friend for finding an awesome way to implement this!!!

@PalasX
Copy link
Author

PalasX commented Apr 6, 2021

I must be doing something wrong, i cannot get the SVG import to work.

I place a map image on the map layer, select it, view the properties, and select upload SVG. Then i select the walls SVG from the asset manager, aaaaaaaand nothing happens.

Do i need to do something special when crafting the SVG?
map_101x101.svg.txt
hate3

@PalasX
Copy link
Author

PalasX commented Apr 6, 2021

aaaaah, i had to turn on "Blocks light" and "Blocks movement" for the properties of the map asset itself on the map layer. is that how it's supposed to work?

@Kruptein
Copy link
Owner

Kruptein commented Apr 6, 2021

Yeah, I suppose it shoud automatically toggle those on when you add an svg

@PalasX
Copy link
Author

PalasX commented Apr 6, 2021

That's probably the best behavior, yeah. The process works beautifully,. by the way. Just gotta find a better offline vectorizer. Thanks again, your continued work on this project keeps making the world of difference to our gaming group!

@PalasX
Copy link
Author

PalasX commented Apr 6, 2021

SVGs created with vectorizer.io work, but those that are outputed by dungeonscrawler (even after removing ALL the extra thatching and fluff and background so that you only have a 2 color, unfilled, outline of the map) do not create any walls.

The SVG from vectorizer.io seems to be using PATH elements, whereas the ones coming out of use POLYGON. Is this what's causing the flub?

vectorizer -

<path d="M2050.3 4974.3 l0 -25.3 99.7 0 99.7 0 0 -24 .............. etc etc etc

dungeonscrawler, https://probabletrain.itch.io/dungeon-scrawl, all background, thatching, shadows, etc disabled -
<polygon points="477.6595044494085,56.924455795979505 599.3202932660953,56.924455795979505 599.3202932660953,62.21412558216337 599.3202932660953,62.21412558216337 599.3202932660953,67.50364843511613 599.320 .........etc etc etc

EDIT:
https://convertio.co/ also converts with PATHs, but sizes things in PTs isntead of PXs, and then tries to transform each shape by a factor of 0.1. This output loads wall data, but it is vastly out of proportion, and appears FLIPPED VERTICALLY!?!
map_161x161_nodoors_outline_convertio3.svg.txt

EDIT: Same goes for POTRACE ( http://potrace.sourceforge.net/ ). Outputs SVG with pt sizes and transforms/scales and is flipped vertically. the transform moves the map offset by its total height and the scale sets y axis to -0.1, which combines into a vertical flip (offset by height and scale by negative. manually flipping the image of the map first creates a correct SVG, but the scale is still off.

Here's the steps i took to get Donjon TSV -> SVG working:

  1. Generate a donjon map to your liking at https://donjon.bin.sh/5e Random dungeon generator. Download the files you want need (HTML, player map, print map, TSV). you MUST download the TSV text file, and a copy of the player map with GRID: NONE. Grid lines will confuse the SVG parser.
  2. Upload the TSV to Dungeon Scrawl at https://probabletrain.itch.io/dungeon-scrawl . You can do so in the EXTRA tab on the right, under DONJON GENERATOR, IMPORT TSV. Be patient, this process can be very slow for large maps, but i tested with "colossal" and "gargantuan" sized maps just to make sure it does.
    2a. There will be 2 layers of the dungeon scrawl map when the import is done. Click on the first layer, Dungeon Layer 0, to highlight it if it is not already selected. Using the STYLE, SHADOW, and GRID tabs above, disable "Layer hatching", "Show Shadow", and "Show Grid". Click on the 2nd layer, Background, to select and highlight it. Using the STYLES, HATCHING, and SHADING tabs above, disable "Show Grid", "Show Hatching", and "Show Shading".
    2b. Zoom out with the mouse scroll wheel until the entire map is visible in Dungeon Scrawler's canvas. Click FILE, then EXPORT, change "Pixles per inch" from 70 to 50 (this makes it openable by MS PAINT, and probably helps with alignment later), and choose "Rect Download (Recommended)". Draw a rectangle around your entire map, being sure to leave EXACTLY one grid block margin. After a few seconds, you will be prompted to save a PNG file to your computer.
    2c. Open this PNG file in MS PAINT, or your favorite image editor. Flip the image vertically (Home -> Rotate -> Flip Vertial in MSPAINT), and then save it as a MONOCHROME bitmap file (File -> SAVE AS, and then change the filetype to Monochrome Bitmap in the download list available). MSPAINT will warn you that you're going to lose color fidelity. Accept the warning and save the file with the .bmp extension.
  3. Download and extract/install POTRACE ( http://potrace.sourceforge.net/ ). It is a command line, open source program to convert raster graphics to vector graphics. Copy your MonoChrome_Bitmap.bmp file to the potrace directory. Open your operating systems version of a terminal, navigate to the directory with potrace in it and issue the command "potrace -u 1.333333 -s MonoChrome_Bitmap.bmp". This will output "MonoChrome_Bitmap.svg". This is your map file ready for use in Planar Ally.
  4. Upload your map image to the Planar Ally asset manager. This map file can be the player map without a grid, the player map with a grid, or even a stylized version of the map created with Donjon-Painter ( https://github.com/Blackflighter/donjon-painter ). Adjust the map image to be correctly aligned with your planar ally grid. If you do not use a grid for your games, i still suggest doing this, as it will help ensure that map and svg line up correctly.
    4a. Upload the MonoChrome_Bitmap.svg file to the PlanarAlly asset manager. At this point you could have renamed the svg file to whatever you want. I like mine in NameOfMap.png and NameOfMap.svg pairs, but you do you.
    4b. Return to map, go to the map layer, select the map you meticulously aligned to your right, right click it, and go to show properties. under the EXTRA tab, click the UPLOAD button next to UPLOAD WALLS (SVG). Select your SVG from the asset modal window that appears, and click SELECT. After a few seconds, the map properties window will update, showing "Remove walls (svg)" at the bottom of the Extra tab. Go to the properties tab and enable/checkmark "Blocks vision/light" and "Blocks movement". Now would be a good time to lock your map as well, so you dont accidentally move it. Close the Edit Asset window for the map.
  5. Create a basic token and give it a lightsource aura. Enjoy your map with automatic walls!

There. all sorted. Thanks for the space to write it up, puzzle it out, and get it working. Hope it helps someone else. The only reason i use Dungeon Scrawler is a SUPER easy way to remove all the door/trap/etc graphics from Donjon's TSV format when creating an image. Since we ONLY want walls in our SVG, we have to remove extras like the floor grid and those pesky doors/traps/etc. You can choose NONE as grid type when creating the DONJON map, but the easiest program that imports TSV files is DungeonScrawl, and it has the added bonus of removing anything that isnt a wall automatically and spitting out a nice clean image of the walls.

Cheers!

@dthv
Copy link
Contributor

dthv commented Apr 7, 2021

@PalasX just in case there will be some sort of FAQ and/or list of tricks or something – may I copy your comment and/or parts thereof into the documentation?

@PalasX
Copy link
Author

PalasX commented Apr 7, 2021

@dthv I consent entirely to the free use, without any further stipulations or addendums, of my previous post, in whatever capacity anyone wants to use. Go for it, i wrote it all down 50% to get it straight in my head and document what i was doing so i wouldnt forget, and 50% to help anyone else.

Additionally, mirroring the image vertically MAY NOT be necessary for some maps. I had to do it for all "normal" maps so far, but not when creating SOME "cavern" type maps. Also, do NOT try to do this with large cavern type maps. Everything will work fine until you turn on enable blocking light/movement, then it will all grind to a halt. On the plus side, cavern player maps from donjon dont have doors or anything, so you can use the player map right away without feeding the tsv through dungeon crawler (which would also make it blocky again, and not cavern-y).

Also additionally, you could probably do the conversion from PNG to 2bit BMP in the terminal/command line with ImageMagick, and thus skip the MS Paint requirement. It's what i'll end up doing in the future.

tl;dr: Yes. You can use my post, the contents therein, or any part of it, in any manner you choose.

EDIT: had to do vertical flip on a cavern map today. also, for cavern style donjon maps, use the playermap.png and do an edge-find on them in your favorite image processing program (i used gimp) to get nice contiguous lines for the cavern walls. then feed it to potrace. your svg will be MUCH smaller since it wont be filling in the walls as solids, and will load faster in planarally. on a colossal sized cavern, i still had to wait 2-3 minutes and tell chrome to WAIT on the script when turning on block-light. it REALLY helps to make your edge-find lines a little "fat", as it reduces the fiddly-bit details significantly. the image attached is one that i made just a little too fat for my liking, but it loaded fairly quickly for a 160x160 grid, 8050x8050 pixel map.
171363771_199504365015418_1335481012015432921_n

For CAVERN style donjon maps, my process is this:
start with your flipped monochrome BMP
smooth it out by selecting FILTERS -> LINEAR MOTION BLUE -> Length 10, Angle 0.
Find the edges with FILTER -> EDGE-DETECT -> EDGE... -> Algorithm Sobel, Amount 2
FILE -> Export -> some file.bmp, this will be what we use for potrace.
"potrace.exe -u 1.333333 -s -O 1 "some file.bmp"
The resulting SVG file should be nice and optimized and small. a 160x160 grid map will have an svg smaller than 400kb.

if you "break" planarally and it just keeps timing out while loading your map, as i did several times while testing, just go to the asset manager from the main page and delete the map image asset. without the asset, it will stop trying to load your monstrous svg/walls, and will load to the map in question again without issue.
Screenshot 2021-04-09 134041

@PalasX
Copy link
Author

PalasX commented Apr 9, 2021

possible solution to relying on an online tool for TSV to SVG: https://thetrove.is/Resources/Programs/Donjon_TSV_to_SVG_converter.zip

Outputs an svg from a tsv, but makes a separate for each tile, and does not output some header into like doctype and viewport sizes, but those can be added manually with any text editor. released as a compile .JAR, with no source available :(

Does not work for direct use in PlanarAlly, even with the added doctype and css and what not. It loads, and the top ~10 grid squares work, then it acts like theres a wall present at y=10 for the entire width of the map? at least its an offline way to get TSV to renderable SVG, which can be saved out to raster image PNG, and then get fed into the above process.

@PalasX
Copy link
Author

PalasX commented Apr 10, 2021

Using ImageMagick ( https://imagemagick.org/script/download.php ) and the above linked TSV_to_SVG converter, we can avoid the use of ANY online tools:

TSVtoSVG, rename TSV to map.txt, run DonjonTSVtoSVGconverter.jar, get mapoutYxZ.txt

rename mapoutYxZ.txt mapoutYxZ.svg

ImageMagick> convert mapoutYxZ.svg -resize 8050x8050 -background white -gravity center -extent 8050x8050 mapoutYxZ.bmp
where 8050 is the size in pixels of the player map, minus 1.

ImageMagick> convert mapoutYxZ.bmp -flip mapoutYxZ.bmp

potrace.exe -u 1.333333 -x 0.1 -s -O 1 mapoutYxZ.bmp

upload to planar along with the player map, or whatever stylized version you want. match the map up to your grid, then apply the svg.

This process skips the need to monochrome the BMP first, but DOES NOT WORK ON CAVE STYLE MAPS! Well, it will, but it will reduce them to the squared off style and not keep the cave-y-ness of them.

Gif attached of the resulting map after following these step by step instructions, took less than 5 minutes. I don't think i can make the process any simpler for importing Donjon randomly generated maps :) THANK YOU to dev and contributors for giving me such a fun project to write up and a great creative outlet <3

recording

@Kruptein
Copy link
Owner

Hey there quite a bunch of chat I missed :D

Could someone summarize if there is something that needs to happen / be checked on my end?
I see some things related to flipped images for example.

@PalasX
Copy link
Author

PalasX commented Nov 1, 2021

Just wanted to update that this step is no longer needed since the SVG handling has been updated to account for transforms:
ImageMagick> convert mapoutYxZ.bmp -flip mapoutYxZ.bmp

verified that omitting it from the process still yields a perfect working SVG from a donjon TSV. My continued appreciation for the project and respect to it's contributors <3

Adding attchment of the TSV to SVG converter, since the original link has since gone down:
Donjon_TSV_to_SVG_converter.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Vision
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants