go-nexrad icon indicating copy to clipboard operation
go-nexrad copied to clipboard

WASM Webapp and initial support for SVG rendering

Open SteepAtticStairs opened this issue 2 years ago • 3 comments

WEBAPP I have made a super rudimentary version of this project using wasm, and it was taken almost entirely from go-wasm-pdfcpu.

To build the nexrad.wasm file yourself, run

git clone https://github.com/bwiggs/go-nexrad.git
cd go-nexrad && cd cmd && cd nexrad-render

GOOS=js GOARCH=wasm go build -o nexrad.wasm

I struggled a while on Go 1.18 because I was getting some errors, but then I downgraded to 1.12 and it worked fine. Specifically go version go1.12 darwin/amd64.

Then put the binary under the webapp directory I have made:

git clone https://github.com/SteepAtticStairs/go-nexrad.git
cd go-nexrad && cd webapp

These instructions are just if you want to build it yourself. A live demo of what I (but mostly the author of go-wasm-pdfcpu) have done can be found here: https://steepatticstairs.github.io/go-nexrad/webapp/

I plan to do a lot more cleanup.

VECTOR RENDERING

This is very scuffed code, forgive me - I mainly work with JavaScript, not Go! But this is a basic implementation of vector rendering using the draw2d library. By passing the -v flag with arguments png or svg (png is default), it will generate the relevant file.

However, I think there are three major issues with the code I have written. First, the file size of these svg files are extremely large, hovering around 70 MB. I have tried to reduce the DPI, the canvas size, but nothing has worked, so I would like to try and work out a solution in the future. Any suggestions on combatting this issue would be welcome.

Second issue (fixed for now I think??)

Second, the svg image has a slight problem with rendering the pixels closest to the origin. For example, when I generate an svg file from KLZK20220607_194517_V06 by doing go run . -f testdata/KLZK20220607_194517_V06 -p ref -v svg, I get this error right in the middle of the image: Screen Shot 2022-06-07 at 6 07 36 PM As you can see, there is a ring of thick pixels that shouldn't be there. This is NOT an issue with PNG rendering.

Third, the variables canvas and gc have been replaced with PNGcanvas PNGgc and SVGcanvas SVGgc, and I will explain that here. I wanted to use an if statement, basically giving these variables their proper arguments if the user passed png or svg. For example, the correct canvas variable for an svg render would be

canvas := draw2dsvg.NewSvg()

while the correct variable for a png render would be

canvas := image.NewRGBA(image.Rect(0, 0, int(width), int(height)))

I wanted to set these dynamically with an if statement, ideally something like this:

if vectorize == "png" {
	canvas := image.NewRGBA(image.Rect(0, 0, int(width), int(height)))
	draw.Draw(canvas, canvas.Bounds(), image.Black, image.ZP, draw.Src)
	gc := draw2dimg.NewGraphicContext(canvas)
} else if vectorize == "svg" {
	canvas := draw2dsvg.NewSvg()
	canvas.Width = strconv.Itoa(int(width)) + "px"
	canvas.Height = strconv.Itoa(int(width)) + "px"
	gc := draw2dsvg.NewGraphicContext(canvas)
}

However, the issue with this is that each of these variables using :=, which obviously means that they are declared and set in the same line, where they don't require you to specify a type. This will not work here, because you need to define the variables outside of the if statement. You could do this by writing something like

var canvas *image.RGBA;
var gc *draw2dimg.GraphicContext;

if vectorize == "png" {
	canvas = image.NewRGBA(image.Rect(0, 0, int(width), int(height)))
	draw.Draw(canvas, canvas.Bounds(), image.Black, image.ZP, draw.Src)
	gc = draw2dimg.NewGraphicContext(canvas)
}

but this would mean you would have to change the types of canvas and gc for the case that the user renders an svg.

My solution to this, of course, was to create two separate draw2d objects that the program will draw to simultaneously, but only one will get exported to a file 😂. This, of course, is not the best way to do it, because it slows down the program and it looks quite ugly. Again, any suggestions on combatting this issue would be welcome.

Andrew

SteepAtticStairs avatar Jun 07 '22 19:06 SteepAtticStairs

June 10, 2022 10:30 PM EST

See the original PR comment for more specific details. This comment is meant to provide an easy way to look at my changes, so you don't only have to go digging through my super messy and unnecessarily plentiful commits.

TOTAL COMMITS SO FAR: 15 🤦‍♂️

Summary of PR so far:

  • I have made some changes to the code, mostly in cmd/nexrad-render/main.go
    • added a timer that prints out how long the rendering of the radar file took
    • commented out the pb library, because it wasn't allowing WASM to compile and it wasn't serving much purpose in the first place (that I could tell)
    • updated a couple of gitignores to make working with my input and output files easier
  • Added two new command flags for svg vector rendering, detailed below
  • -v svg
    • generates an SVG image using the draw2d library, exactly how a png image is created, but with svg options. Highly inefficient, most output svgs are over 70 MB.
    • default output name is radar.svg
  • -v svgtest
    • Uses another library for svg generation: svgo. Draws each radial gate as a single circle, in an attempt to make it more efficient. Uglier output, but 40 MB compared to 95 MB of the same radar file generated using the method above.
    • default output name is TESTradar.svg
  • added a new folder under cmd/nexrad-render called dump. Contains a file called svgMinify.go, using the library minify for svg minimization. works ok-ish, 95 MB svg becomes around 70 MB. not the best, and it will not compile into WASM, so I kept the code but moved it into a separate folder so it wouldn't get in the way.
  • added a web app under the directory webapp, live demo here
    • allows you to upload a radar file, specify command flags, and it will give you the resulting png/svg output.
    • I also wrote a small utility on that page for browsing the AWS S3 bucket of L2 radar files, which provides quick downloads for the files. Specify a date and a radar station and it will list all radar files stored for that date as anchor elements, which link to the file URL - which you can click on and download.
    • This radar download utility might take a bit to load the file list, because it has to use a proxy to bypass a CORS error.

SteepAtticStairs avatar Jun 11 '22 03:06 SteepAtticStairs

Sorry about this getting closed. I've update the repo to use main as the new default branch.

bwiggs avatar Jun 13 '22 04:06 bwiggs

June 14, 2022 11:15 PM EST

See the original PR comment for more specific details. This comment is meant to provide an easy way to look at my changes, so you don't only have to go digging through my super messy and unnecessarily plentiful commits.

TOTAL COMMITS SO FAR: 34 🤦‍♂️

Summary of PR so far (things that have changed / been added since the last summary comment):

  • -v svg and -v svgtest
    • These flags now generate a new directory in cmd/nexrad-render called radials. inside the radials/split directory there are around 70 svg files, each file containing 10 radials. This is toying with the idea I had where I assumed that if I wanted to render the radar image onto a map, it would be easier for the map to render a lot of smaller images at once than one big image.
    • Transparent gates are no longer rendered at all, cutting a 95 MB file down to around 60 MB.
    • The main output svg for -v svg is now gzipped into radar.svg.gz, for further compression. Plans to gzip the radials directory as well.
  • -v png
    • Background is now transparent instead of black
  • Leaflet map
    • I have added a leaflet map page to webapp/map.html, and a demo can be found here.
    • First, upload a radar file generated from go-nexrad. Then, input a radar station and hit Ok. Finally, press the picture frame button on the left hand side of the map to show and hide the image.
    • Gets the coordinates of each radar station from a master JSON I have here. Calculates a bounding box by getting a point 460 km to the northwest and 460 km to the southeast. Loads the uploaded image into that bounding box.
    • The image is slightly misaligned, only by a little bit. This is a bug, but I am not sure what is causing it. The circle in the middle of the radar image should be centered on the coordinates of the radar station, but the image is always a little off.

SteepAtticStairs avatar Jun 15 '22 03:06 SteepAtticStairs