Programmatically generate a composite portrait mosaic - javascript

I need to create composite portrait mosaics (i.e. portraits made out of other portraits). See reference below.
Another good reference would be AndreaMosaic.
http://www.andreaplanet.com/andreamosaic/samples/
Or this youtube tutorial (skip to the 5min mark)
https://www.youtube.com/watch?v=9cy2gVm_ztQ
Looking for the best way to do this then generate a jpeg file that's ready to download.
Ideally would like to do this with Node/Javascript but open to using PHP or whatever.
Any suggestions as to where to start? There are a few libraries here and there but nothing quite suited to what I'm trying to do.

The faked mosaic is simple. Well I tried a simple multiplication and looks like ti works.
create a photo texture pattern covering the size of input image
modulate the grayscale photo pattern and original image
simple multiplication will do.
Both steps can be combined into single one... here simple C++ code for this:
// globals
const int txrs=41; // number of textures for mosaic
picture txr[txrs]; // mosaic textures
picture pic0,pic1; // input and output images
// init
pic0.load("MonaLisa.jpg");
int sz=32; // mosaic grid size
for (int i=0;i<txrs;i++) // load/resize/grayscale textures
{
txr[i].load(AnsiString().sprintf("textures\\%03i.jpg",i)); // load image
txr[i].resize_fit(sz,sz,0x00000000); // resize to tile size
txr[i].enhance_range();
txr[i].pixel_format(_pf_u); // convert to grayscale <0,765>
txr[i].pixel_format(_pf_rgba); // convert to grayscale RGBA
}
pic0.resize_fit((pic0.xs/sz)*sz,(pic0.ys/sz)*sz,0x00000000); // cut not full tile size part of pic1
// mosaic
int xx,yy,x,y,i,j,sz=txr[0].xs,a,b;
color c0,c1;
pic1=pic0; // copy source image to destination
// process all regions
for (y=0;y<pic1.ys;y+=sz)
for (x=0;x<pic1.xs;x+=sz)
{
// select random texture
i=Random(txrs);
// proces region
for (yy=0;yy<sz;yy++)
for (xx=0;xx<sz;xx++)
{
// grayscale texture and original color image pixels
c0=txr[i].p[yy][xx];
c1=pic1.p[y+yy][x+xx];
// mutiply them
for (j=0;j<3;j++)
{
a=BYTE(c0.db[j]);
b=BYTE(c1.db[j]);
a=(a*b)>>8;
c0.db[j]=a;
}
// store to destinatio image
pic1.p[y+yy][x+xx]=c0;
}
}
pic1.save("out.png");
I use my own picture class for images so some members are:
xs,ys is size of image in pixels
p[y][x].dd is pixel at (x,y) position as 32 bit integer type
clear(color) clears entire image with color
resize(xs,ys) resizes image to new resolution
bmp is VCL encapsulated GDI Bitmap with Canvas access
pf holds actual pixel format of the image:
enum _pixel_format_enum
{
_pf_none=0, // undefined
_pf_rgba, // 32 bit RGBA
_pf_s, // 32 bit signed int
_pf_u, // 32 bit unsigned int
_pf_ss, // 2x16 bit signed int
_pf_uu, // 2x16 bit unsigned int
_pixel_format_enum_end
};
color and pixels are encoded like this:
union color
{
DWORD dd; WORD dw[2]; byte db[4];
int i; short int ii[2];
color(){}; color(color& a){ *this=a; }; ~color(){}; color* operator = (const color *a) { dd=a->dd; return this; }; /*color* operator = (const color &a) { ...copy... return this; };*/
};
The bands are:
enum{
_x=0, // dw
_y=1,
_b=0, // db
_g=1,
_r=2,
_a=3,
_v=0, // db
_s=1,
_h=2,
};
The input image I used was this:
And here the result:
It might need some brightness tweaking to match original input image properties.

Related

Mapping ArrayBuffer bytes to corresponding Pixels Positions in Canvas

I have an ArrayBuffer (representing a PNG/JPG) and I want to create a dictionary so I know for each group of bytes what pixels and at what positions were generated on a canvas. The function that I need would look something like this:
getPixelsCoordinatesForBytes(arrayBuffer, bufferStart, bufferEnd){
// crate Image on Canvas from buffer,
// get location in canvas image for
// the pixels that were generated using the bytes beetween bufferStart and bufferEnd
return x,y, img.width, img.height
}
Basically, I need to reverse engineer the getImageData from Canvas context, tried looking into how V8 implements it but the code is a mess. From what I understand each file type is converted to ImageData based on some standard algorithm (also known as bitmaps/raster graphs). I was not able to find how this algorithm is working in javascript.
A solution in any programming language provided to this problem would also be useful as I may be able to rewrite it in Javascript.

How to easily import OpenCV.js into a .js file?

I implemented a CNN that I use on a web application via Tensorflow.js.
I need to preprocess my webcam photos to be accepted by my CNN model. So I want to use OpenCV.js in my .js file but I can't figure out how to simply import this library into my .js file where I turn my canvasElement into a tensor using the tf.browser.fromPixels() function of Tensorflow.js.
The tutorials I see show the use of OpenCV.js in the .html file directly inside a <script>, whereas I would like to use it in my javascript file.
I would especially like to use the method cv.cvtColor(). If not, do you have another solution to convert my canvasElement to grayscale?
The script tag will import OpenCV into the webpage (be sure to load this before you load your code that needs to use it - order matters in HTML). You should then be able to access the OpenCV class / object to call its functions with your canvas data to do your pre processing, and then write that back out and convert to tensor in TF.js land.
If you want to quickly convert canvas to greyscale there are many ways to do this - eg how you average the colours etc will effect the greyscale image you get out.
Here is one method: http://www.vapidspace.com/coding/2012/02/26/converting-images-to-grayscale-using-the-canvas/
Here is the code from that site in case it gets removed:
function grayscale (input,output) {
//Get the context for the loaded image
var inputContext = input.getContext("2d");
//get the image data;
var imageData = inputContext.getImageData(0, 0, input.width, input.height);
//Get the CanvasPixelArray
var data = imageData.data;
//Get length of all pixels in image each pixel made up of 4 elements for each pixel, one for Red, Green, Blue and Alpha
var arraylength = input.width * input.height * 4;
//Go through each pixel from bottom right to top left and alter to its gray equiv
//Common formula for converting to grayscale.
//gray = 0.3*R + 0.59*G + 0.11*B
for (var i=arraylength-1; i>0;i-=4)
{
//R= i-3, G = i-2 and B = i-1
//Get our gray shade using the formula
var gray = 0.3 * data[i-3] + 0.59 * data[i-2] + 0.11 * data[i-1];
//Set our 3 RGB channels to the computed gray.
data[i-3] = gray;
data[i-2] = gray;
data[i-1] = gray;
}
//get the output context
var outputContext = output.getContext("2d");
//Display the output image
outputContext.putImageData(imageData, 0, 0);
}
Notice here how they use a formula to calc gray. Depending on your needs you may want to use different ratios of the RGB mix to get the grayscale image.
Personally I would strongly recommend using vanilla JS here as it's very easy to do and you dont need to include OpenCV just to do grayscale which is a massive overhead to include that file for such a task. If you are using some of the more advanced features of OpenCV too then maybe that is a reason to then use it.

display .raw file image in browser

I have a image file in .raw format which is directly read from fingerprint scanner device. We have to display that in a browser using html and javascript. How can we convert the .raw image and display in the browser?
Following is the manual steps I used to convert using online tools
I am able to convert that hex content as .raw file using online converter http://tomeko.net/online_tools/hex_to_file.php?lang=en
and converted raw file can be converted again as jpeg file by https://www.iloveimg.com/convert-to-jpg/raw-to-jpg url
Sample file will look like this https://imgur.com/a/4snUAFL
I tried the following code to display hex content in the browser but didnt work.
function hexToBase64(str) {
return btoa(String.fromCharCode.apply(null, str.replace(/\r|\n/g, "").replace(/([\da-fA-F]{2}) ?/g, "0x$1 ").replace(/ +$/, "").split(" ")));
}
var img = new Image();
img.src = "data:image/jpeg;base64,"+hexToBase64(getBinary());
document.body.appendChild(img);
complete jsfiddle is http://jsfiddle.net/varghees/79NnG/1334/
First, what you have provided in your fiddle is probably not a .raw file.
While there are tons of different file formats using this extension, I don't quite bite the fact there is no metadata at all, since this is required to at least know the image's size.
So I'm sorry for future readers, but this answer only shows how to convert raw 8bit values into an actual image...
So now, without image size, but if the image is squared, we can actually do it from the byteLength only, (both width and height will be the square-root of the byteLength).
The general steps are
(convert your hex string to an actual Uint8Array)
set all 4th values of an Uint8ClampedArray 4 times bigger than the first Uint8Array (this will set the Alpha channel of our soon to be RGBA image)
pass this Uint8ClampedArray in the ImageData() constructor.
put this ImageData on a canvas
Tadaa!
So using a square full of random values (and thus avoid the hex to buffer conversion):
const fake = new Uint8Array( 256*256 );
crypto.getRandomValues(fake); // get random values
processSquareBitmap(fake.buffer);
function processSquareBitmap(buffer) {
const view = new Uint8Array(buffer);
const out = new Uint8ClampedArray(buffer.byteLength * 4);
const size = Math.sqrt(view.length);
if(size % 1) {
console.error('not a square');
return;
}
// set alpha channel
view.forEach((a,i)=>out[(i*4)+3] = a);
const image = new ImageData(out, size, size)
const canvas = document.createElement('canvas');
canvas.width = canvas.height = size;
canvas.getContext('2d').putImageData(image, 0,0);
// if you want to save a png version
// canvas.toBlob(b=> saveAs(b, 'bitmap.png'));
document.body.appendChild(canvas);
}
But for not squared images, you must have the actual width and height.
I was able to deduce the ones of OP's hex data, and thus could make this fiddle which will display their image.

Save canvas to image using C# and jQuery

I'm trying to correctly save part of image which is highlighted with jcrop to a circle image.
I have canvas element which previews the selected area and how the image will look like, please check the screenshot below:
I also have hidden field which saves the value (example: "data:image/png;base64") which is displayed in the canvas.
I'm able to save image from the hidden field value with this code:
if (hfImageData.Value != string.Empty)
{
string value = hfImageData.Value;
if (value.Contains("jpeg"))
{
value = value.Replace("data:image/jpeg;base64,", "");
}
else if(value.Contains("png"))
{
value = value.Replace("data:image/png;base64,", "");
}
string path = Server.MapPath("/cropimages/");
string fileNameWitPath = path + DateTime.Now.ToString().Replace("/", "-").Replace(" ", "- ").Replace(":", "") + ".png";
using (FileStream fs = new FileStream(fileNameWitPath, FileMode.Create))
{
using (BinaryWriter bw = new BinaryWriter(fs))
{
byte[] data = Convert.FromBase64String(value);
bw.Write(data);
bw.Close();
}
}
}
This is the end result of that code:
What I really want to save is image in circle format as it is highlighted in the jcrop selection with jQuery/C#.
What do I need to modify in the existing code to make the image crop work as expected?
In general computer images are always stored as rectangular blocks of data. A "non-rectangular" images is a rectangular image with a non-rectangular mask or opacity "alpha" layer associated with it.
Per the jcrop online docs, jcrop doesn't do non-rectangular cropping-
Cropping Irregular Selections
If you actually want to crop a circle or an ellipse, you're on your
own. Jcrop will provide the rectangular coordinates for these crops,
and further processing can be done to extract the circle or ellipse
from the image.
If you're aiming to do the image manipulation on the client, then you would need to be working in an image format that supports an alpha channel (probably 32 bit: 8 bits for RGB and Alpha). You would need to apply the mask to the alpha channel in a canvas element. I think alpha support is fairly recent stuff in HTML5 so browser support is probably patchy.
You would then need to communicate that back to the host in a file format that supports alpha. JPEG doesn't, PNG (in 32 bit per pixel format) does.
Alternatively, if your server-side code "knows" the shape of the selection crop mask, you can ship the full (rectangular) image back to the server and have your server-side code apply the correct mask shape, using something like GD in PHP.

Can I copy a javascript image object?

I'm building a simple game engine in javascript, and I'm currently building separate spritesheets for left and right animations, but that seems a bit of a pain... What I want to do is something like this:
function loadSprite(graphic)
{
var left_graphic = graphic;
var right_graphic = graphic.flip(); //Create a flipped copy of the graphic
}
// [...]
function update()
{
if(speed>0) context.drawImage(left_graphic);
if(speed<0) context.drawImage(right_graphic);
}
To clarify, I want to create a copy of an Image() object, and mirror flip all it's pixels, so I don't have to maintain two spritesheets.
Is it possible?
First off, you can copy the pixel data using the method described here: Get image data in JavaScript?
I assume you're using a sprite sheet with fixed-sized images. Then you'll have to write an algorithm to flip each image in your image sheet:
for each image in the sheet:
calculate sheet offset (xOffset, yOffset)
for each pixel in half the image:
read pixel ((x, y) + (xOffset, yOffset))
read opposite pixel ((width - x, y) + (xOffset, yOffset))
write on top of opposite pixel
write opposite pixel on top of current pixel

Categories

Resources