area515 / Photonic3D

Control software for resin 3D printers
http://photonic3d.com
GNU General Public License v3.0
132 stars 115 forks source link

Printer Mask #198

Closed 3dModeller closed 8 years ago

3dModeller commented 8 years ago

Is it possible to get a printer mask automatically processed with the slices when i upload a stl file. What is the workflow to get a printer mask working. I am a little confused, because the user interface does not provide any way to do this.

jmkao commented 8 years ago

The mask is a function, which you enter into the printing profile but you'll need to use the cwhClient to actually generate interactively.

You can learn more about this in #109.

3dModeller commented 8 years ago

I already have a optimized projector mask in PNG format, but I do not know how it can be used in cwh

WesGilster commented 8 years ago

I suppose I'll just have to create this feature, quite literally I've spent more time arguing against than it would take to build it. I've been pushing people away from it because I don't really believe in the idea, but I guess it's time to give in.

WesGilster commented 8 years ago

There is a quick way you can do this without any code changes for now. This is going to be incredibly inefficient, and is probably going to be too slow, but you could try this:

  1. Upload your gradientfile.png file as a printable file through the normal upload process.
  2. Use the following for the "Projector Gradient (Paint)" calculator.
var image = javax.imageio.ImageIO.read(new java.io.File("/tmp/uploaddir/gradientfile.png"));
var rect = new java.awt.geom.Rectangle2D.Double(0, 0, image.getWidth(), image.getHeight());
new java.awt.TexturePaint(image, rect)

I'll have to add a change to the applyBulbMask() function to cache the paint so that it doesn't get executed for every slice.

3dModeller commented 8 years ago

I only need the projector mask when I need a big portion of the build plate. The wall thickness differences in the model would otherwise be a difference of 0.5 mm. In addition, I anyway would need a longer exposure time, so that the weakest area is printed at all. Thus, I extend the exposure time with the projector mask only to what would anyway required for the weaker section. For smaller parts that I can position in the brighter area, then I do not need the projector mask, why this feature should also can individually activated and deactivated. Sorry for my bad english, I hope you understand me

WesGilster commented 8 years ago

The development version now has a checkbox near the projector mask calculator that allows you to turn the projector mask on and off. Let me know if that is what you were looking for.

I've also optimized the bulbmask so that it will only compute the bulb mask once for the entire print.

3dModeller commented 8 years ago

installing of the development version fails

wget https://github.com/WesGilster/Creation-Workshop-Host/raw/master/host/bin/start.sh --2016-04-03 22:35:47-- https://github.com/WesGilster/Creation-Workshop-Host/raw/master/host/bin/start.sh Resolving github.com (github.com)... 192.30.252.122 Connecting to github.com (github.com)|192.30.252.122|:443... connected. HTTP request sent, awaiting response... 302 Found Location: https://raw.githubusercontent.com/WesGilster/Creation-Workshop-Host/master/host/bin/start.sh [following] --2016-04-03 22:35:50-- https://raw.githubusercontent.com/WesGilster/Creation-Workshop-Host/master/host/bin/start.sh Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 23.235.43.133 Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|23.235.43.133|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 5943 (5.8K) [text/plain] Saving to: start.sh' 0K ..... 100% 23.0M=0s 2016-04-03 22:35:53 (23.0 MB/s) -start.sh' saved [5943/5943] chmod 777 start.sh ./start.sh WesGilster mv: cannot stat cwh-0.*.zip': No such file or directory cp: cannot statbuild.number': No such file or directory mv: cannot stat build.number': No such file or directory --2016-04-03 22:39:13-- https://github.com/WesGilster/raw/master/host/build.number Resolving github.com (github.com)... 192.30.252.122 Connecting to github.com (github.com)|192.30.252.122|:443... connected. HTTP request sent, awaiting response... 404 Not Found 2016-04-03 22:39:16 ERROR 404: Not Found. mv: cannot statbuild.number': No such file or directory grep: networkbuildnumber: No such file or directory No install required rm: cannot remove networkbuildnumber': No such file or directory mv: cannot statcurrentbuildnumber': No such file or directory Turning off screen saver and power saving Installing CWH as a service cp: cannot stat /opt/cwh/cwhservice': No such file or directory chmod: cannot access/etc/init.d/cwhservice': No such file or directory update-rc.d: error: unable to read /etc/init.d/cwhservice update-rc.d: using dependency based boot sequencing Determinging if one time install has occurred grep: /root/3dPrinters/config.properties: No such file or directory Starting printer host server

jmkao commented 8 years ago

For running dev builds, download newstart.sh instead:

https://github.com/WesGilster/Creation-Workshop-Host/raw/master/host/bin/newstart.sh

And run it as:

./newstart.sh WesGilster in order to pull Wes's latest release.

3dModeller commented 8 years ago

The installation off the dev-build was successful. In this version, the printer-port /dev/ttyACM0 will not longer offered. Now I got this version deleted and the stable version installed, the interface is now available again.

3dModeller commented 8 years ago

Sorry, pressed the wrong button (close)

jmkao commented 8 years ago

If you're having issues with the port detection on the WesGilster fork, I recommend that you install and run that fork you're having problems with, reproduce the problem, and then perhaps also try firmware autodetect and then start the printer (which will make the server poll the ports).

After doing that, download the diagnostic bundle and attach it to this issue.

You can download the diagnostic bundle at:

http://:9091/services/machine/downloadDiagnostic/logBundle.zip

WesGilster commented 8 years ago

Interesting, I think this is a build related issue. I've made a custom build of the rxtx serial enumeration libraries, and fixed this quite some time ago. Now we are using the standard rxtx libraries and this problem has been reintroduced.

WesGilster commented 8 years ago

I've reproduced 3dModeller's issue on my Raspberry Pi as well. I believe there is a way to kick RXTX in head in order to to use javax.comm.properties but I've never understood why they put this artificial limitation to their Serial search path...

WesGilster commented 8 years ago

Instead of reverting back to using my custom build of RXTX, I decided to remove all serial enumeration dependencies on it and instead used the functions from jssc. I'll keep RXTX jar dependencies included in the event someone wants to use the different serial implementations available.

@3dModeller The latest version of the dev build(DEV022) fixes this issue and you should see all serial ports now.

jmkao commented 8 years ago

Besides RXTX and the avrdude binaries, what other libraries require OS specific libs from the os dir?

WesGilster commented 8 years ago

JSSC is the only other library that requires OS specific libs, but it doesn't keep them in the OS dir. it carries them internal to the jar.

3dModeller commented 8 years ago

I installed the newest dev-build and the interfaces are all available again. Now I tried to print with projector mask. If I try to print a stl-file, then for the first layer it will only be shown the mask without the slice

and afterwords the printer hangs with the error:

Messgitter_flach_2.stl Started: 2016-04-08 12:28:12 Progress: 0 of 5 (0.0%) Time To Completion: 00:00:00 Elapsed Time: 00:00:00 Average Slice Time: 0ms Total Cost: $0.00

Status: PausedWithWarning No Line Number with checksum, Last Line: 0

If I repeat the print with a sliced cws file, the printer works the whole process, but shows also only the mask.

An additional behavior: When I stop the printer, the projektor change from a dark to a bright light, without a shutter the whole plattform will be exposed.

Could not upload "logBundle.zip" with drag & drop Get the error: "Something went really wrong, and we can’t process that file. Try again."

??? why some words so big ???

kloknibor commented 8 years ago

You got the logBundle.zip in your possesion right? But github refuses it? Try renaming the .zip to .pdf... that works for me...

kloknibor commented 8 years ago

Oh by the way, when you stop a printer it is normal for the screen to change. The software stops controlling the display. I assume you didn't used the image we provide but rather an clean raspbian install and then installed the dev software, am I correct? If so try it with our image from here : http://s3-us-west-2.amazonaws.com/photonic3d/photonic-image.zip

It is based on an cleaned raspbian jessie light version. When you close the screen the background will stay black only the trash can will be visible on the screen... So some minor curing will still be there but it will bother you much less ;)!

kloknibor commented 8 years ago

Sorry to answer this in all seperate messages :$ Sorry for spamming! But the bigwords might be because you used an "#" (A number sign) or * * somewhere

3dModeller commented 8 years ago

I now renamed the file in "logBundle_zip.pdf" but got the same error, also with [Uploading logBundle.txt…]() "logBundle.txt"

3dModeller commented 8 years ago

shit, again pressed the wrong button, action was faster than brain

WesGilster commented 8 years ago

Thanks for getting the logBundle uploaded, but I probably won't be needing it. Everything seems to be working pretty well.

Status: PausedWithWarning No Line Number with checksum, Last Line: 0

That was a recent addition to the development version to let you know when their is a warning or caution status coming from the printer. The printer wasn't hanging, it was telling you it was paused with a warning. You could unpause it at any time. I'll open a bug so that you can change the printer setup so that it will only pause on errors that you configure.

If I try to print a stl-file, then for the first layer it will only be shown the mask without the slice

That's good news, but I'm not quite sure how you are able to "see" your mask. A printer mask should be varying levels of transparent black. If you are able to see your mask, it probably means you have white in your mask. If you have white in your mask, you are going to end up printing your mask instead of your model. I suppose you could attach your printer mask.png to this issue and I'll see what might be going on.

3dModeller commented 8 years ago

I did made a test mask with which I want to check the correct orientation before I start with the real Print. The test mask therefore has a very dark corner that stands out even in the processed Layer. When I start the print, I only see this test mask in the layer, the very dark corner and the rest white. I have this test mask uploaded. test_mask_rgb

WesGilster commented 8 years ago

Unless you are showing me a composite of your mask applied over a white background, you don't have a usable projector mask. That mask is just going to print white everywhere. I downloaded the png that you uploaded and it doesn't have any transparent pixels in it. The mask will obscure your entire print.

3dModeller commented 8 years ago

Oh, I thought that the mask as in CW works. There I've tested it and worked there as well. I'll adjust the mask accordingly and report back. thank you

WesGilster commented 8 years ago

Wait, so you are saying that you overlay a completely opaque mask over the top of your model in Creation Workshop? Before I make any changes to allow a mask like this, I'd like someone else to confirm this since it doesn't make any sense:

  1. Creation workshop converts the RGB components(percentage of black) of the color model to represent the alpha channel of the PNG?
  2. Creation Workshop then ignores the alpha channel of the PNG mask?
jmkao commented 8 years ago

That's correct. Creation Workshop applies the PNG as a multiply mask in each of the R, G, and B channels. It actually doesn't work well (not exactly through any fault of its own) if there is also an alpha layer. I spent quite a lot of time messing around with this to do mask application outside of CW using ImageMagick a while back, and ended up needing to do:

ls *.png | xargs -i convert ../../../software/proj-mask.png "{}" -compose darken -composite -alpha remove -alpha off PNG24:"../{}"

to duplicate CW's behavior. I had to use darken instead of multiply because imagemagick is too smart about color spaces and does unpredictable things with multiply, especially without the -alpha remove and -alpha off.

Roughly speaking, what is necessary to apply a mask consistently would be an algorithm like the following:

  1. For whatever the mask's input colorspace and bit depth is, convert to RGB and normalize each channel into a float from 0 to 1, where 1 is whatever value represents max intensity in the input bit depth. This is the internal representation of the multiply mask.
  2. For each output image slice, generate (or convert) to RGB and then multiply each pixel of each channel by the matching pixel in the internal (float) representation of the mask.

While I thought this was weird at first, after spending some time with it, I believe this way (CW's way) of doing it is the most reliable.

Step 1 is particularly important because there are all kinds of complicated metadata that PNGs support that are encoded differently by different programs (e.g. Photoshop, GIMP, or ImageMagick), especially if the mask was generated from one format (e.g. perhaps originally a JPEG or TIFF off a digital camera) into another. The layers of conversions can cause various flags to get set that will request the rendering program to treat the alpha channels differently and have unpredictable effects for different image processing libraries that support PNGs to varying extents.

Taking everything down to the lowest common denominator eliminates most of the hidden variation that could be possible in a source image and allows diagnosing problems to mostly be doable visually by looking at the image rather than having to dig up the metadata with tools. The worst case scenario here would be something like "does your PNG have alpha? if so, remove it". Having to ask about other possible PNG metadata would be much more complicated.

WesGilster commented 8 years ago

Thanks for the confirmation @JMKao, that helps quite a bit. The con to their approach is that it works against the definition of the alpha layer for which the png file was built. It's also an ambiguous spec because we aren't able to determine the intent of the mask designer's color space:

  1. Are we to assume that they want us to use max possible color from the color space as the definition of max light intensity? or
  2. Are we to assume that they want us to use the highest used color from the input to determine max intensity(same goes for min I suppose)? (From what you are saying, it looks as if this is how CW implemented it)

With an alpha channel there is no ambiguity, you just apply the mask as it was intended. Once again, I'm not sure why I mention this since it looks like we'll probably end up supporting everything. In the latest dev version you can use CW masks with this:


var sourceImage = javax.imageio.ImageIO.read(new java.io.File("/tmp/uploaddir/gradientfile.png"));
var convertedImage = new java.awt.image.BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), java.awt.image.BufferedImage.TYPE_INT_ARGB);
convertedImage.getGraphics().drawImage(sourceImage, 0, 0, null);
org.area515.resinprinter.printphoto.CWConverter.convertImage(convertedImage, org.area515.resinprinter.printphoto.CWConverter.MaxIntensityDetermination.UseHighAndLowFromImage);
var rect = new java.awt.geom.Rectangle2D.Double(0, 0, sourceImage.getWidth(), sourceImage.getHeight());
new java.awt.TexturePaint(convertedImage, rect)

UseMaxFromColorSpace = option 1 above UseHighAndLowFromImage = option 2 above

Even though we are now compiling Javascript, I decided not to write the convertImage() method in javascript for performance reasons. That means you'll need to bring down the latest version in dev.

Created a test and it seemed to work fine for @3dModeller's mask.

3dModeller commented 8 years ago

I have now installed the latest dev-version. When I start the print, it stops with the message:

Status: Failed java.util.File

WesGilster commented 8 years ago

Sorry about that, wrong package for File. First line should be:

var sourceImage = javax.imageio.ImageIO.read(new java.io.File("/tmp/uploaddir/gradientfile.png"));

WesGilster commented 8 years ago

Just to confirm, I built this with the assumption that your bulb is positioned in the upper right corner. I'd have to inverse this if it's not correct.

3dModeller commented 8 years ago

At the moment it looks very good. I already had a run with a .CWS file without any problems. The processed layer looks like expected. I would like to perform more tests with the printer, with a higher speed to test the performance. Furthermore, I would also like to test more file formats (stl).

WesGilster commented 8 years ago

Great.

If you are gong to use stl files, I would simulate your prints first and be aware of #111. I'm going to get back to addressing that issue next.

3dModeller commented 8 years ago

With the stl files there is a problem, but not the process of the mask but the size of the object. The object is shown too large on the layer. The image of the layer preview has korekte size of 1920x1080 pixels and thereby implementing my projector, but the geometry of the object is about 1.4 times too large in each axis. Could the factor sqrt(2) indicate?

jmkao commented 8 years ago

Did you perform size calibration for your printer?

3dModeller commented 8 years ago

Ok, now the Layer looks well and is processed with the mask. Previously, I had the sense of the calibration not really understood, since I have the Projector Zoom adjusted accordingly. But now it is clear.

WesGilster commented 8 years ago

Feel free to reopen this issue if your problem isn't solved, but from your last comment, I believe everything is working well for you.