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.