Converting image to imagedata and vice versa without drawing to canvas - javascript

I'm wondering if there's a way to convert images to imagedata and vice versa without drawing to canvas.
I know the methods getImageData() and toDataURL() can be used to copy the canvas but what if I'd prefer to take an imc.src path and convert that directly to imagedata. Or convert imagedata directly to a DataURL without passing it to canvas.

I think the answer to this question is no. If you check out the docs for ImageData, you'll see that it's tied quite directly to the canvas element and all it's properties are read-only. In addition, if you pop into the console and try new ImageData, you'll see that it's not allowed for you to construct one from scratch yourself, and that the function contents are native code.
If someone finds a way to do this, I'd be very impressed -- you never know what you don't know. But since the spec specifically says it shouldn't be possible and clearly efforts have been made to prevent it from happening, I'd say it's probably not a good bet either way.
Perhaps there's another workaround for the issue you are facing. If you re-word your question to include a more broad view of your problem, some of us might be able to suggest possible alternate solutions, as you are starting to see in the first comment.

Related

Drawing and writing on image and save it

I have images hosted on the server, and I would like develop some functionality to let the user have possibility to draw over the picture.
They need to write some text too, and, finally save the result as picture.
Finally, its a simple editor, but I don't find JavaScript library who permit it...
You can see an example of final result I need here : https://nsa40.casimages.com/img/2019/08/29/190829023122267348.jpg
You can achieve this with the Canvas API pretty easily.
Your images can be pulled into the canvas by creating a new Image object. The canvas API itself has a lot of methods for doing the things shown on the image (drawing shapes like ellipses and rasterising text).
Finally a canvas can be saved into a png using the toDataURL method.
I am sure if you dig around the internet, you will find there are already some libraries for these sorts of things. Possibly some keywords to try would be "image editing library JS" or something of that sort. Developing the functionality on your own should be ok if you follow some examples online for how to do each individual bit. Hope this helps :)

Dynamic pattern in javascript

I am curious as to where to start to make something similar to HERE as I cannot find any information about it. It may be fairly simple and im sorry if it is.
What I am hoping to replicate is the colour grid that generates based on the colours and size of the lines. I am looking to replicate the functionality of the application whereby when the user selects a line and changes the width of that line and it will then calculate the image. I have been looking around but cannot find information about how to replicate it. I may be searching for the wrong thing as javascript is not my strongest language.
I know of a roundabout way to do it with svg but where would I start for javascript/jquery?
I know of a way to do it with svg but where would I start for javascript/jquery?
Well, SVG would involve javascript as well, wouldn't it? You're just looking for different ways to display an image. None is native the javascript, that is just a programming language, you'd have to consider which API to use:
There's nothing wrong with SVG! It even seems to be the easiest solution, maybe wrapping DOM code in some nice drawing library.
It has been demonstrated that such is possible with CSS3 background patterns, although I would consider this rather unusable
Use the <canvas> element! This would be the most genuine HTML5 approach, and even though the api is rather simple there exist mighty libraries.

Web worker and scaling images

I need to scale images in array form in a Web Worker. If I was outside a web worker I could use a canvas and drawImage to copy certain parts of an image or scale it.
Look like in a web worker I can't use a canvas so, what can I do? Is there any pure Javascript library that can help me?
Thanks a lot in advance.
Scaling can be done in various ways, but they all boil down to either removing or creating pixels from the image. Since images are essentially matrices (resized as arrays) of pixel values, you can look at scaling up images as enlarging that array and filling in the blanks and scaling down images as shrinking the array by leaving values out.
That being said, it is typically not that difficult to write your own scale function in JavaScript that works on arrays. Since I understand that you already have the images in the form of a JavaScript array, you can pass that array in a message to the Web Worker, scale it your scale function and send the scaled array back to the main thread.
In terms of representation I would advise you to use the Uint8ClampedArray which was designed for RGBA (color, with alpha channel) encoded images and is more efficient than normal JavaScript arrays. You can also easily send Uint8ClampedArray objects in messages to your Web Worker, so that won't be a problem. Another benefit is that a Uint8ClampedArray is used in the ImageData datatype (after replacing CanvasPixelArray) of the Canvas API. This means that it quite easy to draw your scaled image back on a Canvas (if that was what you wanted), simply by getting the current ImageData of the canvas' 2D context using ctx.getImageData() and changing its data attribute to your scaled Uint8ClampedArray object.
By the way, if you don't have your images as arrays yet you can use the same method. First draw the image on the canvas and then use the data attribute of the current ImageData object to retrieve the image in a Uint8ClampedArray.
Regarding scaling methods to upscale an image, there are basically two components that you need to implement. The first one is to divide the known pixels (i.e. the pixels from the image you are scaling) over the larger new array that you have created. An obvious way is to evenly divide all the pixels over the space. For example, if you are making the width of an image twice as wide, you want simply skip a position after each pixel leaving blanks in between.
The second component is then to fill in those blanks, which can be slightly less straightforward. However, there are several that are fairly easy. (On the other hand, if you have some knowledge of Computer Vision or Image Processing you might want to look at some more advanced methods.) An easy and somewhat obvious method is to interpolate each unknown pixel position using its nearest neighbor (i.e. the closest pixel value that is known) by duplicate the known pixel's color. This does typically result in the effect of bigger pixels (larger blocks of the same color) when you scale the images too much. Instead of duplicating the color of the closest pixel, you can also take the average of several known pixels that are nearby. Possibly even combined with weights were you make closer pixels count more in the average than pixels that are farther away. Other methods include blurring the image using Gaussians. If you want to find out what method is the best for your application, look at some pages about image interpolation. Of course, remember that scaling up always means filling in stuff that isn't really there. Which will always look bad if you do it too much.
As far as scaling down is concerned, one typically just removes pixels by transferring only a selection of pixels from the current array to the smaller array. For example if you would want to make the with of an image twice as small, you roughly iterate through the current array with steps of 2 (This depends a bit on the dimensions of the image, even or odd, and the representation that you are using). There are methods that do this even better by removing those pixels that could be missed the most. But I don't know enough about them.
By the way, all of this is practically unrelated to web workers. You would do it in exactly the same way if you wanted to scale images in JavaScript on the main thread. Or in any other language for that matter. Web Workers are however a very nice way to do these calculations on a separate thread instead of on the UI thread, which means that the website itself does not seem unresponsive. However, like you said, everything that involves the canvas element needs to be done on the main thread, but scaling arrays can be done anywhere.
Also, I'm sure there are JavaScript libraries that can do this for you and depending on their methods you can also load them in your Web Worker using importScripts. But I would say that in this case it might just be easier and a lot more fun to try to write it yourself and make it tailor-made for your purpose.
And depending on how advanced your programming skills are and the speed at which you need to scale you can always try to do this on the GPU instead of on the CPU using WebGL. But that does seem a slight overkill in this case. Also, you can try to chop your image in several pieces and try to scale the separate parts on several Web Workers making it multi-threaded. Although it is certainly not trivial to combine the parts later. Perhaps multi-threaded makes more sense when you have a lot of images that need to be scaled on the client side.
It all really depends on your application, the images and your own skills and desires.
Anyway, I hope that roughly answers your question.
I feel some specifics on mslatour's answer are needed, since I just spent 6 hours trying to figure out how to "…simply… change its data attribute to your scaled Uint8ClampedArray object". To do this:
① Send your array back from the web-worker. Use the form:
self.postMessage(bufferToReturn, [bufferToReturn]);
to pass your buffer to and from the web worker without making a copy of it, if you don't want to. (It's faster this way.) (There is some MDN documentation, but I can't link to it as I'm out of rep. Sorry.) Anyway, you can also put the first bufferToReturn inside lists or maps, like this:
self.postMessage({buffer:bufferToReturn, width:500, height:500}, [bufferToReturn]);
You use something like
webWorker.addEventListener('message', function(event) {your code here})
to listen for a posted message. (In this case, the events being posted are from the web worker and the event doing the listening is in your normal JS code. It works the same other way, just switch the 'self' and 'webWorker' variables around.)
② In your browser-side Javascript (as opposed to worker-side), you can use imageData.data.set() to "simply" change the data attribute and put it back in the canvas.
var imageData = context2d.createImageData(width, height);
imageData.data.set(new Uint8ClampedArray(bufferToReturn));
context2d.putImageData(imageData, x_offset, y_offset);
I would like to thank hacks.mozilla.org for alerting me to the existence of the data.set() method.
p.s. I don't know of any libraries to help with this… yet. Sorry.
I have yet to test it out myself, but there is a pure JS library that might be of use here:
https://github.com/taisel/JS-Image-Resizer

box2d-js element with external image

So far in the samples of varies box2d js implementation I can find only element defined in shapes (ball/box/etc), is there a way to create an element defined by an image, e.g. a boulder?
You can use the b2PolyDef and b2PolyShape objects to create polygons.
This documentation is meant for AS3 but it is relatively simple to figure out the JavaScript equivalent.
If you wanted to automate the mapping from an image's bounding box to the polygon, you could use canvas and getImageData() to seek through the pixels looking for non transparent (assuming your image has a transparent background). This is probably more effort than it is worth though.
Also see Understanding custom polygons in Box2D.
I was trying to solve a same kind of problem when i came across this brilliant answer. Hope this will help you.

current transform being applied by canvas

How can I determine the current transform that's being applied by an html5 canvas.
It seems that it only supports two methods for dealing with transforms "transform", "setTransform" but I can't seem to discover the results of applying the transforms.
Short of tracking them all myself and duplicating the the matrix mathematics that it must be doing natively, how can I figure out the current transform?
I've made a wrapper which adds this method to Canvas.
http://proceduralgraphics.blogspot.com/2010/03/canvas-wrapper-with-gettransform.html
Firefox's Canvas 2D contexts have (non-standard) mozCurrentTransform and mozCurrentTransformInverse properties.
The WhatWG have now defined currentTransform and currentTransformInverse properties (the former even being writable). Here's the relevant part of the spec:
http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#transformations
However these probably won't be universally implemented in browsers for some time yet, so if you want portability you will have to fall back to tracking the matrix manually as #Dave and #James say.
Every man and his dog seems to have written such a Canvas-transform-matrix-tracker. I just had a look at #Dave Lawrence's one; I think mine is better in a few ways, even though I'm sure it's also inferior in other ways.
Mine doesn't require any changes to user JS code - it modifies the Canvas and context prototypes, so you just add a
script
tag and you're good to go.
It intercepts setting of the currentTransform property.
It tries hard only to do what it needs to do.
It works in latest Chrome and Firefox, but I haven't tested it in IE yet.
I put mine in a jsfiddle, with a simple demonstration:
http://jsfiddle.net/XmYqL/1/
Here is a code block to placate stackoverflow so it lets me link to jsfiddle (??):
code, code, wonderful code
I finally got around to uploading my polyfill to GitHub:
https://github.com/supermattydomain/canvas.currentTransform.js
I know it's not perfect, but I'd really like to see us all work together on implementing One True Solution to this problem. I don't care if it's mine or someone else's. This corner of JavaScript/HTML5/Canvas is too much like the Balkans: a sea of partial solutions.
Please, everybody, fork mine, add your changes and send me pull requests, or send me your URL so I can merge your code in, or replace mine wholesale with yours, or whatever.
This is a stupid problem that I just want to nail. If we work together we can do it.
You can look here for the functions that affect transformation:
http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#transformations
If you use the setTransform function, then the current transform matrix is set to the identity matrix, then it uses what was set.
At that point you have the current transform matrix.
Now, if you are going to reset it, then start to call the other transformation methods, if you need to know what it is, it is easy to do the math to calculate the transformation matrix, so just do the operations, using your own transformation functions, then you can set the transform, as you have calculated it.
If you can't do that, then you are currently out of luck, but this post also has the same problem, so you may want to petition to have a new function added, getTransform.
http://forums.whatwg.org/viewtopic.php?t=4164
Although not a solution for how to get the current transform, it may be an useful fact that contexts include a save() and a restore() function that can be used to push and pop context state, including the current transformation matrix.
(At least it may benefit those, who, similarly to me, were looking for getTransform in order to implement a stack using it...)

Categories