JavaScript convert text to pixel coordinates - javascript

In short, given a font (with size, weight, etc.) and a string, is there a way I extract an array of pixel coordinates relative to the top left of the first letter using JavaScript?
E.g. I might become
[
[0,0],
[0,1],
...
]
Edit: I am not looking for the bounding box, rather I am looking for the coordinates of each and every individual pixel that makes up the text. I need this information to essentially recreate the text later using squares.

Yes, you can use the canvas element to obtain text metrics:
// setup canvas
var c = document.createElement("canvas"),
ctx = c.getContext("2d");
// define (pre-loaded) font:
ctx.font = "bold 16px sans-serif";
// get metrics
var m = ctx.measureText("Hello");
The metrics object will give you the width and height etc. But - only width is currently supported in most browsers. There exists a poly-fill that will cover things like ascend and descend which you would need.
An alternative is to scan the bitmap to detect the rectangle the text coverts. I have given an answer here which covers this technique:
Javascript Method to detect area of a PNG that is not transparent
Also, if you only need the bounding box of the text (not pixel-accurate start point of the text itself) you can use a DOM element to get the width and height for that box. Here is one approach for that:
Use Javascript to get Maximum font size in canvas
Updated after clarification: For extracting pixels from the bitmap and convert those into points:
https://stackoverflow.com/a/30204783/1693593

Related

Very simple javascript ocr on black text white background

I have a super simple need of OCR.
My application allows creating image from text. Its very simple. People choose a font face, bold or not, and size.
So they get outputs like this, ignoring the border:
I wanted to create a very simple OCR to read these. I thought of this approach:
In the same way I generate an image for the message. I should generate an image for each character. Then I go through and try to match each character image to the black occourances in the canvas. Is this right approach?
The method I use to draw element to image is this copy paste example here: MDN :: Drawing DOM objects into a canvas
Ok, another couple of tries...
Another method that's simpler than OCR: use Steganography to embed the text message as part of the image itself. Here's a script that uses the alpha channel of an image to store text: http://www.peter-eigenschink.at/projects/steganographyjs/index.html
You can try this "home brewed" OCR solution...but I have doubts about its effectiveness.
Use the clipping form of context.drawImage to draw just the message-text area of your image on the canvas.
Use context.getImageData to grab the pixel information.
Examine each vertical column starting from the left until you find an opaque pixel (this is the left side of the first letter).
Continue examining each vertical column until you find a column with all transparent pixels (this is the right side of the first letter).
Resize a second canvas to exactly contain the discovered letter and drawImage just the first letter to a second canvas.
Set globalCompositeOperation='destination-out' so that any new drawing will erase any existing drawings where the new & old overlap.
fillText the letter "A" on the second canvas.
Use context.getImageData to grab the pixel information on the second canvas.
Count the opaque pixels on the second canvas.
If the opaque pixel count is high, they you probably haven't matched the letter A, so repeat steps 5-9 with the letter B.
If the opaque pixel count is low, then you may have found the letter A.
If the opaque pixel count is medium-low, you may have found the letter A but the 2 A's are not quite aligned. Repeat steps 5-9 but offset the A in step#7 by 1 pixel horizontally or vertically. Continue offsetting the A in 1 pixel offsets and see if the opaque pixel count becomes low.
If step#12 doesn't produce a low pixel count, continue with the letter B,C,etc and repeat steps 5-9.
When you're done discovering the first letter, go back to step#1 and only draw the message-text with an offset that excludes the first letter.
OCR is always complex and often inaccurate.
I hate to wave you off of a solution, but don't use OCR for your purpose
Simple and effective solution...
Put your message in the image's file name.
Solution found - GOCR.js - https://github.com/antimatter15/gocr.js/tree/d820e0651cf819e9649a837d83125724a2c1cc37
download gocr.js
decide if you want to go from WebWorker, or mainthread
worker
In the worker put this code:
importScripts(gocr.js)
GOCR(aImgData)
where aImgData is, take an image, load it, draw it to canvas, then send the data to the webworker. (see mainthread method)
mainthread
<script src="gocr.js">
<script>
var img = new Image()
img.onerror = function() {
console.error('failed')
}
img.onload = function() {
var can = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
can.width = img.width;
can.height = img.height;
var ctx = can.getContext('2d')
ctx.drawImage(img, 0, 0)
// to use this in a worker, do ctx.getImageData(0, 0, img.width, img.height), then transfer the image data to the WebWorker
var text = GOCR(can);
}
</script>

Making rectangular image an irregular shape on a canvas

After searching the web for just over an hour, I have not found any luck.
I am wondering if it is possible, if so how do I create a transparent image on a js canvas not to be considered as a rectangle, rather only the visible area of it.
For example if you click in a transparent spot on the png the script does not considered that part of the object.
Thank you :)
Yes, you can get info about every pixel on the canvas using context.getImageData
A Demo: http://jsfiddle.net/m1erickson/tMmzc/
This code will get an array containing info about every pixel on the canvas:
var data=ctx.getImageData(0,0,canvas.width,canvas.height).data;
The data array is organized with 4 sequential element representing the red,green,blue & alpha(opacity) information about one pixel.
The data array's elements #0-3 have the top-left pixel's r,g,b,a info.
The data array's elements #4-7 have the next rightward pixel's r,g,b,a info.
...and so on...
Therefore, given the mouse position on the canvas you can fetch that pixel's alpha info. If the alpha value is zero then that pixel is transparent.
This code will read the alpha value under the mouse and determine if it's transparent:
var isTransparent = data[(mouseY*canvas.width+mouseX)*4+3]>0;

Resizing canvas with its text content

I have one canvas with some text and i want to re-size it in all directions but problem is that text content inside that canvas is getting blurred if i make it re-sizable by using css properties.
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.font = "30px Arial";
ctx.fillText("Hello World",10,50);
I have tried jquery re-sizable with container to canvas and resize canvas by using css but getting text content's height/width problem and also text is getting blurred.
can anyone help me please..
Yes, text has many small & tight curves whose flaws quickly become visible if you try to resize the original text. Therefore, resizing text-especially resizing larger, will always result in the texts natural "jaggies" and anti-aliasing artifacts becoming more visible.
The usual approach to canvas is to treat everything on the canvas as redrawable. Using that approach, you could clear the canvas and redraw the text using an appropriately resized font.
If your text will always appear topmost on your canvas drawings, an alternative would be to place an SVG element on top of your canvas. SVG text scales well because it is vector based, rather than pixel based. You could use the svg translate+scale to position & resize the svg text according to your scale factor. Here's a link showing how it's done: http://msdn.microsoft.com/en-us/library/gg589508(v=vs.85).aspx

How can I determine accurate height of Raphael text()?

Using Raphael JS 2.1.2, the following code:
var distance = 250;
var sizes = [ 14, 18, 24, 48, 72, 96 ];
for(var i = 0; i < sizes.length; i++)
{
var size = sizes[i];
var text = me.paper.text(distance + (size * 5), me.top + 200, size).attr({ 'font-size': size });
var rect = text.getBBox();
text.paper.rect(rect.x, rect.y, rect.width, rect.height).attr({ stroke: '#FF0000' });
}
produces this output:
How can I accurately measure the height of the text, as you can see the bounding box includes vertical padding which is relative to the font size?
Also $(text.node).height() returns the same value as rect.height. I am trying to align the top and/or bottom of text with other elements so I need some way to determine the padding or text height per font-size.
I could maintain a collection of { size: [font size], padding: [padding] }, but it would be good if I could generate this at runtime.
You can't. Actually this is not a "padding". getBBox returns dimentions given from a font metric, not individual glyphs. BBox height for text element includes font ascent and descent.
In most fonts, ascent reserves a gap above cap-height for glyphs such as "Ä". Discenders are reserved for lowercase characters with "tails" such as "g", "j", "q" and etc. For example, draw a rect around text "Äg".
For more detais see:
http://commons.oreilly.com/wiki/index.php/SVG_Essentials/Text
http://www.w3.org/TR/SVG11/text.html#BaselineAlignmentProperties
http://en.wikipedia.org/wiki/Baseline_(typography)
It's possible but it's messy. You can do this by using OpenType.js, then drawing a path using same text/size as Raphael with OpenType getPath and measuring the path. You can measure the outputted path with Raphael.pathBBox(path.toPathData()) or (preferable as its faster though more limited browser support) with creating a temp SVG as outlined here.
The size of the path will be the exact size of your text as you desired.
Along the same lines you may also encounter a position challenge i.e. trying to determine how the svg box fits over the raphael box. You can use the ascender/descender values provided by the font object returned from OpenType load alongside with the y/y2 values of your SVG path. All of these will allow you to figure out the baseline of OpenType text and you can match this to your Raphael box.

Which algorithm to use for finding out whether a coordinate is in a specific area?

I want to know whether a point is in the "black" area of some image like the one below.
For the time being I created a large array like this (generated outside JavaScript):
area = [ [0,200], [0,201], [0,202], ..., [1,199], [1,200], ...]
to indicate which coordinates are black. Since this is getting very memory heavy for larger areas (I'm talking of image sizes of about 2000x2000 pixels), which kind of algorithm would you choose that is fast and not too memory hungry for finding out whether a specific coordinate is inside the black area?
You can draw the image to a canvas with same width and height as the image and then retrieve the pixelColor from the canvas at the specific point(x|y).
Here is a thread on how to retrieve the pixcel color:
Get pixel color from an image
This is how i retrieve the pixel color from the mouseposition and return a colorcode('#rrggbb'):
var pixelData = canvas.getContext('2d').getImageData(event.offsetX, event.offsetY, 1, 1).data;
var hex= '#' + valToHex(pixelData[0]) + valToHex(pixelData[1]) + valToHex(pixelData[2]);

Categories

Resources