Modulate colors with drawImage on HTML5 canvas - javascript

I'm playing around with the idea of modifying my game development IDE to produce HTML5 versions of the games created with it. One of the features of the IDE is the ability to define frames, which not only define how a graphics cell is transformed (rotated, stretched, etc), but also how it is colored when it is drawn. So if I wanted green hills and brown hills and uphills and downhills, I would only need 1 graphic defined for all of those, simply transformed and colored differently.
I can see how an HTML5 canvas context will allow me to transform drawImage results, but I don't see a practical way to modulate the colors. I want to be able to say, for example, R=255, G=255, B=0, A=127 and have none of the blue channel come through (a yellow-tinted version of the graphic) drawn at 50% translucency (keeping in mind that portions of the graphic cell may already be translucent or transparent).
Is this possible? Or will I need to getImageData and manipulate the pixels and cache manipulated copies? If I need to cache manipulated copies, what's the best JavaScript data structure to accomplish this? I think I'd want some kind of dictionary where the key is an image index and an RGBA composed as a single value somehow. Look-ups would have to be very fast because it would potentially be done for a majority of the tiles being drawn.

Sadly I don't think you can do it without the help of getImageData.
Here's an example of tinting an image using getImageData:
http://jsfiddle.net/3eUBk/2/
It was something I made to answer this question, which has an explanation of everything thats going on: How can I use a gradient map to tone a HTML5 canvas with an image in the canvas.
Let me know if you need more information.

Related

Is it possible in JavaScript to create a div, put a \u#### character in that div, then copy to canvas as a putImage?

I am working with fTelnet.js - I have gotten down to the this_Font.GetChar() code and have found all characters are from a Font Sprite, it getItemData(....) changes the color where The pixel is 0x80 and colors it foreground [r][g][b][alpha], or colors it background [r][g][b][alpha].
Since Unicode goes outside what is in its 40+ fonts - I need to cheat and .createElement("div"), .innerHTML = "\u#####"; then somehow take that as ImageData so I can patch the above logic and introduce unicode support to fTelnet's canvas routine.
Does anyone know what command(s) I am needed to do this? e.g. I have spent hours trying to resolve this via Google, HTML5 Context docs, without success... mainly not knowing what I am searching for ;-)
or as I re-read this... maybe a hidden canvas, do the ctx.strokeText("\u#####", 25, 50); and then copy from that CTX as a IMAGEDATA to the displayed? (what command would I look up then?)... I normally do not dabble in 2D/3D graphics world (obviously)...
Regards,
Generally, rendering HTML to canvas is not possible - and that seems to be by design (it would make issues like tainting much harder to navigate).
But stamping one canvas on top of another is simple - you can just use the standard #drawImage call, same as with any other image you would draw on canvas.
Actually, if you look at the API documentation and click through the definitions you will see that you can use drawImage to "stamp" any instance of svg or html image, a bitmap, offscreen canvas, video or audio tags.

Is there a way to change tint of selected pixels in a Sprite?

Hello dear StackOverflow's community!
This is my very first question on the site, so I hope I'll be clear enough. Also, I am a French guy and I apologize in advance for the language mistakes!
Let me explain my situation (I like to be precise so it will be a bit long) :
I am currently doing an internship in my University. Here's the topic : my teacher made a 2D serious game based on image processing, where each player (4 maximum) must replace the right colors on each part of an animal. She used the XNA framework of Visual Studio to do it.
My task is to develop a new version of this game using Javascript technologies, particularly Pixi.js.
The game works like this : the main Container of the application is separated in 4 areas, one per player ; each of these areas sets its background using a Sprite that I create from the grey-scaled image of the animal the player chosed. At the center of the screen is a color palette represented by an array of Sprites. From this I can drag n' drop a color to the animal Sprite, and the region that represents a part of its body detects the drop. Everything works fine until here, but this is the point where I encounter difficulties.
I would like to change the tint of only the pixels corresponding to this region. The positions of these pixels are registered in an array I create from a text file, that's how I can detect which region receives the color.
I already tried to use a Graphics object from Pixi to redraw the color above the Sprite, but it is extremely slow. I also tried to use Filter, but since I want to color only some pixels and not the entire Sprite, I need to pass (using uniforms) the array of positions to my WebGL shader to make it verify for each pixel if it is part of the ones I want to change. But the shader needs me to declare this array indicating its size. I cannot do that because every region has a different number of pixels.
I am blocked now, and I don't know how to perform what I want...
Is there any solution that does not imply separating my image in several Sprites? I think it would work but if there can be another way, allowing me to avoid this, I would be very thankful!
Thanks in advance, and sorry that this message is so long!

Antialiasing text on canvas

I have to create .pngs for a lot of clients that are printed by an industrial inkjet (ads on back of a children's magazines).
Unfortunately, all browsers seem to switch on antialiasing - no matter what I try. Neither CSS nor ctx.mozImageSmoothingEnabled=false; seem to work.
Does anyone have any idea to get text displayed on canvas WITHOUT any grey-scaled pixels trying to make the font sharper?
The canvas will anti-alias everything drawn to it, with the exception of images when imageSmoothingEnabled is set to false (and then only for resampling purposes).
There are various options though -
SVG
Using SVG would be ideal as it is vectors and can be easily converted to postscript. If the printer supports postscript it will rasterize the vectors into the optimal raster-mask and make sharp edges.
Large bitmap
You can reduce the effect of anti-aliasing by using a very large bitmap, but from my own experience, and probably yours as well, it won't eliminate the gray points.
There is also the risk of meeting the limitation of canvas element itself which in some browsers is limited to 6k. Depending on the printer's DPI this may or may not be enough.
A combination of a large bitmap and threshold (see below) can perhaps get you around this though.
The Deep Dive implementation
Another way, but more advanced, to get around this is to load the font manually and draw the paths of it using Bresenham or similar algorithm. An additional aspect is that you would need to use polygon fill-algorithms as well (ie. even-odd or non-zero winding).
All this is doable without too much effort:
To load fonts and get the path data you can use f.ex. opentype.js
Use Bresenham or EFLA for rendering vectors to lines (if needed)
Use a polygon fill algorithm even-odd or non-zero winding to fill the polygons (you may get away with normal canvas fill if you can cover the edges with the Bresenham/EFLA lines).
As you are in print industry Open-Type may not be sufficient as Adobe fonts are more common from the typical repository. You can probably get the path data via other means or find the equivalent in an Open Type version or even a SVG font type.
Threshold
Another approach is to quantize the gray-levels. You can iterate over the bitmap and use a threshold value to set the pixel either transparent or solid color.
The result may not be so good as you will end up with some sharp transitions around some edges. You may however be able to reduce these artifacts depending on the print-resolution as well as the chosen threshold value.

Rendering on html5 canvas takes cosumes too much time, buffering barely helps

For a game, I'm trying to calculate light and shadows. For this, I break down my canvas into square areas and calculate, if a light ray would be blocked on the way from the player to each square position. I've managed now to reach a reasonably good performance for those calculations.
The results are then visualized by covering non-visible areas with dark squares (Canvas.fillRect(...)), but this step becomes too expensive when a want a nice resolution, i.e. ~10'000 squares for calculation. I've tried to first render them into an off-screen canvas (=buffer), then draw the buffer on my visible canvas, but I could not experience any remarkable performance improvement.
Is there something I missed, or are there other methods to fasten up drawing?
Update:
The affected code can be found here: https://github.com/otruffer/Ape_On_Tape/blob/master/src/client/js/visibility.js (Code is a bit too big to post here)
The actual drawing takes place in drawCloudAt(...) and flushBuffer() in the lower part of this file.
Doing real-time light calculation in software is always a performance killer. Did you consider using a real 3d engine instead which does the light calculation on the video card? Yes, Javascript can do that now - this new feature is called WebGL.
When you just need a faster way to apply your lightmap, you could manipulate the RGB values of your canvas directly instead of using fillRect. You can use getImageData to get an array of raw 8 bit RGBA values of your canvas. You can then manipulate this array and put it back with putImageData.

Remove background color from image in HTML5 Canvas

I'm trying to strip the background out of a photo image loaded into a HTML5 Canvas. Think of something like a green screen effect.
I'm using HTML/JS/jQuery
The background of the photo will be, for example, a green curtain. The color wont be exact across the curtain because of lighting and such like.
What i'm doing right now is grabbing the RGB value of a pixel that the user clicks on within the Canvas. That's then considered to be the background. I add the R+G+B of that pixel to set what is considered as the background.
I'm then going through the canvas, pixel by pixel, checking if the pixel is close to the RGB value set as the background (say within 50 above or below). If it matches, I change the pixel to be transparent within the canvas.
This works well enough as a proof of concept but not well enough to do anything with.
Does anyone have any better ideas on background subtraction?
Cheers!
Have a look at the GrabCut algorithm or GrowCut algorithm; the former describing 'Foreground Extraction using Iterated Graph Cuts' and the latter, 'Image Segmentation By Cellular Automata'. Both those papers will give you a deeper insight into some of the older algorithms used to remove background image data. If you could somehow implement one of those algorithms in Javascript then I think you're most of the way there.
The OPENcv computer vision library (written in c/c++) has plenty of efficient image manipulation methods to examine. You could try and port one of the OPENcv library's BackgroundSubtractor methods (which I believe is partly based on Chris Stauļ¬€er and W.E.L Grimson's algorithm) to Javascript and then use that to analyse the background and therefore subtract it, but I think they are based on progressive video frames rather than static images.
The js-aruco project on Google code has ported some of the functionality of the OPENcv library already (codebase is here) so you might want to look there first for some inspiration and then, if you're feeling brave, have a look at how you could program the GrabCut or GrowCut algorithms

Categories