Reputation: 2396
Execution time to build a canvas pixel-by-pixel in GWT is extremely slow. For the following code, the 2D for loop with calls to "cpa.set(...)" is very slow.
...
RootPanel.get().add(canvas);
context = canvas.getContext2d();
ImageData id = context.createImageData(canvasWidth, canvasHeight);
CanvasPixelArray cpa = id.getData();
for (int y=0; y<canvasHeight; y++){
for (int x=0; x<canvasWidth; x++){
cpa.set(y*canvasWidth*4 + x*4 + 0,r);
cpa.set(y*canvasWidth*4 + x*4 + 1,g);
cpa.set(y*canvasWidth*4 + x*4 + 2,b);
cpa.set(y*canvasWidth*4 + x*4 + 3,a);
}
}
context.putImageData(id, 0, 0);
For example, with a 100x100 canvas, it takes 10 seconds. I've seen in some other javascript posts here showing that it may be more efficient to use a separate array buffer in the for loop, then just set the ImageData array equal to that buffer, but GWT doesn't seem to allow that with CanvasPixelArray, you can only set a single pixel at a time in GWT, rather than copy an entire pixel array buffer into a CanvasPixelArray or ImageData.
Any ideas for efficient pixel manipulation with GWT canvas?
Thanks.
Upvotes: 1
Views: 1595
Reputation: 1134
Given that you have diagnosed your problem as Running in Devmode, I'll detail some solutions here.
First off, like Strelock commented, DevMode in Firefox is a good deal faster. Personally, I do all of my development in Firefox.
Still, it sounds like Devmode will be unmanagable for you while developing/testing this. Your only option here is to compile. Thankfully, there are some parameters that we can tweak to speed it up, reducing it down to the 20 to 40 second mark assuming you have a project of decent size.
Given a main com/foobar/MyApplication.gwt.xml file like so:
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to="myapplication">
...
</module>
Lets create another, com/foobar/MyApplication-Firefox.gwt.xml:
<?xml version="1.0" encoding="UTF-8"?>
<module rename-to='myapplication'>
<inherits name='com.foobar.MyApplication'/>
<!-- If you want to compile for a different browser, substitute this value. -->
<set-property name="user.agent" value="gecko1_8"/>
</module>
Now when we compile, make sure to use the -draftCompile
parameter. The compiled version may be a little less efficient, but it'll compile down faster. If you are using the default build.xml file, you can add another target like so:
<target name="gwtc-firefox" depends="javac" description="GWT compile to JavaScript (for FireFox)">
<java failonerror="true" fork="true" classname="com.google.gwt.dev.Compiler">
<classpath>
<pathelement location="src"/>
<path refid="project.class.path"/>
<pathelement location="${gwt.path}/validation-api-1.0.0.GA.jar" />
<pathelement location="${gwt.path}/validation-api-1.0.0.GA-sources.jar" />
</classpath>
<jvmarg value="-Xmx256M"/>
<arg line="-war"/>
<arg value="war"/>
<arg line="-draftCompile"/>
<arg value="com.foobar.MyApplication-Firefox"/>
</java>
</target>
Upvotes: 1