Display Image with Base64 String from PostgreSql - javascript

I want to display an image that comes from PostgreSql database. My image is saved as bytea in the postgre DB.
So I select my image from a php script :
$img = pg_unescape_bytea($row[7]);
$bs64 = base64_encode($img);
I see that "pg_unescape_bytea" is mandatory with bytea type, and I encode the result in base64.
So, my Javascript client receive a base64 string, and I try to display it in a canvas.
var canvas = document.getElementById('canvasPrev');
var ctx = canvas.getContext('2d');
var imageData = ctx.createImageData(200, 200);
var pixels = imageData.data;
if (obj[i].image != null) {
var data = text2ua(obj[i].image);
var buffer = data;
for (var j = 0; j < buffer.length; j += 4) {
pixels[j] = buffer[j];
pixels[j + 1] = buffer[j + 1];
pixels[j + 2] = buffer[j + 2];
pixels[j + 3] = buffer[j + 3];
}
console.log(pixels);
ctx.putImageData(imageData, 0, 0);
}
And text2ua function :
function text2ua(s) {
var ua = new Uint8Array(s.length);
for (var i = 0; i < s.length; i++) {
ua[i] = s.charCodeAt(i);
}
return ua;
}
I know that my canvas is working because I achieve to display an image by the same way, but that doesn't come from postgre DB.
My result image looks like the original, but the colors aren't good and the image is semi transparent.
The result that I have :
What I want :
(Dimensions are the same in reality)

Related

Javascript: Convert 2D Integer array to base64 string and back

I'm not much familiar with javascript, but I faced a need to send and receive big static 2D integer arrays (where values are > 255) as base64 strings (this is essential). At the moment I've came up with this straightforward and inefficient solution converting them element-wise and manually constructing strings, which, as far as I understand, should involve a lot of copying of the data and turns to be very slow.
Can it be done in a more efficient way, if possible without usage of some big side libraries like Node.js, etc?
//----------- serializing/deserializing procedures
//encoding int contours array to be sent as base64 string
function getBase64IntArray(arr) {
var width = arr.length;
//This works given the inner arrays length never changes.
var height = arr[0].length;
//string that would contain data
var str = width.toString()+","+height.toString()+",";
for(var x = 0; x < height; x++) {
for(var y = 0; y < width; y++) {
str = str + arr[x][y].toString() + ",";
}
}
var str64 = btoa(str);
return str64;
}//getBase64IntArray
//deconding this string back to array
function getIntArrayfromBase64(str64) {
var str = atob(str64);
//first occurence of ","
var width_str = str.substr(0,str.indexOf(','));
str = str.substr(str.indexOf(',')+1); // cut the beginning
//again first occurence of ","
var height_str = str.substr(0,str.indexOf(','));
str = str.substr(str.indexOf(',')+1); // cut the beginning
var width = parseInt(width_str);
var height = parseInt(height_str);
//declare new array and fill it
var arr = new Array(height);
var curr_str = "";
for(var x = 0; x < height; x++) {
arr[x] = new Array(width);
for(var y = 0; y < width; y++) {
//first occurence of ","
curr_str = str.substr(0,str.indexOf(','));
// cut the beginning
str = str.substr(str.indexOf(',')+1);
arr[x][y]=parseInt(curr_str);
}
}
return arr;
}// getIntArrayfromBase64
Sending/receiving works:
//----------- example usage
function send(){
//encoding to base64
var arr = [
[1, 2],
[3, 4]
];
var base64 = getBase64IntArray(arr);
webSocket.send(base64);
}
webSocket.onmessage = function(event){
//reading array as base64 string
var arr = getIntArrayfromBase64(event.data);
var width = arr.length;
var height = arr[0].length;
writeResponse("Received "+width+" "+height+" "+arr[0][0]+arr[1][1]);
};
How about going through JSON? JSON will add minimal overhead to the wire format, but the serialization/deserialization will be fast, because it's implemented natively.
function getBase64IntArray(arr) {
return btoa(JSON.stringify(arr))
}
function getIntArrayfromBase64(str64) {
return JSON.parse(atob(str64))
}

Split javascript string into array

I have this javscript string:
response
"[[[#],[b,#],[b,w,b,b,b,#],[b,#],[b,w,w,b,#]],[[b,#],[b,b,#],[b,b,w,#],[b,b,b,#],[b,b,#]],[[b,#],[b,b,b,b,#],[b,w,#],[b,b,b,#],[b,#]],[[b,#],[b,#],[w,w,w,#],[b,b,w,w,#],[b,w,#]],[[b,#],[b,b,b,b,#],[b,w,b,#],[b,w,#],[b,b,#]]]"
This corresponds to a board game and which field (e.g [b,w,b,b,b,#]) is a cell with black and white pieces. The # is the top of the stack.
I need to parse this in order to create an array of tiles.
I have this:
XMLscene.prototype.readBoard = function(data){
var response = data.target.response;
console.log("REPONSE NO PARS" + response);
response = response.split("],");
console.log("REPONSE " + response);
response[0] = response[0].substring(1);
response[5] = response[5].substring(0, response[5].length - 2);
for(var i = 0; i < response.length; i++)
{
response[i] = response[i].substring(1);
response[i] = response[i].split("),");
for(var j = 0; j < response[i].length; j++)
response[i][j] = response[i][j].substring(5);
}
this.scene.board.loadTiles(response);
//this.scene.client.getPrologRequest('quit', 0, 1);
};
to be parsed in this function:
gameBoard.prototype.loadTiles = function(board){
console.log("BOARD : " + board);
this.tiles = [];
for (var i = 0; i < board.length; i++){
for (var j = 0; j < board[i].length; j++){
var player = board[i][j].split(",")[0];
console.log("PLAYER : " + player);
var type = board[i][j].split(",")[1];
console.log("Type : " + type);
if (type != "e") {
var tile = this.createTile(type, this.scene ,i*6 + j+100, player);
tile.line = i;
tile.col = j;
this.tiles.push(tile);
}
}
}
}
The board structure I want is something like this:
for the first stack: [#]
It's an empty cell
[b,#] - A cell with one piece - black
[b,w,w,b,#] - A cell with a black piece in the bottom, then two white pieces and a black on the top, therefore the black player is the owner of the stack!
The stack owner is the player that have his piece on the top of the stack (closest to #)
Is there any way to get an array with each stack being the element of it?
Regards
You could transform the data to JSON like this, ignoring the hashes as they seem to give information that is already known (the stack ends at the right):
var response = JSON.parse(response.replace(/,?#/g, '').replace(/[bw]/g, '"$&"'));
Then you can for instance identify the current player for a stack at (i, j), like this:
var player = board[i][j].slice(-1)[0]; // last element on the stack
Snippet:
// Sample data
var response = "[[[#],[b,#],[b,w,b,b,b,#],[b,#],[b,w,w,b,#]],[[b,#],[b,b,#],[b,b,w,#],[b,b,b,#],[b,b,#]],[[b,#],[b,b,b,b,#],[b,w,#],[b,b,b,#],[b,#]],[[b,#],[b,#],[w,w,w,#],[b,b,w,w,#],[b,w,#]],[[b,#],[b,b,b,b,#],[b,w,b,#],[b,w,#],[b,b,#]]]";
// Convert to nested array
var board = JSON.parse(response.replace(/,?#/g, '').replace(/[bw]/g, '"$&"'));
// Print the stack at 3, 3
console.log(board[3][3].join(','));
// Print player for that stack:
console.log(board[3][3].slice(-1)[0]);
A quick and dirty solution is to quote all your elements by using String.prototype.replace() and then put the entire result in an eval():
var str = "[[[#],[b,#],[b,w,b,b,b,#],[b,#],[b,w,w,b,#]],[[b,#],[b,b,#],[b,b,w,#],[b,b,b,#],[b,b,#]],[[b,#],[b,b,b,b,#],[b,w,#],[b,b,b,#],[b,#]],[[b,#],[b,#],[w,w,w,#],[b,b,w,w,#],[b,w,#]],[[b,#],[b,b,b,b,#],[b,w,b,#],[b,w,#],[b,b,#]]]";
var res = eval(str.replace(/[bw#]/g, "'$&'"));
console.log(res);
Modify your string to look like this...
var myString = '[[[#],[b,#],[b,w,b,b,b,#],[b,#],[b,w,w,b,#]],[[b,#],[b,b,#],[b,b,w,#],[b,b,b,#],[b,b,#]],[[b,#],[b,b,b,b,#],[b,w,#],[b,b,b,#],[b,#]],[[b,#],[b,#],[w,w,w,#],[b,b,w,w,#],[b,w,#]],[[b,#],[b,b,b,b,#],[b,w,b,#],[b,w,#],[b,b,#]]]'
replace elements with ""
Now run following:
var myArrayObject = JSON.parse(myString);
You just converted it to array.
Sample code:
https://fiddle.jshell.net/3gvzmwef/21/

How to convert Uint8ClampedArray of webp image picked from canvas to base64

I'm trying to convert Uint8ClampedArray picked from webp images on canvas using the getImageData method.
I've tried the method found in this thread: How can I create a canvas imageData array from an arrayBuffer representation of a JPG
The output I get is only this part:
AAAAAA==
How to get the full data. Here's how I tried unsuccessful:
function Uint8toBase64(idata) {
this.idata = idata;
var u = new Uint8ClampedArray(4);
for (var i = 0; i < idata.length; i += 4) {
idata[0] = u[i];
idata[1] = u[i + 1];
idata[2] = u[i + 2];
idata[3] = u[i + 3];
}
var str = String.fromCharCode.apply(null, u);
var b64 = btoa(str);
console.log(b64);
}
Thanks in advance,

JavaScript Reference Several Images With Similar Names Without Linking to Each One

I have the following code which chooses a background image depending from the images array. The problem is that I have about 200 images and I was hoping there would be a quicker way to put all of them in the images array than have to list each image like I have the six currently. They have very similar names (i.e. image001, image002, ... image200) so if somehow the number could just be added onto the "image".
This would save me a lot of time and space. The code is below.
var images = [
'image0.png',
'image1.png',
'image2.png',
'image3.png',
'image4.png',
'image5.png'
];
$("#container").on("scroll", function(){
var $container = $("#container");
var $content = $("#content");
var totalScrollAmount = $content.height() - $container.height();
var percentScrolled = $container.scrollTop() / totalScrollAmount;
$content.css({
background:"url("+images[Math.floor(percentScrolled * images.length)]+")"
});
});
var images = [];
for(var i = 0; i < 200; i++)
images.push("image" + ("000" + i).substr(-3, 3) + ".png");
Here is a generator written as an IIFE
var images = (function (maxlen, arr, i) {
function pad3(i) { // helper
return ('000' + i).slice(-3);
}
arr || (arr = []); // defaults
i || (i = 0);
arr.length = maxlen;
for (; i < maxlen; ++i) { // do the loop
arr[i] = 'image' + pad3(i) + '.png';
}
return arr;
}(3)); // 3 for 3 items
images; // ["image000.png", "image001.png", "image002.png"]

Convert Data-URL to valid byte string

I am attempting to allow the user to save images that have been rendered to the canvas. There may be several images and I want the user to be able to download all the images at once as a single tar file. I am trying to write the code to generate this tar file. I have most of this working, but when the tar file is downloaded to my computer at the end I discover that some of the binary data that composes the png files has been corrupted. Here is the relevant code:
var canvBuffer = $('<canvas>').attr('width', canvasWidth).attr('height', canvasHeight);
var ctxBuffer = canvBuffer[0].getContext('2d');
imgData.data.set(renderedFrames[0]);
ctxBuffer.putImageData(imgData,0,0);
var strURI = canvBuffer[0].toDataURL();
var byteString = atob(decodeURIComponent(strURI.substring(strURI.indexOf(',')+1)));
toTar([byteString]);
function toTar(files /* array of blobs to convert */){
var tar = '';
for (var i = 0, f = false, chkSumString, totalChkSum, out; i < files.length; i++) {
f = files[i];
chkSumString = '';
var content = f;
var name = 'p1.png'.padRight('\0', 100);
var mode = '0000664'.padRight('\0', 8);
var uid = (1000).toString(8).padLeft('0', 7).padRight('\0',8);
var gid = (1000).toString(8).padLeft('0', 7).padRight('\0',8);
var size = (f.length).toString(8).padLeft('0', 11).padRight('\0',12);
var mtime = '12123623701'.padRight('\0', 12); // modification time
var chksum = ' '; // enter all spaces to calculate chksum
var typeflag = '0';
var linkname = ''.padRight('\0',100);
var ustar = 'ustar \0';
var uname = 'chris'.padRight('\0', 32);
var gname = 'chris'.padRight('\0', 32);
// Construct header with spaces filling in for chksum value
chkSumString = (name + mode + uid + gid + size + mtime + chksum + typeflag + linkname + ustar + uname + gname).padRight('\0', 512);
// Calculate chksum for header
totalChkSum = 0;
for (var i = 0, ch; i < chkSumString.length; i++){
ch = chkSumString.charCodeAt(i);
totalChkSum += ch;
}
// reconstruct header plus content with chksum inserted
chksum = (totalChkSum).toString(8).padLeft('0', 6) + '\0 ';
out = (name + mode + uid + gid + size + mtime + chksum + typeflag + linkname + ustar + uname + gname).padRight('\0', 512);
out += content.padRight('\0', (512 + Math.floor(content.length/512) * 512)); // pad out to a multiple of 512
out += ''.padRight('\0', 1024); // two 512 blocks to terminate the file
tar += out;
}
var b = new Blob([tar], {'type': 'application/tar'});
window.location.href = window.URL.createObjectURL(b);
}
I am putting a previously rendered frame onto a non-rendered canvas and using the canvases toDataURL() method to an encoded png version of the frame with Base64 encoding. Next I use atob to convert this to a byte string so it can be appended to the contents of the tar file I am generating.
When I view the file in a hex editor my tar header is correct, but the contents of the png are not quite right. The ASCII contents looks normal but binary data is scrambled.
Any help offered would be greatly appreciated. Thanks.
PS
I have attached links to related posts that I have looked at. They have been helpful, but I have not yet seen anything there that fully resolves my issues. Thanks.
Convert Data URI to File then append to FormData, and Data URI to Object URL with createObjectURL in chrome/ff
OK, I have resolved the issue. The problem was the Blob constructor at the end of toTar. passing it a string caused the blob to treat my data as UTF-8 instead of binary, I need to instead pass it arrayBuffer for an array of unsigned integers. Below is my solution
var byteArray = new Uint8Array(tar.length);
for (var b = 0; b < tar.length; b++) {
byteArray[b] = tar.charCodeAt(b);
}
var b = new Blob([byteArray.buffer], {'type': 'application/tar'});
window.location.href = window.URL.createObjectURL(b);
I should rewrite toTar to build the file in Uint8Array and remove the need to convert at the end, but this adequately answers my question and hopefully will help someone else. Thanks.

Categories